在开篇springcloud微服务架构-CSDN博客中,对网关进行了功能的说明,下面将按照其核心功能进行逐一的实现。
本篇将讲解建立一个gateway项目,微服务注册到nacos中。实现用gateway动态实现路由功能。
Client ----> gateway ----> Ribbion负载均衡 取一个服务A ---->转发到服务A
划重点:服务注册-nacos,gateway也是微服务。
功能实现包括:路由服务、鉴权与加密、日志服务、负载均衡、限流熔断。?
这里为了演示效果,我们分别建立服务a,服务b,网关注册到nacos。
网上关于maven项目有多,这里我以grdle构建的项目为例进行讲解。
idea新版用spring初始时不支持jdk8,所以我用start.aliyun.com来初始化。
初始化完成后,build.gradle文件修改repositories,增加阿里镜像url,以解决下载插件慢的问题。
repositories { mavenLocal() maven { url 'https://maven.aliyun.com/repository/central' } maven { url 'https://maven.aliyun.com/repository/public' } maven { url 'https://maven.aliyun.com/repository/spring' } maven { url 'https://maven.aliyun.com/repository/spring-plugin' } maven { url 'https://repo.spring.io/release' } mavenCentral() }
如果下载gradle-7.5.1的包慢的话,可以改为最新的8.1.1版。?
等待gradle下载完所有依赖插件后,启动项目成功就完了一个初始项目的建立。
添加完后的完整的dependencies配置如下:
dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' // alibaba-nacos-discovery 服务注册依赖 implementation 'com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-discovery:2021.0.1.0' // starter-alibaba-nacos-config 读取nacos配置的依赖。如果不需要配置中心可以不添加 // implementation 'com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-config:2021.0.1.0' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' }
完整文件如下:
resource目录下默认是application.properties,请自行创建(application.yml或application.yaml)
不同的后缀都可以的,需注意不同的后缀采用不同的格式
(加载优先级properties>yml>yaml,后加载的覆盖同名的先加载的配置)
spring: application: name: servies-a cloud: nacos: discovery: server-addr: 192.168.189.3:8849 username: nacos password: nacos namespace: 4ddd4368-c3ed-45fd-8d7b-e28f9661498d
?配置完成后,重启项目,会看到控制台进行了nacos的注册
nacos registry, DEFAULT_GROUP servies-a 192.168.2.6:8080 register finished
4)nacos后台查看服务列表
5)编写一个用于查看应用名称的接口。
?通过enviroment返回配置属性,获得spring.application.name.
新建gateway项目和上面的普通微服务差不多。区别在于不要勾选spring-web。
初始化项目以后,参照上面的项目修改repositories和修改grdle版本。
然后,我们添加gateway依赖:
核心是:implementation 'org.springframework.cloud:spring-cloud-starter-gateway',
需要指定spring-cloud-dependencies版本在2021.0.0及上版本。
dependencies { implementation 'org.springframework.boot:spring-boot-starter' implementation 'org.springframework.cloud:spring-cloud-starter-gateway' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' } ext { set('springCloudVersion', "2021.0.6") } dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" } }
启动项目,运行如下:?
将gateway项目注册到nacos。?
添加依赖:
implementation 'com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-discovery:2021.0.1.0'
application中设置nacos地址和服务名称:
spring: application: name: gateway cloud: nacos: discovery: server-addr: 192.168.189.3:8849 username: nacos password: nacos namespace: 4ddd4368-c3ed-45fd-8d7b-e28f9661498d
我们在nacos后台查看服务:
?
到这,我们gateway项目的新项目注册到nacos就算成功了。
在application文件中配置(网关的端口为22060):
spring: application: name: gateway cloud: nacos: discovery: server-addr: 192.168.189.3:8849 username: nacos password: nacos namespace: 4ddd4368-c3ed-45fd-8d7b-e28f9661498d gateway: routes: # 下面的路由是配合nacos的注册,实现自动地址 - id: service-a # 全局唯一,不能重复 uri: http://192.168.189.3:8080 # 表示将服务名ip路由指向这个url地址 predicates: - Path=/se-a/** # 表示将匹配路径为se-a开头的请求 filters: #这个必须写 - StripPrefix=1 # 请求/se-a/home/get,会把/se-a这一级去掉,最后转发到目标服务的路径为/home/get server: port: 22060
由于各微服务都是单独开发,部署,所以网关并不知道各微服务的实际地址。即然我们用了nacos,这个就交由微服务中心来管理了。
Gateway有两种客户端负载均衡器,LoadBalancerClientFilter
和ReactiveLoadBalancerClientFilter。
所以,我们可以loadbalancer来解决这个问题,先引用依赖:
implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-loadbalancer', version: '4.1.0'
然后,application.yaml中配置服务:
gateway: routes: # 下面的路由是配合nacos的注册,实现自动地址 - id: service-a # 全局唯一,不能重复 uri: http://192.168.189.3:8080 # 表示将服务名ip路由指向这个url地址 predicates: - Path=/se-a/** # 表示将匹配路径为se-a开头的请求 filters: #这个必须写 - StripPrefix=1 # 请求/se-a/home/get,会把/se-a这一级去掉,最后转发到目标服务的路径为/home/get - id: service-b uri: lb://service-b # lb:服务名称。表示调用nacos注册的服务名称为service-b的服务 predicates: - Path=/se-b/** filters: #这个必须写 - StripPrefix=1 # 请求/openapi/home/get,会把/open这一级去掉,最后转发到目标服务的路径为/home/get # - JwtAuthFilter
这样,我们就可以访问这个se-b服务了:
?官网介绍流程如下:
核心点:
Route(路由):路由是构建网关的基础模块儿,它由ID,目标URI,包括一系列的断言和过滤器组成,如果断言为True则匹配该路由。
Predicate(断言):开发人员可以匹配http请求中的所有内容(如:请求头或请求参数),请求与断言匹配则进行路由。
Filter(过滤):指Spring框架中GatewayFilter的实例,使用过滤器可以在请求被路由前或者之后对请求进行修改。
除此之外,还有用springboot本身的过滤器、拦截器,全局过滤器等进行更加个性化的设置。
总结:路由断言 + 过滤器链
学习文档地址:
官网(英文):Spring Cloud Gateway
中文:Spring Cloud Gateway 中文文档 (springdoc.cn)?
?? ? id: ?路由的ID
?? ? uri: 匹配路由的转发地址
?? ? predicates: ?配置该路由的断言,通过PredicateDefinition类进行接收配置。
?? ? order: ?路由的优先级,数字越小,优先级越高。
?? ? Filter: 过滤器 过滤掉一些请求, 满足则转发
?
Predicate 来源于Java8,接受输入参数,返回一个布尔值结果
? ?Spring Cloud Gateway 中 Spring 利用 Predicate 的特性实现了各种路由匹配规则
? ?转发的判断条件.
? ?SpringCloud Gateway支持多种方式,常见如:Path、Query、Method、Header等
? ?支持多个Predicate请求的转发是必须满足所有的Predicate后才可以进行路由转发
?
?官方自带了很多实用的断言,参见:Spring Cloud Gatewayhttps://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories
?
举例:
spring:
cloud:
gateway:
routes:
- id: after_route
uri: lb://service-a
predicates:
- Cookie=mycookie,mycookievalue
spring:
cloud:
gateway:
routes:
- id: after_route
uri: lb://service-a
predicates:
- name: Cookie
args:
name: mycookie
regexp: mycookievalue
spring:
cloud:
gateway:
routes:
- id: weight_high
uri: lb://service-a
predicates:
- Weight=group1, 8
- id: weight_low
uri: lb://service-a
predicates:
- Weight=group1, 2
Spring Cloud Gateway 包括许多内置的?GatewayFilter
?工厂。
具体的使用请见上述学习文档的,说得比较详细,有用例和说明,比如:
Forwarded
?Headers Filter 创建一个?Forwarded
?header来发送给下游服务。它将当前请求的?Host
?header、scheme和port添加到任何现有的?Forwarded
?头中。
GlobalFilter
?接口的签名与?GatewayFilter
?相同。这些是特殊的过滤器,有条件地应用于所有路由
?
由于gateway的内容过多,不得不分篇来介绍。这篇仅讲到路由的动态转发。下篇将继续介绍gateway中的鉴权实现。