OpenFeign服务调用
Feign
Feign 是一个声明式 WebService 客户端。使用 Feign 能让编写Web Service 客户端更加简单。
Feign 旨在使编写Java Http 客户端变得更容易。 前面在使用 Ribbon+RestTemplate时,利用RestTemplate 对http请求的封装处理,形成了一套模板化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。所以,Feign 在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义。在Feign的实现下,我们只需创建一个接口并使用注解的方式来配置它(以前是Dao接口上面标注Mapper注解,现在是一个微服务接口上面标注衣一个Feign注解即可),即可完成对服务提供方的接口绑定,简化了使用Spring Cloud Ribbon时,自动封装服务调用客户端的开发量。
Feign集成了Ribbon
利用Ribbon维护了Payment 的服务列表信息,并且通过轮询实现了客户端的负载均衡。而与Ribbon不同的是,通过feign 只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用。
OpenFeign
OpenFeign是springcloud在Feign的基础上支持了SpringMVC的注解,如@RequestMapping等等。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。
开启Feign主启动类上加@EnableFeignClients
注解
几个简单的示例代码:
我先在消费端80启动类中添加注解
@SpringBootApplication
@EnableFeignClients
public class OrderFeignMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderFeignMain80.class,args);
}
}
@FeignClient(value = "cloud-payment-service")
public interface PaymentFeignService {
//直接用URI的方式去8001/8002集群去调用服务
@GetMapping("/payment/get/{id}")
CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);
@GetMapping("/payment/feign/timtout")
String paymentFeignTimeout();
}
@RestController
public class OrderFeignController {
@Resource
private PaymentFeignService paymentFeignService;
@GetMapping(value = "/consumer/payment/get/{id}")
public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){
return paymentFeignService.getPaymentById(id);
}
}
OpenFeign超时控制
默认Feign客户端只等待一秒钟, 但是服务端处理需要超过1秒钟,导致Feign客户端不想等待了,直接返回报错。为了避免这样的情况,有时候我们需要设置Feign客户端的超时控制。
怎么做呢,直接在application.yml中配置即可。
重点:由于Feign天生支持Ribbon所以在超时控制这块由Ribbon来控制
#设置feign 客户端超时时间(openFeign默认支持ribbon)
ribbon:
#指的是建立连接后从服务器读取到可用资源所用的时间
ReadTimeout: 5000
#指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
ConnectTimeout: 5000
不放心的朋友可以用线程等待来测试一下:
在服务提供者中添加一个故意等待的方法:
@GetMapping("/payment/feign/timtout")
public String paymentFeignTimeout(){
try{
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
return serverPort;
}
在消费者这边去调用一下:
@GetMapping("/payment/feign/timtout")
String paymentFeignTimeout();
@GetMapping("/consumer/payment/feign/timtout")
String paymentFeignTimeout() {
return paymentFeignService.paymentFeignTimeout();
}
访问,你会发现不加超时控制配置,就会超时的错误。加上即可!
日志打印
Feign 提供了日志打印功能,可以通过配置来调整日志级别,从而了解 Feign 中 Http 请求的细节。 说白了就是对接口的调用情况进行监控和输出
日志级别
- NONE:默认的,不显示任何日志
- BASIC:仅记录请求方法、URL、响应状态码及执行时间
- HEADERS:除了 BASIC 中定义的信息之外,还有请求和响应的头信息
- FULL:除了 HEADERS 中定义的信息之外,还有请求和响应的正文及元数据
怎么开启呢,添加一个配置类:
@Configuration
public class FeignConfig {
@Bean
Logger.Level feignloggerLevel(){
return Logger.Level.FULL;
}
}
application.yml
logging:
level:
#feign日志以什么级别监控哪个接口,注意,这里是你要监控的接口类全路径
com.xn2001.springcloud.service.PaymentFeignService: debug
- Gym 100952C&&2015 HIAST Collegiate Programming Contest C. Palindrome Again !!【字符串,模拟】
- HDU 1013 Digital Roots【字符串,水】
- Gym 100952I&&2015 HIAST Collegiate Programming Contest I. Mancala【模拟】
- bootstrap + requireJS+ director+ knockout + web API = 一个时髦的单页程序
- Gym 100952E&&2015 HIAST Collegiate Programming Contest E. Arrange Teams【DFS+剪枝】
- Gym 100952H&&2015 HIAST Collegiate Programming Contest H. Special Palindrome【dp预处理+矩阵快速幂/打表解法】
- Gym 100952G&&2015 HIAST Collegiate Programming Contest G. The jar of divisors【简单博弈】
- Gym 100952F&&2015 HIAST Collegiate Programming Contest F. Contestants Ranking【BFS+STL乱搞(map+vector)+
- Gym 100952D&&2015 HIAST Collegiate Programming Contest D. Time to go back【杨辉三角预处理,组合数,dp】
- Gym 100952B&&2015 HIAST Collegiate Programming Contest B. New Job【模拟】
- 51 Nod 1008 N的阶乘 mod P【Java大数乱搞】
- 【AlphaGo Zero 核心技术-深度强化学习教程代码实战06】给Agent添加记忆功能
- Gym 100952A&&2015 HIAST Collegiate Programming Contest A. Who is the winner?【字符串,暴力】
- [开源,学习,分享]UWP第三方简书客户端分享
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【python实现卷积神经网络】全连接层实现
- 来我们聊聊“简单工厂模式”
- 【python实现卷积神经网络】批量归一化层实现
- 【python实现卷积神经网络】池化层实现
- srand()和rand(),生成随机数,留给我自己看
- 【python实现卷积神经网络】padding2D层实现
- mybatis之全局配置文件中的标签
- 【python实现卷积神经网络】Flatten层实现
- Shiro框架学习笔记(二)基于内置ini文件的身份认证
- 【python实现卷积神经网络】上采样层upSampling2D实现
- mybatis映射文件之获取自增的主键
- django实战(二)--带多字段模糊查询的分页(也是不容易)
- 【python实现卷积神经网络】Dropout层实现
- 【python实现卷积神经网络】激活层实现
- django实战(三)--删除和批量删除