Spring Cloud构建微服务架构(五)服务网关

由于Zuul 2.x的不断跳票,Spring Cloud自行研发了另外一款服务网关产品:Spring Cloud Gateway,并且在最新版本中推荐使用,所以Gateway出现的原因就是为了代替Zuul。相比Zuul,Gateway是Spring体系内的产物,和Spring融合更好。同时相比于Zuul 1.x的阻塞和多线程方式,Gateway采用了Netty异步非阻塞模型,占用资源更小,性能更有优势。同时增加了Predicate和限流等功能。

1 传统路由方式

创建一个Spring Boot项目,命名为api-gateway。

1.1 pom.xml

<?xml version="1.0" encoding="UTF-8"?>4.0.0org.springframework.bootspring-boot-starter-parent2.1.7.RELEASE<!-- lookup parent from repository -->com.hysapi-gateway0.0.1-SNAPSHOTapi-gatewayDemo project for Spring Cloud 1.8Greenwich.SR2 org.springframework.cloudspring-cloud-starter-gatewayorg.springframework.bootspring-boot-starter-testtest org.springframework.cloudspring-cloud-dependencies${spring-cloud.version}pomimport org.springframework.bootspring-boot-maven-plugin

1.2 启动类

packagecom.hys.apigateway; importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplicationpublicclassApiGatewayApplication{ publicstaticvoidmain(String[] args){        SpringApplication.run(ApiGatewayApplication.class, args);    } }

1.3 路由方式

Gateway的路由方式有两种,分别为编码方式和配置方式。

1.3.1 编码方式

在上面的启动类中加入下面的自定义RouteLocator的方法即可:

@BeanpublicRouteLocatorcustomRouteLocator(RouteLocatorBuilder builder){returnbuilder.routes().route("route_a", r -> r.path("/hello").uri("http://localhost:8081/"))                .build();    }

1.3.2 配置方式

将上面自定义RouteLocator的方法注释掉,在application.properties文件中输入下面的内容:

spring.application.name=api-gatewayserver.port=5555spring.cloud.gateway.routes[0].id=route_aspring.cloud.gateway.routes[0].uri=http://localhost:8081/spring.cloud.gateway.routes[0].predicates[0]=Path=/hello

其中后三行的内容和上述编码配置的方式实现的效果是一样的。

1.4 运行及结果

这里采用配置文件的方式来运行,确保之前搭建的eureka-server、hello-service和feign-consumer项目都运行起来,启动本项目,页面输入http://localhost:5555/hello,结果如下所示:

访问http://localhost:5555/hello会被自动路由到http://localhost:8081/hello,这样就验证了路由转发的成功。

2 面向服务的方式

显而易见的是,传统路由的配置方式比较繁琐,如果路由特别多的情况下,维护起来会很麻烦。为此,可以将Gateway与Eureka整合起来,这样不用再写具体的url映射,url交给Eureka的服务发现机制去自动维护。

2.1 pom.xml

pom沿用上面的配置,只需要再加入下面的Eureka依赖即可:

org.springframework.cloudspring-cloud-starter-netflix-eureka-client

2.2 application.properties

spring.application.name=api-gatewayserver.port=5555spring.cloud.gateway.discovery.locator.enabled=truespring.cloud.gateway.discovery.locator.lowerCaseServiceId=trueeureka.client.service-url.defaultZone=http://peer1:1111/eureka/,http://peer2:1112/eureka/,http://peer3:1113/eureka/

其中spring.cloud.gateway.discovery.locator.enabled设置为true表示开启通过注册中心进行路由转发的功能,spring.cloud.gateway.discovery.locator.lowerCaseServiceId设置为true表示通过小写形式来访问服务名称。

2.3 运行及结果

重启本项目,页面分别访问http://localhost:5555/feign-consumer/feign-consumer、http://localhost:5555/feign-consumer/feign-consumer2和http://localhost:5555/feign-consumer/feign-consumer3,结果如下所示:

可以看到,和之前通过OpenFeign的消费者访问的结果是一样的,路由转发是成功的。

3 Predicate和Filter

Predicate和Filter是Gateway中的核心,Predicate是选择哪些请求需要处理,而Filter给选择出来的请求做一些改动,比如参数处理和安全校验等等。

3.1 Predicate

新建一个Spring Boot项目,命名为test-gateway,pom文件依赖和上述第1.1节中的pom依赖一致。这里我们用Postman来查看运行结果。

3.1.1 时间匹配

spring.application.name=gateway-testserver.port=5556spring.cloud.gateway.routes[0].id=route_testspring.cloud.gateway.routes[0].uri=https://www.baidu.com/spring.cloud.gateway.routes[0].predicates[0]=After=2019-08-12T12:00:00+08:00[Asia/Shanghai]

上述After表示在2019年8月12日12点之后的请求可以被路由,而Before代表在指定时间之前可以被路由,Between则代表在指定的时间区隔之内可以被路由:

After=2019-08-12T12:00:00+08:00[Asia/Shanghai]Before=2019-08-12T12:00:00+08:00[Asia/Shanghai]Between=2019-08-12T12:00:00+08:00[Asia/Shanghai],2019-08-13T12:00:00+08:00[Asia/Shanghai]

3.1.2 请求方式匹配

spring.application.name=gateway-testserver.port=5556spring.cloud.gateway.routes[0].id=route_testspring.cloud.gateway.routes[0].uri=https://www.baidu.com/spring.cloud.gateway.routes[0].predicates[0]=Method=GET

上述表示只有GET请求才能被成功路由,访问Postman得到如下结果:

状态码为200,说明成功访问,这时我们改成POST请求,再来访问:

状态码为404,说明访问失败。

3.1.3 请求路径匹配

spring.application.name=gateway-testserver.port=5556spring.cloud.gateway.routes[0].id=route_testspring.cloud.gateway.routes[0].uri=https://www.baidu.com/spring.cloud.gateway.routes[0].predicates[0]=Path=/foo/{segment}

由上配置了匹配的请求路径,Postman访问http://localhost:5556/foo/1,访问成功:

访问http://localhost:5556/foo/1/2,访问失败:

3.1.4 请求参数匹配

spring.application.name=gateway-testserver.port=5556spring.cloud.gateway.routes[0].id=route_testspring.cloud.gateway.routes[0].uri=https://www.baidu.com/spring.cloud.gateway.routes[0].predicates[0]=Query=p1

上述配置了请求参数中必须含有p1参数才能路由成功,Postman访问http://localhost:5556/?p1=1,路由成功:

访问http://localhost:5556/?p2=2,路由失败:

Query的值还可以使用正则表达式来进行匹配,如下面的例子:

spring.application.name=gateway-testserver.port=5556spring.cloud.gateway.routes[0].id=route_testspring.cloud.gateway.routes[0].uri=https://www.baidu.com/spring.cloud.gateway.routes[0].predicates[0]=Query=p1,1.

上面配置了参数中的键必须含有p1,同时它所对应的值是以1开头的两个字符,Postman访问http://localhost:5556/?p1=1s,路由成功:

Postman访问http://localhost:5556/?p1=1,路由失败:

3.2 Filter

这里只演示AddRequestParameter的用法,更多的用法详见Spring官网。

AddRequestParameter是在请求的路径中添加相应的参数,我们继续使用上述的api-gateway项目。

3.2.1 hello-service

首先需要对之前的hello-service项目做些更改,在其中的HelloController中添加一个foo方法如下所示:

@RequestMapping("/foo")publicStringfoo(Stringfoo) {returnfoo;    }

3.2.2 feign-consumer

然后在feign-consumer项目中的ConsumerController中添加下面的方法:

@RequestMapping("/foo")publicStringfoo(Stringfoo) {returnhelloService.foo(foo);    }

在IHelloService中添加下面的方法:

@RequestMapping("/foo")Stringfoo(@RequestParam("foo")Stringfoo);

在相应的HelloServiceImplFallback降级类中填入下面的降级方法:

@OverridepublicStringfoo(Stringfoo) {return"访问超时,请重新再试!";    }

3.2.3 application.properties

api-gateway网关的配置文件需要做些修改:

spring.application.name=api-gatewayserver.port=5555spring.cloud.gateway.discovery.locator.enabled=truespring.cloud.gateway.discovery.locator.lower-case-service-id=truespring.cloud.gateway.routes[0].id=add_request_parameter_routespring.cloud.gateway.routes[0].uri=lb://hello-servicespring.cloud.gateway.routes[0].predicates[0]=Method=GETspring.cloud.gateway.routes[0].filters[0]=AddRequestParameter=foo, bareureka.client.service-url.defaultZone=http://peer2:1112/eureka/,http://peer3:1113/eureka/

其中,uri表示配置路由转发到hello-service的服务提供者。filters表示给匹配的请求中添加了一个foo=bar的参数。需要注意的是,filters必须和predicates联用,否则项目启动会失败。

3.2.4 运行及结果

随后分别启动eureka-server、hello-service和feign-consumer项目,然后启动api-gateway网关项目,首先页面访问http://localhost:9001/foo,以OpenFeign消费者的方式来访问服务:

由上可以看到,当没有使用网关来访问服务的时候,页面上没有结果,也就是说服务提供者没有接收到foo参数。然后我们访问http://localhost:5555/foo,以网关的方式来访问服务:

以上可知,页面上显示了bar,foo参数被成功接收,在请求中会添加一个foo=bar的参数。

参考:http://blog.didispace.com/springcloud2/https://blog.csdn.net/weixin_30342639/article/details/99303710

https://mp.weixin.qq.com/s/WAQkqRAYo50ddRp5CbGuvw

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,776评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,527评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,361评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,430评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,511评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,544评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,561评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,315评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,763评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,070评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,235评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,911评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,554评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,173评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,424评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,106评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,103评论 2 352

推荐阅读更多精彩内容