在前面的文章中可以发现当我们通过RestTemplate调用其它服务的API时,所需要的参数须在请求的URL中进行拼接,如果参数少的话或许我们还可以忍受,一旦有多个参数的话,这时拼接请求字符串就会效率低下,并且维护起来也很难受。
那么有没有更好的解决方案呢?答案是确定的有,SpringCloud已经为我们提供了一个框架:Feign。
Feign是一个声明式的Web Service客户端,它的目的就是让Web Service调用更加简单。Feign提供了HTTP请求的模板,通过编写简单的接口和插入注解,就可以定义好HTTP请求的参数、格式、地址等信息。
而Feign则会完全代理HTTP请求,我们只需要像调用方法一样调用它就可以完成服务请求及相关处理。Feign整合了Ribbon和Hystrix(关于Hystrix我们后面再讲),可以让我们不再需要显式地使用这两个组件。
总起来说,Feign具有如下特性:
- 可插拔的注解支持,包括Feign注解和JAX-RS注解;
- 支持可插拔的HTTP编码器和解码器;
- 支持Hystrix和它的Fallback;
- 支持Ribbon的负载均衡;
- 支持HTTP请求和响应的压缩。
这有点像我们springmvc模式的Controller层的RequestMapping映射,这种模式是我们最常用也是用起来最舒服的,Feign是用@FeignClient来映射服务的。
首先,在前面的项目的基础上新建一个Feign模块serice-feign,接着引入相关依赖,引入Feign依赖,如下:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
application.yml配置如下:
eureka:
client:
serviceUrl:
defaultZone: http://localhost1:1000/eureka/,http://localhost2:1100/eureka/
server:
port: 5000
spring:
application:
name: service-feign
SericeFeignApplication启动类上面加入注解:
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class SericeFeignApplication {
public static void main(String[] args) {
SpringApplication.run(SericeFeignApplication.class, args);
}
}
消费者和服务注册中心,我们用之前的项目,接下来我们在刚刚创建的Feign模块新建一个service接口,如下:
@FeignClient(value = "service-hi") //服务名称
public interface SchedualServiceHi {
@RequestMapping(value = "/hi", method = RequestMethod.GET)
String sayHiFromClientOne(@RequestParam(value = "name") String name);
}
然后我们创建controller一个类,如下:
@RestController
public class HiController {
@Autowired
SchedualServiceHi schedualServiceHi;
@RequestMapping(value = "/hi", method = RequestMethod.GET)
public String sayHi(@RequestParam String name) {
return schedualServiceHi.sayHiFromClientOne(name);
}
}
最后,为了方便我们观察负载均衡,我们启动两个服务注册中心和两个eurekaclient服务,启动成功如下:
然后我们再启动fegin模块,并且调用我们的接口http://localhost:5000/hi?name=feign,如下:
然后我们再次请求该地址,会发现现Feign已经对服务进行轮询消费,进而实现基于客户端的负载均衡,返回的端口信息改变,如下: