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