SpringCloud Openfeign

一、 Openfeign简介

Openfeign是一种声明式、模板化的HTTP客户端(仅在Application Client中使用)。声明式调用是指,就像调用本地方法一样调用远程方法,无需感知操作远程http请求。
Spring Cloud的声明式调用, 可以做到使用 HTTP请求远程服务时能就像调用本地方法一样的体验,开发者完全感知不到这是远程方法,更感知不到这是个HTTP请求。Openfeign的应用,让Spring Cloud微服务调用像Dubbo一样,Application Client直接通过接口方法远程调用Application Service,而不需要通过常规的RestTemplate构造请求再解析返回数据。它解决了让开发者调用远程接口就跟调用本地方法一样,无需关注与远程的交互细节,更无需关注分布式环境开发。

1 使用Feign技术开发时的应用部署结构
在这里插入图片描述

二、 Openfeign的实现

1 创建 springcloudopenfeign 项目

在这里插入图片描述

1.1 pom.xml

<?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>
    <packaging>pom</packaging>
    <modules>
        <module>feigncommons</module>
        <module>feignapi</module>
        <module>feignservice</module>
        <module>feignclient</module>
    </modules>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
    </parent>
    <groupId>com.bjsxt</groupId>
    <artifactId>springcloudopenfeign</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>
2 创建 feigncommons 子模块

在这里插入图片描述
2.1 pom.xml

<?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">
    <parent>
        <artifactId>springcloudopenfeign</artifactId>
        <groupId>com.bjsxt</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>feigncommons</artifactId>

</project>

2.2 com.bjsxt.feign.entity 创建实体类 User

package com.bjsxt.feign.entity;

import java.io.Serializable;
import java.util.Objects;

public class User implements Serializable {
    private Integer id;
    private String name;
    private String password;

    public User(){}
    //省略get set toString equals方法

3 创建 feignapi 子模块

在这里插入图片描述
3.1 pom.xml

<?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">
    <parent>
        <artifactId>springcloudopenfeign</artifactId>
        <groupId>com.bjsxt</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>feignapi</artifactId>
    <dependencies>
        <dependency>
            <groupId>com.bjsxt</groupId>
            <artifactId>feigncommons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

</project>

3.2 UserServiceAPI 接口

package com.bjsxt.feign.api;

import com.bjsxt.feign.entity.User;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

/**
 * 类型命名随意
 * 类型是用于约束微服务特性的。
 * 在约束请求参数的时候,Openfeign技术要特殊的限制要求:
 *  1、 简单类型参数,必须使用@RequestParam注解描述,且需要提供请求参数命名。
 *  2、 自定义类型参数,必须使用@RequestBody注解描述,且自定义类型参数数量唯一。
 *      就是参数表中只有唯一的参数,且是自定义类型参数。
 *
 * Application Service需要提供什么服务。
 *  服务1 - 保存用户,方法名、参数表、返回值类型和请求路径地址、请求方式。
 *  服务2 - 更新用户,方法名、参数表、返回值类型和请求路径地址、请求方式。
 * Application Client可以访问什么远程服务。
 *  服务1 - 保存用户,方法名、参数表、返回值类型和请求路径地址、请求方式。
 *  服务2 - 更新用户,方法名、参数表、返回值类型和请求路径地址、请求方式。
 */
public interface UserServiceAPI {
    @PostMapping("/user/save") // 就是约束了只处理POST请求方式的RequestMapping注解。
    Map<String, Object> saveUser(@RequestBody  User user);
    @PostMapping("/user/update")
    Map<String, Object> updateUser(@RequestBody User user);
}

4 创建 feignservice 子模块 (Application server)

在这里插入图片描述
4.1 pom.xml

<?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">
    <parent>
        <artifactId>springcloudopenfeign</artifactId>
        <groupId>com.bjsxt</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>feignservice</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>com.bjsxt</groupId>
            <artifactId>feignapi</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

</project>

4.2 UserController 控制类

package com.bjsxt.feign.controller;

import com.bjsxt.feign.api.UserServiceAPI;
import com.bjsxt.feign.entity.User;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

@RestController
public class UserController implements UserServiceAPI {
    @Override
    public Map<String, Object> saveUser(User user) {
        Map<String, Object> result = new HashMap<>();
        System.out.println("保存用户数据:" + user);
        result.put("message", "保存用户数据成功");
        return result;
    }

    @Override
    public Map<String, Object> updateUser(User user) {
        Map<String, Object> result = new HashMap<>();
        System.out.println("更新用户数据:" + user);
        result.put("message", "更新用户数据成功");
        return result;
    }
    
}

4.3 application.yml 配置文件

server:
  port: 8082

spring:
  application:
    name: feign-app-service

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

4.4 启动类(集群)

package com.bjsxt.feign;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

package com.bjsxt.feign;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

5 创建 feignclient 子模块 (Application client)

在这里插入图片描述
5.1 pom.xml

<?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">
    <parent>
        <artifactId>springcloudopenfeign</artifactId>
        <groupId>com.bjsxt</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>feignclient</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>com.bjsxt</groupId>
            <artifactId>feignapi</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>

</project>

5.2 UserController 控制类

package com.bjsxt.feign.client.controller;

import com.bjsxt.feign.client.service.UserService;
import com.bjsxt.feign.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

@RestController
public class UserController {
    @Autowired
    private UserService userService;
    @GetMapping("/user/save")
    public Object save(User user){
        Map<String, Object> result = this.userService.saveUser(user);
        System.out.println(result);
        return result;
    }
    @GetMapping("/user/update")
    public Object update(User user){
        Map<String, Object> result = this.userService.updateUser(user);
        System.out.println(result);
        return result;
    }
    
}

5.3 UserService 接口

package com.bjsxt.feign.client.service;

import com.bjsxt.feign.api.UserServiceAPI;
import org.springframework.cloud.openfeign.FeignClient;

/**
 * 本地服务,是用于远程访问Application Service的本地服务接口。
 */
@FeignClient("feign-app-service")
public interface UserService extends UserServiceAPI {
}

5.4 application.yml 配置文件

server:
  port: 8081
  compression:

spring:
  application:
    name: feign-app-client

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

feign-app-service: # 配置负载均衡
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

5.5 启动类

package com.bjsxt.feign.client;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * 需要提供一个新的注解
 * @EnableFeignClients - 开启OpenFeign客户端技术。扫描@FeignClient注解。
 *   默认扫描当前类所在包,及子包中所有的类型。
 */
@SpringBootApplication
@EnableFeignClients(basePackages = {"com.bjsxt.feign.client.service"})
public class FeignClientApp {
    public static void main(String[] args) {
        SpringApplication.run(FeignClientApp.class, args);
    }
}

三、 Openfeign的请求参数处理

在Openfeign处理远程服务调用时,传递参数是通过HTTP协议传递的,参数存在的位置是请求头或请求体中。请求头传递的参数必须依赖@RequestParam注解来处理请求参数,请求体传递的参数必须依赖@RequestBody注解来处理请求参数。

    /**
     * 简单类型的请求参数,如:字符串,8种基本类型,包装类型,简单类型数组
     * 可以通过请求头和请求体传递,可以使用GET|POST请求方式来进行处理
     * Openfeign强制要求,简单类型的请求参数,必须使用@RequestParam注解描述。
     */
    /**
     * 自定义类型请求参数处理
     * Openfeign强制要求,处理自定义类型请求参数的时候,必须使用@RequestBody注解描述。
     * @RequestBody注解强制约束: 一个方法的参数表中,只能有唯一的一个参数使用此注解描述。
     * Openfeign强制要求,所有的自定义类型请求参数,必须使用POST请求处理传递。
     * Openfeign处理自定义类型参数的时候:只能处理唯一的一个自定义类型参数对象,必须使用POST
     * 请求方式传递处理,对简单类型数据无约束。
     */

四、 Openfeign的性能优化

1 GZIP简介

gzip介绍:

gzip是一种数据格式,采用用deflate算法压缩数据;gzip是一种流行的数据压缩算法,应用十分广泛,尤其是在Linux平台。

gzip能力:

当Gzip压缩到一个纯文本数据时,效果是非常明显的,大约可以减少70%以上的数据大小。

gzip作用:

网络数据经过压缩后实际上降低了网络传输的字节数,最明显的好处就是可以加快网页加载的速度。网页加载速度加快的好处不言而喻,除了节省流量,改善用户的浏览体验外,另一个潜在的好处是Gzip与搜索引擎的抓取工具有着更好的关系。例如 Google就可以通过直接读取gzip文件来比普通手工抓取更快地检索网页。

2 HTTP协议中的压缩传输简介

第一:客户端向服务器请求头中带有:Accept-Encoding:gzip, deflate 字段,向服务器表示,客户端支持的压缩格式(gzip或者deflate),如果不发送该消息头,服务器是不会压缩的。
第二:服务端在收到请求之后,如果发现请求头中含有Accept-Encoding字段,并且支持该类型的压缩,就对响应报文压缩之后返回给客户端,并且携带Content-Encoding:gzip消息头,表示响应报文是根据该格式压缩过的。
第三:客户端接收到响应之后,先判断是否有Content-Encoding消息头,如果有,按该格式解压报文。否则按正常报文处理。

3 在Openfeign技术中应用GZIP压缩

在Spring Cloud微服务体系中,一次请求的完整流程如下:
在整体流程中,如果使用GZIP压缩来传输数据,涉及到两次请求-应答。而这两次请求-应答的连接点是Application Client,那么我们需要在Application Client中配置开启GZIP压缩,来实现压缩数据传输。

3.1 只配置Openfeign请求-应答中的GZIP压缩 (即Application Server 和 Application Client之间)

application.yml

server:
  port: 8081

spring:
  application:
    name: feign-app-client

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

feign-app-service: # 配置负载均衡
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

feign:
  compression:
    request:
      enabled: true # 开启请求GZIP压缩
      mime-types:  # 什么请求类型开启GZIP压缩 a,b,c
        - text/html
        - text/plain
        - text/xml
        - application/json
      min-request-size: 512 # 请求容量超过这个阀值的时候,开启压缩。默认值2048字节
    response:
      enabled: true # 开启响应GZIP压缩。

3.2 配置全局GZIP压缩 (即配置 浏览器与Application Client、Application Server 和 Application Client之间)

在全局配置文件中配置下述内容,来开启所有请求-应答中的GZIP压缩,这里使用的是Spring Boot中的GZIP技术。在Spring Boot中已经集成了GZIP压缩技术,并对所有的请求-应答实现GZIP数据压缩。工程中已经依赖了Spring Boot技术,所以在配置文件中可以开启Spring Boot中的GZIP压缩技术,对完整流程中所有相关的请求-应答开启GZIP压缩。

application.yml

server:
  port: 8081
  compression:
    enabled: true # 开启全局GZIP压缩
    mime-types:  # 设置开启GZIP压缩的请求头类型
      - text/html
      - text/plain
      - text/xml
      - application/json
      - application/javascript
      - application/xml
    min-response-size: 512  # 最小的响应容量阀值,超过这个容量,进行压缩,默认2048字节。

spring:
  application:
    name: feign-app-client

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

feign-app-service: # 配置负载均衡
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

feign:
  compression:
    request:
      enabled: true # 开启请求GZIP压缩
      mime-types:  # 什么请求类型开启GZIP压缩 a,b,c
        - text/html
        - text/plain
        - text/xml
        - application/json
      min-request-size: 512 # 请求容量超过这个阀值的时候,开启压缩。默认值2048字节
    response:
      enabled: true # 开启响应GZIP压缩。

五、 配置Openfeign负载均衡请求超时时间

Openfeign技术底层是通过Ribbon技术实现的,那么在负载均衡和超时时间配置上,主要对Ribbon的配置。

超时时间配置-----在Application Client应用的配置文件 application.yml 上:

server:
  port: 8081
  compression:
    enabled: true # 开启全局GZIP压缩
    mime-types:  # 设置开启GZIP压缩的请求头类型
      - text/html
      - text/plain
      - text/xml
      - application/json
      - application/javascript
      - application/xml
    min-response-size: 512  # 最小的响应容量阀值,超过这个容量,进行压缩,默认2048字节。

spring:
  application:
    name: feign-app-client

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

feign-app-service: # 配置负载均衡
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

feign:
  compression:
    request:
      enabled: true # 开启请求GZIP压缩
      mime-types:  # 什么请求类型开启GZIP压缩 a,b,c
        - text/html
        - text/plain
        - text/xml
        - application/json
      min-request-size: 512 # 请求容量超过这个阀值的时候,开启压缩。默认值2048字节
    response:
      enabled: true # 开启响应GZIP压缩。

ribbon:
  ConnectTimeout: 1000 # 连接超时时间
  ReadTimeout: 3000 # 操作超时时间。必须大于等于ConnectTimeout。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AloneDrifters

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值