实例:订单服务调用商品服务
在订单服务调用商品服务的时候,首先要考虑负载均衡策略,为了体现出轮巡的结果,我们在商品服务输出的地方加上端口号,以区分是哪个节点。
1.ribbon (消费者)
a.创建spring boot项目:web / Cloud Routing:ribbon / Cloud Discovery:Eureka Discovery
application.yml:
server:
port: 8781
#指定注册中心地址
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
#服务的名称
spring:
application:
name: order-service
b.编写商品订单逻辑接口,保存订单时需根据商品Id,调用商品服务获取信息
c.使用ribbon(内部其实就是封装了一层层的类似httpClient,URLConnnection,伪http请求去调用提供者)
启动类增加注解
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
d.在service实现类中注入restTemplate (也有别的方法,可以看官方文档,比如注入LoadBalancerClient)
@Autowired
private RestTemplate restTemplate;
在方法中引用restTemplate获取要在注册中心调用的地址:
restTemplate.getForObject("http://product-service/api/v1/product/find?id="+productId,Object.class);
e. 启动项目,执行接口,可以看出采用负载均衡,在商品服务的8771和8772接口之间轮巡(软负载均衡,在调用方做的)
在商品服务方再启一个节点,注册中心可以看到了,但此时订单服务还调不到这个端口,因为Client端是定时去注册注册中心取的,要过一段时间就会更新。
f.ribbon源码分析
@LoadBalanced
在这个注解中配置了LoadBalancerClient,相当于负载均衡器,查看继承结构:
用LoadBalancerClient 可以写成:
public class MyClass {
@Autowired
private LoadBalancerClient loadBalancer;
public void doStuff() {
ServiceInstance instance = loadBalancer.choose("stores"); URI storesUri = URI.create(String.format("http://%s:%s", instance.getHost(), instance.getPort())); // ... do something with the URI } }
所以查看RibbonLoadBalancerClient中的choose方法
负载均衡采用轮巡策略
g.自定义负载均衡轮策略
http://cloud.spring.io/spring-cloud-static/Finchley.RELEASE/single/spring-cloud.html#_customizing_the_ribbon_client_by_setting_properties
application.yml:
#自定义负载均衡策略
product-service:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
选取随机策略,后面也可以选择各种IRule的实现类,不过一般都不用调整策略,直接采用轮巡的,这样可以把压力平均分配到每个节点上去
策略选择:
1、如果每个机器配置一样,则建议不修改策略 (推荐)
2、如果部分机器配置强,则可以改为 WeightedResponseTimeRule