確保您的 MQTT 客戶端、MQTT 服務(Netty MQTT 服務)和 Nginx 都支持代理協議。不是所有的軟件都支持這種協議。
以下是Ngin與MQTT服務端修改,客戶端針對每個平臺自行搜索修改
Nginx配置修改
stream {
upstream mqtt_backend {
server mqtt_server_ip:mqtt_server_port;
}
server {
listen mqtt_proxy_port proxy_protocol;
proxy_pass mqtt_backend;
proxy_protocol on;
}
}
示例
stream { upstream mqtt_backend { server 192.168.1.10:1883; # MQTT 後端服務器的 IP 地址和端口 } server { listen 8888 proxy_protocol; # 使用代理協議監聽的端口,客戶端將連接到此端口 proxy_pass mqtt_backend; proxy_protocol on; } }
在這個示例中:
192.168.1.10:1883
是您的 MQTT 服務(Netty MQTT 服務)的 IP 地址和端口。8888
是 Nginx 代理將監聽的端口,客戶端將連接到此端口。這個端口可以是任何可用的端口號,但請確保它與您的實際需求相符。proxy_protocol
是一個指令,用於告訴 Nginx 使用代理協議。在listen 8888 proxy_protocol;
中,proxy_protocol
指示 Nginx 使用代理協議處理傳入的連接。
客戶端將連接到 Nginx 代理的 8888
端口,Nginx 會將連接轉發到 MQTT 後端服務器(IP 地址爲 192.168.1.10
,端口爲 1883
)。通過使用代理協議,Nginx 將把客戶端的連接信息(如原始 IP 地址和端口)傳遞給 MQTT 服務。
Netty服務端
- 首先,將以下 HAProxy 代理協議庫添加到您的項目中:
Maven 依賴:
<dependency> <groupId>io.netty</groupId> <artifactId>netty-codec-haproxy</artifactId> <version>4.1.72.Final</version> </dependency>
- 在
ChannelInitializer
類中將HAProxyMessageDecoder
添加到管道中:
import io.netty.channel.ChannelInitializer; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.haproxy.HAProxyMessageDecoder; public class MyMqttServerInitializer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); // 將 HAProxyMessageDecoder 添加到管道中 pipeline.addLast(new HAProxyMessageDecoder()); // ... 添加其他處理器,例如 MQTT 編解碼器和業務處理器 ... } }
- 在您的自定義
ChannelInboundHandler
中,獲取代理協議頭中的客戶端真實 IP 和端口:
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.handler.codec.haproxy.HAProxyMessage; public class ProxyProtocolHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { if (msg instanceof HAProxyMessage) { HAProxyMessage haProxyMessage = (HAProxyMessage) msg; String clientIp = haProxyMessage.sourceAddress(); int clientPort = haProxyMessage.sourcePort(); // 在這裏,您可以將客戶端的真實 IP 和端口傳遞給後續處理器 // 例如,將它們設置爲 ChannelHandlerContext 的屬性 ctx.channel().attr(AttributeKey.valueOf("clientIp")).set(clientIp); ctx.channel().attr(AttributeKey.valueOf("clientPort")).set(clientPort); // 繼續處理其他消息 ctx.fireChannelRead(msg); } else { super.channelRead(ctx, msg); } } }