老张正准备下班,路太小齐的位置,发现他正在阅读Spring Cloud Gataway的官方文档。html
看了看时间,等公交车还有一下子,顺便就和小齐交流一下,便问道:“你在学习Spring Cloud网关吗?”前端
小齐听到声音后转过身来,便看到老张拉了一把椅子坐下。正好本身有一些疑惑的地方,也想找人交流学习一下。程序员
“是啊,我最近不是在学习微服务这部分知识吗,如今学到网关这部分了。其实我不是特别明白,为何咱们的微服务须要网关呢?”web
老张神秘一笑,说道:“我给你看两张图你就明白了。”而后在小齐的电脑上搜出了这篇文章里面的两张图。面试
“咱们假设你如今要作一个电商应用,前端是移动端的APP,后端是各类微服务。那你可能某个页面须要调用多个服务的数据来展现。若是没有网关,你的系统看起来就是这个样子的:”spring
“而若是加上了网关,你的系统就会变成这个样子:”编程
“嗯,这看起来是一个‘高内聚,低耦合’的思想,若是不使用网关,可能有什么坏处呢?”小齐问道。后端
“这个其实从刚刚的第一张图你就看得出来,若是没有网关,你的客户端就会变得很是麻烦。对每个微服务,可能都要作权限认证、负载均衡等工做;并且后端的微服务可能还使用了不一样的消息通讯协议;最重要的是,若是你想对微服务进行重构,好比拆分或者合并为服务器,那也必须得修改客户端,增长了复杂性。”跨域
小齐:“那看来网关确实是相当重要,如今市面上有哪些微服务网关呢?”缓存
“咱们在实现网关的时候,须要考虑到的是它的性能和可扩展性。对于现成的产品来讲,NGINX Plus是一个很不错的选择,NGINX Plus 提供了一个成熟的、可扩展的、高性能 web 服务器和一个易于部署的、可配置可编程的反向代理。NGINX Plus 能够管理身份验证、访问控制、负载均衡请求、缓存响应,并提供应用程序可感知的健康检查和监控。除此以外,你还可使用Node.js或者Netty根据本身的需求去本身写一个网关。并且Spring Cloud也提供了一些已经写好的微服务网关框架,你知道有哪些吗?”
“我查了一下,好像Spring Cloud Gataway和Netflix的Zuul都挺不错的。但Netflix的套件暂停开发了,因此我如今主要在看Spring Cloud Gateway。”
老张点点头,道:“是的,Netflix不少组件到中止开发了。前两天咱们讨论的Hystrix也是,可是Hystrix的替代产品还在孵化中。但网关方面,Spring Cloud Gateway已经孵化完成了,能够用来替代Zuul。那你知道Spring Cloud Gateway的原理吗?”
小齐把刚刚本身正在看的官方文档打开,而后给老张看了官网文档的这个图,一边说道:“Spring Cloud Gateway是基于Spring Boot 2.0, Spring WebFlux, Reactor项目构建的,底层是Netty。它的流程其实和Zuul很类似,使用一系列的过滤器去处理请求,达到咱们本身想要的定制化。”
老张问:“那里刚刚看完了官方文档,能够跟我总结一下它有哪些功能吗?”
“Spring Cloud Gateway几乎能够知足绝大多数网关的需求。它主要有下面一些功能:”
断言能够指定「在什么状况下」能够匹配某个路由。断言是基于Java 8提供的Predicate
接口。Gateway(如下简称Spring Cloud Gateway为Gateway)提供了一些默认的断言。你能够在官方文档查看具体有哪些断言以及它们的用法。
支持时间、Cookie、Header、Host、HTTP Method、相对路径、URL查询语句、远程IP等来作断言。好比:
spring: cloud: gateway: routes: - id: method_route uri: https://example.org predicates: - Method=GET 复制代码
Gateway也提供了一些已经写好的过滤器。能够查看官方文档。主要有重写request或者response的header、parameter、body、session、安全、重写路径、重试以及对熔断的一些支持。
全局过滤器与网关过滤器相似,只是默认会给全部的请求都添加上全局过滤器。固然,也能够本身定义全局过滤器。过滤器的顺序能够经过@Order
注解来指定:
@Bean @Order(-1) public GlobalFilter a() { return (exchange, chain) -> { log.info("first pre filter"); return chain.filter(exchange).then(Mono.fromRunnable(() -> { log.info("third post filter"); })); }; } @Bean @Order(0) public GlobalFilter b() { return (exchange, chain) -> { log.info("second pre filter"); return chain.filter(exchange).then(Mono.fromRunnable(() -> { log.info("second post filter"); })); }; } @Bean @Order(1) public GlobalFilter c() { return (exchange, chain) -> { log.info("third pre filter"); return chain.filter(exchange).then(Mono.fromRunnable(() -> { log.info("first post filter"); })); }; } 复制代码
Gateway还提供了其它不少功能,好比说SSL方面的配置、基于netty的access log、跨域、actuator端点等等。具体的用法能够参考官方文档。
尤为是actuator端点,它可让咱们使用HTTP请求去动态地获取、新增、删除路由。具体的使用方法和参数查看官方文档。
除此之外,Gateway提供了一些接口和抽象类。用户还能够本身定制化断言、Filter、路由等,实现更个性化的要求。参考文档在这里,可是目前文档还不完善,能够本身看看源码。
老张:“嗯,上面基本上把Spring Cloud Gateway的功能总结全了。它还能够与Spring Cloud的注册中心无缝集成。”
小齐接着老张的话,说道:“是的,Gateway能够很方便地与注册中心配合起来使用,默认使用Ribbon实现了负载均衡。你只须要加入某个注册中心的依赖,好比consul-discovery,而后把配置打开就好了:”
spring.cloud.gateway.discovery.locator.enabled=true 复制代码
“这样你就能够请求Gataway的/service-id/path
来访问服务名叫service-id
的某个微服务的/path
路径了。好比:”
❝http://gateway:8080/service-user/hello
->
http://service-user:8080/hello
❞
也能够对某个微服务作个性化的配置,参考文档。
说完后,小齐问道:“那全部微服务就只有一个网关,万一并发量上去了,网关承受不住怎么办?”
老张笑道:“正如你上面所说,Spring Cloud Gateway底层是Netty的,它自己就能承受比较大的并发。若是仍是承受不了并发量,那能够注册多个Gateway实例,而后在前面弄一个Nginx或者F5等负载均衡器。大概图是这样:”
老张看了看时间,差很少该去赶车了。“今天就到这吧,下次再交流~”
微信公众号:编了个程
我的网站:https://yasinshaw.com
笔名Yasin,一个有深度,有态度,有温度的程序员。工做之余分享编程技术和生活,若是喜欢个人文章,能够顺手「关注」一下公众号,也欢迎「转发」分享给你的朋友~
在公众号回复“面试”或者“学习”能够领取相应的资源哦~