OpenFeign和Gateway
OpenFeign和Gateway
- 一.OpenFeign介绍
- 二.快速上手
- 1.引入依赖
- 2.开启openfeign的功能
- 3.编写客户端
- 4.修改远程调用代码
- 5.测试
- 三.OpenFeign参数传递
- 1.传递单个参数
- 2.多个参数、传递对象和传递JSON字符串
- 3.最佳方式写代码
- 继承的方式
- 抽取的方式
- 四.部署OpenFeign
- 五.统一服务入口-Gateway
- 1.网关
- 2.常见网关实现
- 六.快速上手
- 七.Gateway
- 1.Predicate
- 2.Route Predicate Factories
- 3.Gateway Filter Factories(网关过滤器工厂)
- GatewayFilter
- GlobalFilter
- 过滤器执行顺序
- ⾃定义过滤器
- 八.部署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的依赖:
<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文件中:
-
先进行install,把当前工程打成jar包,放在Maven的本地仓库
-
打包好后对其进行引入后,就会有POM文件自动生成:
-
实现接口:
-
订单的微服务中ProductAPI继承接口:
-
使用了ProductInfo和继承了或者实现了ProductInterface都要将ProductInfo的包重新引入,并对方法进行一些修改。
抽取的方式
-
依旧是先建一个module,并在pom文件中引入对应的依赖:
-
将Order微服务的ProductAPI接口放到product-api微服务项目中的api包中,删除Order原有的api接口:
-
对product-api进行打包:
-
启动服务端
-
抽取调用方:
-
进行测试即可
四.部署OpenFeign
对两个服务进行打包,Maven打包默认是从远程仓库下载的,product-api 这个包在本地,有以下解决方案:
- 上传到Maven中央仓库(参考:如何发布Jar包到Maven中央仓库,比较麻烦)[不推荐]
- 搭建Maven私服,上传Jar包到私服 [企业推荐]
- 从本地读取Jar包 [个人学习阶段推荐]
前两种方法比较复杂,咱们使用第三种方式
- 从product-api的打包成功后的结果里找到本地Maven路径写到Order微服务的POM文件中:
- 上传到云服务器上:
- 启动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倍。测
试报告参考
六.快速上手
- 创建项目和之前相同
- 引入网关的依赖:
<?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>
- 写启动类:
- 写配置信息:
server:port: 10030 # ⽹关端⼝
spring:application:name: gateway # 服务名称cloud:nacos:discovery:server-addr: 1.95.194.117:8848gateway:routes: # ⽹关路由配置- id: order-service #路由ID, ⾃定义, 唯⼀即可uri: lb://order-service #⽬标服务地址predicates: #路由条件- Path=/order/**,/feign/**- id: product-service #路由ID, ⾃定义, 唯⼀即可uri: lb://product-service #⽬标服务地址predicates: #路由条件- Path=/product/**
- 测试
七.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如何使用。
快速上手:
- 添加yml配置
- order微服务中添加过滤器参数:
- 通过网管访问后,日志中打印出userName:
GatewayFilter详细介绍官网
Default Filters
前面的filter添加在指定路由下,所以只对当前路由生效,若需要对全部路由生效,可以使用spring.cloud.gateway.default-filters 这个属性需要⼀个filter的列表。
yml配置
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
演示:
- 添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- 添加yml配置
spring:application:name: gateway # 服务名称cloud:nacos:discovery:server-addr: gateway:metrics:enabled: true
management:endpoints:web:exposure:include: "*"endpoint:health:show-details: alwaysshutdown:enabled: true
- 测试
过滤器执行顺序
一个项目中,既有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
- 写一个Custom的Config
- 自定义一个CustomGatewayFilterFactory类:
- 增加一点yml的配置:
- 测试:
**自定义GlobalFilter **
GlobalFilter的实现比较简单,它不需要额外的配置,只需要实现GlobalFilter接口,自动会过滤所有的
Filter.
定义GlobalFilter:
八.部署Gateway
- 打包
- 把打好的jar包上传云服务器
- 再通过nohup命令启动jar包