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

相关推荐
Fly-ping5 分钟前
【前端】JavaScript 的事件循环 (Event Loop)
开发语言·前端·javascript
在逃的吗喽1 小时前
黑马头条项目详解
前端·javascript·ajax
超浪的晨1 小时前
Java 实现 B/S 架构详解:从基础到实战,彻底掌握浏览器/服务器编程
java·开发语言·后端·学习·个人开发
JHCan3332 小时前
一个没有手动加分号引发的bug
前端·javascript·bug
追逐时光者2 小时前
一款超级经典复古的 Windows 9x 主题风格 Avalonia UI 控件库,满满的回忆杀!
后端·.net
天涯学馆3 小时前
为什么越来越多开发者偷偷用上了 Svelte?
前端·javascript·svelte
拾光拾趣录3 小时前
为什么浏览器那条“假进度”救不了我们?
前端·javascript·浏览器
香菜狗3 小时前
vue3响应式数据(ref,reactive)详解
前端·javascript·vue.js
Python涛哥3 小时前
go语言基础教程:【1】基础语法:变量
开发语言·后端·golang
我命由我123453 小时前
PostgreSQL 保留关键字冲突问题:语法错误 在 “user“ 或附近的 LINE 1: CREATE TABLE user
数据库·后端·sql·mysql·postgresql·问题·数据库系统