主程序启动类加入@RibbonClient
@SpringBootApplication
@EnableEurekaClient
//在启动该微服务的时候就能去加载自定义Ribbon配置类,从而使配置生效
@RibbonClient(name="MICROSERVICECLOUD-USER")
public class DemoApplication{
public static void main(String[] args){
SpringApplication.run(DemoApplication.class, args);
}
}
如何使用Ribbon
使用RestTemplate进行Eureka Client(包括服务提供者以及服务消费者,在这里其实是服务消费者使用RestTemplate)之间的通信,为RestTemplate配置类添加@LoadBalanced注解即可,如下所示:
@Primary
@Bean(value = "restTemplate")
RestTemplate restTemplate() {
return new RestTemplate();
}
@Primary
@LoadBalanced
@Bean(value = "loadBalanced")
public RestTemplate loadBalanced(@Qualifier(value = "clientHttpRequestFactory") ClientHttpRequestFactory clientHttpRequestFactory) {
return new RestTemplate(clientHttpRequestFactory);
}
@Primary
@Bean
public ClientHttpRequestFactory clientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(15000);
factory.setReadTimeout(5000);
return factory;
}
如何解决硬编码
不使用@LoadBalanced注解的RestTemplate调用服务提供者的接口时,使用真实IP地址。
restTemplate.postForObject(“http://localhost:8081/user/save”, user, Boolean.class);
使用添加@LoadBalanced注解后的RestTemplate调用服务提供者的接口时,可以使用虚拟IP替代真实IP地址。
所谓的虚拟IP就是服务提供者在application.properties或yml文件中配置的spring.application.name属性的值。
loadBalanced.postForObject(“http://MICROSERVICECLOUD-USER/user/save”, user, Boolean.class);
Ribbon和Eureka整合后Consumer可以直接调用服务而不用再关心ip地址和端口号
Ribbon负载均衡组件
默认的是RoundRibonRule(轮询算法)
RandomRule(随机算法)
AvailabilityFilteringRule():会先过滤由于多次访问故障而处于断路器跳闸状态的服务,还有并发的连接数量超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问
WeightedResponseTimeRule():根据平均响应的时间计算所有服务的权重,响应时间越快服务权重越大被选中的概率越高,刚启动时如果统计信息不足,则使用RoundRobinRule策略,等统计信息足够会切换到WeightedResponseTimeRule
RetryRule():先按照RoundRobinRule的策略获取服务,如果获取失败则在制定时间内进行重试,获取可用的服务。
BestAviableRule():会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务
ZoneAvoidanceRule():默认规则,符合判断server所在区域的性能和server的可用性选择服务器
自定义负载均衡算法
官方文档指出:自定义的类不能放在@ComponentScan所扫描的当前包以及子包下,否则自定义的这个配置类就会被所有的Ribbon客户端所共享,也就是达不到特殊化指定的目的了。
自定义算法MyRandomRule必须继承AbstractLoadBalanceRule类
public class MyRandomRule extends AbstractLoadBalancerRule{
// total = 0 // 当total==5以后,指针才能往下走,
// index = 0 // 当前对外提供服务的服务器地址,
// total需要重新置为零,但是已经达到过一个5次,我们的index = 1
private int total = 0; // 总共被调用的次数,目前要求每台被调用5次
private int currentIndex = 0; // 当前提供服务的机器号
public Server choose(ILoadBalancer lb, Object key){
if (lb == null) {
return null;
}
Server server = null;
while (server == null) {
if (Thread.interrupted()) {
return null;
}
List<Server> upList = lb.getReachableServers(); //激活可用的服务
List<Server> allList = lb.getAllServers(); //所有的服务
int serverCount = allList.size();
if (serverCount == 0) {
return null;
}
if(total < 5){
server = upList.get(currentIndex);
total++;
}else {
total = 0;
currentIndex++;
if(currentIndex >= upList.size()){
currentIndex = 0;
}
}
if (server == null) {
Thread.yield();
continue;
}
if (server.isAlive()) {
return (server);
}
// Shouldn't actually happen.. but must be transient or a bug.
server = null;
Thread.yield();
}
return server;
}
@Override
public Server choose(Object key){
return choose(getLoadBalancer(), key);
}
@Override
public void initWithNiwsConfig(IClientConfig clientConfig){
}
}
如果想使用某个自定义算法则注入到bean中即可。
@Configuration
public class MyRobinRuleConfig {
@Bean
public IRule myRule() {
//return new RoundRobinRule();//轮询算法
//return new RandomRule();//随机算法
return new MyRandomRule();
}
}
在主启动类中@RibbonClient注解中绑定自定义算法
@RibbonClient(name="MICROSERVICECLOUD-USER", configuration = MyRobinRuleConfig.class)
public class DemoApplication{
public static void main(String[] args){
SpringApplication.run(DemoApplication.class, args);
}
}