Feign简介:
- Feign是声明式的web service客户端,它让微服务之间的调用变得更简单了,类似controller调用service。Spring Cloud集成了Ribbon和Eureka,可在使用Feign时提供负载均衡的http客户端。Feign是基于Ribbon实现的工具。
- Spring Cloud对Feign进行了增强,使Feign支持了Spring MVC注解,并整合了Ribbon和Eureka。
- 在Spring Cloud中,Feign的使用:创建一个接口并用注解方式配置它,即可完成服务提供方的接口绑定,简化了在使用Spring Cloud Ribbon时自行封装服务调用客户端的开发量。且它支持Feign注解、JAX-RS注解和Spring MVC的注解。
Ribbon和Feign的区别:
Ribbon和Feign都是用于调用其他服务的,不过方式不同。
- 启动类使用的注解不同,Ribbon用的是@RibbonClient,Feign用的是@EnableFeignClients。
- 服务的指定位置不同,Ribbon是在@RibbonClient注解上声明,Feign则是在定义抽象方法的接口中使用@FeignClient声明。
- 调用方式不同,Ribbon需要自己构建http请求,模拟http请求然后使用RestTemplate发送给其他服务,步骤相当繁琐。Feign则是在Ribbon的基础上进行了一次改进,采用接口的方式,将需要调用的其他服务的方法定义成抽象方法即可,不需要自己构建http请求。不过要注意的是抽象方法的注解、方法签名要和提供服务的方法完全一致。
Feign较Ribbon的优点:
- Feign本身里面就包含有了Ribbon
- Feign自身是一个声明式的伪http客户端,写起来更加思路清晰和方便
- Fegin是一个采用基于接口的注解的编程方式,更加简便
使用Feign实现负载均衡:(注:代码接 Rest构建分布式微服务 一期的博客
- 创建Fegin模块
- 配置pom.xml
- 创建application.yml配置文件
- 创建自定义Rest相关配置类ConfigBean
- 创建ProductClientService接口
- 创建ProductController_Feign
- 创建ProductConsumer_80_Fegin主启动类
- 测试
基本步骤:
0. 增加一个数据库和一个服务提供者,将这个新的服务提供者连接到这个新增的数据库,测试时方便区分(实际开发中访问的是同一个数据库。
1. 创建名为microService-consumer-feign的Maven工程(jar包)
2. 配置pom.xml
<dependencies>
<!--依赖关系-->
<dependency>
<groupId>cn.zf</groupId>
<artifactId>microService-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--eureka依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--feign依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
3. 在src/main/resources下创建application.yml配置文件
server:
port: 80
eureka:
client:
register-with-eureka: false
fetch-registry: true #发现服务中 获得注册信息
serviceUrl:
defaultZone: http://eureka6001.com:6001/eureka,http://eureka6002.com:6002/eureka
4. 在src/main/java下创建自定义Rest相关配置类ConfigBean
package cn.zf.springcloud.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* Rest相关配置类访问RestFull的方法(url,requestMap,ResponseBean.class)
*/
@Configuration
public class ConfigBean {
// 向容器中添加RestTemplate组件 直接通过该组件可以调用REST接口
@LoadBalanced
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
5. 在src/main/java下创建ProductClientService接口
package cn.zf.springcloud.service;
import cn.zf.springcloud.entities.Product;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.util.List;
@FeignClient(value = "MICROSERVICE-PRODUCT")
public interface ProductClientService {
@RequestMapping(value = "/product/get/{id}",method = RequestMethod.GET)
Product get(Long id);
@RequestMapping(value = "/product/list",method = RequestMethod.GET)
List<Product> list();
@RequestMapping(value = "/product/add",method = RequestMethod.POST)
boolean add(Product product);
}
6. 在src/main/java下创建ProductController_Fegin
package cn.zf.springcloud.controller;
import cn.zf.springcloud.entities.Product;
import cn.zf.springcloud.service.ProductClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class ProductorController_Feign {
@Autowired
private ProductClientService service;
@RequestMapping(value = "/consumer/product/add")
public boolean add(Product product){
return service.add(product);
}
@RequestMapping(value = "/consumer/product/get/{id}")
public Product get(@PathVariable("id") Long id){
return service.get(id);
}
@RequestMapping(value = "/consumer/product/list")
public List<Product> list(){
return service.list();
}
}
7. 创建ProductConsumer_80_Feign主启动类
package cn.zf.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableFeignClients(basePackages = {"cn.zf.springcloud"})
@EnableEurekaClient // 向注册中心进行注册
@SpringBootApplication
public class ProductConsumer_80_Feign {
public static void main(String[] args) {
SpringApplication.run(ProductConsumer_80_Feign.class,args);
}
}
8. 测试,先启动两个eureka注册中心的主启动类(两个注册中心顺序无所谓),再启动两个服务提供者的主启动类(两个服务提供者顺序无所谓),最后启动ProductConsumer_80_Feign服务消费者的主启动类
over~