Feign是一个声明式的web service客户端,它使得编写web service客户端更为容易。创建接口,为接口添加注解,即可使用Feign。Feign可以使用Feign注解或者JAX-RS注解,还支持热插拔的编码器和解码器。Spring Cloud为Feign添加了Spring MVC的注解支持,并整合了Ribbon和Eureka来为使用Feign时提供负载均衡。
启动注册中心和服务提供者
https://blog.csdn.net/miaodichiyou/article/details/104160284
1、启动SpringCloud高可用服务注册中心(Eureka)搭建的注册中心
2、启动三个springcloud-eureka-provider实例,端口分别为8001,8002和8003
创建服务消费者
添加依赖包文件POM.xml
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.springcloud</groupId>
<artifactId>springcloud-root</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>springcloud-feign</artifactId>
<name>springcloud-feign</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<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-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
配置application.yml文件
spring:
application:
name: springcloud-feign
freemarker:
prefer-file-system-access: false
security:
user:
name: admin
password: 123456
server:
port: 8101
eureka:
instance:
hostname: eureka-feign.com
instance-id: eureka-feign
client:
service-url:
defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@eureka-peer1.com:8897/eureka/,http://${spring.security.user.name}:${spring.security.user.password}@eureka-peer2.com:8898/eureka/,http://${spring.security.user.name}:${spring.security.user.password}@eureka-peer3.com:8899/eureka/
修改C:\Windows\System32\drivers\etc\hosts
127.0.0.1 eureka-feign.com
添加服务消费者启动类
-
FeignApplication.java
在程序的启动类加上注解@EnableFeignClients开启Feign Client功能
package org.springcloud.feign;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class FeignApplication {
public static void main(String[] args) {
SpringApplication.run(FeignApplication.class, args);
}
}
新建接口
-
FeignConsumer.java
新建一个FeignConsumer的接口:
- 通过@FeignClient(“服务名”),来指定调用哪个服务。value为远程调用其他服务的服务名,FeignConfig.class为配置类。
- 在FeignConsumer内部有一个sayHiFromEurekaProvider()的方法,该方法通过Feign来调用springcloud-eureka-provider服务的“/hi”的api接口。
package org.springcloud.feign;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Component
/*指定这个接口所要调用的提供者服务名称 */
@FeignClient(value = "springcloud-eureka-provider",configuration = FeignConfig.class)
public interface FeignConsumer {
@GetMapping(value = "/hi")
String sayHiFromEurekaProvider(@RequestParam(value = "name")String name);
}
添加配置
-
FeignConfig .java
在FeignConfig类上加上@Configuration注解,表明这是一个配置类,并注入一个BeanName为feignRetryer的Retryer的Bean。可使feign在远程调用失败后会进行重试。
package org.springcloud.feign;
import java.util.concurrent.TimeUnit;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import feign.Retryer;
@Configuration
public class FeignConfig {
@Bean
public Retryer feignRetryer(){
return new Retryer.Default(100,TimeUnit.SECONDS.toMillis(1),5);
}
}
添加service消费服务提供者实例提供的服务
-
FeignService .java
Service层FeignService类注入FeignConsumer的Bean
package org.springcloud.feign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class FeignService {
@Autowired
FeignConsumer feignConsumer;
public String hi(String name){
return feignConsumer.sayHiFromEurekaProvider(name);
}
}
创建controller,调用service中的方法
-
FeignController.java
FeignController类调用FeignService的hi()方法,FeignService通过FeignConsumer远程调用springcloud-eureka-provider服务的API接口“/hi”。
package org.springcloud.feign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/*调用提供者的home方法*/
@RestController
public class FeignController {
@Autowired
FeignService feignService;
@GetMapping("/hi")
public String hi(@RequestParam(defaultValue = "zhaojq",required = false)String name){
return feignService.hi(name);
}
}
总结
Feign源码实现过程如下:
- 首先通过@EnableFeignClients注解开启FeignClient功能。只有这个注解的存在,程序启动时才会开启对@FeignConfig注解的包的扫描,
- 根据Feign的规则实现接口,并在接口上面加上@FeignClient注解。
- 程序启动后会进行包扫描,扫描所有@FeignClient注解的类,并将这些信息注入IOC容器中。
- 当接口的方法被调用时,通过JDK的代理来生成具体的RequestTemplate模板对象。
- 根据RequestTemplate再生成Http请求的Request对象。
- Request对象交给Client去处理,其中Client的网络请求框架可以是HttpURLConnection、HttpClient和OkHttp。
- 最后Client被封装到LoadBalanceClient类,这个类结合类Ribbon做到了负载均衡。
启动springcloud-feign工程
查看Eureka注册中心
运行启动类,访问http://eureka-peer1.com:8897/
http://eureka-peer2.com:8898/,http://eureka-peer3.com:8899/ 结果同上。
服务消费者实例已成功注册。
浏览器多次访问http://eureka-feign.com:8101/hi
在命令窗口curl http://eureka-feign.com:8101/hi,发现Feign已经实现负载均衡