Spring - Ribbon 客户端负载均衡
一种基HTTP和TCP的客户端负载均衡工,基于Netflix Ribbon实现。不需要独立部署,作为工具类框架使用。
使用方式
启动类
/*注册为Eureka客户端应用*/ @EnableDiscoveryClient @SpringBootApplication public class SpringBootTestRibbonConsumerApplication { /*对,就是这个东西实现客户端负载均衡的*/ @Bean @LoadBalanced TestRestTemplate restTemplate(){ return new TestRestTemplate(); } public static void main(String[] args) { SpringApplication.run(SpringBootTestRibbonConsumerApplication.class, args); } }
pom.xml
<dependencies> ...... <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency> ....... </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Brixton.SR5</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
配置文件【可配置的东西】
spring.application.name=ribbon-consumer server.port=9000 eureka.client.service-url.defaultZone=http://localhost:1111/eureka/ # 重试机制 hello-service 服务调用为例 # 用于开启重试机制,默认为关闭。 spring.cloud.loadablancer.retry.enabled = true # 断路器的超时时间需要大于Ribbon的超时时间,不然不会触发重试 hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds = 10000 # 请求连接超时时间 hello-service.ribbon.ConnectTimeout=250 # 请求处理超时时间 hello-service.ribbon.ReadTimeout=1000 # 对所有操作请求都进行重试 hello-service.ribbon.OkRoRetryOnAllOperations = true # 切换实例的重试次数 hello-service.ribbon.MaxAutoRetriesNextServer = 2 # 对当前实例的重试册次数 hello-service.ribbon.MaxAutoRetries = 1 ### sample-client in baidu ## Max number of retries #ribbon.MaxAutoRetries=1 ## Max number of next servers to retry (excluding the first server) #ribbon.MaxAutoRetriesNextServer=1 ## Whether all operations can be retried for this client #ribbon.OkToRetryOnAllOperations=true ## Interval to refresh the server list from the source #ribbon.ServerListRefreshInterval=2000 ## Connect timeout used by Apache HttpClient #ribbon.ConnectTimeout=3000 ## Read timeout used by Apache HttpClient #ribbon.ReadTimeout=3000 ## Initial list of servers, can be changed via Archaius dynamic property at runtime #ribbon.listOfServers=testserver1:80,testserver2 :80,testserver3:80 #ribbon.EnablePrimeConnections=true
对其的实例使用情况:
@RestController public class UsedHelloController { /*这个就是自动加载的重要东东*/ @Autowired RestTemplate restTemplate; @RequestMapping(value = "ribbon-consumer",method = RequestMethod.GET) public String helloConsumer(){ /*对,就是下面这个进行调用服务的实例接口*/ return restTemplate.getForEntity("http://hello-service/hello",String.class).getBody(); } //对RestTemplate的介绍 @RequestMapping(value = "ribbon-consumer-get",method = RequestMethod.GET) public String helloConsumerTestGet(){ /*getForEntity的重载1:提供3个参数 * String URL:请求地址 * Class responseType:返回类型 * Object... urlVariables:代替占位符的一个数组*/ ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://hello-service/hello?name={1}",String.class,"参数1"); String body = responseEntity.getBody(); /*getForEntity的重载2:提供3个参数 * String URL:请求地址 * Class responseType:返回类型 * Map urlVariables : 参数对应Map */ Map<String,String> params = new HashMap<>(); params.put("name","name"); responseEntity = restTemplate.getForEntity("http://hello-service/hello?name={name}",String.class,params); body = responseEntity.getBody(); /*getForEntity的重载3:提供2个参数 * URI:是java.net包下的一个雷 表示同意资源标示符 * Class responseType:返回类型 * 例子:忽略╮(╯_╰)╭ */ /*与此差不多的3个方法是 getForObject(。。。) 有一样的3种的重载*/ return body; } @RequestMapping(value = "ribbon-consumer-post",method = RequestMethod.POST) public String helloConsumerTestPost(){ User user = new User("name"); // String user = new String(); ResponseEntity<String> responseEntity = restTemplate.postForEntity("http://hello-service/hello",user,String.class); /*这里的返回类型,在服务提供方也必须存在,否则会报错 无法找到类定义*/ String body = responseEntity.getBody(); return body; /*与get一样也是有3中的重载,具体的参数可以直接查看源码 * 还有 postForObject 和 postForLocation */ } public class User { private String name; public User(String name){ this.name = name; } public User() { } } @RequestMapping(value = "ribbon-consumer-put",method = RequestMethod.PUT) public String helloConsumerTestPut(){ User user = new User("name"); Long id = 100L; restTemplate.put("http://hello-service/hello/{1}",user,id); /*也是一样有3个的重载,不过put是没有返回内容的*/ return null; } @RequestMapping(value = "ribbon-consumer-del",method = RequestMethod.DELETE) public String helloConsumerTestDel(){ User user = new User("name"); Long id = 100L; restTemplate.delete("http://hello-service/hello/{1}",id); /*也是一样有3个的重载,不过put是没有返回内容的*/ return null; } }
一些配置说明和详解
简单默认:不使用其他治理框架的情况下的配置:
* IclientConfig:Ribbon的客户端配置,默认采用 com.netflix.client.config.DefaultClientConfigImpl实现
* IRule:Ribbon的复杂均衡策略,默认采用com.netflix.loadbalancer.ZoneAvoidanceRule实现,改策略能够在多区域环境下选出最佳区域的实例进行访问。
* IPing:Ribbon的实例检查策略,默认为com.netflix.loadbalancer.NoOpPing,实际上并不会检查,而是直接返回true,默认实例都是可用的。
* SercerList:服务实例清单的维护机制,默认为:com.netflix.loadbalancer.ConfigurationBasedSercerList实现。
* ServerLisetFilter:服务实例清单过滤机制,默认为:org.springframework.netflix.ribbon.ZonePreferenceServerListFilter实现,策略有限过滤出与请求调用方处于同区域的服务实例。
* ILoadBalancer:负载均衡器,默认使用:com.netflix.loadbalancer.ZoneAwareLoadBalancer实现,具备区域感知的能力。
这些自动化配置内容,仅在没有使用Rureka等服务治理框架时 是这个样子的 (ノ`Д)ノ
Camden版本对RibbonClient配置进行了优化:
使用配置文件即可:e.g.:
hello-server.ribbon.NFLoadBalancerPingClassName = com.net.loadbalancer.PingUrl
## 这个PingUrl为自定义的IPing接口实现类
## 这里是对hello-server这个服务进行设置的
## 进行动态创建这些配置的接口实现为:org.springframework.cloud.netflix.ribbon.PropertiesFactory
与Eureka结合使用:
会自动触发Eureka对Ribbon的自动化配置:
ServerLiset维护:com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSSercerList
IPing:com.netflix.niws.loadbalancer.NIWSDiscoveryPing
ServerList实现:com.SpringFamework.cloud.netflix.ribbon.eureka.DomainExtractingServerLiset
可以通过Eureka的实例数据源进行配:配置自定义的区域值:
eureka.instance.metadataMap.zone = shanghai
关闭Eureka对Ribbon的服务实例维护实现:【谁呀的会去关啊(ノ`⊿´)ノ】
ribbon.eureka.enabled = false
20171208 小杭 ε=(´ο`*)))唉 感冒。。。。。