实例:订单服务调用商品服务

在订单服务调用商品服务的时候,首先要考虑负载均衡策略,为了体现出轮巡的结果,我们在商品服务输出的地方加上端口号,以区分是哪个节点。

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