微服务远程调用
在微服务架构中,不同微服务都应该有自己独立的数据库以减少服务之间的冗余。而不同的服务之间可能需要共享数据。但拆分后的服务,它们的数据库是相互独立的,一个服务不可能去调用另一个服务的数据库,所以服务之间的信息共享成为一个问题。
为了解决服务之间的信息共享,微服务通过将业务暴露为接口,以供其它微服务使用。这种服务调用方式与用户调用服务的方式是相同的,都是通过URL来远程调用接口。
在微服务远程调用中,有一下两种角色:
-
服务提供者(Provider):一次业务中,被其它微服务调用的服务。
即提供接口给其它微服务的服务。
-
服务消费者(Consumer):一次业务中,调用其它微服务的服务。
即调用其它微服务提供的接口的服务。
服务的角色是相对而言的。抛开业务来讲,服务既可以是提供者也可以消费者。
RestTemplate 远程调用
在SpringCloud中,微服务的远程调用方式可以通过RestTemplate发起HTTP请求来调用。而HTTP请求做远程调用是与语言无关的调用,只要知道对方的ip、端口、接口路径、请求参数即可。
例如有两个服务,分别是用户服务和订单服务,订单服务在获取订单信息时需要将用户信息一同发送:
-
使用
RestTemplate需要先进行注册(配置)。在订单服务模块(消费者)中新建一个配置并声明一个Bean:
1/** 2 * 创建RestTemplate,并注入Spring容器 3 */ 4@Bean 5public RestTemplate getRestTemplate() { 6 return new RestTemplate(); 7} -
在
OrderService中注入RestTemplate,并通过RestTemplate远程调用用户服务模块:1@Service 2public class OrderService { 3 4 @Autowired 5 private OrderMapper orderMapper; 6 // 注入RestTemplate 7 @Autowired 8 private RestTemplate restTemplate; 9 10 public Order queryOrderById(Long orderId) { 11 // 1.查询订单 12 Order order = orderMapper.findById(orderId); 13 // 2.利用RestTemplate发起HTTP请求,查询用户信息 14 // 2.1.URL路径 15 String url = "http://localhost:8081/user/" + order.getUserId(); 16 // 2.2.发送HTTP(GET)请求,实现远程调用 17 User user = restTemplate.getForObject(url, User.class); 18 // 3.封装User到Order 19 order.setUser(user); 20 // 4.返回 21 return order; 22 } 23}RestTemplate.getForObject()是RestTemplate调用HTTP-GET请求的方法,该方法接收一个字符串类型的URL参数,并可以通过.class来指定响应的类型。用户服务模块中相应的接口如下(假设服务的端口为本地
8081端口):1@RestController 2@RequestMapping("/user") 3public class UserController { 4 5 @Autowired 6 private UserService userService; 7 8 /** 9 * 根据用户ID获取用户信息 10 * @param id 用户ID 11 * @return 用户信息 12 */ 13 @GetMapping("/{id}") 14 public User queryById(@PathVariable("id") Long id) { 15 return userService.queryById(id); 16 } 17}
使用RestTemplate存在以下问题:
- URL的硬编码问题。
- 服务消费者该如何获取服务提供者的地址信息。
- 如果有多个服务提供者,消费者该如何选择。
- 消费者如何得知服务提供者的健康状态。
RestTemplate是Spring Cloud自带的,所以不用引入依赖。
评论