本篇文章将介绍SpringCloud Ribbon在客户端负载均衡的调用服务。
Ribbon:客户端的负载均衡。
什么是客户端的负载均衡呢?
就是客户端是知道哪些服务是高可用的,哪些服务还没有挂掉。
pom文件如下:
4.0.0
com.cloud
demo
0.0.1-SNAPSHOT
jar
demo
Demo project for Spring Boot
org.springframework.boot
spring-boot-starter-parent
1.5.8.RELEASE
UTF-8
UTF-8
1.8
org.springframework.cloud
spring-cloud-starter-ribbon
1.4.0.RELEASE
org.springframework.cloud
spring-cloud-starter-eureka
1.3.5.RELEASE
org.springframework.cloud
spring-cloud-starter-hystrix
1.4.0.RELEASE
org.springframework.cloud
spring-cloud-starter-hystrix-dashboard
1.4.0.RELEASE
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-actuator
org.springframework.boot
spring-boot-maven-plugin
server.port=9000
spring.application.name=ribbon-consumer
eureka.client.service-url.defaultZone=http://localhost:8888/eureka/
package com.cloud.demo.consumer;
import com.netflix.hystrix.HystrixRequestCache;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import rx.Observable;
import rx.Observer;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@RestController
public class ConsumerController {
@Autowired
private LoadBalancerClient loadBalancerClient;
@RequestMapping("/consumer")
public String helloConsumer() throws ExecutionException, InterruptedException {
ServiceInstance instance = loadBalancerClient.choose("stores");
URI uri = URI.create(String.format("http://%s:%s",instance.getHost(),instance.getPort()));
return uri.toString();
}
}
访问http://127.0.0.1:9000/consumer:
会轮询访问
默认的负载均衡算法是轮询算法。
如果要改为别的算法:在配置文件中加如下代码:
stores.ribbon.NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
在Application中:添加:
@Bean
public IRule ribbonRule(){
return new RandomRule();
}
再进行访问就会发现是随机的了。
但是现在又出现了一个新问题,上面的配置中,地址都是写死在配置文件中的,万一有一个服务挂掉了,就无法将它剔除了。
解决办法:和Eureka结合起来使用。
1.将自己想注册中心注册:
eureka.client.service-url.defaultZone=http://localhost:8888/eureka/
2.在启动类中加入做如下修改:
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
}
3.Controller中:
package com.cloud.demo.consumer;
import com.netflix.hystrix.HystrixRequestCache;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import rx.Observable;
import rx.Observer;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@RestController
public class ConsumerController {
@Autowired
private LoadBalancerClient loadBalancerClient;
@Autowired
private HelloService helloService;
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/consumer")
public String helloConsumer() throws ExecutionException, InterruptedException {
//根据服务调用
return restTemplate.getForEntity("http://HELLO-SERVICE/hello",String.class).getBody();
}
}
现在看一下Eureka仪表盘,发现Ribbon也注册进去了:
进行访问就发现实现负载均衡了。