Gateway导航

简介

最近都在弄微服务的东西,现在来记录下收获。我从一知半解到现在能从0搭建使用最大的感触有两点

1.微服务各大组件的版本很多,网上很多博客内容不一定适合你的版本,很多时候苦苦琢磨都是无用功

2.网上博客参差不齐,有些甚至错误的。更离谱的是,好的文章阅读量除非高出天际,不然就都很低,比那些复制粘贴,随便应付的都低(这个搜索推荐算法不知道基于什么的)

通过这段时间学习,我觉得最重要是从好的博客入手,先不要着急怎么组件怎么使用,而是先了解组件的作用,大概的原理,然后才是使用,这样搭建和尝试的过程中才能更好的定位问题,最后再次回到原理和一些实际问题的处理(不知道实际问题怎样的,直接搜那个组件的面试题往往效果最好)

接下来的内容,都以导航的形式展现给大家(毕竟优秀的轮子很多,直接看大佬写的不香嘛),再顺带提些自己的理解

传送门

更多微服务的介绍可点击下方链接

微服务介绍Nginx导航Nacos导航Gateway导航Ribbon导航Feign导航Sentinel导航

博主微服务git练手项目:https://github.com/NiceJason/SpringCloudDemo

Gateway简介

SpringCloudGateway的简介:http://www.ityouknow.com/springcloud/2018/12/12/spring-cloud-gateway-start.html

Gateway主要由:路由(Route)、断言(Predicate)和过滤器(Filter)3个部分组成

1个路由可以由多个断言和多个过滤器共同组成,而组件自身为我们准备了很多断言可以直接使用,具体看简介

自定义过滤器如何实现:https://blog.csdn.net/forezp/article/details/85057268

这里提个坑:

全网网关拦截器若想要生效,以下条件之一需要符合
1.当前网关必须配置其他非全网拦截器(还真的很神奇)
2.全网网关拦截器必须实现Ordered接口

自定义断言如何实现:https://blog.csdn.net/qq_29064815/article/details/107236161

下面说些不一样的

1.Gateway不依赖Web

       Spring Cloud Gateway 是使用 netty+webflux实现,webflux与web是冲突的。所以Maven依赖不能用Web相关的内容,这句话说的很简单,但是做起来却不容易。特别是Maven依赖混乱的项目更难抽离,例如公共服务里包含了Web依赖,那么你的Gateway服务就不能引用公共服务了,这样会导致Gateway服务需要自身拷贝一份公共服务的代码,所以好的Maven模块化依赖是很重要的。

Springboot十分方便,但又不能直接引用,但是不引用第三方组件没准又有问题,可以在父类做如下引用

 1 <dependencyManagement>
 2     <dependencies> 
 3         <dependency>
 4                 <groupId>org.springframework.boot</groupId>
 5                 <artifactId>spring-boot-dependencies</artifactId>
 6                 <version>${spring-boot.version}</version>
 7                 <type>pom</type>
 8                 <scope>import</scope>
 9         </dependency>
10      </dependencies>
11 </dependencyManagement>

2.不要在Gateway做复杂的逻辑

       首先要知道,网关的作用只有一个,那就是这个请求到底是放行还是拒绝,所以不要在这里做复杂的操作,对于http请求最好做到只读,通过读取的内容就能完成逻辑,而不需要往请求里增删改一些东西(如Cookie,body参数等等),因为这操作是很困难的,而且即使成功了没准也问题多多(项目里就试过操作Session导致Set-Cookie变成小写,微信浏览器识别不了而导致错误)

 1 @Component
 2 public class MsgGatewayFilterFactory extends AbstractGatewayFilterFactory {
 3 
 4     /**
 5      * Cookie里是否有token
 6      * 如果没有则拒绝请求
 7      * @param config
 8      * @return
 9      */
10     @Override
11     public GatewayFilter apply(Object config) {
12         return ((exchange, chain) -> {
13             System.out.println("进入MsgGatewayFilterFactory");
14             ServerHttpRequest serverRequest = exchange.getRequest();
15             HttpCookie tokenCookie = serverRequest.getCookies().getFirst("token");
16             if(tokenCookie ==null || StringUtils.isEmpty(tokenCookie.getValue())){
17                 System.out.println("MsgGatewayFilterFactory拦截 因为cookie里未找到token");
18                 //这里也可以return Mono.empty()
19                 throw new SystemException("cookie里未找到token");
20             }
21             System.out.println("获取到token = "+tokenCookie.getValue());
22 
23             System.out.println("退出MsgGatewayFilterFactory");
24             return exchange.getSession().flatMap(webSession -> {
25                 System.out.println("Gateway开始操作WebSession");
26                 ServerHttpResponse response = exchange.getResponse();
27 
28                 //获得全局拦截器的记录
29                 String globalMsg = webSession.getAttribute("GlobalGateway");
30                 System.out.println(globalMsg);
31 
32                 //这Session只能在网关里用
33                 //除非这里自己存到缓存里去,像做SpringSession那样,不然分布式不了
34                 webSession.getAttributes().put("Gateway","Gateway记录了值");
35                 JSONObject message = new JSONObject();
36 
37 
38                 //操作头部,body,cookie
39                 ServerHttpRequest request = exchange.getRequest();
40 
41                 HttpHeaders headers = request.getHeaders();
42                 MultiValueMap<String, HttpCookie> cookies = request.getCookies();
43                 MultiValueMap<String, String> queryParams = request.getQueryParams();
44                 Flux<DataBuffer> body = request.getBody();
45 
46                 //想要操作body的值不容易的
47                 //参考:https://blog.csdn.net/seantdj/article/details/100546713
48                 //参考:https://www.haoyizebo.com/posts/876ed1e8/
49 
50                 //头部里面放值,会报错,这是个ReadOnlyHttpHeaders
51                 //headers.add("GatewayKey-header","GatewayValue-header");
52                 //想要设置要这样设,传输中文需要编码,不然乱码
53                 try{
54                     request.mutate().header("GatewayKey-header", URLEncoder.encode("mutate的方式设置头的值是可以的","UTF-8"));
55                 }catch (Exception e){
56                     System.out.println("Gateway头部设置信息出错");
57                     System.out.println(e);
58                 }
59 
60 
61                 //cookie里面放值,会报错,只能读
62                 //cookies.add("GatewayKey-cookie",new HttpCookie("GatewayCookieKey","GatewayCookieValue"));
63 
64                 //往参数里面放,会报错,只能读
65                 //queryParams.add("GatewayKey-param","GatewayValue-param");
66 
67                 return chain.filter(exchange);
68             });
69         });
70     }
71 }

其实很重要的一点Gateway使用的是响应式编程。这部分架构、理念、用法不熟悉的话不要弄骚操作,出BUG都不知道怎么整

真的想搞幺蛾子看:https://blog.csdn.net/u010647035/article/details/84726266

里面有各式的过滤器去操作http请求,搜索你想要了解的过滤器,去结合源码和网上内容做自定义改造

小结

本篇博客主要介绍常用的方式,对于具体的原理和高深的用法都没怎么涉及(菜鸡一枚,真的不太懂响应式编程),希望能帮到大家~

学习和点赞一样,可不能下次一定啊! 感谢你的三连~
原文地址:https://www.cnblogs.com/top-housekeeper/p/14785670.html