配置Nginx的Websocket
Websocket是一种在Web浏览器和Web服务器之间建立实时、双向、基于消息的连接的技术。Nginx可以用作Websocket的代理服务器,本文将介绍如何配置Nginx的Websocket。
安装Nginx
如果您还没有安装Nginx,请按以下步骤安装:
# Ubuntu或Debian
$ sudo apt-get update
$ sudo apt-get install nginx
# CentOS或Red Hat
$ sudo yum update
$ sudo yum install nginx
配置Nginx
1. 增加HTTP/HTTPS支持
当Nginx作为Websocket代理时,需要开启HTTP/HTTPS支持。请在Nginx配置文件中增加以下配置:
# HTTP配置
server {
listen 80;
server_name yourdomain.com;
location / {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
# HTTPS配置
server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /path/to/yourdomain.com.crt;
ssl_certificate_key /path/to/yourdomain.com.key;
location / {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
2. 增加Websocket支持
请在Nginx配置文件中增加以下配置:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name yourdomain.com;
location / {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 86400;
}
}
以上配置使得Nginx支持Websocket连接,当有Websocket连接请求时,Nginx将把连接转发到指定的后端服务。
示例1:配置Nginx代理到Node.js服务器
以下为配置Nginx代理到Node.js服务器的示例。
# 安装Node.js
$ sudo apt-get update
$ sudo apt-get install nodejs npm
$ sudo ln -s /usr/bin/nodejs /usr/bin/node
# 安装WebSocket模块
$ npm install ws
创建Node.js服务器文件server.js
如下:
const http = require('http');
const WebSocket = require('ws');
const server = http.createServer();
const wss = new WebSocket.Server({ server });
wss.on('connection', (ws) => {
ws.on('message', (message) => {
console.log(`Received message => ${message}`)
});
ws.send('Hello! Message received.');
});
server.listen(8081, () => {
console.log('Websocket server listening on http://localhost:8081');
});
创建Nginx配置文件/etc/nginx/sites-available/yourdomain.com
如下:
upstream nodejs {
server localhost:8081;
}
server {
listen 80;
server_name yourdomain.com;
location / {
proxy_pass http://nodejs;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
启动Node.js服务器和Nginx:
$ node server.js &
$ sudo service nginx start
以上配置使得Nginx代理Websocket连接到Node.js服务器,将收到的消息打印到控制台并回复一个“Hello! Message received.”的消息。
示例2:配置Nginx代理到Java服务器
以下为配置Nginx代理到Java服务器的示例。
创建Java Maven项目,并添加以下依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>sockjs-client</artifactId>
<version>0.3.4</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>stomp-websocket</artifactId>
<version>2.3.3</version>
</dependency>
</dependencies>
创建Java WebSocket服务器文件WebSocketServer.java
如下:
package com.example.websocketdemo;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketServer extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/my-websocket-endpoint").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic");
registry.setApplicationDestinationPrefixes("/app");
}
}
创建Java WebSocket客户端文件WebSocketClient.java
如下:
package com.example.websocketdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.messaging.simp.stomp.StompSession;
import org.springframework.messaging.simp.stomp.StompSessionHandler;
import org.springframework.messaging.simp.stomp.StompSessionHandlerAdapter;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
import org.springframework.web.socket.messaging.WebSocketStompClient;
import java.lang.reflect.Type;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
@Controller
@SpringBootApplication
public class WebSocketClient {
private static final String WEBSOCKET_ENDPOINT = "ws://localhost:8082/my-websocket-endpoint";
private WebSocketStompClient webSocketStompClient;
@RequestMapping(value="/test", method=RequestMethod.GET)
public @ResponseBody String test() throws InterruptedException, ExecutionException, TimeoutException {
webSocketStompClient = new WebSocketStompClient(new StandardWebSocketClient());
webSocketStompClient.setMessageConverter(new MyMessageConverter());
StompSessionHandler stompSessionHandler = new MyStompSessionHandler();
StompSession stompSession = webSocketStompClient.connect(WEBSOCKET_ENDPOINT, stompSessionHandler).get();
stompSession.subscribe("/topic/my-topic", new MyStompFrameHandler());
stompSession.send("/app/my-url", "Hello!");
return "OK";
}
public static void main(String[] args) {
SpringApplication.run(WebSocketClient.class, args);
}
private class MyStompSessionHandler extends StompSessionHandlerAdapter {
@Override
public void afterConnected(StompSession session, StompHeaders connectedHeaders) {
System.out.println("Connected to WebSocket server");
}
}
private class MyStompFrameHandler implements StompFrameHandler {
@Override
public Type getPayloadType(StompHeaders headers) {
return String.class;
}
@Override
public void handleFrame(StompHeaders headers, Object payload) {
System.out.println("Received message => " + payload);
}
}
private class MyMessageConverter extends MappingJackson2MessageConverter {
MyMessageConverter() {
List<MediaType> supportedMediaTypes = new ArrayList<>();
supportedMediaTypes.add(MediaType.TEXT_PLAIN);
setSupportedMediaTypes(supportedMediaTypes);
}
}
}
创建Nginx配置文件/etc/nginx/sites-available/yourdomain.com
如下:
upstream java {
server localhost:8083;
}
server {
listen 80;
server_name yourdomain.com;
location /my-websocket-endpoint {
proxy_pass http://java;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
启动Java WebSocket服务器、Java WebSocket客户端和Nginx:
$ ./mvnw spring-boot:run -Dserver.port=8083 &
$ ./mvnw spring-boot:run -Dserver.port=8084 &
$ sudo service nginx start
以上配置使得Nginx代理Websocket连接到Java WebSocket服务器,Java WebSocket客户端向服务器发送一个消息并收到回复,并将收到的消息打印到控制台。