工作笔记 - 使用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服务和客户端代码的相关改造内容。

相关推荐
可观测性用观测云几秒前
解锁DQL高级玩法——对日志关键信息提取和分析
后端
YAY_tyy17 分钟前
【JavaScript 性能优化实战】第五篇:运行时性能优化进阶(懒加载 + 预加载 + 资源优先级)
前端·javascript·性能优化
正义的大古20 分钟前
OpenLayers地图交互 -- 章节七:指针交互详解
前端·javascript·vue.js·openlayers
qwy71522925816324 分钟前
vue自定义指令
前端·javascript·vue.js
niusir25 分钟前
Zustand 实战:10 行代码搞定全局状态
前端·javascript·react.js
niusir25 分钟前
React 状态管理的演进与最佳实践
前端·javascript·react.js
看到我请叫我铁锤40 分钟前
vue3使用leaflet的时候高亮显示省市区
前端·javascript·vue.js
Chan1642 分钟前
【 设计模式 | 结构型模式 代理模式 】
java·spring boot·后端·设计模式·intellij-idea
南囝coding1 小时前
Vercel 发布 AI Gateway 神器!可一键访问数百个模型,助力零门槛开发 AI 应用
前端·后端
耀耀_很无聊1 小时前
14_Spring Boot 跨域(CORS)处理指南
spring boot·后端