java websocket问题排查

背景:由于远端websocket的限制,项目后端同时作为websocket的客户端和服务端,服务端对接前台,客户端连接远端websocket服务,相当于做一个服务中介。近期排查问题,发现原本本地可以测试联通的功能突然无法连接。linux服务器上功能完全正常。

前端vue,后端springboot

后台的contextpath为AAA/BBB,同时设置spring.mvc.servlet.path=web

正常controller的地址为:ip:port/AAA/BBB/web/xxxxx

websocket使用java原生接口,@ServerEndpoint("/websocket/xxxx")

websocket地址为ws://ip:port/websocket/xxxx

问题1:前端调用后台 404。调用到后台的地址变成了 AAA/BBB/web/error

前台使用proxytable:{

'AAA/BBB/websocket:{

ws:true,

target:"http://ip:port"

}

}

排查过程中增加过 changeOrigin:true 无法解决问题

后台ServerEndpointExporter也已经注册到spring容器(此处网上说有用
@component和@configuration的区别,没有仔细研究)

spring使用ServerEndpointExporter将@ServerEndpoint标注的类动态注册到tomcat容器里

如果是外置tomcat,则tomcat会自动扫描并注册。

各种百度得知:从tomcat8开始,websocket不再有单独的servlet,使用filter处理升级的请求,WsServerContainer实现了ServerContainer接口,在tomcat启动的时候会初始化该类,该类会注册tomcat websocket (JSR356) filter,这个filter就是解决websocket请求的。会处理上述@ServerEndpoint注册的path

一个请求过来,tomcat会通过Mapper这个类按各种规则寻找请求的路径对应的wrapper(wrapper和servlet有对应关系),如果找不到就用默认的,也即/目录的。但是springboot内嵌的tomcat容器并没有注册默认的wrapper,所以导致tomcat直接转成了默认的error路径。

如果能找到,即可走到上述的filter的逻辑。

解决方案有两种:1,将websocket的路径转移到web下。2,随便注册一个/目录的servlet

 问题2:websocket客户端调用远端不通

调试发现报错为:

no subject alternative dns name matching <hostname> found

客户端调用远端没有使用证书,采用了网上的不验证证书的方式。

 

 

 

但是调试发现,在类HostnameChecker中,jdk还是会校验请求的host和证书中的dns匹配证书签发与 SubjectAltName 扩展项 - 知乎

linux环境下,可以校验通过,原因搞不懂,可能和jdk版本,windows环境等有关吧。。

-Djdk.tls.trustNameService=true也不好用。

最终解决方案是将X509TrustManager改成X509ExtenedTrustManager即可。

 

排查过程非常恶心,特此记录,希望对你有所帮助

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值