Spring Cloud學(xué)習(xí)day99:聲明式服務(wù)調(diào)用Feign

一淘邻、Feign的定義

1.什么是Feign窑眯?

Feign 是一種聲明式屏积、模板化的 HTTP 客戶端(僅在 consumer 中使用)。
Feign 的英文表意為“假裝磅甩,偽裝炊林,變形”, 是一個http請求調(diào)用的輕量級框架卷要,可以以Java接口注解的方式調(diào)用Http請求铛铁,而不用像Java中通過封裝HTTP請求報文的方式直接調(diào)用。Feign通過處理注解却妨,將請求模板化饵逐,當(dāng)實際調(diào)用的時候,傳入?yún)?shù)彪标,根據(jù)參數(shù)再應(yīng)用到請求上倍权,進(jìn)而轉(zhuǎn)化成真正的請求,這種請求相對而言比較直觀捞烟。
Feign被廣泛應(yīng)用在Spring Cloud 的解決方案中薄声,是學(xué)習(xí)基于Spring Cloud 微服務(wù)架構(gòu)不可或缺的重要組件。

  • Feign解決了什么問題:

裝了Http調(diào)用流程题画,更適合面向接口化的變成習(xí)慣默辨。
在服務(wù)調(diào)用的場景中,我們經(jīng)常調(diào)用基于Http協(xié)議的服務(wù)苍息,而我們經(jīng)常使用到的框架可能有HttpURLConnection缩幸、Apache HttpComponnets壹置、OkHttp3 、Netty等等表谊,這些框架在基于自身的專注點提供了自身特性钞护。而從角色劃分上來看,他們的職能是一致的提供Http調(diào)用服務(wù)爆办。

  • 調(diào)用流程:

調(diào)用方Client框架服務(wù)方構(gòu)造Http請求URL填寫Http請求頭信息填寫消息報文信息發(fā)送Http請求處理請求难咕,返回結(jié)果返回報文提取報文信息,轉(zhuǎn)換成對應(yīng)的Java bean根據(jù)Bean中的定義距辆,業(yè)務(wù)處理調(diào)用方Client框架服務(wù)方余佃。

2.什么是聲明式?

聲明式調(diào)用就像調(diào)用本地方法一樣調(diào)用遠(yuǎn)程方法;無感知遠(yuǎn)程 http 請求跨算。

  • 聲明式的作用:

Spring Cloud 的聲明式調(diào)用, 可以做到使用 HTTP 請求遠(yuǎn)程服務(wù)時能就像調(diào)用本地 方法一樣的體驗爆土,開發(fā)者完全感知不到這是遠(yuǎn)程方法,更感知不到這是個 HTTP 請求漂彤。
它像 Dubbo 一樣雾消,consumer 直接調(diào)用接口方法調(diào)用 provider灾搏,而不需要通過常規(guī)的 Http Client 構(gòu)造請求再解析返回數(shù)據(jù)挫望。

  • 解決了什么問題:

它解決了讓開發(fā)者調(diào)用遠(yuǎn)程接口就跟調(diào)用本地方法一樣,無需關(guān)注與遠(yuǎn)程的交互細(xì) 節(jié)狂窑,更無需關(guān)注分布式環(huán)境開發(fā)媳板。


二、Feign簡單案例

1.實現(xiàn)Feign的簡單操作:

需求實現(xiàn)對商品的基本操作泉哈。

示例
1.1創(chuàng)建Product-Service項目:

使用Eclipse創(chuàng)建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>
  • 創(chuàng)建Service接口:
/**
 * 服務(wù)的接口
 * @author zhang
 */
@RequestMapping("/product")
public interface ProductService {

    // 查詢所有
    @RequestMapping(value = "/findAll", method = RequestMethod.GET)
    public List<Product> findAll();
}
  • 創(chuàng)建實體類(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創(chuàng)建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
#設(shè)置服務(wù)注冊的中心地址丛晦,指向另一個注冊中心
eureka.client.serviceUrl.defaultZone=http://admin:123456@eureka1:8761/eureka/,http://admin:123456@eureka2:8761/eureka/ 
  • 創(chuàng)建Controller:
/**
 * Provider服務(wù)
 * @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,"手機(jī)"));
        list.add(new Product(3,"電視"));
        
        return list;
    }
}
  • 創(chuàng)建啟動類:
@EnableEurekaClient
@SpringBootApplication
public class ProductApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(ProductApplication.class, args);
    }
}
1.3創(chuàng)建Product-Consumer:
  • 修改POM文件添加依賴:

添加Product-Service的坐標(biāo)奕纫;添加Feign的坐標(biāo)。

    <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 坐標(biāo) -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
        </dependency>
        <!-- 添加 product-service 坐標(biāo) -->
        <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

#設(shè)置服務(wù)中心地址烫沙,指向另一個注冊中心
eureka.client.serviceUrl.defaultZone=http://admin:123456@eureka1:8761/eureka/,http://admin:123456@eureka2:8761/eureka/
  • 創(chuàng)建Service接口:
@FeignClient(name = "product-provider")
public interface ConsumerService extends ProductService{
}
  • 創(chuàng)建Controller:
/**
 * Consumer服務(wù)
 * 
 * @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;
    }
}
  • 創(chuàng)建啟動類:
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class ConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }
}
Provid

Consumer

注冊中心

2.Feign的單個參數(shù)處理:

基于上面的項目環(huán)境進(jìn)行修改匹层;添加在Service中添加參數(shù)傳遞的方法。

  • 修改Product-Service:
// 傳遞單個參數(shù)
    @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:
    // 單個參數(shù)傳遞
    @RequestMapping(value = "findById", method = RequestMethod.GET)
    public Product findById(@RequestParam("id") Integer id) {
        return consumerService.findById(id);
    }
Consumer

Provider

3.Feign的多個參數(shù)傳遞:

3.1基于GET的提交方式:
  • 修改Product-Service
    // 方式一:使用GET請求锌蓄,傳遞多個參數(shù)升筏,(傳遞對象必須拆分為多個單個參數(shù))
    @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:
    // 多個參數(shù)傳遞,方式一: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請求瘸爽,傳遞多個參數(shù)
    @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請求您访,多參數(shù)傳遞
    @RequestMapping(value = "add2",method = RequestMethod.GET)
    public Product add(Product product) {
        return consumerService.addProduct2(product);
示例

三、Feign操作案例使用MyBatis操作數(shù)據(jù)庫

實現(xiàn)對數(shù)據(jù)庫的增查操作剪决,演示Feign中的不同參數(shù)傳遞灵汪。
使用Eclipse創(chuàng)建項目搭建環(huán)境檀训。

示例
  • 數(shù)據(jù)庫:
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.創(chuàng)建MyBatis-Service項目:

  • 修改POM文件添加相關(guān)依賴:
    <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>
  • 創(chuàng)建接口:
@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);
}
  • 創(chuàng)建實體類(get和set):
    private int userid;
    private String username;
    private int userage;

2.創(chuàng)建MyBatis-Provider:

  • 修改POM文件,添加相關(guān)依賴:
    <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 數(shù)據(jù)庫驅(qū)動 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- druid 數(shù)據(jù)庫連接池 -->
        <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/ 
  • 創(chuàng)建實體類:
    private int userid;
    private String username;
    private int userage;
  • 創(chuàng)建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>
  • 創(chuàng)建Service接口和實現(xiàn)類:
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);
    }
}
  • 創(chuàng)建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;
    }
}
  • 創(chuàng)建啟動類:
@EnableEurekaClient
@MapperScan({"com.zlw.mapper"})
@SpringBootApplication
public class ProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
}

3.創(chuàng)建MyBatis-Consumer:

  • 修改POM文件识虚,添加相關(guān)依賴:
    <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/
  • 創(chuàng)建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);
    }
}
  • 頁面跳轉(zhuǎn):
@Controller
public class PageShow {
    
    @RequestMapping("/{page}")
    public String show(@PathVariable String page) {
        return page;
    }
}
  • 在templates目錄下創(chuàng)建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>
  • 創(chuàng)建啟動類:
@EnableFeignClients(basePackages = "com.zlw.service")
@EnableDiscoveryClient
@SpringBootApplication
public class ConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }
}
查詢所有

單個參數(shù)

四肢扯、Feign的性能優(yōu)化

1.使用Gzip壓縮算法:

  • 什么是gzip?

gzip 是一種數(shù)據(jù)格式担锤,采用用 deflate 算法壓縮 data蔚晨;gzip 是一種流行的文件 壓縮算法,應(yīng)用十分廣泛肛循,尤其是在 Linux 平臺铭腕。
當(dāng) Gzip 壓縮到一個純文本文件時,效果是非常明顯的多糠,大約可以減少 70%以上的文件大小累舷。

  • gzip的作用:

網(wǎng)絡(luò)數(shù)據(jù)經(jīng)過壓縮后實際上降低了網(wǎng)絡(luò)傳輸?shù)淖止?jié)數(shù),最明顯的好處就是可 以加快網(wǎng)頁加載的速度夹孔。網(wǎng)頁加載速度加快的好處不言而喻被盈,除了節(jié)省流量,改善用戶的瀏 覽體驗外搭伤,另一個潛在的好處是 Gzip 與搜索引擎的抓取工具有著更好的系只怎。例如 Google 就可以通過直接讀取 gzip 文件來比普通手工抓取 更快地檢索網(wǎng)頁。

  • HTTP協(xié)議中對壓縮傳輸?shù)囊?guī)定:

(1)客戶端向服務(wù)器請求中帶有:Accept-Encoding:gzip, deflate 字段怜俐,向服務(wù)器表示身堡, 客戶端支持的壓縮格式(gzip 或者 deflate),如果不發(fā)送該消息頭拍鲤,服務(wù)器是不會壓縮的贴谎。
(2)服務(wù)端在收到請求之后,如果發(fā)現(xiàn)請求頭中含有 Accept-Encoding 字段季稳,并且支 持該類型的壓縮擅这,就對響應(yīng)報文壓縮之后返回給客戶端,并且攜帶 Content-Encoding:gzip 消 息頭景鼠,表示響應(yīng)報文是根據(jù)該格式壓縮過的仲翎。
(3)客戶端接收到請求之后,先判斷是否有 Content-Encoding 消息頭莲蜘,如果有谭确,按該 格式解壓報文。否則按正常報文處理票渠。

示例

2.測試支持Gzip壓縮的案例:

使用Feign簡單案例中的測試環(huán)境逐哈,創(chuàng)建新的Product-Consumer項目。

2.1通過 Feign 到 Provider 的請求與相應(yīng)的 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
#配置響應(yīng) GZIP 壓縮 
feign.compression.response.enabled=true
#配置壓縮支持的 MIME TYPE 
feign.compression.request.mime-types=text/xml,application/xml,application/json 
#配置壓縮數(shù)據(jù)大小的最小閥值问顷,默認(rèn) 2048 
feign.compression.request.min-request-size=512
示例
2.2對客戶端瀏覽器的請求以及 Consumer 對 provider 的請求與響應(yīng)做 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)兩臺服務(wù)器建立 http 連接的過程是很復(fù)雜的一個過程昂秃,涉及到多個數(shù)據(jù)包的交換禀梳,并 且也很耗時間。
(2)Http 連接需要的 3 次握手 4 次分手開銷很大肠骆,這一開銷對于大量的比較小的 http 消 息來說更大算途。

  • 優(yōu)化性能的解決方案:

(1)如果我們直接采用 http 連接池,節(jié)約了大量的 3 次握手 4 次分手蚀腿;這樣能大大提升吞 吐率嘴瓤。
(2)feign的http 客戶端支持3種框架;HttpURLConnection莉钙、httpclient廓脆、okhttp;默認(rèn)是 HttpURLConnection磁玉。
(3)傳統(tǒng)的 HttpURLConnection 是 JDK 自帶的停忿,并不支持連接池,如果要實現(xiàn)連接池的 機(jī)制蚊伞,還需要自己來管理連接對象席赂。對于網(wǎng)絡(luò)請求這種底層相對復(fù)雜的操作,如果有可用的 其他方案时迫,也沒有必要自己去管理連接對象颅停。
(4)HttpClient 相比傳統(tǒng) JDK 自帶的 HttpURLConnection,它封裝了訪問 http 的請求頭别垮, 參數(shù)便监,內(nèi)容體扎谎,響應(yīng)等等碳想;它不僅使客戶端發(fā)送 HTTP 請求變得容易,而且也方便了開發(fā)人 員測試接口(基于 Http 協(xié)議的)毁靶,即提高了開發(fā)的效率胧奔,也方便提高代碼的健壯性;另外 高并發(fā)大量的請求網(wǎng)絡(luò)的時候预吆,還是用“連接池”提升吞吐量龙填。

4.1使用HttpClient客戶端工具:

使用Feign簡單案例中的測試環(huán)境,創(chuàng)建新的Product-Consumer項目拐叉。

  • 修改POM配置文件添加HTTPClient的坐標(biāo):
        <!-- 使用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:
    // 添加商品傳遞多個參數(shù) 方式二 :POST 方式
     @RequestMapping(value="/add2",method=RequestMethod.POST,consumes=MediaType.APPLICATION_JSON_VALUE) 
     public ProductaddProduct2(@RequestBody Product product); 
     //使用 HttpClient 工具 添加商品傳遞多個參數(shù) :基于GET 方式 
     @RequestMapping(value="/add3",method=RequestMethod.GET,consumes=MediaType.APPLICATION_JSON_VALUE) 
     public Product addProduct3(Productproduct); 

4.查看微服務(wù)日志中記錄每個接口 URL,狀態(tài)碼和耗時信息 :

  • 日志的級別:
級別 說明
NONE 不做任何記錄
BASIC 只記錄輸出Http 方法名稱蔬芥、請求URL梆靖、返回狀態(tài)碼和執(zhí)行時間
HEADERS 記錄輸出Http 方法名稱控汉、請求URL、返回狀態(tài)碼和執(zhí)行時間 和 Header 信息
FULL 記錄Request 和Response的Header返吻,Body和一些請求元數(shù)據(jù)
  • 創(chuàng)建Consumer:

使用Feign簡單案例中的環(huán)境姑子。創(chuàng)建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> 

<!--日志異步到數(shù)據(jù)庫 -->  
<!--     <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
        日志異步到數(shù)據(jù)庫 
        <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:不記錄任何信息剂公,默認(rèn)值 
// BASIC:記錄請求方法希俩、請求 URL、狀態(tài)碼和用時
// HEADERS:在 BASIC 基礎(chǔ)上再記錄一些常用信息 
// FULL:記錄請求和相應(yīng)的所有信息 
    @Bean
    public Logger.Level getLog(){
        return Logger.Level.FULL;
    }

5.配置Feign負(fù)載均衡請求超時時間:

Feign 的負(fù)載均衡底層用的就是 Ribbon纲辽。

5.1修改Consumer中的配置文件:
  • 全局配置:
#全局配置 
# 請求連接的超時時間 默認(rèn)的時間為 1 秒 ribbon.ConnectTimeout=5000 
# 請求處理的超時時間 
ribbon.ReadTimeout=5000 
  • 局部配置:
#局部配置 
# 對所有操作請求都進(jìn)行重試 
ego-product-provider.ribbon.OkToRetryOnAllOperations=true 
# 對當(dāng)前實例的重試次數(shù) 
ego-product-provider.ribbon.MaxAutoRetries=2 
# 切換實例的重試次數(shù) 
ego-product-providert.ribbon.MaxAutoRetriesNextServer=0 
# 請求連接的超時時間 
ego-product-provider.ribbon.ConnectTimeout=3000 
# 請求處理的超時時間 
ego-product-provider.ribbon.ReadTimeout=3000 
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末颜武,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子拖吼,更是在濱河造成了極大的恐慌鳞上,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吊档,死亡現(xiàn)場離奇詭異篙议,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)怠硼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進(jìn)店門鬼贱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人香璃,你說我怎么就攤上這事这难。” “怎么了葡秒?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵姻乓,是天一觀的道長。 經(jīng)常有香客問我眯牧,道長蹋岩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任学少,我火速辦了婚禮剪个,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘旱易。我一直安慰自己禁偎,他們只是感情好腿堤,可當(dāng)我...
    茶點故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著如暖,像睡著了一般笆檀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上盒至,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天酗洒,我揣著相機(jī)與錄音,去河邊找鬼枷遂。 笑死樱衷,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的酒唉。 我是一名探鬼主播矩桂,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼痪伦!你這毒婦竟也來了侄榴?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤网沾,失蹤者是張志新(化名)和其女友劉穎癞蚕,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體辉哥,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡桦山,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了醋旦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恒水。...
    茶點故事閱讀 40,567評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖浑度,靈堂內(nèi)的尸體忽然破棺而出寇窑,到底是詐尸還是另有隱情鸦概,我是刑警寧澤箩张,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站窗市,受9級特大地震影響先慷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜咨察,卻給世界環(huán)境...
    茶點故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一论熙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧摄狱,春花似錦脓诡、人聲如沸无午。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宪迟。三九已至,卻和暖如春交惯,著一層夾襖步出監(jiān)牢的瞬間次泽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工席爽, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留意荤,地道東北人。 一個月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓只锻,卻偏偏與公主長得像玖像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子齐饮,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,585評論 2 359

推薦閱讀更多精彩內(nèi)容