OpenFeign和Gateway

OpenFeign和Gateway

一.OpenFeign介绍

OpenFeign是⼀个声明式的Web Service 客户端。它让微服务之间的调⽤变得更简单,类似controller

调⽤service,只需要创建一个接口,然后添加注解即可使⽤OpenFeign。

OpenFeign的前身:

Feign 是 Netflix 公司开源的一个组件。

  • 2013年6月:Netflix发布 Feign的第一个版本 1.0.0
  • 2016年7月:Netflix发布Feign的最后一个版本 8.18.0
  • 2016年:Netflix 将 Feign 捐献给社区
  • 2016年7月:OpenFeign 的首个版本 9.0.0 发布,之后一直持续发布到现在.

可以简单理解为Netflix Feign 是OpenFeign的祖先。或者说OpenFeign 是Netflix Feign的升级版。OpenFeign 是Feign的一个更强大更灵活的实现。

Spring Cloud Feign

Spring Cloud Feign 是 Spring 对 Feign 的封装,将 Feign 项目集成到 Spring Cloud生态系统中。

受 Feign 更名影响,Spring Cloud Feign 也有两个 starter

  • spring-cloud-starter-feign
  • spring-cloud-starter-openfeign
    由于Feign的停更维护,对应的,我们使用的依赖是 spring-cloud-starter-openfeign

OpenFeign 官方文档
Spring Cloud Feign官方文档

二.快速上手

1.引入依赖

在订单项目中引入openfeign的依赖:

xml 复制代码
		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

2.开启openfeign的功能

给订单项目的启动类加上openfeign的注解:

3.编写客户端

在订单服务中写一个api,value代表微服务的名称,path代表Feign客户端的统一前缀

4.修改远程调用代码

5.测试



三.OpenFeign参数传递

1.传递单个参数

ProductController:

ProductAPI:
在Order项目中写一个FeignController:

2.多个参数、传递对象和传递JSON字符串

ProductController:

ProductAPI:

FeignController:

3.最佳方式写代码

继承的方式

创建一个公共的包来提取公共代码,创建包的方式和之前相同:


再将ProductAPI里面写的代码复制到新的ProductAPI项目的包中的,写成接口的形式:

此时需要将ProductInfo引入到这个项目中,但是其他的几个微服务项目都有这个类于是,可以将这个代码复制到这个API项目中,其他的微服务项目直接删除原来的ProductInfo这个类,通过API项目打包的形式放入到起到微服务的POM文件中:

  1. 先进行install,把当前工程打成jar包,放在Maven的本地仓库

  2. 打包好后对其进行引入后,就会有POM文件自动生成:

  3. 实现接口:

  4. 订单的微服务中ProductAPI继承接口:

  5. 使用了ProductInfo和继承了或者实现了ProductInterface都要将ProductInfo的包重新引入,并对方法进行一些修改。

抽取的方式

  1. 依旧是先建一个module,并在pom文件中引入对应的依赖:

  2. 将Order微服务的ProductAPI接口放到product-api微服务项目中的api包中,删除Order原有的api接口:

  3. 对product-api进行打包:

  4. 启动服务端

  5. 抽取调用方:

  6. 进行测试即可

四.部署OpenFeign

对两个服务进行打包,Maven打包默认是从远程仓库下载的,product-api 这个包在本地,有以下解决方案:

  • 上传到Maven中央仓库(参考:如何发布Jar包到Maven中央仓库,比较麻烦)[不推荐]
  • 搭建Maven私服,上传Jar包到私服 [企业推荐]
  • 从本地读取Jar包 [个人学习阶段推荐]
    前两种方法比较复杂,咱们使用第三种方式
  1. 从product-api的打包成功后的结果里找到本地Maven路径写到Order微服务的POM文件中:


  2. 上传到云服务器上:
  3. 启动jar包:

五.统一服务入口-Gateway

1.网关

API网关(简称网关)也是⼀个服务,通常是后端服务的唯一入口。它的定义类似设计模式中的Facade模式(门面模式,也称外观模式)。它就类似整个微服务架构的门面,所有的外部客户端访问,都需要经过它来进行调度和过滤。

网关核心功能:
权限控制: 作为微服务的入口,对用户进行权限校验,如果校验失败则进行拦截
动态路由: ⼀切请求先经过网关,但网关不处理业务,而是根据某种规则,把请求转发到某个微服务
负载均衡 :当路由的目标服务有多个时,还需要做负载均衡
限流: 请求流量过高时,按照网关中配置微服务能够接受的流量进行放行,避免服务压力过大

2.常见网关实现

业界常用的网关方式有很多,技术方案也较成熟,其中不乏很多开源产品,比如Nginx,Kong,Zuul,

Spring Cloud Gateway等。下面介绍两种常见的网关方案。

Zuul

Zuul 是 Netflix 公司开源的一个API网关组件,是Spring Cloud Netflix 子项目的核心组件之一,它可以

和 Eureka、Ribbon、Hystrix 等组件配合使用

在Spring Cloud Finchley正式版之前,Spring Cloud推荐的网关是Netflix提供的Zuul(此处指Zuu 1.X).

然而Netflix在2018年宣布一部分组件进入维护状态,不再进行新特性的开发。这部分组件中就包含Zuul

Spring Cloud Gateway

Spring Cloud Gateway 是Spring Cloud的⼀个全新的API网关项目,基于Spring + SpringBoot等技术

开发,目的是为了替换掉Zuul。

旨在为微服务架构提供一种简单而有效的途径来转发请求,并为他们提供横切关注点,比如:安全性,监控/指标和弹性。

在性能方面,根据官方提供的测试报告,Spring Cloud Gateway的RPS(每秒请求数)是Zuul的1.6倍。测
试报告参考

六.快速上手

  1. 创建项目和之前相同
  2. 引入网关的依赖:
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>
    <parent>
        <groupId>org.example</groupId>
        <artifactId>spring-cloud-gateway</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>gateway</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
    </dependencies>

</project>
  1. 写启动类:
  2. 写配置信息:
xml 复制代码
server:
  port: 10030 # ⽹关端⼝
spring:
  application:
    name: gateway # 服务名称
  cloud:
    nacos:
      discovery:
        server-addr: 1.95.194.117:8848
    gateway:
      routes: # ⽹关路由配置
        - id: order-service #路由ID, ⾃定义, 唯⼀即可
          uri: lb://order-service #⽬标服务地址
          predicates: #路由条件
            - Path=/order/**,/feign/**
        - id: product-service #路由ID, ⾃定义, 唯⼀即可
          uri: lb://product-service #⽬标服务地址
          predicates: #路由条件
            - Path=/product/**
  1. 测试

七.Gateway

1.Predicate

Predicate是Java 8提供的一个函数式编程接口,它接收一个参数并返回一个布尔值,用于条件过滤,请求参数的校验。

代码:

直接通过实现接口后,调用方法来使用:

直接是在创建对象的时候重写方法来使用:

使用lambda表达式的使用:

Predicate 的其他方法

  • isEqual(Object targetRef):比较两个对象是否相等,参数可以为Null
  • and(Predicate other):短路与操作,返回一个组成Predicate
  • or(Predicate other):短路或操作,返回一个组成Predicate
  • test(T t):传入一个Predicate参数,用来做判断
  • negate(): 返回表示此Predicate逻辑否定的Predicate

2.Route Predicate Factories

Route Predicate Factories (路由断言工厂,也称为路由谓词工厂,此处谓词表示一个函数),在Spring

Cloud Gateway中,Predicate提供了路由规则的匹配机制。

我们在配置文件中写的断言规则只是字符串,这些字符串会被Route Predicate Factory读取并处理,转

变为路由判断的条件。比如前面章节配置的 Path=/product/** ,就是通过Path属性来匹配URL前缀是 /product 的请求。

这个规则是由org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory 来实现的。Spring Cloud Gateway默认提供了很多Route Predicate Factory,这些Predicate会分别匹配HTTP请求的不同属性,并且多个Predicate可以通过and逻辑进行组合。




更多参考

3.Gateway Filter Factories(网关过滤器工厂)

Predicate决定了请求由哪⼀个路由处理,如果在请求处理前后需要加⼀些逻辑,这就是Filter(过滤器)的

作用范围了。

Filter分为两种类型:Pre类型和Post类型。

Pre类型过滤器:路由处理之前执行(请求转发到后端服务之前执行),在Pre 类型过滤器中可以做鉴权,限流等。

Post类型过滤器:请求执行⾏完成后,将结果返回给客户端之前执行。

Spring Cloud Gateway 中内置了很多Filter,用于拦截和链式处理web请求。比如权限校验,访问超时等设定。

Spring Cloud Gateway从作用范围上,把Filter可分为GatewayFilter 和GlobalFilter。
GatewayFilter: 应用到单个路由或者一个分组的路由上。
GlobalFilter: 应用到所有的路由上,也就是对所有的请求生效。

GatewayFilter

GatewayFilter 同 Predicate 类似,都是在配置文件 application.yml 中配置,每个过滤器的逻辑都是固定的。比如 AddRequestParameterGatewayFilterFactory 只需要在配置文件中写AddRequestParameter,就可以为所有的请求添加⼀个参数,我们先通过⼀个例子来演示GatewayFilter如何使用。

快速上手:

  1. 添加yml配置
  2. order微服务中添加过滤器参数:
  3. 通过网管访问后,日志中打印出userName:

GatewayFilter详细介绍官网

Default Filters

前面的filter添加在指定路由下,所以只对当前路由生效,若需要对全部路由生效,可以使用spring.cloud.gateway.default-filters 这个属性需要⼀个filter的列表。

yml配置

xml 复制代码
spring:
cloud:
gateway:
default-filters:
- AddResponseHeader=X-Response-Default-Red, Default-Blue
- PrefixPath=/httpbin

GlobalFilter

lobalFilter是Spring Cloud Gateway中的全局过滤器,它和GatewayFilter的作用是相同的。

GlobalFilter 会应用到所有的路由请求上,全局过滤器通常用于实现与安全性,性能监控和日志记录等相关的全局功能。

Spring Cloud Gateway 内置的全局过滤器也有很多,比如:

  • Gateway Metrics Filter:网关指标,提供监控指标
  • Forward Routing Filter:用于本地forword,请求不转发到下游服务器。
  • LoadBalancer Client Filter:针对下游服务,实现负载均衡。
    更多过滤器参考:Global Filters

演示:

  1. 添加依赖
xml 复制代码
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
  1. 添加yml配置
xml 复制代码
spring:
  application:
    name: gateway # 服务名称
  cloud:
    nacos:
      discovery:
        server-addr: 
    gateway:
      metrics:
        enabled: true
management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: always
    shutdown:
      enabled: true
  1. 测试

过滤器执行顺序

一个项目中,既有GatewayFilter,又有 GlobalFilter时,执行的先后顺序是什么呢? 请求路由后,网关会把当前项目中的GatewayFilter和GlobalFilter合并到一个过滤器链(集合)中,并进行排序,依次执行过滤器。

每一个过滤器都必须指定一个int类型的order值,默认值为0,表示该过滤的优先级。order值越小,优先级越高,执行顺序越靠前。

  • Filter通过实现Order接口或者添加@Order注解来指定order值。
  • Spring Cloud Gateway提供的Filter由Spring指定.用户也可以自定义Filter,由用户指定。
  • 当过滤器的order值⼀样时,会按照 defaultFilter > GatewayFilter > GlobalFilter的顺序执行

⾃定义过滤器

Spring Cloud Gateway提供了过滤器的扩展功能,开发者可以根据实际业务来⾃定义过滤器,同样自定

义过滤器也⽀持GatewayFilter 和 GlobalFilter两种.

自定义GatewayFilter

自定义GatewayFilter,需要去实现对应的接口 GatewayFilterFactory,Spring Boot 默认帮我们实现的抽象类是 AbstractGatewayFilterFactory,我们可以直接使用。

定义GatewayFilter

  1. 写一个Custom的Config
  2. 自定义一个CustomGatewayFilterFactory类:
  3. 增加一点yml的配置:
  4. 测试:

**自定义GlobalFilter **

GlobalFilter的实现比较简单,它不需要额外的配置,只需要实现GlobalFilter接口,自动会过滤所有的

Filter.

定义GlobalFilter:

八.部署Gateway

  1. 打包
  2. 把打好的jar包上传云服务器
  3. 再通过nohup命令启动jar包
相关推荐
XiaoLeisj1 小时前
【设计模式】深入解析代理模式(委托模式):代理模式思想、静态模式和动态模式定义与区别、静态代理模式代码实现
java·spring boot·后端·spring·设计模式·代理模式·委托模式
pwzs2 小时前
常见的 Spring Boot 注解汇总
java·spring boot·后端·spring
非ban必选3 小时前
spring-ai使用Document存储至milvus的数据结构
前端·spring·milvus
无业哥4 小时前
Mac搭建Spring5源码环境
spring
Chase_______6 小时前
Java后端开发——分层解耦详解
java·开发语言·spring·web
ApeAssistant7 小时前
Spring + 设计模式 (十八) 行为型 - 责任链模式
spring·设计模式
写bug写bug8 小时前
Spring事务失效的9大场景,你踩过几个?
java·后端·spring
ApeAssistant8 小时前
Spring + 设计模式 (十六) 行为型 - 状态模式
spring·设计模式
ApeAssistant8 小时前
Spring + 设计模式 (十五) 行为型 - 模板方法模式
spring·设计模式