SpringCloud Gateway 测试问题解决

发布时间:2021-09-19 06:12:06


本文针对于测试环境SpringCloud Gateway问题解决。



1.背景介绍

本文遇到的问题都是在测试环境真正遇到的问题,不一定试用于所有人,仅做一次记录,便于遇到同样问题的干掉这些问题。


使用版本:SpringCloud 2.0.0.RELEASE


1.1 Gateway配置

之前系统是由阿里云SLB直接分发到几台生产服务器,但是经过研究,决定在中间加一层网关,也就是阿里云SLB分发流量到Gateway到下游服务。但是又由于种种原因,决定使用Host方式进行拦截处理,以下为部分配置代码:


spring:
cloud:
gateway:
discovery:
locator:
enabled: true
routes:
- id: test_client
uri: lb://TEST-CLIENT
predicates:
- Host=www.dalaoyang.cn
order: 1
filters:
- DalaoyangAuth

复制代码

注意,其中部分内容并非真实环境内容,但是场景绝对真实,如:


test_client:routes的ID。uri:这里使用的Eureka内的application nameHost:需要拦截的域名filters:域名前缀
1.2 Gateway过滤器

过滤器内容如下,稍后介绍:



@Component
public class DalaoyangAuthFilterFactory extends AbstractGatewayFilterFactory {
private static final Logger logger = LoggerFactory.getLogger(DalaoyangAuthFilterFactory.class);

@Override
public GatewayFilter apply(Object config) {
return (exchange, chain) -> {
ServerHttpRequest host = exchange.getRequest().mutate().headers(httpHeaders -> {
httpHeaders.remove("gate_way_auth");
httpHeaders.add("gate_way_auth", "yes");
}).build();
//将现在的request 变成 change对象
ServerWebExchange build = exchange.mutate().request(host).build();
return chain.filter(build);
};
}
}
复制代码
1.3 下游服务拦*

下游服务拦*鞔笾履谌萑缦拢舛未胧窃械拇耄飧龉δ艽蟾啪褪羌釉毓驳氖粜詁asePath,用于加载静态资源,比如前端的jquery.js,根据域名判断,然后选择是加载为http://127.0.0.1:8080/jquery.js还是https://www.dalaoyang.cn/jquery.js这种:


public class GlobalInterceptorAdapter extends HandlerInterceptorAdapter {

private static Logger logger = LoggerFactory.getLogger(GlobalInterceptorAdapter.class);

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws
Exception {
String scheme = request.getScheme();
String serverName = request.getServerName();
int port = request.getServerPort();
String path = request.getContextPath();
String basePath = "";
if(serverName.indexOf("www.dalaoyang.cn")!=-1){
basePath = "//" + serverName + path;
}else {
basePath = scheme + "://" + serverName + ":" + port + path;
}
if (logger.isDebugEnabled()) {
logger.debug(basePath);
}
request.setAttribute("basePath", basePath);
return true;
}

}
复制代码

1.4 下游服务用户过滤器

这段代码也是原有的代码,用户Session过滤器,这个完整内容很多,只截取遇到问题的片段,大致内容就是判断用户是否在其他地方登录,如果登录了就弹出的固定的提示页面,内容如下:


String url = null;
ApplicationConfig applicationConfig0 = getApplicationConfig();
if(applicationConfig0 != null) {
String scheme = applicationConfig0.getUrlScheme();
if(scheme != null) {
String requestUrl = request.getRequestURL().toString();
if(requestUrl != null && requestUrl.length() > 8) {
requestUrl = requestUrl.substring(requestUrl.indexOf(":"),
requestUrl.indexOf("/", 8));
url = scheme + requestUrl;
}
}
}
if(url != null) {
response.sendRedirect(url + request.getContextPath() + "/session-time-out");
} else {
response.sendRedirect(request.getContextPath() + "/session-time-out");
}
复制代码

1.5 跳转流程

跳转如下:


1.域名指向了Gateway地址。
2.在浏览器使用域名访问Gateway,被Gateway转发到下游服务,返回对应响应。


2.问题一 下游服务无法获取域名

在使用上述配置后,使用request.getServerName()方法已经无法获取到域名了,经过测试,获取到的是服务器的ip地址,导致虽然页面可以正常跳转,但是无法获取到正确的域名,导致静态资源加载有问题。


在网上请教了很多人,本想看看是不是什么地方没有设置对,但是后台还是采取大多数人的建议,在header中加入一个域名信息,修改后Gateway过滤器如下:


@Component
public class DalaoyangAuthFilterFactory extends AbstractGatewayFilterFactory {
private static final Logger logger = LoggerFactory.getLogger(DalaoyangAuthFilterFactory.class);

@Override
public GatewayFilter apply(Object config) {
return (exchange, chain) -> {
ServerHttpRequest host = exchange.getRequest().mutate().headers(httpHeaders -> {
httpHeaders.remove("gate_way_auth");
httpHeaders.add("gate_way_auth", "yes");

httpHeaders.add("realServerName",
exchange.getRequest().getURI().getHost());
logger.info("headers:" + httpHeaders.toString());
}).build();
//将现在的request 变成 change对象
ServerWebExchange build = exchange.mutate().request(host).build();
return chain.filter(build);
};
}
}
复制代码

很容易看到,就是如下这句话:


httpHeaders.add("realServerName",
exchange.getRequest().getURI().getHost());
复制代码

下游服务过滤修改为:


public class GlobalInterceptorAdapter extends HandlerInterceptorAdapter {
private static Logger logger = LoggerFactory.getLogger(GlobalInterceptorAdapter.class);
private final String TEST_SERVERNAME = "www.dalaoyang.cn";

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws
Exception {
String scheme = request.getScheme();
String serverName = request.getServerName();
String realServerName = request.getHeader("realServerName");
int port = request.getServerPort();
String path = request.getContextPath();
String basePath = "";
if((!StringUtils.isBlank(realServerName))){
if(realServerName.contains(TEST_SERVERNAME)){
basePath = "//" + realServerName + path;
}
}else {
basePath = scheme + "://" + serverName + ":" + port + path;
}
if (logger.isDebugEnabled()) {
logger.debug(basePath);
}
request.setAttribute("basePath", basePath);
return true;
}
}
复制代码

其实大致内容就是,使用如下方式获取域名:


String realServerName = request.getHeader("realServerName");
复制代码

到此,问题解决了,大部分内容跳转正常。


3.问题二 NPE异常

部分请求,经过路由访问报如下错误。


2018-06-20 01:26:04.254 ERROR 1 --- [reactor-http-client-epoll-11] .a.w.r.e.DefaultErrorWebExceptionHandler : Failed to handle request [DELETE http://localhost:8080/entity/5b29ad2cb3cb1f00010a1546]

java.lang.NullPointerException: null
at java.util.concurrent.ConcurrentHashMap.putVal(ConcurrentHashMap.java:1011) ~[na:1.8.0_111]
at java.util.concurrent.ConcurrentHashMap.put(ConcurrentHashMap.java:1006) ~[na:1.8.0_111]
at org.springframework.cloud.gateway.filter.NettyRoutingFilter.lambda$filter$3(NettyRoutingFilter.java:117) ~[spring-cloud-gateway-core-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:177) ~[reactor-core-3.1.8.RELEASE.jar!/:3.1.8.RELEASE]
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:108) ~[reactor-core-3.1.8.RELEASE.jar!/:3.1.8.RELEASE]
at reactor.core.publisher.FluxRetryPredicate$RetryPredicateSubscriber.onNext(FluxRetryPredicate.java:81) ~[reactor-core-3.1.8.RELEASE.jar!/:3.1.8.RELEASE]
at reactor.core.publisher.MonoCreate$DefaultMonoSink.success(MonoCreate.java:146) ~[reactor-core-3.1.8.RELEASE.jar!/:3.1.8.RELEASE]
at reactor.ipc.netty.channel.PooledClientContextHandler.fireContextActive(PooledClientContextHandler.java:85) ~[reactor-netty-0.7.8.RELEASE.jar!/:0.7.8.RELEASE]
at reactor.ipc.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:578) ~[reactor-netty-0.7.8.RELEASE.jar!/:0.7.8.RELEASE]
at reactor.ipc.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:136) ~[reactor-netty-0.7.8.RELEASE.jar!/:0.7.8.RELEASE]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-transport-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-transport-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) ~[netty-transport-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:438) ~[netty-transport-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:310) ~[netty-codec-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:284) ~[netty-codec-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:253) ~[netty-transport-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-transport-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-transport-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) ~[netty-transport-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434) ~[netty-transport-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-transport-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-transport-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965) ~[netty-transport-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:808) ~[netty-transport-native-epoll-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:408) ~[netty-transport-native-epoll-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:308) ~[netty-transport-native-epoll-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884) ~[netty-common-4.1.25.Final.jar!/:4.1.25.Final]
at java.lang.Thread.run(Thread.java:745) ~[na:1.8.0_111]
复制代码

遇到问题后,没有很慌,打开了百度查了查(微笑)。百度没让我很失望,基本上没啥答复,然后谷歌了一下,看到了github上的一个issues,大致内容感觉是SpringCloud Gateway 2.0.0.RELEASE版本有些问题,升级一下版本就好了,如图。


Github issues地址:


github.com/spring-clou… github.com/spring-clou…







说实话,感觉是版本问题,但是又看到了一篇国人的文章,地址是:xiaoqiangge.com/aritcle/154…,问题大致类似,加了一下博主的微信,请教了一下,大致了解到了,升级了一下版本,问题解决。


感谢小强哥!!!


4.问题三 下游用户过滤器跳转失效

问题是这样的,刚刚介绍了,用户在其他地方登录会自动跳转至一个界面提示给用户,发现问题是无法跳转。


查看gateway日志,大概提示了这样一句话,如下:


Unhandled failure: Connection has been closed, response already set (status=302)
复制代码

从内容大致可以看出,重定向有问题,想到了在用户过滤器中最后的重定向,决定在这里下手,修改后内容如下:


String scheme = request.getScheme();
String serverName = request.getServerName();
String realServerName = request.getHeader("realServerName");
int port = request.getServerPort();
String path = request.getContextPath();
String basePath = "";
if((!StringUtils.isEmpty(realServerName))){
if(realServerName.contains(TEST_SERVERNAME)){
basePath = "https://" + realServerName + path;
}else {
basePath = scheme + "://" + serverName + ":" + port + path;
}
response.sendRedirect(basePath + "/session-time-out");
复制代码

问题也解决了,目前还在踩坑测试中,如果大家有类似经验可以一起探讨。



转载于:https://juejin.im/post/5c87cf3c5188257edb45e371

相关文档

  • 执政的意思及造句
  • 什么叫串联电路什么叫并联电路
  • 如何开展单词记忆
  • 帕玛氏和娇韵诗哪个好?帕玛氏和娇韵诗的区别
  • 怎么把字写好看
  • 解放语文的论文参考
  • 手机开机太慢怎么解决
  • 文明礼仪演讲一年级儿歌
  • mysql的cpu飙升到500_【原创】记一次MySQL大表高并发写入引发CPU飙升的排障过程...
  • 治理的同义词
  • 有关友情的朗诵稿件
  • 双子座男与白羊座女配不配
  • 来吧,一文彻底搞懂Java中最特殊的存在??null
  • 最搞笑的经典语句
  • 我的中秋节四年级作文
  • 2021好家风伴我成长中考作文
  • kafka topicPartitions问题
  • 古风伤感情侣个性签名
  • 某建材市场国庆节促销活动方案
  • C语言实现按分隔符来截取字符串
  • 市委办公室系统领导班子述职述廉报告精选多篇
  • 霍金奋斗的故事霍金的励志故事
  • 基于petri网的工作流笔记(一)
  • 小学生歌颂党、赞美党的诗歌
  • 建设学习型党组织工作汇报
  • 情人节写给情人的短信
  • 七年级上册历史测试题第9课甲骨文与青铜器 七年级上册数学测试题
  • 逛西街 暑假旅游作文500字
  • 初中国庆节手抄报图片大全
  • 小米手机一有电话就关机怎么办
  • 猜你喜欢

  • (3份试卷汇总)2019-2020学年四川省内江市物理八年级(上)期末学业水平测试模拟试题
  • 风水与人居环境
  • 2018年湖南省怀化市中考数学试卷含答案解析
  • 昌黎瑞鹏钢结构工程有限公司(企业信用报告)- 天眼查
  • 罗汉果查尔酮合成酶基因的生物信息学分析
  • Linux界面编程
  • 小学“素质教导月”运动工作总结
  • 【范文】最新精选行业工作范文·化验组安全注意事项
  • 足部反射区图实用足部反射区和穴位现用现用图解
  • 喝哪些茶可以排毒养颜
  • XX年瑟肽旯ぷ骷觳榧捌兰鄯治鲅芯啃怨ぷ髯芙帷⑾掳肽旯ぷ骷苹?ㄋ湍0
  • 七年级班主任个人工作总结
  • 微观经济学各校考研试题及答案整理-第四章汇编
  • 电焊工安全教育培训试卷
  • 最新初中英语语法归纳(过去进行时)
  • 年生产xxx万吨石灰石增划资源项目可行性研究报告模板参考
  • 立项备案纸罩项目可行性研究报告
  • (小学教育)2019年青岛版小学二年级数学上册第七单元测试题
  • 【精品】最新(新)冀教版七年级英语下册Unit+2+Lesson+8+Marco+Polo+and+the+Silk+Road课件
  • 小学英语作文:Me 我
  • 去年的树教学设计-推荐下载
  • 天津创新微蓝科技有限公司企业信用报告-天眼查
  • 英语口语训练中学生心理障碍论文
  • 九年级化学上册第三单元物质构成的奥秘课题2原子的结构第2课时离子与相对原子质量课件新版新人教版(1)ppt版
  • 崇明县总工会第二工人俱乐部企业信用报告-天眼查
  • 2020年河北省张家口市察北管理区医院招聘公告
  • 牛鬼蛇神一词从何处来出处是什么
  • 【推荐下载】新年幼儿园大班个人工作计划范例-word范文 (2页)
  • 飞鹤智纯奶粉怎么样飞鹤智纯试用测评
  • 陕西云龙智联信息技术有限公司企业信用报告-天眼查
  • 高三家长会课件 (5-PPT精品文档
  • 英语作文经典常用句型集:主题篇
  • 上海冠品建筑装潢有限公司企业信息报告-天眼查
  • 梦见给别人瓜子吃是怎么回事
  • 客服人员个人工作总结与客服工作总结结尾范文汇编.doc
  • 工业和信息化部:辛国斌出席2016年“创客中国”创新创业大赛决赛启动仪式
  • 北京甄美食品有限公司(企业信用报告)- 天眼查
  • 西瓜号称夏季瓜果之王 三款清热去火的西瓜炖盅
  • 《我是猫》读书笔记1000字精选
  • 第一章 商务谈判概述
  • CA6140车床实验
  • 2017年北京大学汉语国际教育硕士考研-育明斯泰朗考研