目录
搭建server-provide并创建HelloController类
3、在FeignController类中调用FeignService中的方法
Feign简介
认识Feign
Feign是Netflix开发的声明式、模板化的HTTP客户端。当Feign与Eureka和Ribbon组合使用时,Feign就具有了负载均衡的功能。在Feign的实现下,我们只需要定义一个接口并使用注解方式配置,即可完成服务接口的绑定,从而简化了Ribbon自动封装服务调用客户端的开发工作量。如此看来,我们可以把Feign理解为一个Spring Cloud远程服务的框架或者工具,它能够帮助开发者用更少的代码,更好的兼容方式对远程服务进行调用
第一个Feign程序
为了帮助大家快速认识Feign,本节我们将通过一个案例讲解如何使用Feign实现声明式服务调用。第一个Feign程序的架构如下图所示。
搭建Eureka Server
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
spring:
application:
name: eureka-server
server:
port: 7000
eureka:
client:
fetch-registry: false
register-with-eureka: false
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
instance:
hostname: localhost
搭建server-provide并创建HelloController类
spring:
application:
name: eureka-provide
server:
port: 7006
eureka:
client:
service-url:
defaultZone: http://localhost:7000/eureka/
@SpringBootApplication
@EnableEurekaClient
public class EurekaProvideApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaProvideApplication.class, args);
}
}
HelloController
@RestController
public class HelloController {
@GetMapping("/hello")
public String sayHello(){
return "hello Feign!";
}
}
创建Feign客户端
使用Spring Initializr方式创建一个名称为eureka-feign-client的Spring Boot项目,添加Eureka Client、Feign、Web、Test依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
spring:
application:
name: eureka-feign-client
server:
port: 8764
eureka:
client:
service-url:
defaultZone: http://localhost:7000/eureka/
添加@EnableFeignClients注解:在启动类EurekaFeignClientApplication中添加@EnableEurekaClient注解开启Eureka Client功能,再添加@EnableFeignClients注解开启Feign Client功能。
@SpringBootApplication
@EnableFeignClients //开启Feign的功能
@EnableEurekaClient
public class EurekaFeignClientApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaFeignClientApplication.class, args);
}
}
创建FeignService类并添加@FeignClient注解:在eureka-feign-client中创建service包,并在该包下创建接口FeignService,通过添加@FeignClient注解指定要调用的服务。
@Service
@FeignClient(name = "eureka-provider") //指定调用的服务
public interface FeignService {
@GetMapping("/hello")
public String sayHello();
}
创建FeignController类,调用sayHello()方法:在eureka-feign-client中创建controller包,并在该包下创建FeignController类,该类定义的hello()方法用于调用FeignService的sayHello()方法。
@RestController
public class FeignController {
@Autowired
FeignService feignService;
@GetMapping("/hello")
public String hello(){
return feignService.sayHello();
}
}
测试运行
依次启动eureka-server、eureka-provider和eureka-feign-client。启动成功后,使用浏览器访问http://localhost:8764/hello,效果如下图所示。
参数绑定
第一个Feign程序实现的是一个不带参数的REST服务绑定。实际业务中,我们经常需要在调用服务时传递各种参数。下面我们在第一个Feign程序的基础上改进,使用eureka-feign-client远程调用eureka-provider的接口。不同的是,此时调用eureka-provider接口时,需要传递一个不同类型的参数。
改造服务提供者eureka-provider
1、创建User实体类
在eureka-provider中创建entity包,并在该包中创建User实体类
public class User {
private String name;
private Integer age;
public User() {
}
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
2、修改HelloController
在HelloController中新增3个不同类型参数的方法。
@RestController
public class HelloController {
@GetMapping("/hello1")
public String hello(@RequestParam String name){
return "hello,"+name;
}
@GetMapping("/hello2")
public User hello(@RequestParam String name,@RequestHeader Integer age){
return new User(name,age);
}
@GetMapping("/hello3")
public String hello(@RequestBody User user){
return "hello,"+user.getName()+","+user.getAge();
}
}
改造含有Feign的eureka-feign-client
1、创建User实体类
在eureka-feign-client中创建entity包,并在该包中创建和eureka-provider中相同的User实体类。
2、在FeignService类中增加绑定参数的方法
在FeignService类中增加三个绑定不同参数类型的方法。
@Service
@FeignClient(name = "eureka-provide")
public interface FeignService {
@GetMapping("/hello1")
public String hello(@RequestParam("name") String name);
@GetMapping("/hello2")
public User hello(@RequestParam("name") String name, @RequestHeader("age") int age);
@GetMapping("/hello3")
public String hello(@RequestBody User user);
}
3、在FeignController类中调用FeignService中的方法
在FeignController中新增HelloUser()方法处理“/helloUser”请求,该方法调用了FeignService中的方法。
@RestController
public class FeignController{
@Autowired
FeignService feignService;
@GetMapping("/helloUser")
public String helloUser(){
StringBuilder sb=new StringBuilder();
sb.append(feignService.hello("czbk")).append("<BR/>");
sb.append(feignService.hello(new User("czbk ",30)))
.append("<BR/>");
sb.append(feignService.hello("czbk ",30))
.append("<BR/>");
return sb.toString();
}
}
测试运行
依次启动eureka-server、eureka-provider、eureka-feign-client,启动成功后,使用浏览器访问http://localhost:8764/helloUser,效果如下图所示。
Feign配置
Ribbon的相关配置
Feign默认整合了Ribbon能够实现负载均衡,我们可以通过配置Ribbon,自定义各个服务的调用方式。接下来,我们从全局配置和指定服务配置两个方面介绍如何在Spring Cloud Feign中进行Ribbon的相关配置。
全局配置
Ribbon的全局配置其实非常简单,我们可以直接在application.yml配置文件中,使用ribbon.<key>=<value>的方式设定ribbon的各项默认参数,示例代码如下:
ribbon:
ConnectTimeout: 5000 #设置连接超时时间,默认为1s
ReadTimeout: 5000 #设置读取超时时间
OkToRetryOnAllOperations:true # 对所有操作请求都进行重试
MaxAutoRetries:1 # 对当前实例的重试次数
MaxAutoRetriesNextServer:2 # 切换实例的重试次数
指定服务配置
大多数的情况下,我们对于服务调用的超时时间可能会根据实际服务的特性做一些调整,所以仅仅依靠默认的全局配置是不行的。使用Spring Cloud Feign时,如果要对各个服务消费者进行不同配置,可以采用<client>.ribbon.key=value的格式进行设置,示例代码如下
eureka-provider:
ribbon:
ConnectTimeout: 5000 #设置连接超时时间,默认为1s
ReadTimeout: 5000 #设置读取超时时间
OkToRetryOnAllOperations:true # 对所有操作请求都进行重试
MaxAutoRetries:1 # 对当前实例的重试次数
MaxAutoRetriesNextServer:2 # 切换实例的重试次数
Feign的工作原理
Feign服务调用的工作原理可以分为以下几个步骤:
(1)首先通过@EnableFeignClients注解开启FeignClient功能。程序启动时,会 通过该注解开启对@FeignClient注解的包扫描。
(2)根据Feign规则实现接口,并在接口上面添加@FeignClient注解。
(3)程序启动后,会进行包扫描,扫描所有的@FeignClient注解类,并将这些信息注入IoC容器。
(4)当接口方法被调用时,通过JDK的代理生成具体的RequestTemplate模板对象。根据RequestTemplate再生成HTTP请求的Request对象,Request对象交给Client处理。