Heim> Java> javaLernprogramm> Hauptteil

Java Websocket-Entwicklungspraxis: Umgang mit großen gleichzeitigen Verbindungen

WBOY
Freigeben: 2023-12-02 09:07:21
Original
1250 Leute haben es durchsucht

Java Websocket开发实践:如何处理大规模并发连接

Java Websocket ist ein Protokoll, das zum Aufbau einer bidirektionalen Echtzeitkommunikation zwischen einem Webbrowser und einem Webserver verwendet wird. In heutigen Internetanwendungen wird Echtzeit immer wichtiger, und eines der Szenarien, die Echtzeitkommunikation erfordern, ist Social Chat. In Chat-Szenarien müssen umfangreiche gleichzeitige Verbindungen verwaltet werden. Und Java Websocket ist eine ausgezeichnete Wahl.

In diesem Artikel stellen wir anhand von Codebeispielen vor, wie Sie Java Websocket verwenden, um große gleichzeitige Verbindungen zu verarbeiten.

Werfen wir zunächst einen Blick auf die gängigen Ideen. In Java Websocket werden häufig Servlet und WebSocketEndpoint von Java EE verwendet. In einigen einfachen Beispielen werden wir diese Klassen verwenden, aber wenn die Anzahl der Verbindungen zunimmt, kann die direkte Verwendung dieser Klassen leicht zu Leistungsengpässen führen, und wir müssen einige effizientere Tools für die Verarbeitung von Verbindungen verwenden.

Hier verwenden wir die Netty-Socketio-Bibliothek von JavaTreasureChest, um Java-Websocket-Verbindungen zu verwalten. Netty ist ein leistungsstarkes Netzwerkprogrammierungsframework und SocketIO ist ein Protokoll zur Implementierung von Echtzeitanwendungen.

Codebeispiel

Zuerst müssen wir die Abhängigkeit der Netty-Socketio-Bibliothek hinzufügen. Im Maven-Projekt können wir die folgenden Abhängigkeiten in der Datei pom.xml hinzufügen:

 com.corundumstudio.socketio netty-socketio 1.7.17 
Nach dem Login kopieren

Als nächstes müssen wir eine Java-Klasse als WebSocket-Server implementieren und auf Verbindungsanfragen warten. Der Beispielcode lautet wie folgt:

import com.corundumstudio.socketio.*; import com.corundumstudio.socketio.listener.*; public class WebSocketServer { public static void main(String[] args) { // 创建配置对象 Configuration config = new Configuration(); config.setHostname("localhost"); config.setPort(9092); // 创建SocketIO服务器 SocketIOServer server = new SocketIOServer(config); // 添加连接事件监听器 server.addConnectListener(new ConnectListener() { @Override public void onConnect(SocketIOClient client) { System.out.println("连接成功:" + client.getSessionId().toString()); } }); // 启动服务器 server.start(); // 等待连接关闭 System.in.read(); server.stop(); } }
Nach dem Login kopieren

In diesem Code verwenden wir die SocketIOServer-Klasse in der SocketIO-Bibliothek, um einen WebSocket-Server zu erstellen. Wenn die Verbindung erfolgreich ist, wird die Verbindungserfolgsmeldung gedruckt.

Als nächstes müssen wir den Listener beim Server registrieren, damit er verarbeitet werden kann, wenn der Client eine Verbindung herstellt. Der Code lautet wie folgt:

// 添加事件监听器 server.addEventListener("client_msg", String.class, new DataListener() { @Override public void onData(SocketIOClient client, String data, AckRequest ackRequest) { System.out.println("收到消息:" + data + ",sessionId=" + client.getSessionId()); } });
Nach dem Login kopieren

In diesem Codeausschnitt haben wir ein Ereignis namens „client_msg“ registriert und einen DataListener hinzugefügt, um die empfangenen Nachrichten zu verarbeiten.

Manchmal müssen wir möglicherweise auch die Verbindung authentifizieren. Die SocketIO-Bibliothek stellt eine AuthorizationListener-Schnittstelle bereit, die wir für die Authentifizierung implementieren können. Der Beispielcode lautet wie folgt:

// 添加身份验证监听器 server.addAuthorizationListener(new AuthorizationListener() { @Override public boolean isAuthorized(HandshakeData handshakeData) { // 验证用户是否具有连接权限 return true; } });
Nach dem Login kopieren

In diesem Codeausschnitt haben wir einen AuthorizationListener hinzugefügt, um die Authentifizierungsanfrage zu verarbeiten. Die Logik hier besteht darin, alle Verbindungen zu authentifizieren.

Zuletzt müssen wir den WebSocket-Server starten und warten, bis die Verbindung geschlossen wird. Der Code lautet wie folgt:

// 启动服务器 server.start(); // 等待连接关闭 System.in.read(); server.stop();
Nach dem Login kopieren

Dies ist eine einfache Java-Websocket-Serverimplementierung, die jedoch keine großen gleichzeitigen Verbindungen verarbeiten kann. Im nächsten Abschnitt erfahren Sie, wie Sie mit der Netty-Socketio-Bibliothek große gleichzeitige Verbindungen verarbeiten.

Namespace und Raum nutzen, um gleichzeitige Verbindungen abzuwickeln

Um eine große Anzahl gleichzeitiger Verbindungen abzuwickeln, müssen wir die Verbindungen gruppieren. In der Netty-Socketio-Bibliothek können wir Namespace und Raum für die Gruppierung verwenden. Ein Namespace ist ein logischer Kanal, der eine Gruppe von Räumen enthält. Ein Raum ist ein Raum, der eine Gruppe von Benutzern enthält.

Die spezifische Verwendung ist wie folgt:

// 创建SocketIO服务器 SocketIOServer server = new SocketIOServer(config); // 创建namespace SocketIONamespace chatNamespace = server.addNamespace("/chat"); // 设置连接事件监听器 chatNamespace.addConnectListener(new ConnectListener() { @Override public void onConnect(SocketIOClient client) { // 加入默认房间 client.joinRoom("default"); } }); // 设置事件监听器 chatNamespace.addEventListener("client_msg", String.class, new DataListener() { @Override public void onData(SocketIOClient client, String data, AckRequest ackRequest) { String sessionId = client.getSessionId().toString(); System.out.println("收到消息:" + data + ",sessionId=" + sessionId); // 广播消息到房间的所有用户 chatNamespace.getRoomOperations("default").sendEvent("server_msg", sessionId + ":" + data); } }); // 启动服务器 server.start();
Nach dem Login kopieren

In diesem Codeausschnitt verwenden wir Namespace und Raum, um die Verbindung abzuwickeln. Zuerst haben wir einen logischen Kanal namens „Chat“ erstellt und einen Standardraum hinzugefügt. Als nächstes fügen wir bei der Handhabung von Client-Verbindungen die Verbindung zum Standardraum hinzu.

Wenn wir eine Nachricht vom Kunden erhalten, senden wir die Nachricht an alle Benutzer im Standardraum. Hier wird die Methode getRoomOperations verwendet, um die Operationsobjekte im Raum abzurufen.

Auf diese Weise können wir große gleichzeitige Verbindungen mithilfe von Namespace und Raum verarbeiten.

Leistungsoptimierung

Um die Leistung bei großen gleichzeitigen Verbindungen sicherzustellen, müssen wir eine Leistungsoptimierung durchführen. Hier listen wir einige gängige Optimierungsmethoden auf.

  1. Thread-Pool verwenden

Wenn die Anzahl gleichzeitiger Verbindungen zunimmt, können wir den Thread-Pool verwenden, um die Leistung zu verbessern. In netty-socketio können wir einen Thread-Pool erstellen, indem wir:

// 创建配置对象 Configuration config = new Configuration(); ... // 创建线程池 config.setWorkerThreads(100);
Nach dem Login kopieren
  1. Datenbankverbindungen zwischenspeichern

Bei Datenbankoperationen können wir Verbindungen zwischenspeichern, um eine häufige Erstellung von Verbindungen zu vermeiden. In netty-socketio können wir die Datenbankverbindung in ConnectListener zwischenspeichern und in DataListener verwenden. Der Beispielcode lautet wie folgt:

chatNamespace.addConnectListener(new ConnectListener() { @Override public void onConnect(SocketIOClient client) { // 加入默认房间 client.joinRoom("default"); // 缓存数据库连接 client.set("conn", getDBConnection()); } }); chatNamespace.addEventListener("client_msg", String.class, new DataListener() { @Override public void onData(SocketIOClient client, String data, AckRequest ackRequest) { String sessionId = client.getSessionId().toString(); System.out.println("收到消息:" + data + ",sessionId=" + sessionId); // 使用缓存的数据库连接 Connection conn = (Connection)client.get("conn"); ... } });
Nach dem Login kopieren

Hier verwenden wir die Set-Methode von SocketIOClient, um die Datenbankverbindung zwischenzuspeichern und im DataListener zu verwenden.

  1. Zwischengespeicherte Nachrichtenwarteschlange verwenden

Wenn die Anzahl gleichzeitiger Nachrichten groß ist, können wir die Nachrichten in der zwischengespeicherten Nachrichtenwarteschlange speichern und auf die anschließende Verarbeitung warten. Dies kann den unmittelbaren Parallelitätsdruck verringern. Der Beispielcode lautet wie folgt:

private Queue messageQueue = new ConcurrentLinkedDeque<>(); chatNamespace.addEventListener("client_msg", String.class, new DataListener() { @Override public void onData(SocketIOClient client, String data, AckRequest ackRequest) { String sessionId = client.getSessionId().toString(); System.out.println("收到消息:" + data + ",sessionId=" + sessionId); // 将消息放入缓存队列 messageQueue.offer(sessionId + ":" + data); } }); // 消息处理线程 new Thread(new Runnable() { @Override public void run() { while (true) { try { // 从队列取出消息并处理 String message = messageQueue.poll(); processMessage(message); // 睡眠1秒 Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start();
Nach dem Login kopieren

Hier definieren wir eine ConcurrentLinkedDeque-Warteschlange zum Speichern von Nachrichten. Stellen Sie die Nachricht im DataListener in die Warteschlange. Im Verarbeitungsthread wird die Nachricht aus der Warteschlange entnommen und verarbeitet. Beachten Sie, dass hier die Thread-Ruhezeit eingestellt werden muss, um eine übermäßige CPU-Auslastung zu vermeiden.

Zusammenfassung

In diesem Artikel haben wir vorgestellt, wie man Netty-Socketio für die Verarbeitung großer gleichzeitiger Verbindungen verwendet. Die Verwendung von Namespace und Raum zum Gruppieren von Verbindungen und Optimieren der Leistung kann uns dabei helfen, eine große Anzahl von Verbindungen in synchronen Kommunikationsszenarien zu bewältigen.

Darüber hinaus ist zu beachten, dass das WebSocket-Protokoll normalerweise zur Implementierung langer Verbindungen in Echtzeit-Kommunikationsszenarien verwendet wird, es jedoch auch Sicherheitsrisiken bergen kann. Daher müssen wir es in praktischen Anwendungen mit Vorsicht verwenden und die Sicherheit berücksichtigen.

Das obige ist der detaillierte Inhalt vonJava Websocket-Entwicklungspraxis: Umgang mit großen gleichzeitigen Verbindungen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!