服务网关Gateway怎么玩?(服务网关kong)
ztj100 2024-10-29 18:18 11 浏览 0 评论
文章已收录到我的Github精选,欢迎Star:https://github.com/yehongzhi/learningSummary
介绍服务网关
要认识一样东西,最好的方法是从为什么需要他开始说起。
按照现在主流使用微服务架构的特点,假设现在有A、B、C三个服务,假如这三个服务都需要做一些请求过滤和权限校验,请问怎么实现?
- 每个服务自己实现一遍。
- 写在一个公共的服务,然后让A、B、C服务引入公共服务的Maven依赖。
- 使用服务网关,所有客户端请求服务网关进行请求过滤和权限校验,然后再路由转发到A、B、C服务。
第一种方式显然是逆天的,这里不做讨论。第二种方法稍微聪明点,但是如果公共服务的逻辑发生改变,那么所有依赖公共服务的服务都需要重新打包部署才能生效。
所以显而易见,使用服务网关则解决了以上的问题,其他服务不需要加入什么依赖,只需要在网关配置一些参数,然后就能路由转发到对应的后端服务,如果需要请求过滤和权限检验的话,都可以在网关层实现,如果需要更新权限校验的逻辑,只需要网关层修改就可以,其他后端服务不需要修改。
接下来再介绍一下服务网关的功能,主要有:
- 路由转发
- API监控
- 权限控制
- 限流
所以服务网关很重要!那么接下来我们就以目前比较主流的GateWay进行学习吧。
GateWay入门
首先第一步需要创建一个作为网关的项目,这里使用的SpringBoot版本是2.0.1,引入依赖:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
我们需要使用网关转发请求,那么首先需要有个后端服务,这里我简单地创建了一个user项目。然后启动user项目,写个获取所有用户信息的接口:
那么我们现在配置网关的application.yml实现请求转发。
server:
port: 9201
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: user_getList #路由的ID
uri: http://localhost:8080/user/getList #最终目标的请求地址
predicates: #断言
- Path=/user/getList #路径相匹配的进行路由
也就是说我请求http://localhost:9201/user/getList后,9201端口是网关服务,会匹配/user/getList的路由,最终转发到目标地址http://localhost:8080/user/getList。
这就算是gateway网关的简单使用了。
继续深入
在上面入门的例子中,我们注意到有个predicates的配置,有点对其似懂非懂的感觉。中文翻译过来叫做断言,有点类似于Java8的Stream流里的Predicate函数的意思。如果断言是真的,则匹配路由。
除此之外,gateway的另一个核心是Filter(过滤器),Filter有全局和局部两种。那么整个gateway的流程是怎么样的呢?请看下图:
从图中可以看出,gateway的两大核心就是断言(Predicate)和过滤(Filter),接下来我们重点讲讲这两者的使用。
Route Predicate 的使用
Spring Cloud Gateway包括许多内置的Route Predicate工厂,所以可以直接通过配置直接使用各种内置的Predicate。
After Route Predicate
在指定的时间之后请求匹配该路由。
spring:
cloud:
gateway:
routes:
- id: user_getList
uri: http://localhost:8080/user/getList
predicates:
- After=2021-10-30T01:00:00+08:00[Asia/Shanghai]
Before Route Predicate
在指定时间之前的请求会匹配该路由。
spring:
cloud:
gateway:
routes:
- id: user_getList
uri: http://localhost:8080/user/getList
predicates:
- Before=2021-10-30T02:00:00+08:00[Asia/Shanghai]
Between Route Predicate
在指定时间区间内的请求会匹配该路由。
spring:
cloud:
gateway:
routes:
- id: user_getList
uri: http://localhost:8080/user/getList
predicates:
- Between=2021-10-30T01:00:00+08:00[Asia/Shanghai],2021-10-30T02:00:00+08:00[Asia/Shanghai]
Cookie Route Predicate
带有指定Cookie的请求会匹配该路由。
spring:
cloud:
gateway:
routes:
- id: user_getList
uri: http://localhost:8080/user/getList
predicates:
- Cookie=username,yehongzhi
使用POSTMAN发送带有Cookie里username=yehongzhi的请求。
Header Route Predicate
带有指定请求头的请求会匹配该路由。
spring:
cloud:
gateway:
routes:
- id: user_getList
uri: http://localhost:8080/user/getList
predicates:
- Header=X-Id, \d+
使用POSTMAN发送请求头带有X-Id的请求。
Host Route Predicate
带有指定Host的请求会匹配该路由。
spring:
cloud:
gateway:
routes:
- id: user_getList
uri: http://localhost:8080/user/getList
predicates:
- Host=**.yehongzhi.com
使用POSTMAN发送请求头带有Host=www.yehongzhi.com的请求。
Path Route Predicate
发送指定路径的请求会匹配该路由。
spring:
cloud:
gateway:
routes:
- id: user_getList
uri: http://localhost:8080/user/getList
predicates:
- Path=/user/getList
直接在浏览器输入该地址http://localhost:9201/user/getList,即可访问。
Method Route Predicate
发送指定方法的请求会匹配该路由。
spring:
cloud:
gateway:
routes:
- id: user_getList
uri: http://localhost:8080/user/getList
predicates:
- Method=POST
用POSTMAN以POST方式发送请求。
Query Route Predicate
带指定查询参数的请求可以匹配该路由。
spring:
cloud:
gateway:
routes:
- id: user_query_byName
uri: http://localhost:8080/user/query/byName
predicates:
- Query=name
在浏览器输入http://localhost:9201/user/query/byName?name=tom地址,发送请求。
Weight Route Predicate
使用权重来路由相应请求,以下配置表示有80%的请求会被路由到localhost:8080,20%的请求会被路由到localhost:8081。
spring:
cloud:
gateway:
routes:
- id: user_1
uri: http://localhost:8080
predicates:
- Weight=group1, 8
- id: user_2
uri: http://localhost:8081
predicates:
- Weight=group1, 2
RemoteAddr Route Predicate
从指定的远程地址发起的请求可以匹配该路由。
spring:
cloud:
gateway:
routes:
- id: user_1
uri: http://localhost:8080/user/getList
predicates:
- RemoteAddr=192.168.1.4
使用浏览器请求。
组合使用
spring:
cloud:
gateway:
routes:
- id: user_1
uri: http://localhost:8080/user/getList
predicates:
- RemoteAddr=192.168.1.4
- Method=POST
- Cookie=username,yehongzhi
- Path=/user/getList
使用POSTMAN发起请求,使用POST方式,uri是/user/getList,带有Cookie,RemoteAddr。
自定义Predicate
如果我们需要自定义Predicate,怎么玩呢?其实很简单,看源码,有样学样,需要继承AbstractRoutePredicateFactory类。
下面举个例子,需求是token值为abc的则匹配路由,怎么写呢,请看代码:
@Component
public class TokenRoutePredicateFactory extends AbstractRoutePredicateFactory<TokenRoutePredicateFactory.Config> {
public static final String TOKEN_KEY = "tokenValue";
public TokenRoutePredicateFactory() {
//当前类的Config类,会利用反射创建Config并赋值,在apply传回来
super(TokenRoutePredicateFactory.Config.class);
}
@Override
public List<String> shortcutFieldOrder() {
//"tokenValue"跟Config的接收字段一致
return Arrays.asList(TOKEN_KEY);
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
//这里获取的config对象就是下面自定义的Config对象
return new Predicate<ServerWebExchange>() {
@Override
public boolean test(ServerWebExchange exchange) {
MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();
//获取请求参数
String value = params.getFirst("token");
//请求参数和配置文件定义的token进行对比,相等则返回true
return config.getTokenValue() != null && config.getTokenValue().equals(value);
}
};
}
//用来接收配置文件定义的值
public static class Config {
private String tokenValue;
public String getTokenValue() {
return tokenValue;
}
public void setTokenValue(String tokenValue) {
this.tokenValue = tokenValue;
}
}
}
这里需要注意的一点是类名必须是RoutePredicateFactory结尾,前面的则作为配置名。比如TokenRoutePredicateFactory的配置名则为Token,这是一个约定的配置。
接着在配置文件中加上该配置:
spring:
cloud:
gateway:
routes:
- id: user_1
uri: http://localhost:8080/user/getList
predicates:
- Token=abc ##使用TokenRoutePredicateFactory进行断言
然后用POSTMAN发送请求,带上token参数,参数值为abc。
如果token的值不正确的话,会报404。
整合注册中心
为什么要整合注册中心呢?因为每个服务一般背后都不只一台机器,而且一般使用服务名进行配置,而不是配置服务的IP地址,并且要实现负载均衡调用。
这里我就使用Nacos作为注册中心。
引入Maven依赖:
<dependency><!-- SpringCloud nacos服务发现的依赖 -->
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>0.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
启动类加上注解,开启注册中心。
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
在application.yml加上配置:
spring:
application:
name: api-gateway
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
service: ${spring.application.name}
gateway:
routes:
- id: consumer
uri: lb://consumer #使用lb协议,consumer是服务名,不再使用IP地址配置
order: 1
predicates:
- Path=/consumer/** #匹配/consumer/**的请求路径
server:
port: 9201
创建一个consumer也注册到nacos,并提供一个接口:
@RestController
public class ConsumerController {
@Value("${server.port}")
private String port;
@RequestMapping("consumer/getDetail/{id}")
public String getDetail(@PathVariable("id") String id) {
return "端口号:" + port + ",获取ID为:" + id + "的商品详情";
}
}
启动consumer和gateway两个项目,然后打开nacos控制台,可以看到两个服务。
连续请求地址http://localhost:9201/consumer/getDetail/1,可以看到实现了负载均衡调用服务。
可能有人会觉得每个服务都要配一个路由,很麻烦。有个很简单的配置可以解决这个问题:
spring:
gateway:
discovery:
locator:
enabled: true
然后启动服务,再试一次,请求地址需要加上服务名,依然没有问题!
写在最后
这篇文章主要介绍GateWay的路由转发功能,并且整合了注册中心。权限控制可以用过滤器实现,由于篇幅有点长,过滤器放到下一篇文章了,感谢大家的阅读。
觉得有用就点个赞吧,你的点赞是我创作的最大动力~
我是一个努力让大家记住的程序员。我们下期再见!!!
能力有限,如果有什么错误或者不当之处,请大家批评指正,一起学习交流!
相关推荐
- 从IDEA开始,迈进GO语言之门(idea got)
-
前言笔者在学习GO语言编程的时候,GO语言在国内还没有像JAVA/Php/Python那样普及,绕了不少的弯路,要开始入门学习一门编程语言,最好就先从选择一个好的编程语言的开发环境开始,有了这个开发环...
- 基于SpringBoot+MyBatis的私人影院java网上购票jsp源代码Mysql
-
本项目为前几天收费帮学妹做的一个项目,JavaEEJSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。一、项目介绍基于SpringBoot...
- 基于springboot的个人服装管理系统java网上商城jsp源代码mysql
-
本项目为前几天收费帮学妹做的一个项目,JavaEEJSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。一、项目介绍基于springboot...
- 基于springboot的美食网站Java食品销售jsp源代码Mysql
-
本项目为前几天收费帮学妹做的一个项目,JavaEEJSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。一、项目介绍基于springboot...
- 贸易管理进销存springboot云管货管账分析java jsp源代码mysql
-
本项目为前几天收费帮学妹做的一个项目,JavaEEJSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。一、项目描述贸易管理进销存spring...
- SpringBoot+VUE员工信息管理系统Java人员管理jsp源代码Mysql
-
本项目为前几天收费帮学妹做的一个项目,JavaEEJSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。一、项目介绍SpringBoot+V...
- 目前见过最牛的一个SpringBoot商城项目(附源码)还有人没用过吗
-
帮粉丝找了一个基于SpringBoot的天猫商城项目,快速部署运行,所用技术:MySQL,Druid,Log4j2,Maven,Echarts,Bootstrap...免费给大家分享出来前台演示...
- SpringBoot+Mysql实现的手机商城附带源码演示导入视频
-
今天为大家带来的是基于SpringBoot+JPA+Thymeleaf框架的手机商城管理系统,商城系统分为前台和后台、前台用的是Bootstrap框架后台用的是SpringBoot+JPA都是现在主...
- 全网首发!马士兵内部共享—1658页《Java面试突击核心讲》
-
又是一年一度的“金九银十”秋招大热门,为助力广大程序员朋友“面试造火箭”,小编今天给大家分享的便是这份马士兵内部的面试神技——1658页《Java面试突击核心讲》!...
- SpringBoot数据库操作的应用(springboot与数据库交互)
-
1.JDBC+HikariDataSource...
- SpringBoot 整合 Flink 实时同步 MySQL
-
1、需求在Flink发布SpringBoot打包的jar包能够实时同步MySQL表,做到原表进行新增、修改、删除的时候目标表都能对应同步。...
- SpringBoot + Mybatis + Shiro + mysql + redis智能平台源码分享
-
后端技术栈基于SpringBoot+Mybatis+Shiro+mysql+redis构建的智慧云智能教育平台基于数据驱动视图的理念封装element-ui,即使没有vue的使...
- Springboot+Mysql舞蹈课程在线预约系统源码附带视频运行教程
-
今天发布的是由【猿来入此】的优秀学员独立做的一个基于springboot脚手架的Springboot+Mysql舞蹈课程在线预约系统,系统项目源代码在【猿来入此】获取!https://www.yuan...
- SpringBoot+Mysql在线众筹系统源码+讲解视频+开发文档(参考论文
-
今天发布的是由【猿来入此】的优秀学员独立做的一个基于springboot脚手架的在线众筹管理系统,主要实现了普通用户在线参与众筹基本操作流程的全部功能,系统分普通用户、超级管理员等角色,除基础脚手架外...
- Docker一键部署 SpringBoot 应用的方法,贼快贼好用
-
这两天发现个Gradle插件,支持一键打包、推送Docker镜像。今天我们来讲讲这个插件,希望对大家有所帮助!GradleDockerPlugin简介...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- 从IDEA开始,迈进GO语言之门(idea got)
- 基于SpringBoot+MyBatis的私人影院java网上购票jsp源代码Mysql
- 基于springboot的个人服装管理系统java网上商城jsp源代码mysql
- 基于springboot的美食网站Java食品销售jsp源代码Mysql
- 贸易管理进销存springboot云管货管账分析java jsp源代码mysql
- SpringBoot+VUE员工信息管理系统Java人员管理jsp源代码Mysql
- 目前见过最牛的一个SpringBoot商城项目(附源码)还有人没用过吗
- SpringBoot+Mysql实现的手机商城附带源码演示导入视频
- 全网首发!马士兵内部共享—1658页《Java面试突击核心讲》
- SpringBoot数据库操作的应用(springboot与数据库交互)
- 标签列表
-
- idea eval reset (50)
- vue dispatch (70)
- update canceled (42)
- order by asc (53)
- spring gateway (67)
- 简单代码编程 贪吃蛇 (40)
- transforms.resize (33)
- redisson trylock (35)
- 卸载node (35)
- np.reshape (33)
- torch.arange (34)
- node卸载 (33)
- npm 源 (35)
- vue3 deep (35)
- win10 ssh (35)
- exceptionininitializererror (33)
- vue foreach (34)
- idea设置编码为utf8 (35)
- vue 数组添加元素 (34)
- std find (34)
- tablefield注解用途 (35)
- python str转json (34)
- java websocket客户端 (34)
- tensor.view (34)
- java jackson (34)