一、Feign的定义
1.什么是Feign?
Feign 是一种声明式、模板化的 HTTP 客户端(仅在 consumer 中使用)。
Feign 的英文表意为“假装,伪装,变形”, 是一个http请求调用的轻量级框架,可以以Java接口注解的方式调用Http请求,而不用像Java中通过封装HTTP请求报文的方式直接调用。Feign通过处理注解,将请求模板化,当实际调用的时候,传入参数,根据参数再应用到请求上,进而转化成真正的请求,这种请求相对而言比较直观。
Feign被广泛应用在Spring Cloud 的解决方案中,是学习基于Spring Cloud 微服务架构不可或缺的重要组件。
- Feign解决了什么问题:
装了Http调用流程,更适合面向接口化的变成习惯。
在服务调用的场景中,我们经常调用基于Http协议的服务,而我们经常使用到的框架可能有HttpURLConnection、Apache HttpComponnets、OkHttp3 、Netty等等,这些框架在基于自身的专注点提供了自身特性。而从角色划分上来看,他们的职能是一致的提供Http调用服务。
- 调用流程:
调用方Client框架服务方构造Http请求URL填写Http请求头信息填写消息报文信息发送Http请求处理请求,返回结果返回报文提取报文信息,转换成对应的Java bean根据Bean中的定义,业务处理调用方Client框架服务方。
2.什么是声明式?
声明式调用就像调用本地方法一样调用远程方法;无感知远程 http 请求。
- 声明式的作用:
Spring Cloud 的声明式调用, 可以做到使用 HTTP 请求远程服务时能就像调用本地 方法一样的体验,开发者完全感知不到这是远程方法,更感知不到这是个 HTTP 请求。
它像 Dubbo 一样,consumer 直接调用接口方法调用 provider,而不需要通过常规的 Http Client 构造请求再解析返回数据。
- 解决了什么问题:
它解决了让开发者调用远程接口就跟调用本地方法一样,无需关注与远程的交互细 节,更无需关注分布式环境开发。
二、Feign简单案例
1.实现Feign的简单操作:
需求实现对商品的基本操作。
1.1创建Product-Service项目:
使用Eclipse创建Maven项目。使用Eureka的集群注册中心。
- 修改POM文件添加依赖:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<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>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
</dependencies>
- 创建Service接口:
/**
* 服务的接口
* @author zhang
*/
@RequestMapping("/product")
public interface ProductService {
// 查询所有
@RequestMapping(value = "/findAll", method = RequestMethod.GET)
public List<Product> findAll();
}
- 创建实体类(getter和setter方法)
public class Product {
private Integer id;
private String name;
public Product() {
super();
}
public Product(Integer id, String name) {
super();
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
1.2创建Product-Provider项目:
- 修改POM文文件添加依赖:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<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>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>com.zlw</groupId>
<artifactId>springcloud-feign-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
- 添加全局配置文件:
spring.application.name=product-provider
server.port=9093
#设置服务注册的中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://admin:123456@eureka1:8761/eureka/,http://admin:123456@eureka2:8761/eureka/
- 创建Controller:
/**
* Provider服务
* @author zhang
*
*/
@RestController
public class ProductController implements ProductService{
@Override
public List<Product> findAll() {
List<Product> list=new ArrayList<Product>();
list.add(new Product(1,"电脑"));
list.add(new Product(2,"手机"));
list.add(new Product(3,"电视"));
return list;
}
}
- 创建启动类:
@EnableEurekaClient
@SpringBootApplication
public class ProductApplication {
public static void main(String[] args) {
SpringApplication.run(ProductApplication.class, args);
}
}
1.3创建Product-Consumer:
- 修改POM文件添加依赖:
添加Product-Service的坐标;添加Feign的坐标。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<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>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</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>
</dependency>
<!-- 添加 product-service 坐标 -->
<dependency>
<groupId>com.zlw</groupId>
<artifactId>springcloud-feign-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
- 添加全局配置文件:
spring.application.name=product-consumer
server.port=9094
#设置服务中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://admin:123456@eureka1:8761/eureka/,http://admin:123456@eureka2:8761/eureka/
- 创建Service接口:
@FeignClient(name = "product-provider")
public interface ConsumerService extends ProductService{
}
- 创建Controller:
/**
* Consumer服务
*
* @author zhang
*
*/
@RestController
public class ConsumerController {
@Autowired
ConsumerService consumerService;
// 查询所有
@RequestMapping(value = "list", method = RequestMethod.GET)
public List<Product> list() {
List<Product> list = consumerService.findAll();
return list;
}
}
- 创建启动类:
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
2.Feign的单个参数处理:
基于上面的项目环境进行修改;添加在Service中添加参数传递的方法。
- 修改Product-Service:
// 传递单个参数
@RequestMapping(value = "findById", method = RequestMethod.GET)
public Product findById(@RequestParam("id") Integer id);
- 修改Product-Provider:
@Override
public Product findById(Integer id) {
return new Product(id,"ProductName");
}
- 修改Product-Consumer:
// 单个参数传递
@RequestMapping(value = "findById", method = RequestMethod.GET)
public Product findById(@RequestParam("id") Integer id) {
return consumerService.findById(id);
}
3.Feign的多个参数传递:
3.1基于GET的提交方式:
- 修改Product-Service
// 方式一:使用GET请求,传递多个参数,(传递对象必须拆分为多个单个参数)
@RequestMapping(value = "addProduct", method = RequestMethod.GET)
public Product addProduct(@RequestParam("id") Integer id, @RequestParam("name") String name);
- 修改Product-Provider:
@Override
public Product addProduct(Integer id, String name) {
return new Product(id,name);
}
- 修改Product-Consumer:
// 多个参数传递,方式一:GET请求
@RequestMapping(value = "add", method = RequestMethod.GET)
public Product addProduct(Product product) {
return consumerService.addProduct(product.getId(), product.getName());
}
3.2基于POST的提交方式:
- 修改 Product-Service :
//方式二:使用POST请求,传递多个参数
@RequestMapping(value = "addProduct2",method = RequestMethod.POST)
public Product addProduct2(@RequestBody Product product);
- 修改 Product-Provider:
@Override
public Product addProduct2(@RequestBody Product product) {
return product;
}
- 修改 Product-Consumer :
//方式二:POST请求,多参数传递
@RequestMapping(value = "add2",method = RequestMethod.GET)
public Product add(Product product) {
return consumerService.addProduct2(product);
三、Feign操作案例使用MyBatis操作数据库
实现对数据库的增查操作,演示Feign中的不同参数传递。
使用Eclipse创建项目搭建环境。
- 数据库:
CREATE TABLE `users` (
`userid` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(30) DEFAULT NULL,
`userage` int(5) DEFAULT NULL,
PRIMARY KEY (`userid`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8;
1.创建MyBatis-Service项目:
- 修改POM文件添加相关依赖:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
- 创建接口:
@FeignClient(name = "users-provider")
public interface UserServiceFeign {
@RequestMapping("/user")
public List<User> findAll();
@RequestMapping("/user/{userid}")
public User findById(@PathVariable("userid") int userid);
@RequestMapping("/findOne")
public User findOne(@RequestParam("userid") int userid);
@RequestMapping(value = "/add", method = RequestMethod.POST)
public int addUser(@RequestBody User user);
}
- 创建实体类(get和set):
private int userid;
private String username;
private int userage;
2.创建MyBatis-Provider:
- 修改POM文件,添加相关依赖:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- Mybatis 启动器 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<!-- mysql 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- druid 数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.9</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<!--配置资源拷贝插件 -->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.yml</include>
<include>**/*.properties</include>
</includes>
</resource>
</resources>
</build>
- 修改全局配置文件:
spring.application.name=user-provider
#配置端口
server.port=9096
#mybatis
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/ssm
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
mybatis.type-aliases-package=com.zlw.pojo
#配置eureka信息
eureka.client.serviceUrl.defaultZone=http://admin:123456@eureka1:8761/eureka/,http://admin:123456@eureka2:8761/eureka/
- 创建实体类:
private int userid;
private String username;
private int userage;
- 创建mapper接口和映射文件:
public interface UserMapper {
public List<User> findAll();
public User findById(int userid);
public int AddUser(User user);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zlw.mapper.UserMapper">
<select id="findAll" resultType="user">
select * from users
</select>
<select id="findById" resultType="user">
select *from users where userid=#{userid}
</select>
<insert id="addUser" parameterType="user">
insert into users(username,userage) values(#{username},#{userage})
</insert>
</mapper>
- 创建Service接口和实现类:
public interface UserService {
// 查询所有
public List<User> findAll();
// 查询指定
public User findById(int userid);
// 添加
public int addUser(User user);
}
@Service
public class UserServiceImpl implements UserService {
@Autowired
UserMapper userMapper;
@Override
public List<User> findAll() {
return userMapper.findAll();
}
@Override
public User findById(int userid) {
return userMapper.findById(userid);
}
@Override
public int addUser(User user) {
return userMapper.AddUser(user);
}
}
- 创建Controller:
@RestController
public class UserController {
@Autowired
UserService userService;
// 查询所有
@RequestMapping("/user")
public List<User> findAll() {
List<User> list = userService.findAll();
return list;
}
// 查询指定
@RequestMapping("/user/{userid}")
public User findById(@PathVariable int userid) {
User user = userService.findById(userid);
return user;
}
// 添加
@RequestMapping(value = "/add", method = RequestMethod.POST)
public int add(User user) {
int num = userService.addUser(user);
return num;
}
}
- 创建启动类:
@EnableEurekaClient
@MapperScan({"com.zlw.mapper"})
@SpringBootApplication
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
3.创建MyBatis-Consumer:
- 修改POM文件,添加相关依赖:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<dependency>
<groupId>com.zlw</groupId>
<artifactId>springcloud-feign-mybits-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
- 修改配置文件:
spring.application.name=user-consumer
server.port=9097
eureka.client.serviceUrl.defaultZone=http://admin:123456@eureka1:8761/eureka/,http://admin:123456@eureka2:8761/eureka/
- 创建Controller:
@RestController
public class UserController {
@Autowired
UserServiceFeign userService;
@RequestMapping("/user")
public List<User> findAll() {
return userService.findAll();
}
@RequestMapping("/user/{userid}")
public User findById(@PathVariable int userid) {
return userService.findById(userid);
}
@RequestMapping("/findOne")
public User findOne(int userid) {
return userService.findOne(userid);
}
@RequestMapping("/addUser")
public int addUser(User user) {
return userService.addUser(user);
}
}
- 页面跳转:
@Controller
public class PageShow {
@RequestMapping("/{page}")
public String show(@PathVariable String page) {
return page;
}
}
- 在templates目录下创建addUser.html:
<html xmlns:th="www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form th:action="@{/addUser}" method="post">
<p>
用户名:<input type="text" name="username" />
</p>
<p>
年龄:<input type="text" name="userage" />
</p>
<p>
<input type="submit" value="添加" />
</p>
</form>
</body>
</html>
- 创建启动类:
@EnableFeignClients(basePackages = "com.zlw.service")
@EnableDiscoveryClient
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
四、Feign的性能优化
1.使用Gzip压缩算法:
- 什么是gzip?
gzip 是一种数据格式,采用用 deflate 算法压缩 data;gzip 是一种流行的文件 压缩算法,应用十分广泛,尤其是在 Linux 平台。
当 Gzip 压缩到一个纯文本文件时,效果是非常明显的,大约可以减少 70%以上的文件大小。
- gzip的作用:
网络数据经过压缩后实际上降低了网络传输的字节数,最明显的好处就是可 以加快网页加载的速度。网页加载速度加快的好处不言而喻,除了节省流量,改善用户的浏 览体验外,另一个潜在的好处是 Gzip 与搜索引擎的抓取工具有着更好的系。例如 Google 就可以通过直接读取 gzip 文件来比普通手工抓取 更快地检索网页。
- HTTP协议中对压缩传输的规定:
(1)客户端向服务器请求中带有:Accept-Encoding:gzip, deflate 字段,向服务器表示, 客户端支持的压缩格式(gzip 或者 deflate),如果不发送该消息头,服务器是不会压缩的。
(2)服务端在收到请求之后,如果发现请求头中含有 Accept-Encoding 字段,并且支 持该类型的压缩,就对响应报文压缩之后返回给客户端,并且携带 Content-Encoding:gzip 消 息头,表示响应报文是根据该格式压缩过的。
(3)客户端接收到请求之后,先判断是否有 Content-Encoding 消息头,如果有,按该 格式解压报文。否则按正常报文处理。
2.测试支持Gzip压缩的案例:
使用Feign简单案例中的测试环境,创建新的Product-Consumer项目。
2.1通过 Feign 到 Provider 的请求与相应的 Gzip 压缩:
- 修改Consumer的配置文件:
spring.application.name=product-consumer
server.port=9095
eureka.client.serviceUrl.defaultZone=http://admin:123456@eureka1:8761/eureka/,http://admin:123456@eureka2:8761/eureka/
#-----------------------------feign gzip
#配置请求 GZIP 压缩
feign.compression.request.enabled=true
#配置响应 GZIP 压缩
feign.compression.response.enabled=true
#配置压缩支持的 MIME TYPE
feign.compression.request.mime-types=text/xml,application/xml,application/json
#配置压缩数据大小的最小阀值,默认 2048
feign.compression.request.min-request-size=512
2.2对客户端浏览器的请求以及 Consumer 对 provider 的请求与响应做 Gzip 压缩:
- 修改Consumer的配置文件:
#-----------------------------spring boot gzip
#是否启用压缩
server.compression.enabled=true
server.compression.mime-types=application/json,application/ xml,text/html,text/xml,text/plain
3.使用Http连接池:
- Http的背景原理:
(1)两台服务器建立 http 连接的过程是很复杂的一个过程,涉及到多个数据包的交换,并 且也很耗时间。
(2)Http 连接需要的 3 次握手 4 次分手开销很大,这一开销对于大量的比较小的 http 消 息来说更大。
- 优化性能的解决方案:
(1)如果我们直接采用 http 连接池,节约了大量的 3 次握手 4 次分手;这样能大大提升吞 吐率。
(2)feign的http 客户端支持3种框架;HttpURLConnection、httpclient、okhttp;默认是 HttpURLConnection。
(3)传统的 HttpURLConnection 是 JDK 自带的,并不支持连接池,如果要实现连接池的 机制,还需要自己来管理连接对象。对于网络请求这种底层相对复杂的操作,如果有可用的 其他方案,也没有必要自己去管理连接对象。
(4)HttpClient 相比传统 JDK 自带的 HttpURLConnection,它封装了访问 http 的请求头, 参数,内容体,响应等等;它不仅使客户端发送 HTTP 请求变得容易,而且也方便了开发人 员测试接口(基于 Http 协议的),即提高了开发的效率,也方便提高代码的健壮性;另外 高并发大量的请求网络的时候,还是用“连接池”提升吞吐量。
4.1使用HttpClient客户端工具:
使用Feign简单案例中的测试环境,创建新的Product-Consumer项目。
- 修改POM配置文件添加HTTPClient的坐标:
<!-- 使用Apache HttpClient替换Feign原生httpURLConnection -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-httpclient</artifactId>
<version>8.17.0</version>
</dependency>
- 修改配置文件开启HttpClient的使用:
spring.application.name=product-consumer
server.port=9098
eureka.client.serviceUrl.defaultZone=http://admin:123456@eureka1:8761/eureka/,http://admin:123456@eureka2:8761/eureka/
#启用 httpclient
feign.httpclient.enabled=true
- 注意:
如果使用 HttpClient 作为 Feign 的客户端工具。那么在定义接口上的注解是需要 注意,如果传递的是一个自定义的对象(对象会使用 json 格式来专递)。需要制定类型。
- 修改Product-Service:
// 添加商品传递多个参数 方式二 :POST 方式
@RequestMapping(value="/add2",method=RequestMethod.POST,consumes=MediaType.APPLICATION_JSON_VALUE)
public ProductaddProduct2(@RequestBody Product product);
//使用 HttpClient 工具 添加商品传递多个参数 :基于GET 方式
@RequestMapping(value="/add3",method=RequestMethod.GET,consumes=MediaType.APPLICATION_JSON_VALUE)
public Product addProduct3(Productproduct);
4.查看微服务日志中记录每个接口 URL,状态码和耗时信息 :
- 日志的级别:
级别 | 说明 |
---|---|
NONE | 不做任何记录 |
BASIC | 只记录输出Http 方法名称、请求URL、返回状态码和执行时间 |
HEADERS | 记录输出Http 方法名称、请求URL、返回状态码和执行时间 和 Header 信息 |
FULL | 记录Request 和Response的Header,Body和一些请求元数据 |
- 创建Consumer:
使用Feign简单案例中的环境。创建Consumer项目。
- 添加logback.xml配置文件:
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<property name="LOG_HOME" value="${catalina.base}/logs/" />
<!-- 控制台输出 -->
<appender name="Stdout" class="ch.qos.logback.core.ConsoleAppender">
<!-- 日志输出编码 -->
<layout class="ch.qos.logback.classic.PatternLayout">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
</pattern>
</layout>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/server.%d{yyyy-MM-dd}.log</FileNamePattern>
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
</pattern>
</layout>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>
<!-- 日志输出级别 -->
<root level="DEBUG">
<appender-ref ref="Stdout" />
<appender-ref ref="RollingFile" />
</root>
<!--日志异步到数据库 -->
<!-- <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
日志异步到数据库
<connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
连接池
<dataSource class="com.mchange.v2.c3p0.ComboPooledDataSource">
<driverClass>com.mysql.jdbc.Driver</driverClass>
<url>jdbc:mysql://127.0.0.1:3306/databaseName</url>
<user>root</user>
<password>root</password>
</dataSource>
</connectionSource>
</appender> -->
</configuration>
- 在启动类中添加方法:
// NONE:不记录任何信息,默认值
// BASIC:记录请求方法、请求 URL、状态码和用时
// HEADERS:在 BASIC 基础上再记录一些常用信息
// FULL:记录请求和相应的所有信息
@Bean
public Logger.Level getLog(){
return Logger.Level.FULL;
}
5.配置Feign负载均衡请求超时时间:
Feign 的负载均衡底层用的就是 Ribbon。
5.1修改Consumer中的配置文件:
- 全局配置:
#全局配置
# 请求连接的超时时间 默认的时间为 1 秒 ribbon.ConnectTimeout=5000
# 请求处理的超时时间
ribbon.ReadTimeout=5000
- 局部配置:
#局部配置
# 对所有操作请求都进行重试
ego-product-provider.ribbon.OkToRetryOnAllOperations=true
# 对当前实例的重试次数
ego-product-provider.ribbon.MaxAutoRetries=2
# 切换实例的重试次数
ego-product-providert.ribbon.MaxAutoRetriesNextServer=0
# 请求连接的超时时间
ego-product-provider.ribbon.ConnectTimeout=3000
# 请求处理的超时时间
ego-product-provider.ribbon.ReadTimeout=3000