SpringCloudGateway+Nacos注册与转发Netty+WebSocket
背景
项目中有个拍卖服务是长连接的,需要加入到注册中心中方便统一的管理,并且方便动态扩容。
问题
Nacos没有对长连接的服务注册的支持,需要手动实现把服务注册上线下线,感知服务状态。并需要支持域名转发WebSocket的请求。
实现
- 自动注册,下线服务
@Async
public void start() {
log.info("=================Netty服务开启==================");
try {
//ServerBootstrap 是一个启动类
ServerBootstrap serverBootstrap = new ServerBootstrap();
// 设置主从线程组
// ... 业务
// 注册到nacos
nettyNacosService.registerNamingService();
bindFuture = serverBootstrap.bind(nettyNacosService.getNettPort()).sync();
log.info("netty监听端口:{},后台服务器启动.....", nettyNacosService.getNettPort());
} catch (Exception e) {
log.error("netty服务器启动异常:{}", e.getMessage());
}
}
public void destroy() {
// 将NacosNetty注销服务
nettyNacosService.deregisterInstance();
log.info("=================Netty服务关闭==================");
if (bindFuture != null) {
bindFuture.channel().closeFuture();
}
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
// 注册伪代码:
/**
* 将Netty服务注册进Nacos
*/
public void registerNamingService() {
try {
Properties properties = getNacosProperties();
NamingService namingService = NamingFactory.createNamingService(properties);
Instance nettyInstance = getNettyInstance();
namingService.registerInstance(nettyInstance.getServiceName(),getGroup(),nettyInstance);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private Properties getNacosProperties() {
Properties properties = new Properties();
properties.setProperty(PropertyKeyConst.SERVER_ADDR, nacosDiscoveryProperties.getServerAddr());
properties.setProperty(PropertyKeyConst.NAMESPACE, nacosDiscoveryProperties.getNamespace());
properties.setProperty(PropertyKeyConst.USERNAME, nacosDiscoveryProperties.getUsername());
properties.setProperty(PropertyKeyConst.PASSWORD, nacosDiscoveryProperties.getPassword());
return properties;
}
/**
* 将NacosNetty注销服务
*/
public void deregisterInstance() {
try {
Properties properties = getNacosProperties();
NamingService namingService = NamingFactory.createNamingService(properties);
Instance nettyInstance = getNettyInstance();
namingService.deregisterInstance(nettyInstance.getServiceName(),getGroup(),nettyInstance);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
- gateway增加路由
{
"id": "web-socket",
"order": 3,
"predicates": [{
"args": {
"pattern": "/ws/**"
},
"name": "Path"
}],
"filters":[{"name":"StripPrefix","args":{"parts":"1"}}],
"uri": "lb:ws://web-socket"
}
- nginx配置
这里支持长连接的配置跟http稍微有点不同。
主要看这个配置:$http_upgrade
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
location /ws {
proxy_pass https://abc.com/web-socket # 这里改为对应的域名
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}