微服务之服务调用与负载均衡

概述

在微服务架构中,一个功能需要多个服务配合才能完成。服务之间的相互调用时一个关键问题,常见的服务调用有两种方式,一是 RPC 方式,二是事件驱动方式,也称发消息方式,第一种是紧耦合方式,第二种是松耦合方式。在调用服务时,我们可以使用一些工具来做负载均衡处理,使服务效率更高。

服务调用

RPC

RPC,即 Remote Procedure Call,意为远程过程调用,就是一个节点调用另一个节点提供的服务,rpc 调用时就像调用本地服务方法一样。dubbo 就是典型的使用 rpc 方式调用服务,其他常见的 rpc 调用方式还有 RESTful、gRPC 等。

事件驱动

事件驱动,Event-Driven,事件驱动可分为两种方式,一是事件通知,事件的生产者和消费者与消息队列耦合,而不是直接耦合,达到了解耦的效果。二是事件溯源,将所有事件持久化存储,每个事件代表一次状态变化,应用通过重放事件类重新创建聚合的当前状态。

示例

在服务中可以使用 RestTemplate 来请求其他服务提供的服务,这种方式是通过 http 进行远程调用。

  • 注册一个 RestTemplate,RestTemplateConfig.java:

    1
    2
    3
    4
    5
    6
    7
    8
    @Configuration
    public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate(){
    return new RestTemplate();
    }
    }
  • 在方法中使用 RestTemplate 调用其他服务的方法,UserController.java:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @RestController
    public class UserController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/findOrderByUser/{id}")
    public String findOrderByUserId(@PathVariable String id){
    int oid = 123;
    return this.restTemplate.getForObject("http://localhost:8788/order/"+oid,String.class);
    }
    }

负载均衡

负载均衡(Load Balance) 是将服务请求分摊到多个节点上执行,以此增加吞吐量、加强网络数据处理能力,能够更方便实现微服务系统的高可用、集群扩容。负载均衡的实现分为硬件和软件两种实现方式,硬件负载均衡器有 F5、Array、深信服等,软件有 Nginx、LVS、HAProxy等。

在微服务中也需要使用到负载均衡来协调服务的调用,spring cloud 中使用 ribbon 来实现负载均衡。

ribbon,读音 [ˈrɪbən] ,意为带子、丝带。

Ribbon 项目是 Netflix 公司发布的开源项目,功能是提供客户端软件负载均衡算法。Ribbon 提供了一系列完善的配置项,如连接超时、重试等。

示例

在 Eureka 的自动配置依赖模块 spring-cloud-starter-eureka 中,已经集成了 Ribbon ,可以直接使用 Ribbon 实现客户端负载均衡,在服务调用时 Ribbon 会利用从 Eureka 读取到的服务信息列表,在调用服务的实例中进行合理负载。

在使用时只需要在 RestTemplate 实例方法上添加 @LoadBalanced 注解,并在请求服务的方法中用服务实例的名称即可。

  • 修改 RestTemplate ,添加 @LoadBalanced 注解。RestTemplateConfig.java :

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @Configuration
    public class RestTemplateConfig {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
    return new RestTemplate();
    }
    }
  • 修改请求其他服务的方法,不在使用具体的服务地址和端口,改为使用服务名。UserController.java:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @RestController
    public class UserController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/findOrderByUser/{id}")
    public String findOrderByUserId(@PathVariable String id){
    int oid = 123;
    return this.restTemplate.getForObject("http://microserver-eureka-order/order/"+oid,String.class); // microserver-eureka-order 是其他微服务的服务名
    }
    }

参考资料

总结

使用 spring cloud eureka 中的 Ribbon 完成服务调用的负载均衡非常方便,只需要提供要调用的服务名与服务接口即可。