自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(272)
  • 资源 (2)
  • 收藏
  • 关注

原创 Hystrix服务隔离实例

public class GetStockServiceCommand extends HystrixCommand<String>{ private StockService stockService; public GetStockServiceCommand(){ super(setter()); } private static Setter setter(){ //服务分组 HystrixCommandGroupKey groupKey =

2022-01-22 18:39:19 392

原创 Hystrix简介以及在分布式服务中的作用

Hystrix简介Netflix开源的一个针对分布式系统的延迟和容错库,目的是用来隔离分布式服务故障。它提供线程和信号量隔离,以减少不同服务之间的资源竞争带来的相互影响,提供优雅降级机制;提供熔断机制使得服务可以快速失败。其主要作用主要有1.限制调用分布式服务的资源使用,某一个调用的服务出现问题不会影响到其他服务调用,通过线程池隔离和信号量隔离实现2.提供优雅降级机制,超时降级,资源不足时候,可以配置降级接口返回拖底数据3.提供熔断实现,当失败率达到阈值出发自动降级,熔断器触发的快速失败会进行快速

2022-01-22 17:58:07 337

原创 网络爬虫和主业务隔离

实际业务中,爬虫和正常的流量的比例能达到5比1,甚至更高。而一些系统是因为爬虫访问量太大而导致服务不可用。一种解决办法是通过限流解决,另一种解决办法是在负载均衡层面把爬虫路由到单独集群,从而保证正常流量可用,爬虫流量尽量可用最简单的方法是使用Nginx,配置如下set $flag = 0;if($http_user_agent ~* "spider"){ set $flag "1";}if($flag = "0"){ //代理到正常集群}if($flag = "1"){ //代理

2022-01-21 17:49:15 2524

原创 系统设计中的动静隔离

当用户访问如结算页时,如果JS/CSS等静态资源也在结算页系统中,很可能因为带宽打满,导致不可用因此,应将动态内容和静态资源分离,一般应该将静态资源放在CDN上,如下图

2022-01-21 17:33:36 316

原创 Redis实现读写隔离

通过主从模式将读和写集群分离,读服务只从Redis集群获取数据,当主Redis集群出现问题时,从Redis集群还是可用的,从而不影响用户访问。而当从Redis集群出现问题时,可以进行其他集群的重试。先读取从status,resp=slave_get(key)if status == STATUS_OK then return status,valueend--如果从获取失败了,从主获取status,resp=master_get(key)...

2022-01-21 17:24:24 1260

原创 系统设计中的集群隔离和机房隔离

集群隔离随着系统的发展,单实例服务已经无法满足需求,此时需要服务化技术,通过部署多个服务形成服务集群,来提升系统容量随着调用方的增多,当请求调用会影响到其他服务稳定性时,应该考虑为该类型服务提供单独的服务集群,即服务分组,这样当某一个分组出现问题时,不会影响其他分组,从而实现了故障隔离。举例:注册生产者时候提供分组名<jsf:provider id="myService" interface="com.jd.MyService" alias="${分组名}" ref="myServiceIm

2022-01-20 16:39:28 2491

原创 系统设计中的进程隔离

公司发展初期,一般是先进行从0到1,不会以上来就进行系统拆分,这样就会开发出一些大而全的系统,系统中的一个模块出现问题时,整个系统就不可用了,首先想到的解决方案是通过部署多个实例,通过负载均衡进行路由转发,但是这种情况无法避免某个模块因为BUG而导致内存溢出,导致整个系统瘫痪的风险,因此,遮样的解决方案只是一个过渡,比较好的解决方案是通过将系统拆解分为多个子系统来实现物理隔离,通过进程隔离使得某一个子系统出现问题时不会影响到其他子系统。...

2022-01-19 21:35:00 544

原创 线程隔离JAVA

线程隔离主要是指线程池隔离,在实际使用时,我们会把请求分类,然后交给不同的线程池处理。当一种业务处理发生问题时,不会将故障扩散到其他线程池,从而保证其他服务可用。会根据服务等级划分两个线程池,以下是池的抽象<bean id="zeroLevelAsyncContext" class="com.xx.noah.base.web.DynamicAsyncContext" destroy-method="stop"> <property name="asyncTimeoutIn

2022-01-19 20:53:57 2012

原创 SpringBoot+Consoul Java Client实现Nginx上游服务器的动态注册删除

Maven导入依赖 com.orbitz.consul consul-client 0.12.8服务注册与擦除public static void main(String[] args){ //启动嵌入容器 SpringBootApplication.run(Bootstrap.class,args); //服务注册 Consul consul = Consul.builder().withHostAndPort(HostAndPort.fromString("192.1

2022-01-18 13:08:11 523

原创 Nginx网络配置的反向代理实例

反向代理除了实现负载均衡之外,还提供如缓存来减少上游服务器的压力全局配置proxy_buffering on;proxy_buffer_size 4k;proxy_buffers 512k;proxy_busy_buffers_size 64k;proxy_temp_file_write_size 256k;proxy_cache_lock on;proxy_cache_lock_timeout 200ms;proxy_temp_path /tepfs/proxy_temp;proxy_

2022-01-17 15:10:34 1274

原创 Nginx配置与上游服务器的长链接

可以通过keep-alive指令配置长链接数量upstream backend{ server 192.168.61.1:9080 weight=1; server 192.168.61.1:9090 weight=2 backend; keepalive 100;}通过这个指令配置了每个Worker进程与上游服务器可缓存的空闲连接的最大数量。当超出这个数量时,最近最少使用的连接将被关闭。keepalive指令不限制Worker进程与上游服务器的总连接。如果想要跟上游服务器建立长链

2022-01-16 15:49:30 1778

原创 Nginx网络配置当中的备份上游服务器以及不可用上游服务器

备份上游服务器upstream backend{ server 192.168.61.1:9080 weight=1; server 192.168.61.1:9090 weight=2 backup;}将90端口上游服务器配置为备份上游服务器,当所有的主上服务器都不存活时,请求会转发给备上游服务器如果通过缩容上游服务器进行压测时,要摘掉一些上游服务器进行压缩,但为了保险,会配置一些备份服务器,当压测的服务器都挂了,流量可以直接都给到备份上游服务器,从而不影响用户的请求处理不可用上游服务

2022-01-14 16:38:07 565

原创 Nginx对上游服务的心跳检测健康检查

nginx对上游服务器的健康检查默认采用惰性策略,可以集成nginx_upstream_check_module模块来进行主动健康检查nginx_upstream_check_module支持tcp心跳和http心跳检测TCP心跳检查upstream backend{ server 192.168.61.1:9080 weight=1; server 192.168.61.1:9090 weight=2; check interval=3000 rise=1 fail=3 timeout

2022-01-14 16:21:19 1328

原创 Nginx网络配置当中的失败重试配置

主要有两部分配置:upstream server 和 proxy_passupstream backend{ server 192.168.61.1:9080 max_fails=2 fail_timeout=10s weight=1; server 192.168.61.1:9090 max_fails=2fail_timeout=10s weight=1;}通过上游服务器的配置max_fails和fail_timeout来指定每个上游服务器,当fail_timeout时间内失败了max

2022-01-14 16:04:59 1216

原创 Nginx当中的负载均衡算法类型

round_robin轮询,默认负载均衡算法,以轮询的方式请求转发到上游服务器,通过配合weight配置可以实现基于权重的轮询ip_hash根据客户的ip进行负载均衡,相同的IP将负载均衡到同一个上游服务器upstream backend{ ip_hash; server 192.168.61.1:9080 weight=1; server 192.168.61.1:9090 weight=2;}hash key[consistent]对某一个key进行哈希或者使用一致性hash

2022-01-13 16:07:09 255

原创 Nginx网络架构下的反向代理负载均衡upstream配置

用例第一步需要给Nginx配置上游服务器,即负载均衡到的真实处理业务服务器,通过在http指令下配置upstreamupstream{ server 102.168.61.1:9080 weight=1; server 102.168.61.1:9090 weight=1;}主要配置1.IP地址和端口配置上游服务器的IP地址和端口2.权重weight用来配置权重,默认都是1,权重越高分配给这台服务器的请求就越多,需要根据服务器的处理能力设置权重然后可以配置如下proxy_pass

2022-01-12 15:01:42 972

原创 系统的基础网络架构

扩容当应用单实例不能支撑用户请求,需要扩容,从一台服务器扩容到多台,几十台一种方式是通过域名映射多个IP,但是存在一个简单的容灾问题,假如其中的某一个服务器挂了,DNS会有一定的缓存时间,故障后,切换时间很长,会影响用户体验,并且没有重试机制和心跳检测外网DNS应用GSLB(全局负载均衡)进行流量调度,比如将用户分配到最近的服务器提升体验,当某一个区的机房出现问题时,可以通过DNS指向其他区域的IP来提供服务基于Nginx的网络架构对于一般的应用,Nginx可以满足需求。但是吞吐量有一定的限制,

2022-01-12 14:40:37 849

原创 业务的设计原则

防重设计结算页需要考虑重复提交,还有如下单扣减库存的时候,防止重复扣减库存,解决方案可以考虑防重key,防重表,而有些场景的重复支付是无法避免的,比如现在有些电商网站同时支持支付宝和微信以及其他支付方式,这种情况,可以在系统设计时候,将每笔交易情况记录下来,以便退款的时候可回溯幂等设计交易系统中,经常会用到消息,而现有的消息中间件基本不保证发生重复消息的消息,因此,需要业务系统在重复消息消费时进行幂等处理,在使用第三方支付时,第三方支付会进行异步回调,也要考虑做好回调的幂等处理状态与状态机设计交易

2022-01-11 15:36:07 286

原创 系统设计中的切流量

对于一个大型应用,切流量是非常重要的,比如多机房环境下某个机房挂了,某个机架挂了,或者某台服务器挂了,都需要切流量,有如下几种类型1.DNS 切换机房入口2.HttpDns 主要是在App场景下,在客户端分配好流量入口,绕过运营商LocalDns并实现精准的流量调度3.LVS/HaProxy 切换故障的Nginx接入层4.Nginx 切换故障的应用层...

2022-01-10 15:30:38 954

原创 限流的目的和思路

目的限流的目的是防止恶意请求流量、恶意攻击,或者防止流量超出系统峰值思路1.恶意请求的流量只访问到cache2.对于穿透到后端应用的流量可以使用Nginx的limit模块处理3.对于恶意IP可以使用Nginx deny进行屏蔽原则是限制流量穿透到后端薄弱的应用层...

2022-01-10 14:06:44 727

原创 高可用原则当中的降级

对于一个高可用服务,很重要的一个设计就是降级开关,在设计降级开关时,依据如下思路1.开关集中化管理通过推送机制把开关推送到各个应用2.可降级的多级读服务比如服务调用降级为只读本地缓存、只读分布式缓存,只读默认降级数据(如库存状态默认有货)3.开关前置化如果架构师tomcat+nginx,可以将开关前置到Nginx接入层,在Nginx层做开关,请求流量不回源后端Tomcat应用或者是一小部分流量回源4.业务降级当高并发流量来袭,在电商系统大促设计时,保障用户能下单、能支付是核心要求,并保障数据

2022-01-10 14:01:16 520

原创 分布式缓存设计思路

首先接入层(Nginx+lua)读取本地proxy_cache/local cache如果未命中,则接入层接着读取分布式的redis集群如果还未命中,则会回源到tomcat,然后读取tomcat应用堆内cache如果缓存都没命中,则调用依赖业务来获取数据,然后异步化写到redis集群。...

2022-01-09 19:02:36 649

原创 系统设计中的应用层缓存

使用tomcat时,可以使用堆内缓存/堆外缓存,堆内缓存最大的问题就是重启时,内存中的缓存会丢失,此时流量风暴来临,则有可能冲垮应用,还可以考虑使用local_redis_cache来代替堆外缓存,或者在接入层使用shared_dict来将缓存前置,以减少风暴。local redis cache通过在应用所在服务器上部署一组redis,应用直接读本机redis获取数据,多机之间使用主从机制同步数据。这种方式没有网络消耗,性能是最优的。...

2022-01-09 18:48:06 481

原创 系统设计的接入层缓存

对于没有CDN缓存的应用来说,可以考虑使用如Nginx搭建一层接入层,该接入层考虑如下机制实现:1.URL重写将url按照指定的顺序或者格式重写,去除随机数2.一致性HASH按照指定的参数做一致性hash,从而保证相同的数据落在同一台服务器上3.PROXY_CACHE使用内存级/ssd级代理缓存来缓存内容4.proxy_cache_lock使用lock机制,将多个回源合并为一个,以减少回源量并设置响应的lock超时时间5.shared_dict如果架构使用了Nginx+lua实现,可以考

2022-01-09 18:39:40 728

原创 并发系统缓存类型汇总

客户端1.使用浏览器缓存设置请求的过期时间,如对响应头Expires、Cache-control进行控制。这种机制适用于对实时性不太敏感的数据,比如商品详情,评分,评价,广告词等,对于实时性要求比较高的数据就不能用2.客户端缓存在促销时,为了防止瞬间流量冲击,一般会在大促前把APP需要访问的一些素材(js/css/image)等提前下发到客户端进行缓存,这样在促销时就不用去拉取这些素材了,另外,首屏的数据也可以缓存起来,在网络异常情况下还是可以有拖底的数据供用户查看客户端网络1.代理服务器开启缓

2022-01-08 13:40:10 292

原创 并发系统设计中的数据异构和数据闭环

数据异构订单分库分表一般按照订单ID进行,如果要查询某个用户的订单列表,需要聚合多个表的数据后才能返回,会导致订单表的读性能降低。此时需要对订单表异构,异构一套用户订单表,按照用户ID进行分库分表。另外还需要考虑对历史订单数据进行归档处理,以提升服务的性能和稳定性。而有些数据异构的意义不大,如库存价格,可以考虑异步加载,活着合并请求。数据闭环实现数据闭环,如商品详情页,因为数据来源太多,影响服务稳定性,最好的办法是把使用到的数据进行异构存储,形成数据闭环,基本步骤:1.数据异构通过消息队列接受数据

2022-01-08 13:04:39 425

原创 并发系统消息队列使用用例

简述消息队列用来解耦一些不需要同步调用的服务或者订阅一些自己系统关心的变化,使用消息对列来实现服务解耦,异步处理,流量削峰、缓冲,比如,电商系统中的交易订单数据,有非常多的系统关心并订阅该数据,比如,订单生产系统,定期送系统,订单风控系统等使用消息队列时还要注意处理生产消息失败,以及消息重复接收时的场景。有些消息队列会提供重试功能,在达到指定重试次数未生产成功时,会对外通知生产失败。这时,对于不能容忍生产失败的业务场景来说,一定要做好后续数据处理工作,如持久化数据要同时增加日志、报警等。对于消息重复问题

2022-01-07 12:02:25 714

原创 并发系统设计原则

无状态如果设计的应用是无状态的,那么应用比较容易进行扩展。实际生产环境可能是这样,应用无状态,配置文件有状态。比如不同的机房需要读取不同的数据,此时就需要通过配置文件或者配置中心指定拆分在系统设计初期的时候,是做一个大而全的系统还是按照功能拆分系统,需要根据环境和用户访问量预估来决定,比如,做一个内部使用的在线学习系统,因为使用的人不会特别多,并且资源有限,因此,就没有必要对系统进行拆分,做一个大而全的系统就可以满足需求,而像电商巨头的秒杀系统,访问量巨大,设计时投入的资源充足,就应该拆分系统,通常,

2022-01-06 13:16:43 650

原创 Dubbo构造调用链源码

//保存引用,后续用于把真正的调用者保存到过滤器链的最后Invoker<T> last = invoker;List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.gerUrl(),key,group);if(!filters.isEmpty()){ for(int i = filters.size();i>=0;i--)

2022-01-04 18:55:53 225

原创 Dubbo的服务端上下文的获取和使用

public class DemoServiceImpl implements DemoService{ public void hello(){ //判断是否为服务端 boolean isProviderSide = RpcContext.getContext().isProviderSide(); //获取当前服务配置信息,所有配置信息都将转化为url参数 String clientIp = RpcContext.getContext().getRemoteH

2022-01-04 16:19:30 1063

原创 Dubbo的异步回调服务端实现

public interface CallbackService{ void addListener(String key,CallbackListener listener);}public interface CallbackListener{ void changed(String msg);}public class CallbackServiceImpl implements CallbackService{ private final Map<String,Call

2022-01-04 16:08:50 920

原创 Dubbo的高级特性汇总

1.服务分组和版本支持同一个服务有多个分组和多个版本,用于服务强制隔离,服务多个版本实现2.参数回调当消费方调用服务提供时,支持服务提供方能够异步回调到当前消费方,用于stub做热数据缓存3.隐士参数支持客户端隐士传递参数到服务端4.异步调用并行发起多个请求,但只使用一个线程,用于业务请求非阻塞场景5.上下文信息上下文中存放的是当前调用过程中所需要的环境信息6.结果缓存结果缓存,用于加速热门数据的访问速度,Dubbo提供声明式缓存,以减少用户加缓存的工作量...

2022-01-04 15:45:23 392

原创 Dubbo的Registry层扩展点

Registry层可以理解为注册层,这一层中最重要的扩展点就是org.apache.dubbo.registry.RegistryFactory.整个框架的注册与服务发现都是由这个扩展点负责创建的。该扩展点有@Adaptive({“protocol”})注解,可以根据URL中的protocol参数创建不同的注册中心客户端。例如protocol=redis,该工厂会创建基于redis的注册中心客户端。因此,如果我们扩展了自定义的注册中心,那么只需要配置不同的protocol即可@SPI("dubbo")

2022-01-04 14:38:44 1462

原创 Dubbo的ProxyFactory接口

@SPI("javaassist")public interface ProxyFactory{ @Adaptive({Constants.PROXY_KEY}) <T> T getProxy(Invoker<T> invoker) throws RpcException; @Adaptive({Constants.PROXY_KEY}) <T> T getProxy(Invoker<T> invoker,boolean generic)

2022-01-04 14:31:52 99

原创 Dubbo种的Mock用法

在cluster中,具有MockClusterWrapper,由它实现了Dubbo的本地伪装。这个功能的使用场景较多,通常用于以下两种场景:1.服务降级,部分非关键服务全部不可用,希望主流程继续进行2.在下游某些节点调用异常时,可以用Mock结果返回配置方式//文件中配置<dubbo:reference interface="com.foo.BarService" mock="true" /><dubbo:reference interface="com.foo.BarSer

2021-12-30 20:50:51 1423

原创 Dubbo的merger实现

当一个接口有多个实现,消费者又需要同时引用不同的实现时,可以用group来区分不同的实现<dubbo:service group=“group1” interface=“com.xxx.testService” /><dubbo:service group=“group2” interface=“com.xxx.testService” />如果我们需要并行调用不同的group服务,并且要把结果集合起来,则需要用到Merger特性,merger实现了多个服务调用后结果合并的逻

2021-12-29 14:46:49 291

原创 Dubbo的一致性hash负载均衡

一致性hash负载均衡可以让参数相同的请求每次都陆由到相同的机器上。这种负载均衡的方式可以让请求相对平均,相比直接使用hash而言,当某些节点下线时,请求会平均到其他服务提供者。普通一致性hash会把每个服务节点散列到环形上,然后把请求的客户端散列到环上,顺时针往前找第一个节点就是要调用的节点。普通一致性hash也有一定的局限性,它的散列不一定均匀,容易造成某些节点压力大。因此Dubbo框架使用了优化过的ketama一致性hash,这种算法会为每个真实节点创建多个虚拟节点,让节点分配更均匀一致性has

2021-12-29 14:28:51 700

原创 Dubbo的LeastActive负载均衡

LeastActive负载均衡称为最少活跃调用数负载均衡,即框架会记下每一个invoker的活跃数,每次只从活跃数最少的invoker里选择一个节点...for(int i = 0;i<length;i++){ ... //获得invoker的活跃数、预热权重 if(leastActive == -1 || active < leastAcive){ //发现有更小的活跃数,这里置空之前的计数 ... }else if(active == leastActiv

2021-12-28 15:05:56 568

原创 Dubbo的RoundRobin负载均衡

Dubbo的轮询负载均衡现在采用的平滑权重轮询如下是RoundBin负载均衡的步骤(1)初始化权重缓存Map,以每个Invoker的URL为key,权重对象为value,生成ConcurrentMap,并把这个Map保存到全局的methodWeightMap中,ConcurrentMap<String,ConcurrentMap<String,WeightedRoundRobin>> methodWeightMap.methodWeightMap的key是每个接口的方法名,这一步

2021-12-27 16:58:33 552

原创 Dubbo的Random负载均衡

Random负载均衡是按照权重设置随机概率做负载均衡的。这种负载均衡算法并不能精确地平均请求,但是随着请求数量的增加,最终结果是大致平均的。计算步骤如下1.计算总权重并判断每个Invoker的权重是否一样。遍历整个Invoker列表,求和总权重。遍历过程中,会对比每个Invoker的权重,判断所有Invoker的权重是否相同2.如果权重相同,则说明每个Invoker的概率都一样,因此直接用nextInt随机选一个Invoker返回即可3.如果权重不同,则首先得到偏移值,然后根据偏移值找到对应的Invo

2021-12-26 19:22:40 328

java8讲义与实战全篇

涵盖JAVA8全部知识点以及实战代码

2021-12-07

JavaGuide-main.zip

「Java学习+面试指南」一份涵盖大部分 Java 程序员所需要掌握的核心知识。准备 Java 面试

2021-12-07

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除