• 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请求,搜索你想要了解的过滤器,去结合源码和网上内容做自定义改造

    小结

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

    学习和点赞一样,可不能下次一定啊! 感谢你的三连~
  • 相关阅读:
    Orleans is a framework
    修改emlog后台登录路径的方法(转)
    form表单中的 action=./?> 是什么意思
    10 个迅速提升你 Git 水平的提示(转)
    为什么国外程序员爱用苹果Mac电脑?(转)
    Socket 专题
    Android 时间戳简单转化
    Android 常用时间格式转换代码
    Android AlarmManager(全局定时器/闹钟)指定时长或以周期形式执行某项操作
    Android AlarmManager类的应用(实现闹钟功能)
  • 原文地址:https://www.cnblogs.com/top-housekeeper/p/14785670.html
Copyright © 2020-2023  润新知