Feign受Retrofix、JAXRS-2.0和WebSocket影响,采用了声明式API接口的风格,将Java Http客户端绑定到他的内部。Feign的首要目标是将Java Http客户端调用过程变得简单。

源码地址:https://github.com/OpenFeign/feign

本章案例基于上一章,可参考:

spring boot 2.0.3+spring cloud (Finchley)1、搭建Eureka 以及构建高可用Eureka Server集群

spring boot 2.0.3+spring cloud (Finchley)2、搭建负载均衡Ribbon (Eureka+Ribbon+RestTemplate)

新建module工程eureka-feign-client。pom文件引入相关依赖,包括主maven工程的pom文件,eureka client起步依赖,feign的起步依赖,web的起步依赖(已在主maven工程pom中配置)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">groupId</span><span style="color: #0000ff;">&gt;</span>com.cralor<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">groupId</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">artifactId</span><span style="color: #0000ff;">&gt;</span>eureka-feign-client<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">artifactId</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">version</span><span style="color: #0000ff;">&gt;</span>0.0.1-SNAPSHOT<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">version</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">packaging</span><span style="color: #0000ff;">&gt;</span>jar<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">packaging</span><span style="color: #0000ff;">&gt;</span> <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">name</span><span style="color: #0000ff;">&gt;</span>eureka-feign-client<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">name</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">description</span><span style="color: #0000ff;">&gt;</span>Demo project for Spring Boot<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">description</span><span style="color: #0000ff;">&gt;</span> <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">parent</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">groupId</span><span style="color: #0000ff;">&gt;</span>com.cralor<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">groupId</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">artifactId</span><span style="color: #0000ff;">&gt;</span>chap7-feign<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">artifactId</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">version</span><span style="color: #0000ff;">&gt;</span>0.0.1-SNAPSHOT<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">version</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">relativePath</span><span style="color: #0000ff;">/&gt;</span> <span style="color: #008000;">&lt;!--</span><span style="color: #008000;"> lookup parent from repository </span><span style="color: #008000;">--&gt;</span>
<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">parent</span><span style="color: #0000ff;">&gt;</span> <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">properties</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">project.build.sourceEncoding</span><span style="color: #0000ff;">&gt;</span>UTF-8<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">project.build.sourceEncoding</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">project.reporting.outputEncoding</span><span style="color: #0000ff;">&gt;</span>UTF-8<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">project.reporting.outputEncoding</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">java.version</span><span style="color: #0000ff;">&gt;</span>1.8<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">java.version</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">properties</span><span style="color: #0000ff;">&gt;</span> <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">dependencies</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">dependency</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">groupId</span><span style="color: #0000ff;">&gt;</span>org.springframework.cloud<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">groupId</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">artifactId</span><span style="color: #0000ff;">&gt;</span>spring-cloud-starter-netflix-eureka-client<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">artifactId</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">dependency</span><span style="color: #0000ff;">&gt;</span> <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">dependency</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">groupId</span><span style="color: #0000ff;">&gt;</span>org.springframework.cloud<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">groupId</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">artifactId</span><span style="color: #0000ff;">&gt;</span>spring-cloud-starter-openfeign<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">artifactId</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">dependency</span><span style="color: #0000ff;">&gt;</span> <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">dependency</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">groupId</span><span style="color: #0000ff;">&gt;</span>org.springframework.boot<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">groupId</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">artifactId</span><span style="color: #0000ff;">&gt;</span>spring-boot-starter-test<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">artifactId</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">scope</span><span style="color: #0000ff;">&gt;</span>test<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">scope</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">dependency</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">dependencies</span><span style="color: #0000ff;">&gt;</span> <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">build</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">plugins</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">plugin</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">groupId</span><span style="color: #0000ff;">&gt;</span>org.springframework.boot<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">groupId</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">artifactId</span><span style="color: #0000ff;">&gt;</span>spring-boot-maven-plugin<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">artifactId</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">plugin</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">plugins</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">build</span><span style="color: #0000ff;">&gt;</span>

</project>

配置文件做相关配置

server:
port: 8765
spring:
application:
name: eureka-feign-client
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/

在程序的启动类加上注解@EnableFeignClients开启Feign Client功能

@EnableFeignClients
@SpringBootApplication
public class EurekaFeignClientApplication {
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) {
SpringApplication.run(EurekaFeignClientApplication.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">, args);
}

}

通过以上步骤,该程序已经具备了Feign的功能,现在来实现一个简单的feign client。新建一个EurekaClientFeign的接口,在接口上加@FeignClient注解来声明一个Feign Client。value为远程调用其他服务的服务名,FeignConfig.class为配置类,在EurekaClientFeign内部有一个sayHiFromClientEureka()的方法,该方法通过Feign来调用eureka-client服务的“/hi”的aipi接口。

@Component
@FeignClient(value = "eureka-client",configuration = FeignConfig.class)
public interface EurekaClientFeign {
@GetMapping(value = "/hi")
String sayHiFromClientEureka(@RequestParam(value = "name")String name);
}

在FeignConfig类上加上@Configuration注解,表明这是一个配置类,并注入一个BeanName为feignRetryer的Retryer的Bean。可使feign在远程调用失败后会进行重试。

@Configuration
public class FeignConfig {
@Bean
public Retryer feignRetryer(){
return new Retryer.Default(100,TimeUnit.SECONDS.toMillis(1),5);
}
}

service层HiService类注入EurekaClient的Bean

@Service
public class HiService {
@Autowired
EurekaClientFeign eurekaClientFeign;
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">  String sayHi(String name){
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> eurekaClientFeign.sayHiFromClientEureka(name);
}

}

新建HiController类,调用HiService的sayHi()方法,HiService通过EurekaClientFeign远程调用eureka-client服务的API接口“/hi”。

@RestController
public class HiController {
@Autowired
HiService hiService;
@GetMapping(</span>"/hi"<span style="color: #000000;">)
</span><span style="color: #0000ff;">public</span> String sayHi(@RequestParam(defaultValue = "cralor",required = <span style="color: #0000ff;">false</span><span style="color: #000000;">)String name){
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> hiService.sayHi(name);
}

}

启动eureka-server工程,端口号8761,启动两个eureka-client工程的实例,端口号8762、8763,启动eureka-feign-client工程,端口号8765。在浏览器多次访问http://localhost:8765/hi,浏览器会轮流显示

            

可见Feign Client远程调用了eureka-client的服务(存在端口号为8762和8763的两个实例)的“/hi”API接口,feign client有负载均衡的能力。

总结:feign源码实现过程如下

1.首先通过@EnableFeignClients注解开启FeignClient功能。只有这个注解的存在,程序启动时才会开启对@FeignConfig注解的包的扫描,

2.根据Feig的规则实现接口,并在接口上面加上@FeignClient注解。

3.程序启动后会进行包扫描,扫描所有@FeignClient注解的类,并将这些信息注入IOC容器中。

4.当接口的方法被调用时,通过JDK的代理来生成具体的RequestTemplate模板对象。

5.根据RequestTemplate再生成Http请求的Request对象。

6.Request对象交给Client去处理,其中Client的网络请求框架可以是HttpURLConnection、HttpClient和OkHttp。

7.最后Client被封装到LoadBalanceClient类,这个类结合类Ribbon做到了负载均衡。

参考:https://windmt.com/2018/04/15/spring-cloud-3-service-producer-and-consumer/#Spring-Cloud-Feign

案例代码地址:https://github.com/cralor7/springcloud

原文地址:http://www.cnblogs.com/cralor/p/9228678.html

spring boot 2.0.3+spring cloud (Finchley)3、声明式调用Feign的更多相关文章

  1. spring boot 2.0.3+spring cloud (Finchley)2、搭建负载均衡Ribbon (Eureka+Ribbon+RestTemplate)

    Ribbon是Netflix公司开源的一个负载均衡组件,将负载均衡逻辑封装在客户端中,运行在客户端的进程里. 本例子是在搭建好eureka的基础上进行的,可参考spring boot 2.0.3+sp ...

  2. spring boot 2.0.3+spring cloud (Finchley)5、路由网关Spring Cloud Zuul

    Zuul作为微服务系统的网关组件,用于构建边界服务,致力于动态路由.过滤.监控.弹性伸缩和安全. 为什么需要Zuul Zuul.Ribbon以及Eureka结合可以实现智能路由和负载均衡的功能:网关将 ...

  3. spring boot 2.0.3+spring cloud (Finchley)4、熔断器Hystrix

    在分布式系统中服务与服务之间的依赖错综复杂,一种不可避免的情况就是某些服务会出现故障,导致依赖于他们的其他服务出现远程调度的线程阻塞.某个服务的单个点的请求故障会导致用户的请求处于阻塞状态,最终的结果 ...

  4. spring boot 2.0.3+spring cloud (Finchley)7、服务链路追踪Spring Cloud Sleuth

    参考:Spring Cloud(十二):分布式链路跟踪 Sleuth 与 Zipkin[Finchley 版] Spring Cloud Sleuth 是Spring Cloud的一个组件,主要功能是 ...

  5. spring boot 2.0.3+spring cloud (Finchley)8、微服务监控Spring Boot Admin

    参考:Spring Boot Admin 2.0 上手 Spring Boot Admin 用于管理和监控一个或多个Spring Boot程序,在 Spring Boot Actuator 的基础上提 ...

  6. spring boot 2.0.3+spring cloud (Finchley)1、搭建服务注册和发现组件Eureka 以及构建高可用Eureka Server集群

    一 .搭建Eureka 编写Eureka Server 由于有多个spring boot项目,采用maven多module的结构,项目结构如下: 新建一个maven主工程,在主maven的pom文件中 ...

  7. spring boot 2.0.3+spring cloud (Finchley)6、配置中心Spring Cloud Config

    https://www.cnblogs.com/cralor/p/9239976.html Spring Cloud Config 是用来为分布式系统中的基础设施和微服务应用提供集中化的外部配置支持, ...

  8. spring boot 2.0.3+spring cloud (Finchley)9、 安全组件Spring Boot Security

    官方文档 一.Spring Security介绍 Spring Security是Spring Resource社区的一个安全组件,Spring Security为JavaEE企业级开发提供了全面的安 ...

  9. Spring Boot 2.0 利用 Spring Security 实现简单的OAuth2.0认证方式1

    0. 前言 之前帐号认证用过自己写的进行匹配,现在要学会使用标准了.准备了解和使用这个OAuth2.0协议. 1. 配置 1.1 配置pom.xml 有些可能会用不到,我把我项目中用到的所有包都贴出来 ...

随机推荐

  1. jemter的使用

    1.启动jmeter

  2. MT【292】任意存在求最值

    已知向量$\textbf{a},\textbf{b}$满足:$|\textbf{a}|=|\textbf{b}|=1,\textbf{a}\cdot\textbf{b}=\dfrac{1}{2},\t ...

  3. Python数据采集分析告诉你为何上海二手房你都买不起

    感谢关注Python爱好者社区公众号,在这里,我们会每天向您推送Python相关的文章实战干货. 来吧,一起Python. 对商业智能BI.大数据分析挖掘.机器学习,python,R等数据领域感兴趣的 ...

  4. python3 hashlib模块

    hashlib是一个加密模块,可以将明文加密为密文: md5,sha加密:过程不可逆转.

  5. Codeforces | CF1010C 【Border】

    这道题大致题意是给定\(n\)个十进制整数和一个进制数\(k\),可以用无数多个给定的十进制整数,问这些十进制整数的和在模k意义下有多少种不同的结果(\(k\)进制下整数的最后一位就是这个数模\(k\ ...

  6. 「JLOI2015」管道连接 解题报告

    「JLOI2015」管道连接 先按照斯坦纳树求一个 然后合并成斯坦纳森林 直接枚举树的集合再dp一下就好了 Code: #include <cstdio> #include <cct ...

  7. 【原】cpu消耗高,查看对应的线程栈信息

    在压测过程中,有时候cpu会飙升,造成这种现象的原因很多, 可能是gc造成的,也可能是某个方法造成的, 如果从找对应的方法入手,下面简单罗列下步骤: 1.top,获取pid 下面cpu消耗90%左右 ...

  8. HDU6341 Let Sudoku Rotate (杭电多校4J)

    给一个由4*4个4*4的小格组成数独,这些数独是由一个块逆时针旋转得来的,所以要还原的话就模拟出顺时针的过程,先把里面的字母转化成数字,然后从第一个块开始枚举,每个dfs和之前枚举的已经满足条件的块, ...

  9. 覆盖的面积 HDU - 1255 (扫描线, 面积交)

    求n个矩阵面积相交的部分,和求面积并一样,不过这里需要开两个数组保存覆盖一次和覆盖两次以上的次数的部分,还是模板,主要注意点就是pushup部分,如果我已经被两次覆盖,那我的两个数组在这个root点的 ...

  10. JIRA和Confluence更改JVM内存大小解决访问打开缓慢问题

    原因: 根据主机物理内存不同,默认的java虚拟机内存也会不同(一个较低值),有时候不够用,可以修改默认设置,改善内存不足导致的问题. 操作步骤: JIRA 1. 打开至相应目录: ~]# cd  / ...