详细介绍SpringCloud之Ribbon
一:ribbon是什么?
ribbon是netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将netflix的中间层服务连接在一起。ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出load balancer(简称lb)后面所有的机器,ribbon会自动的帮助你基于某种规则(如简单轮询,随即连接等)去连接这些机器。我们也很容易使用ribbon实现自定义的负载均衡算法。
二:lb方案分类
目前主流的lb方案可分成两类:一种是集中式lb, 即在服务的消费方和提供方之间使用独立的lb设施(可以是硬件,如f5, 也可以是软件,如nginx), 由该设施负责把访问请求通过某种策略转发至服务的提供方;另一种是进程内lb,将lb逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。ribbon就属于后者,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址。
三:ribbon的主要组件与工作流程
ribbon的核心组件(均为接口类型)有以下几个:
serverlist
用于获取地址列表。它既可以是静态的(提供一组固定的地址),也可以是动态的(从注册中心中定期查询地址列表)。
serverlistfilter
仅当使用动态serverlist时使用,用于在原始的服务列表中使用一定策略过虑掉一部分地址。
irule
选择一个最终的服务地址作为lb结果。选择策略有轮询、根据响应时间加权、断路器(当hystrix可用时)等。
ribbon在工作时首选会通过serverlist来获取所有可用的服务列表,然后通过serverlistfilter过虑掉一部分地址,最后在剩下的地址中通过irule选择出一台服务器作为最终结果。
四:ribbon提供的主要负载均衡策略介绍
1:简单轮询负载均衡(roundrobin)
以轮询的方式依次将请求调度不同的服务器,即每次调度执行i = (i + 1) mod n,并选出第i台服务器。
2:随机负载均衡 (random)
随机选择状态为up的server
3:加权响应时间负载均衡 (weightedresponsetime)
根据相应时间分配一个weight,相应时间越长,weight越小,被选中的可能性越低。
4:区域感知轮询负载均衡(zoneavoidancerule)
复合判断server所在区域的性能和server的可用性选择server
ribbon自带负载均衡策略比较
策略名 | 策略声明 | 策略描述 | 实现说明 |
bestavailablerule | public class bestavailablerule extends clientconfigenabledroundrobinrule | 选择一个最小的并发请求的server | 逐个考察server,如果server被tripped了,则忽略,在选择其中activerequestscount最小的server |
availabilityfilteringrule | public class availabilityfilteringrule extends predicatebasedrule | 过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值) | 使用一个availabilitypredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态 |
weightedresponsetimerule | public class weightedresponsetimerule extends roundrobinrule | 根据相应时间分配一个weight,相应时间越长,weight越小,被选中的可能性越低。 | 一 个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权重。当刚开始运行,没有形成statas时,使用roubine策略选择 server。 |
retryrule | public class retryrule extends abstractloadbalancerrule | 对选定的负载均衡策略机上重试机制。 | 在一个配置时间段内当选择server不成功,则一直尝试使用subrule的方式选择一个可用的server |
roundrobinrule | public class roundrobinrule extends abstractloadbalancerrule | roundrobin方式轮询选择server | 轮询index,选择index对应位置的server |
randomrule | public class randomrule extends abstractloadbalancerrule | 随机选择一个server | 在index上随机,选择index对应位置的server |
zoneavoidancerule | public class zoneavoidancerule extends predicatebasedrule | 复合判断server所在区域的性能和server的可用性选择server | 使 用zoneavoidancepredicate和availabilitypredicate来判断是否选择某个server,前一个判断判定一个 zone的运行性能是否可用,剔除不可用的zone(的所有server),availabilitypredicate用于过滤掉连接数过多的 server。 |
五:ribbon单独使用
创建一个maven工程 名称 ribbon_client
pom内容
<dependencies> <dependency> <groupid>com.netflix.ribbon</groupid> <artifactid>ribbon-core</artifactid> <version>2.2.0</version> </dependency> <dependency> <groupid>com.netflix.ribbon</groupid> <artifactid>ribbon-httpclient</artifactid> <version>2.2.0</version> </dependency> </dependencies>
sample-client.properties配置文件
# max number of retries sample-client.ribbon.maxautoretries=1 # max number of next servers to retry (excluding the first server) sample-client.ribbon.maxautoretriesnextserver=1 # whether all operations can be retried for this client sample-client.ribbon.oktoretryonalloperations=true # interval to refresh the server list from the source sample-client.ribbon.serverlistrefreshinterval=2000 # connect timeout used by apache httpclient sample-client.ribbon.connecttimeout=3000 # read timeout used by apache httpclient sample-client.ribbon.readtimeout=3000 # initial list of servers, can be changed via archaius dynamic property at runtime sample-client.ribbon.listofservers=www.sohu.com:80,www.163.com:80,www.sina.com.cn:80 sample-client.ribbon.enableprimeconnections=true
ribbonmain代码
import java.net.uri; import com.netflix.client.clientfactory; import com.netflix.client.http.httprequest; import com.netflix.client.http.httpresponse; import com.netflix.config.configurationmanager; import com.netflix.loadbalancer.zoneawareloadbalancer; import com.netflix.niws.client.http.restclient; public class ribbonmain { public static void main( string[] args ) throws exception { configurationmanager.loadpropertiesfromresources("sample-client.properties"); system.out.println(configurationmanager.getconfiginstance().getproperty("sample-client.ribbon.listofservers")); restclient client = (restclient)clientfactory.getnamedclient("sample-client"); httprequest request = httprequest.newbuilder().uri(new uri("/")).build(); for(int i = 0; i < 4; i ++) { httpresponse response = client.executewithloadbalancer(request); system.out.println("status for uri:" + response.getrequesteduri() + " is :" + response.getstatus()); } zoneawareloadbalancer lb = (zoneawareloadbalancer) client.getloadbalancer(); system.out.println(lb.getloadbalancerstats()); configurationmanager.getconfiginstance().setproperty("sample-client.ribbon.listofservers", "ccblog.cn:80,www.linkedin.com:80"); system.out.println("changing servers ..."); thread.sleep(3000); for(int i = 0; i < 3; i ++) { httpresponse response = client.executewithloadbalancer(request); system.out.println("status for uri:" + response.getrequesteduri() + " is :" + response.getstatus()); } system.out.println(lb.getloadbalancerstats()); } }
代码解析
使用 archaius configurationmanager 加载属性;
使用 clientfactory 创建客户端和负载均衡器;
使用 builder 构建 http 请求。注意我们只支持 uri 的 "/" 部分的路径,一旦服务器被负载均衡器选中,会由客户端计算出完整的 uri;
调用 api client.executewithloadbalancer(),不是 exeucte() api;
动态修正配置中的服务器池;
等待服务器列表刷新(配置文件中定义的刷新间隔是为 3 秒钟);
打印出负载均衡器记录的服务器统计信息。
六:ribbon结合eureka使用
先要启动eureka_register_service工程(注册中心)和biz-service-0工程(服务生产者)
创建maven工程 eureka_ribbon_client 该工程启动和相关配置依赖eureka_register_service和biz-service-0
pom加入
<parent> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-parent</artifactid> <version>1.4.3.release</version> <relativepath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-starter-ribbon</artifactid> </dependency> <dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-starter-eureka</artifactid> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-test</artifactid> <scope>test</scope> </dependency> </dependencies> <dependencymanagement> <dependencies> <dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-dependencies</artifactid> <version>brixton.release</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencymanagement>
在应用主类中,通过@enablediscoveryclient注解来添加发现服务能力。创建resttemplate实例,并通过@loadbalanced注解开启均衡负载能力。
@springbootapplication @enablediscoveryclient public class ribbonapplication { @bean @loadbalanced resttemplate resttemplate() { return new resttemplate(); } public static void main(string[] args) { springapplication.run(ribbonapplication.class, args); } }
创建consumercontroller来消费biz-service-0的getuser服务。通过直接resttemplate来调用服务
@restcontroller public class consumercontroller { @autowired resttemplate resttemplate; @requestmapping(value = "/getuserinfo", method = requestmethod.get) public string add() { return resttemplate.getforentity("http://biz-service-0/getuser", string.class).getbody(); } }
application.properties中配置eureka服务注册中心
spring.application.name=ribbon-consumer server.port=8003 eureka.client.serviceurl.defaultzone=http://localhost:8000/eureka/
完成后可以打开http://localhost:8003/getuserinfo 可以看到结果
总结:ribbon其实就是一个软负载均衡的客户端组件,他可以和其他所需请求的客户端结合使用,和eureka结合只是其中的一个实例。
代码地址:https://github.com/zhp8341/springclouddemo
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。