SpringCloud|SpringCloud Gateway的基本入门和注意点详解
目录
- 1.gateway和zuul
- 2.使用gateway的路由功能
- 1. 搭载springcloud gateway
- 2.简单使用gateway
- 1.application配置
1.gateway和zuul Spring Cloud Finchley版本的gateway比zuul 1.x系列的性能和功能整体要好,且使用 Gateway 做跨域相比应用本身或是 Nginx 的好处是规则可以配置的更加灵活.
这两者相同的地方就是都是作为网关,处理前段的请求,可以进行路由到对应的服务或者url,也可以针对权限做过滤处理,也可以对其他服务响应的结果做处理
截至目前SpringCloud gateway最新版本是2.1.0 RC3,可见官方网站SpringCloud gateway,每个版本增加的功能都比较多,改动的地方也比较多,前几个版本有比较坑的地方,建议使用最新版本
2.使用gateway的路由功能
1. 搭载springcloud gateway
准备一个spring cloud工程,包括eureka-server注册中心,service-client服务提供者,端口8090
service-client提供一个接口:
@RestController@Slf4jpublic class ProducerController {@RequestMapping("/hi")public String hi(@RequestParam String name) {log.info("[client服务] [hi方法]收到请求"); return "hi " + name + ",i am from service-client"; }}
【SpringCloud|SpringCloud Gateway的基本入门和注意点详解】再建一个spring cloud工程,service-gateway网关,端口8088
pom的依赖:
org.springframework.boot spring-boot-starter-parent2.0.4.RELEASE UTF-8UTF-8 1.8 org.springframework.cloud spring-cloud-starter-gatewayorg.springframework.cloud spring-cloud-starter-netflix-eureka-client
application启动类:
package com.zgd.springcloud.gateway; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; /** * service-gateway 客户端 * @author zgd */@EnableEurekaClient@SpringBootApplicationpublic class App {public static void main(String[] args) {SpringApplication.run(App.class, args); }}
这样基本的框架就搭好了,先启动eureka-server注册中心,再启动service-client和service-gateway
直接调用 localhost:8090/hi?name=zgd,可以收到
hi zgd,i am from service-client
2.简单使用gateway
GateWay大体可以分为路由工厂Route Predicate Factories,网关过滤器工厂GatewayFilter Factories,全局过滤器工厂Global Filters处理请求。
对于路由转发,Spring Cloud gateway内置了很多校验条件谓语(predicate)来实现路由功能。
比如
- 根据时间来路由: After Route Predicate Factory某个时间点之后请求路由,Before Route Predicate Factory某个时间点之前请求路由,Between Route Predicate Factory两者时间之间
- 通过请求路径来路由: Path Route Predicate Factory
- 根据请求头来路由
- 根据cookie来路由
- 根据域名来路由
文章图片
有两种方式配置,一种是配置文件application的方式,一种是代码配置
1.application配置 a. 路由到其他地址
spring:cloud:gateway:#可以根据请求参数,cookie,host,请求时间,请求头等进行校验判断路由, 下面根据先后顺序转发routes:- id: host_routeuri: http://httpbin.org:80/getpredicates:- Path=/zzzgd/** # 请求地址携带zzzgd的,则转发
在spring.cloud.gateway.routes中,我们可以根据不同的谓语配置不同的路由,根据配置的先后顺序来跳转,越在前面优先级越高.
其中id,区分不同的路由规则,不可重复,uri,指需要跳转的地址,Predicates就是上面说的谓语了,可以配置多个,使用正则匹配. 这里我们配置的是如果请求地址携带zzzgd则会跳转到我们配置的uri
配置好gateway,重新启动,然后我们调用localhost:8088(网关的地址和端口)/zzzgd/abc,这个地址是没有任何匹配的接口的,按理来说会返回404,但是配置了网关就返回了这些信息,这个是我们配置的uri所返回的:
{"args": {"name": "zgd"}, "headers": {"Accept": "text/html,application/xhtml+xml,application/xml; q=0.9,image/webp,image/apng,*/*; q=0.8", "Accept-Encoding": "gzip, deflate, br", "Accept-Language": "zh-CN,zh; q=0.9", "Connection": "close", "Cookie": "SL_G_WPT_TO=zh; SL_GWPT_Show_Hide_tmp=undefined; SL_wptGlobTipTmp=undefined", "Forwarded": "proto=http; host=\"localhost:8088\"; for=\"0:0:0:0:0:0:0:1:55782\"", "Host": "httpbin.org", "Upgrade-Insecure-Requests": "1", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36", "X-Forwarded-Host": "localhost:8088"}, "origin": "0:0:0:0:0:0:0:1, 119.147.213.42", "url": "http://localhost:8088/get?name=zgd"}
上面的是根据地址来路由,还有下面多种路由配置:
根据域名来转发路由:
routes: - id: host_routeuri: http://httpbin.org:80/getpredicates:- Host=**.csdn.** # 请求域名携带csdn的,则转发 - id: query_routeuri: http://httpbin.org:80/getpredicates:- Query=username, zzz* # 请求参数含有username,且值满足zzz开头的,则转发(对值的匹配可以省略) - id: header_routeuri: http://httpbin.org:80/getpredicates:- Header=request, \d+ # 如果请求头含有request,且为数字,则转发 - id: cookie_routeuri: http://httpbin.org:80/getpredicates:- Cookie=name, zzzgd # 如果携带cookie,参数名为name,值为zzzgd,则转发- id: path_routeuri: http://httpbin.org:80/getpredicates:- Path=/zzzgd/** # 请求地址携带zzzgd的,则转发# 路由到其他服务,url需要用[lb://]+[serviceId]- id: service_clienturi: lb://service-clientpredicates:- Path=/to_client/** # 如果请求地址满足/to_client/**,则转发到 service-client 服务filters:- StripPrefix=1 # 去除请求地址中的to_client- id: after_routeuri: http://httpbin.org:80/getpredicates:- After=2019-01-01T17:42:47.789-07:00[America/Denver] # 如果请求时间大于该时间,则转发
b. 根据服务名路由到其他服务
我们知道,zuul是可以根据服务在eureka的serviceId,来将请求路由到不同的服务上,这也是网关最大的作用之一,gateway也可以
gateway可以通过开启以下配置来打开根据服务的serviceId来匹配路由,默认是大写:
# 配置gateway路由spring:cloud:gateway:discovery:locator:# 是否可以通过其他服务的serviceId来转发到具体的服务实例。默认为false# 为true,自动创建路由,路由访问方式:http://Gateway_HOST:Gateway_PORT/大写的serviceId/**,其中微服务应用名默认大写访问enabled: true
开启配置,重启gateway,访问 localhost:8088/SERVICE-CLIENT/hi?name=zgd,
正常返回了service-client的结果.
如果需要小写serviceId,则配置spring.cloud.gateway.locator.lowerCaseServiceId:true
注意事项
不管小写大写,不能使用下划线,否则会报:
org.springframework.cloud.gateway.support.NotFoundException: Unable to find instance for localhost所以服务的spring.application.name 必须用中划线而不是下划线
如果开启了lowerCaseServiceId,则只能用小写,不能识别大写,如果不开启,只能识别大写
除了上面这种自动设置路由服务,也可以手动设置,在routes中配置
这里使用的是gateway的其中一个过滤器工厂,去除请求地址前缀的过滤器
# 路由到其他服务,url需要用[lb://]+[serviceId]- id: service_clienturi: lb://service-clientpredicates:- Path=/to_client/** # 如果请求地址满足/to_client/**,则转发到 service-client 服务filters:- StripPrefix=1 # 去除请求地址中的to_client
这里的uri不是一个具体的地址了,而是lb://开头,加上serviceId
然后比如上面这个配置,我们 再调用 localhost:8088/to_client/hi?name=zgd
可以看到也正常收到了service-client的返回.说明我们调用到了这个服务.
这里需要注意的一点,如果不加上filters.- StripPrefix=1,那么则无法请求到hi这个接口。因为这个to_client相当于是服务名,只是为了网关的路由加上去的,对于服务提供者service-client来说,不需要这段地址,所以需要去掉
还有其他的predicate,可以参考官方文档
过滤
这个filters也是gateway的一个重要功能,过滤.
gateway内置的过滤器工厂有下面这些:
文章图片
除了上面用到的
- 路径前缀去除过滤器,还有
- 添加请求参数过滤器
- 添加请求头过滤器
- 添加响应头过滤器
- 移除响应头过滤器
可以参考官方文档
举个例子,我们将application配置如下:
spring:cloud:gateway:routes:- id: query_routeuri: http://httpbin.org:80/getpredicates:- Query=username, zzz* # 请求参数含有username,且值满足zzz开头的,则转发(对值的匹配可以省略)filters:- AddRequestHeader=X-Request-Foo, Bar- AddRequestParameter=age, 18
请求 localhost:8088/?username=zzzzzzz
它返回了它所受到的请求,将会看到返回数据中已经添加了一个age=18的请求参数,且请求头也多了X-Request-Foo=Bar
b.代码配置
为了方便在java开发,gateway也提供了代码的方式配置,比如我们注释掉上面的application配置,然后建一个配置类
/** * @Author: zgd * @Date: 2019/1/8 19:09 * @Description: */@Configurationpublic class GateWayConfig {@Beanpublic RouteLocator routeLocator(RouteLocatorBuilder builder) {return builder.routes().route(r -> r.path("/fluent/**").and().query("name").uri("http://httpbin.org:80/get")).build(); }}
启动,访问
http://localhost:8088/fluent/1/?name=bb成功!
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
推荐阅读
- 热闹中的孤独
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 放屁有这三个特征的,请注意啦!这说明你的身体毒素太多
- 一个人的旅行,三亚
- 布丽吉特,人生绝对的赢家
- 慢慢的美丽
- 尽力
- 一个小故事,我的思考。
- 家乡的那条小河
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量