实习闲暇时间杂记一手,简单记录下微服务之间的调用过程,两种调用方式:Feign 过程调用和RestTemleate + Ribbon调用方式 。
Feign介绍:
feign是一个声明性Web服务客户机。它使编写Web服务客户机更加容易。要使用佯装,请创建一个接口并对其进行注释。它具有可插入的注释支持,包括外部注释和JAX-RS注释。Feign还支持可插拔的编码器和解码器。SpringCloud增加了对SpringMVC注释的支持,以及对使用SpringWeb中默认使用的相同httpMessageConverter的支持。SpringCloud集成了Ribbon和Eureka,在使用Feign时提供负载平衡的HTTP客户端。
接上上一节的项目,项目地址:https://github.com/wdgup/cloud_demo,假设有一个场景,创建订单时会调用用户服务的查询方法,实现服务调用先导入依赖:
cloud-order 项目导入 feign 的依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
下面演示下两种调用方式:
一、Feign调用
order服务 调用user服务时,需声明一个调用的客户端接口:
UserClient.java:
package com.wdg.cloudorder.client;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* @author WDG
* @date 2019-4-26
*/
@FeignClient(name = "cloud-user")
public interface UserClient {
@RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
JSONObject findUser(@PathVariable(name = "id") Integer id);
}
接口上加上 @FeignClient 注解 ,name属性声明要调用注册中心的那个服务,当多个相同的服务注册在注册中心时,Ribbon实现了负载均衡,也可以通过 url 属性 明确指定调用哪个服务 ,加上此注解 此时并非起作用,启动类上要加上
@EnableFeignClients注解,开启扫描@FeignClient注解。
调用user服务的某个方法,要在客户端中配置相同的方法,当有参数传递时, 使用@PathVariable或 @RequestParam 注解时必须指定name 值,否则会报错。
OrderContoller.java:
package com.wdg.cloudorder.controller;
import com.alibaba.fastjson.JSONObject;
import com.wdg.cloudorder.client.UserClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;
/**
* @author WDG
* @date 2019-4-26
*/
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private UserClient userClient;
@GetMapping(value = "/createOrder/{userId}")
public ResponseEntity createOrder(@PathVariable(name = "userId") Integer userId){
JSONObject user = userClient.findUser(userId);
System.out.println(user);
return ResponseEntity.ok(user);
}
}
先启动Eureka服务,再启动user和order服务,访问创建订单服务:http://localhost:9003/order/createOrder/1
可以看到调用user服务成功了。
二、RestTemplate + Ribbon
配置类中创建一个RestTemplate 实例:
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
OrderController.java 中增加 代码:
@Autowired
private RestTemplate restTemplate;
@GetMapping(value = "/createOrder")
public ResponseEntity createOrderByRestTemplate(@RequestParam(name = "userId") Integer userId){
ResponseEntity<JSONObject> result = restTemplate.getForEntity("http://localhost:9001/user/" + userId, JSONObject.class);
System.out.println(result.getBody());
return ResponseEntity.ok(result.getBody());
}
指定要调用的 url 和 返回类型,postman 测试
可以看到用RestTemplate 调用成功了。
下面演示一哈 Ribbon的负载均衡策略,修改user 服务的端口号,启动三个user服务:
IRule接口代表负载均衡策略:
可以看到有几种负载均衡策略:其中RandomRule表示随机策略、RoundRobinRule表示轮询策略、WeightedResponseTimeRule表示加权策略、BestAvailableRule表示请求数最少策略等等。Ribbon默认的是轮询策略
调试调用多次http://localhost:9003/order/createOrder/1接口,控制台观察几个用户服务的日志信息,:
可以看到调用每个服务都被调用过了。