做网站赚钱么,南昌网站推广,wordpress 安装的时候是英文,wordpress3.9中文版目录 Spring-Cloud 学习笔记-#xff08;4#xff09;负载均衡器Ribbon1、前言2、什么是负载均衡2.1、问题分析2.2、什么是Ribbon3、快速入门3.1、实现方式一3.1.1、修改代码3.2、实现方式二3.2.1、启动类3.2.2、调用代码3.2.3、测试3.2.4、实现原理3.2.5、断点调式3.3、修改… 目录 Spring-Cloud 学习笔记-4负载均衡器Ribbon1、前言2、什么是负载均衡2.1、问题分析2.2、什么是Ribbon3、快速入门3.1、实现方式一3.1.1、修改代码3.2、实现方式二3.2.1、启动类3.2.2、调用代码3.2.3、测试3.2.4、实现原理3.2.5、断点调式3.3、修改轮询策略3.4、重载机制3.4.1、为什么要有重载机制3.4.2、实现代码 Spring-Cloud 学习笔记-4负载均衡器Ribbon 1、前言 上个章节我们做了什么 上个章节我们说了用eureka来实现服务的注册与发现并且用过服务的seviceId拉取了服务列表ListServiceInstance instances discoveryClient.getInstances(user-service) 从而实现服务的调用方order-service调用服务的提供方user-service本章节我们会做什么 负载均衡2、什么是负载均衡 2.1、问题分析 上个章节我们实现了服务之间的调用把原来代码里面写死的ip地址换成用serviceId拉取服务列表然后从服务列表中获取实例的方式虽然代码变得复杂了但是思想上我们得到的升级但是还是存在一个问题就是ServiceInstance instance instances.get(0);每次我们都取同一个ip要想每次使用不同的ip我们自己就要写负载均衡算法从多个实例当中获取某一个实例进行调用这次我们这一章节讲的就是负载均衡器Ribbon它里面内置了很多负载均衡的算法帮我们从实例列表中获取一个实例。 2.2、什么是Ribbon 3、快速入门 我们按照上节课方法启动一个Eureka注册中心两个方便演示负载均衡服务的提供方user-service最后我们修改服务调用方order-service代码 pom文件 !-- ribbon --
dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-ribbon/artifactId
/dependency 3.1、实现方式一 3.1.1、修改代码 //注入 RibbonLoadBalancerClientAutowiredprivate LoadBalancerClient client;
...//通过serviceId 拉取服务列表//ListServiceInstance instances discoveryClient.getInstances(user-service);//ServiceInstance instance instances.get(0);ServiceInstance instance client.choose(user-service);
String jsonStr restTemplate.getForObject(http://instance.getHost():instance.getPort()/api/v1/user/2, String.class); 之前我们是通过serviceId“user-service”获取到的是服务列表现在我们直接可以通过serviceId返回的是单个实例不是因为列表里面只有一个实例是因为choose方法中已经帮我们做了复杂均衡了。 3.2、实现方式二 3.2.1、启动类 /*** 把RestTemplate注入到Spring容器中*/
Bean
LoadBalanced //增加注解 让RestTemplate内置一个负载均衡器
public RestTemplate restTemplate(){return new RestTemplate();
} 3.2.2、调用代码 String jsonStr restTemplate.getForObject(http://user-service/api/v1/user/2, String.class); 之前我们把serviceId交出去别人帮我们取一堆或者取一个现在直接把serviceId写在url路径中。 3.2.3、测试 启动order-service 访问http://localhost:8781/api/v1/order/2 3.2.4、实现原理 其实实现方式二低层就是用的实现方式一只不过实现方式二加了一个拦截器LoadBalancerInterceptor对RestTemplate请求做了拦截然后把请求路径中的serviceIduser-service拿到然后通过方式一获取某一个实例进行调用。 3.2.5、断点调式 我们按两下shift搜索到LoadBalancerInterceptor这个拦截器在intercept方法中打好断点 public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException {//1.拿到请求路径URI originalUri request.getURI();//2.从路径中获取serviceIdString serviceName originalUri.getHost();Assert.state(serviceName ! null, Request URI does not contain a valid hostname: originalUri);//3.执行execute方法.. 我们接着看execute方法return (ClientHttpResponse)this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution));
}// RibbonLoadBalancerClient类中
public T T execute(String serviceId, LoadBalancerRequestT request) throws IOException {//4.根据serviceId获取到负载均衡器ILoadBalancer loadBalancer this.getLoadBalancer(serviceId);//5.通过负载均衡器拿到某一个实例..我们接着看getServer方法Server server this.getServer(loadBalancer);if (server null) {throw new IllegalStateException(No instances available for serviceId);} else {RibbonLoadBalancerClient.RibbonServer ribbonServer new RibbonLoadBalancerClient.RibbonServer(serviceId, server, this.isSecure(server, serviceId), this.serverIntrospector(serviceId).getMetadata(server));return this.execute(serviceId, ribbonServer, request);}}//RibbonLoadBalancerClient类中
protected Server getServer(ILoadBalancer loadBalancer) {//6.判断负载均衡器是不是为空不为空调用chooseServerdefault方法我们接着看return loadBalancer null ? null : loadBalancer.chooseServer(default);
}//BaseLoadBalancer类中
public Server chooseServer(Object key) {//这里key是默认值“default”if (this.counter null) {this.counter this.createCounter();}this.counter.increment();if (this.rule null) {return null;} else {try {//根据rule调用choose方法其中IRule是一个接口有很多实现类每一个实现类对于不同的负载均衡策略比如RandomRule随机RoundRobinRule轮询等我们BaseLoadBalancer类中有一个属性 private static final IRule DEFAULT_RULE new RoundRobinRule();代表默认轮询策略有兴趣的可以看一下每一个实现的choose方法比如轮询策略RoundRobinRule底层维护一个自增长的count,每调用一次count,然后每次用count模于服务列表的长度比如第一次1%51第二次2%52得到的值为服务列表的位置索引从而实现轮询。return this.rule.choose(key);} catch (Exception var3) {logger.warn(LoadBalancer [{}]: Error choosing server for key {}, new Object[]{this.name, key, var3});return null;}}} 3.3、修改轮询策略 application.yml #--负载均衡轮询策略
# serviceId
user-service:ribbon:#负载均衡策略的classNameNFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule 3.4、重载机制 3.4.1、为什么要有重载机制 在上一章中我们说到一个正常的eureka客户端每间隔30秒没有给服务器发送心跳如果90秒服务器还没有收到心跳服务器就会认为这个客户端已经宕机但是eureka不会马上剔除没间隔60会同意剔除这些失效的客户端这样导致我们服务实际上已经宕机了但是服务列表里面还有这样服务的消费者在调用的时候就会报错假设我们服务的提供方有五个虽然只宕机了一台但是还有四台是正常的在这个时候我们条用这个服务如果出现报错信息肯定不是我们希望看到的所有我们就有了这个重载机制Spring Cloud 整合了Spring Retry 来增强RestTemplate的重试能力当一次服务调用失败后不会立即抛出一次而是再次重试下一个服务。 3.4.2、实现代码 application.yml #服务名称
spring:application:name: order-servicecloud:loadbalancer:retry:enabled: true # 开启Spring Cloud的重试功能#负载均衡轮询策略
user-service:ribbon:#负载均衡策略的classNameNFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRuleConnectTimeout: 250 # Ribbon的连接超时时间ReadTimeout: 1000 # Ribbon的数据读取超时时间OkToRetryOnAllOperations: true # 是否对所有操作都进行重试MaxAutoRetriesNextServer: 1 # 切换实例的重试次数MaxAutoRetries: 1 # 对当前实例的重试次数 我们测试发现就算我们user-service宕机了也能通过另一台服务实例获取到结果 转载于:https://www.cnblogs.com/bigfly277/p/10147083.html