Spring Cloud(三)微服务通信Feign
我们在搭建微服务过程中无疑会涉及服务之间的数据请求,Spring Cloud给我们提供了Feign组建,帮助服务间快速的进行“方法调用”。
如果没有Feign我们应该怎么做?RPC服务或是Http服务(Restful),在这里我们只谈Http服务。通过Http我们进行服务间通信,最直接的方式,当然是直接给对应服务的ip:port/path发送http请求。然后对方服务通过controller进行接受。这种方式一目了然,然而在开发中可以预见有很大的不方便性。
- 其一:各个微服务的ip地址端口号需要维护,一旦任何一个服务的ip或port发生改变,我们都需要向其他服务手动同步,多说一句,这种情况在云端是经常发生的,云服务重启后,ip经常会动态分配,这个系统的地址配置会陷入混乱。
- 其二:在编程中需要额外代码引入和读取各个服务的地址配置。
第一个问题,我们之前说到的eureka已经很好的解决,每个服务对外暴露的只有自己的服务名,而服务名与地址的映射由eureka来维护,无需我们的参与。那么我们在调用服务的时候能不能更清楚的进行调用呢,服务间的调用能不能像调用本地方法一样方便呢?
Feign帮我们实现了服务间调用本地化(作者自取的名字),我们想一想,如果说服务名可以代表其具体地址,那么如果我可以在当前服务中建立自定义方法与被调用的url的mapping关系,岂不是可以把服务间的调用转化成本地方法调用?Feign就是在做这个事情!
Feign的引入
官网介绍Feign的引入只需要引入:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
不得不说我失败了……我按照以上方式引入后,feign的版本为3.8.0,在启动服务时一直说找不到某个class(好像是**Form找不到),我用了另一种方式,调低了版本:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form-spring</artifactId>
<version>3.7.0</version>
</dependency>
在启动类上添加注解:@EnableFeignClients
package com.otof.orgmicoservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class OrgmicoserviceApplication {
public static void main(String[] args) {
SpringApplication.run(OrgmicoserviceApplication.class, args);
}
}
场景介绍
这个时候就可以开始通过Feign进行服务间的调用了。先介绍一下背景:当前服务为orgmicroservice,我需要向usermicroservice传递一个name(String),然后由user服务包装成“hi name”返回给org服务,并最终返回给前端。
实施
在usermicroservice中创建接收name的api:
@RestController
@RequestMapping("test")
public class FeignTestController {
@GetMapping("hi")
public String getHi(@RequestParam String name) {
return "Hi" + name;
}
}
在orgmicroservice中建立user api与本地方法的mapping:新建一个interface并用@FeignClient注解修饰,注解的默认参数为user的application-name,如下可见,目标服务,api路径,http method,参数都一一指定。
@FeignClient("user-microservice")
public interface FeignTest {
@RequestMapping(value = "/test/hi", method = RequestMethod.GET)
String getHiFromUserMicroService(@RequestParam(value = "name") String name);
}
在orgmicroservice中创建一个controller,即接收带name的请求,同时向user服务发call获取返回的字符串:
@RestController
@RequestMapping("test")
public class FeignTestController {
@Autowired
private FeignTest feignTest;
@GetMapping("gethi")
public String getHi(@RequestParam String name) {
return feignTest.getHiFromUserMicroService(name);
}
}
现在我们启动两个服务,并通过浏览器对orgmicrosercive进行访问:
localhost:8091/test/gethi?name=tony
结果
本文并没有提到eureka的配置,当然eureka是必须要有的,具体的配置和使用方式,请参见前面的文章。