Feign是一个声明性web服务客户端,它使得编写web服务客户端变得更加容易,Spring Cloud Feign是基于Netflix Feign实现,整合了Spring Cloud Ribbon与Spring Cloud Hystrix,除了提供两者强大功能外,它还提供了声明式的Web服务客户端定义方式
1.Feign和OpenFeign的区别是什么
Feign是Spring Cloud组件中一个轻量级RESTful的HTTP服务客户端,Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。Feign的使用方式是:使用Feign的注解定义接口,调用接口,就可以调用服务注册中心的服务
引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
OpenFeign是Spring Cloud在Feign的基础上支持了SpringMVC的注解,如@RequestMapping等等。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类
引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
参考代码: GitHub - PNZBEIJINGL/spring-cloud-lab
服务 | IP | 端口 | |
eureka-peer | 127.0.0.1 | 1000 | Eureka服务注册中心 |
feign-consumer | 127.0.0.1 | 8003 | 消费服务(测试Feign调用使用) |
ms-customer | 127.0.0.1 | 8001 | 客户服务 |
ms-customer_interface | 客户接口工程 | ||
2.使用feign实现负载均衡
2.1修改ms-customer_interface应用
ms-customer_interface 中创建接口
@RequestMapping("/customer")
public interface ICustomerService {
//测试
@RequestMapping("/ping")
public String ping();
//根据ID获取客户信息
@RequestMapping(value = "/get/{id}", method = RequestMethod.GET)
public CustomerDTO getCustomerById(@PathVariable("id") Long id) throws InterruptedException;
//保存客户信息
@RequestMapping(value = "/save", method = RequestMethod.POST)
public CustomerDTO addCustomer(@RequestBody CustomerDTO customerDTO) throws InterruptedException;
}
2.2 修改ms-customer应用
.ms-customer 应用中实现接口
@RestController
public class TestController implements ICustomerService {
@Override
public String ping() {
//通过返回当前时间表明服务正常
return new Date().toString();
}
@Override
public CustomerDTO getCustomerById(@PathVariable("id") Long id) throws InterruptedException {
//测试阻塞几秒
int sleepTime = new Random().nextInt(3000);
Thread.sleep(sleepTime);
CustomerDTO customer = mockCustomer();//模拟得到一个客户
customer.setId(id);
return customer;
}
@Override
public CustomerDTO addCustomer(@RequestBody CustomerDTO customerDTO) throws InterruptedException {
//测试阻塞几秒
int sleepTime = new Random().nextInt(3000);
Thread.sleep(sleepTime);
CustomerDTO customer = customerDTO;
return customer;
}
private CustomerDTO mockCustomer() {
CustomerDTO customer = new CustomerDTO();
customer.setId(1000L);
customer.setCode("1000");
customer.setName("zhangsan");
return customer;
}
}
2.3修改feign-consumer应用
feign-consumer应用的pom.xml配置增加依赖,并设置application.properties配置
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 注册服务提供 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!-- 引用Feign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.3.6.RELEASE</version>
</dependency>
<!-- 引用监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 引用customer-intderface中年的接口-->
<dependency>
<groupId>spring.cloud.test</groupId>
<artifactId>ms-customer-interface</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
server.port=8003
#服务的名称
spring.application.name=FEIGN-CONSUMER
############ Eureka ################
#服务注册中心IP
eureka.instance.hostname=127.0.0.1
#指定服务注册中心
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:1000/eureka/
############ Eureka ################
############ Feign ################
#Spring Cloud feign 中默认实现了请求重试机制
#重试策略先尝试首选实例N次
MS-CUSTOMER.ribbon.MaxAutoRetriesNextServer=1
#尝试更换N次实例进行重试
MS-CUSTOMER.ribbon.MaxAutoRetriesr=2
############ ribbon ################
feign-consumer应用主类增加@EnableFeignClients
@EnableFeignClients //开启Spring Cloud Feign支持
@EnableDiscoveryClient
@SpringBootApplication
public class FeignConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(FeignConsumerApplication.class, args);
}
}
feign-consumer 创建RefactorCustomerService 接口继承接口ICusotmerService,通过@FeignClient注解指定服务名来绑定服务,这里服务名不区分大小写
@FeignClient("MS-CUSTOMER")
public interface RefactorCustomerService extends ICustomerService {
}
feign-consumer 创建RefactorCustomerController用于测试Feign客户端调用,Controller都通过RefactorCustomerService 接口调用实现
@RestController
public class RefactorCustomerController {
@Autowired
private RefactorCustomerService refactorHelloService;
//http://127.0.0.1:8003/pingcustomer
@RequestMapping(value = "/pingcustomer", method = RequestMethod.GET)
public String pingCustomer() {
return refactorHelloService.ping();
}
//http://127.0.0.1:8003/getcustomer
@RequestMapping(value = "/getcustomer", method = RequestMethod.GET)
public CustomerDTO getCustomer() {
try {
return refactorHelloService.getCustomerById(800L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
@RequestMapping(value = "/savecustomer", method = RequestMethod.GET)
public CustomerDTO saveCustomer() {
try {
CustomerDTO customer = new CustomerDTO();
customer.setId(70L);
customer.setCode("70");
customer.setName("zhangsan");
return refactorHelloService.addCustomer(customer);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
2.4 测试feign-consumer中的Feign调用
- 启动eureka-peer 服务中心,
- 启动ms-customer服务后ms-customer服务注册到eureka中,
- 启动feign-consumer 服务
- 测试
测试访问:http://127.0.0.1:1000/ 检查好服务注册成功
测试: http://127.0.0.1:8003/pingcustomer
测试:http://127.0.0.1:8003/getcustomer
测试: http://127.0.0.1:8003/savecustomer
如果启动多个ms-customer服务时,多次访问会发现效果和Spring Cloud Ribbon相同,Feign实现的消费者维护了MS-CUSTOMER服务列表,通过轮询实现了客户端负载均衡,和Ribbon实现负载均衡相比,Feigin实现负载均衡通过定义服务绑定接口,以声明式的方法实现服务调用更简单