入口:
@SpringBootApplication
@EnableDiscoveryClient // 开启Eureka客户端
public class CloudConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(CloudConsumerApplication.class);
}
@Bean//将RestTemplate直接注入bean,http restful风格
//@LoadBalanced //开启负载均衡,Eureka中已经帮我们集成了负载均衡组件:Ribbon
//@LoadBalanced
public RestTemplate restTemplate(){
//微服务http客户端工具
//默认URLConnection
// 这次我们使用了OkHttp客户端,只需要注入工厂即可
return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
}
@LoadBalanced
@Bean
public RestTemplate commRestTemplate() {
RestTemplate restTemplate = new RestTemplate(new OkHttp3ClientHttpRequestFactory());
//这行代码是为了防止restTemplate在请求中出现中文乱码,把编码格式设置为UTF-8格式。
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
return restTemplate;
}
}
测试类:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = CloudConsumerApplication.class)
public class RibbonloadBalance {
@Autowired
private RestTemplate commRestTemplate;
@Autowired
private RibbonLoadBalancerClient client;
@Test
public void test(){
for (int i = 0; i <20 ; i++) {
ServiceInstance choose = this.client.choose("user-service");
String s = choose.getHost() + ":" + choose.getPort();
System.out.println(s);
}
}
}
结果:
说明ribbon默认为轮询策略!
修改负载均衡的策略
跟踪源码,发现这么一段代码:
我们看看这个rule是谁:
这里的rule默认值是一个RoundRobinRule
,看类的介绍:
这不就是轮询的意思嘛。
我们注意到,这个类其实是实现了接口IRule的,查看一下:
定义负载均衡的规则接口。
它有以下实现:
SpringBoot也帮我们提供了修改负载均衡规则的配置入口:
user-service:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
格式是:{服务名称}.ribbon.NFLoadBalancerRuleClassName
,值就是IRule的实现类。
在消费者的yml文件中添加负载策略配置
server:
port: 8092
spring:
application:
name: consumer-service
eureka:
client:
service-url: # EurekaServer地址,注册中心地址
#defaultZone: http://127.0.0.1:8769/eureka,http://127.0.0.1:8770/eureka #map<key,value>
defaultZone: http://127.0.0.1:8769/eureka
#消费者拉取服务清单设置
fetch-registry: true #消费者启动,从Eureka Server服务的列表只读备份,然后缓存在本地
registry-fetch-interval-seconds: 5 #默认每隔30秒会重新获取并更新数据 interval 时间间隔
instance:
prefer-ip-address: true # 当其它服务获取地址时提供ip而不是hostname
ip-address: 127.0.0.1 # 指定自己的ip信息,不指定的话会自己寻找
instance-id: ${spring.application.name}:${server.port}
#负载均衡策略配置,
user-service:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
重试机制
不配置重试机制的话,如果一个服务的某个端口宕机了,报错:
解决方案:
添加依赖:
消费者pom
<!--ribbon请求异常处理的重试机制依赖-->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
在消费者的yml中配置服务的均衡策略以及重试机制的配置信息
两部分:
1、开启Spring Cloud的重试功能
2、重试机制的配置信息
server:
port: 8092
spring:
application:
name: consumer-service
cloud:
loadbalancer:
retry:
enabled: true # 开启Spring Cloud的重试功能
eureka:
client:
service-url: # EurekaServer地址,注册中心地址
#defaultZone: http://127.0.0.1:8769/eureka,http://127.0.0.1:8770/eureka #map<key,value>
defaultZone: http://127.0.0.1:8769/eureka
#消费者拉取服务清单设置
fetch-registry: true #消费者启动,从Eureka Server服务的列表只读备份,然后缓存在本地
registry-fetch-interval-seconds: 5 #默认每隔30秒会重新获取并更新数据 interval 时间间隔
instance:
prefer-ip-address: true # 当其它服务获取地址时提供ip而不是hostname
ip-address: 127.0.0.1 # 指定自己的ip信息,不指定的话会自己寻找
instance-id: ${spring.application.name}:${server.port}
#负载均衡策略配置,
user-service:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
ConnectTimeout: 250 # Ribbon的连接超时时间
ReadTimeout: 1000 # Ribbon的数据读取超时时间
OkToRetryOnAllOperations: true # 是否对所有操作都进行重试
MaxAutoRetriesNextServer: 1 # 切换实例的重试次数
MaxAutoRetries: 1 # 对当前实例的重试次数
尝试关闭一个服务