工作笔记 - 使用HTTPS/WS协议发布NATS服务

问题

前几天在研究NATS部署应用的时候,遇到了这么一个问题。

考虑到未来在生产环境中的部署,可能会受到一些网络条件的限制。部署人员可能无法随意管理互联网端口发布,只能受限在一个HTTPS服务和域名空间目录之下。现有的NATS原生协议和端口的发布方式,可能就无法使用了。

关于NATS系统本身的特性、应用和配置,不在本文讨论的范围,读者可以查阅笔者其他相关文章,或者自行检索相关材料。

解决方案概述

通过查阅相关资料,笔者发现可以使用NATS的WS支持特性,来解决这个问题。

大致的解决思路如下:

  • 将NATS配置来支持WS的服务发布
  • 修改HTTP的NGINX配置,将某路径的请求转发到NATS WS端点
  • 配置HTTP协议升级方面的问题
  • 由于HTTP本身已经配置了TLS,WS端口无需配置TLS
  • 改进客户端程序,支持NATS.WS模式

这个请求响应链的工作原理应当是:

  • nats客户端,使用wss协议发起请求,地址是https服务的一个路径
  • https服务(nginx)收到wss请求,解析路径,发现应当使用路径的配置升级并使用ws协议
  • nginx将请求转发到nats ws端点(nats服务)之上,并响应端点返回的内容
  • nats客户端和nats服务建立连接,开始正常的应用

实操

Talk Is Cheap, Show Me The Code !!

NATS服务器

需要在NSTA服务器的配置信息中,增加WS协议支持相关的部分。就是在配置文件中,增加类似下面的内容:

js 复制代码
websocket {
  port: 4223
  no_tls: true

  # 可以指定允许的源(CORS 支持)
  allowed_origins: [ "*" ]
}

内容非常简单:

  • nats配置信息中,有一个websocket对象和区域,可以配置ws相关内容
  • 设置一个独立的端口,如4223,来提供WS端点
  • 选择不使用TLS(因为会使用HTTPS入口)
  • 跨域设置,应当配置成为合法域名

配置完成后,重新启动nats服务,并且检查端口和防火墙是否开启:

shell 复制代码
// 启动nats服务器
 ./nats-server -c n.conf -js
[233317] 2025/07/23 18:45:00.217555 [INF] Starting nats-server
[233317] 2025/07/23 18:45:00.217839 [INF]   Version:  2.11.6
[233317] 2025/07/23 18:45:00.217849 [INF]   Git:      [bc813ee]
[233317] 2025/07/23 18:45:00.217855 [INF]   Name:     ...

// 查看侦听端口打开
sudo netstat -lpnt | grep 4223
tcp6   0    0 :::4223      :::*       LISTEN      233317/./nats-serve

Nginx

需要修改HTTPS服务器的nginx配置信息,将一个WSS请求,转发到nats ws端点之上。相关的参考配置方式如下:

nginx.conf 复制代码
## HTTP区段
location /nats {
  proxy_pass http://192.168.9.194:4223;
  proxy_http_version 1.1;

  # WebSocket 关键头
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";

  proxy_set_header Host $host;
  proxy_read_timeout 60s;

  proxy_buffering off;
}

这里其他的HTTPS协议相关的配置,都已经配置好,我们使用其中的一个路径(nats)来提高WSS服务,不影响其他的https应用,而且可以确保连接和通信通道安全。这里面有几个关键信息:

  • proxy_pass指向nats ws端点地址,但注意这里是http服务
  • 为WS配置了关键的header
  • 关闭缓冲

这里建议先从外部检查一下端点地址,确保已经启动和工作。比如这里使用curl访问,虽然出错(bad request),却可以确定这个路径转发的端点应该是开始工作的:

shell 复制代码
// 外部检查
curl -v https://ulsc.net:10443/nats
VERBOSE: GET with 0-byte payload
curl : Bad Request
At line:1 char:1
+ curl -v https://ulsc.net:10443/nats
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebExc
   eption
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
    

客户端程序

在客户端程序,也需要修改连接方式,来适应和使用这个新的端点地址,参考代码如下:

nats.ts 复制代码
// 引用和连接
import { connect } from "nats.ws";

// 连接和主题配置
const 
TOPIC = "ws.yanjh",
CONN_NATS = {
    servers: "wss://ulsc.net:10443/nats",
    user: 'user',
    pass: 'pass',
    reconnect: true,
    maxReconnectAttempts: 100,
};

// 连接nats服务
const nc = await connect(CONN_NATS);

// 发布消息
setTimeout(() => { 
    nc.publish( TOPIC, new TextEncoder().encode("world"));
}, 2000);

// 订阅消息
const sub = nc.subscribe(TOPIC);
for await (const m of sub) {
    console.log(`Received: ${new TextDecoder().decode(m.data)}`);
}

这里相关的修改如下:

  • 模块修改使用nats.ws,这是一个独立的npm,需要单独安装
  • 注意服务端点的地址,不是https,而是wss(将会从https升级),并且带有配置好的路径信息
  • 这里可以不使用ca和tls配置,因为那是由https入口保证的
  • 理论上只需要修改连接方式,其他应用模式可以不变

小结

本文讨论了由于无法直接使用nats端口,而使用已有的https服务发布nats的解决方案。包括了简单的原理说明,相关nats服务、nginx服务和客户端代码的相关改造内容。

相关推荐
鹤入云霄1 分钟前
vue部署正式环境上传nginx后遇到的问题
前端·javascript·vue.js
沸腾_罗强9 分钟前
redis内存被打爆了
后端
期待のcode11 分钟前
SpringMVC请求与响应
java·后端·spring
Java水解41 分钟前
Spring Boot 全局异常处理与日志监控实战
后端·面试
-睡到自然醒~41 分钟前
[go] 命令模式
java·开发语言·javascript·后端·golang·命令模式
MrSYJ44 分钟前
为什么引入springsecurity的依赖后,会自动创建了过滤器链
spring boot·后端·代码规范
炸薯人1 小时前
每天一个知识点——Java注解
后端
我的div丢了肿么办1 小时前
使用URLSearchParams 优雅的获取URL携带的参数
前端·javascript
用户4099322502121 小时前
如何在 FastAPI 中玩转 APScheduler,让任务定时自动执行?
后端·github·trae
他日若遂凌云志1 小时前
深入剖析 Fantasy 框架的网络数据包解析机制:从抽象基类到多协议适配
后端