摘要
当我们开放一个Netty服务端端口时,一定会出现这样的问题,“对外开放了Netty端口,所以所有的人都可以通过我的长连接端口请求”,这样的话长连接端口就会极度不安全。所以这篇文章讲述一下,如何通过网关来过滤长连接请求。
如果需要网关来管理长连接,那么就需要使用Spring Cloud Gateway组件,因为它本身是基于Netty,所以天生支持长连接。
Spring Cloud Gateway这里就不再过多讲述。
具体的网关管理是指:“所有的长连接请求,都需要经过我的网关,这样网关就可以对请求进行过滤,例如验签、鉴权等,不合法的连接可以拒绝。”
实现
网关代理长连接的大体思路是这样的:
举个例子:
网关的IP和端口为 127.0.0.1:30562
Netty的IP和端口为 127.0.0.1:18026
那么所有的请求是需要通过连接“127.0.0.1:30562”,然后再由网关路由到“127.0.0.1:18026”,以此来建立长连接。
以上例子提到了网关的路由,最常见的Zuul网关亦是如此,但是Zuul不支持代理长连接,所以Spring Cloud Gateway在此非常重要。
上面这张图,是Gateway在数据库中配置的路由规则(当然我做的是动态路由,也可以使用yml或properties方式来配置路由规则)。
字段 | Route URL 说明 |
---|---|
lb | 即指通过注册中心的服务名称来转发请求 |
ws | 代表这是一个socket请求,会通过长连接的方式转发请求 |
http | 转发http请求,可以直接链接到一个web url |
字段 | 断言说明 |
---|---|
name | 匹配方式 |
args | 参数 |
args > pattern | “方式”,在此配置的仅为通过baseUrl路由 |
字段 | Filter说明 |
---|---|
name | 匹配方式 |
args | 参数 |
args > _genkey_0 | “截取前缀”,因路由会携带baseUrl所以需要Filter来截取前缀 |
上表中Route URL说明已经提到,以ws配置的route,会以长连接的方式转发此请求,所以在数据库中配置了一条baseUrl为/nio/v1的断言去匹配转发Netty服务端。
就像这样:发起一个长连接请求到“ws://127.0.0.1:30562/nio/v1”,然后由网关来匹配baseUrl,发现需要路由到ws://127.0.0.1:18026,接着网关转发请求至Netty服务端。
至此,网关管理长连接的大体思路就非常清晰了,接着就是具体的代码实现了。
做过Netty的同学们都知道。NettyClient一般都是以“IP + Port”的方式进行长连接。这样突然冒出来一个URL,这该如何通过Client去发起长连接请求呢。
我这边翻遍Netty所有的Address类,也没有发现可以通过URI去建立长连接的方法。
所以需要使用以WebSocket的方式去建立长连接。
import lombok.extern.slf4j.Slf4j;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import java.net.URI;
/**
* 客户端
*
* @author cuixiaojian
*/
@Slf4j
public class NioSocketClient extends WebSocketClient {
public NioSocketClient(URI serverUri) {
super(serverUri);
}
@Override
public void onOpen(ServerHandshake serverHandshake) {
log.info("--- Socket Open ---");
}
@Override
public void onMessage(String s) {
log.info("--- 接收到服务端数据:{} ---", s);
}
@Override
public void onClose(int i, String s, boolean b) {
log.info("--- Socket Close ---");
}
@Override
public void onError(Exception e) {
log.info("--- Socket Error:{} ---", e.toString());
}
}
import java.net.URI;
/**
* 入口
*
* @author cuixiaojian
*/
public class SocketMain {
public static void main(String[] args) {
// 连接地址
URI uri = URI.create("ws://127.0.0.1:30562/nio/v1");
NioSocketClient myClient = new NioSocketClient(uri);
myClient.connect();
}
}
当然,如果某位同学比较懒,可以试试直接通过 WebSocket在线测试地址 在此页面输入自己的网关地址,可以直接测试长连接是否可以Ping通。
演示效果
启动服务:Config、Gateway、Nio、SocketClient
- 首先进行测试无网关过滤的效果
1.1 启动我的三个服务端
1.2 启动我的SocketClient,开启连接
1.3 在Nio服务中成功发送心跳
- 其次进行测试开启Token验证方式
2.1 可以看到在网关中有配置的Filter,来进行请求鉴权
2.2 这边若是发现Header中无Authroization信息则直接抛出
2.3 启动SocketClient查看网关日志,发现Filter成功执行,达到预期效果
查看更具体的代码查看下篇:
Java 客户端与 VUE 连接 Gateway - Netty
https://blog.csdn.net/cui884658/article/details/105892128