検索
ホームページJava&#&チュートリアルJava Websocket 開発の実践: 大規模な同時接続を処理する方法

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

Java Websocket は、Web ブラウザと Web サーバーの間でリアルタイムの双方向通信を確立するために使用されるプロトコルです。今日のインターネット アプリケーションでは、リアルタイムの重要性がますます高まっており、リアルタイム通信が必要なシナリオの 1 つがソーシャル チャットです。チャット シナリオでは、大規模な同時接続を処理する必要があります。 Java Websocket は優れた選択肢です。

この記事では、Java Websocket を使用して大規模な同時接続を処理する方法をコード例を通して紹介します。

まず、一般的なアイデアを見てみましょう。 Java WebsocketではJava EEのServletやWebSocketEndpointがよく使われます。いくつかの簡単な例では、これらのクラスを使用しますが、接続の数が増えると、これらのクラスを直接使用するとパフォーマンスのボトルネックが発生しやすくなり、接続を処理するにはより効率的なツールを使用する必要があります。

ここでは、JavaTreasureChest の netty-socketio ライブラリを使用して、Java Websocket 接続を処理します。 Netty は高性能ネットワーク プログラミング フレームワークであり、SocketIO はリアルタイム アプリケーションを実装するためのプロトコルです。

コード例

まず、netty-socketio ライブラリへの依存関係を追加する必要があります。 Maven プロジェクトでは、pom.xml ファイルに次の依存関係を追加できます。

<dependency>
    <groupId>com.corundumstudio.socketio</groupId>
    <artifactId>netty-socketio</artifactId>
    <version>1.7.17</version>
</dependency>

次に、Java クラスを WebSocket サーバーとして実装し、接続リクエストをリッスンする必要があります。サンプル コードは次のとおりです。

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();
    }
}

このコードでは、SocketIO ライブラリの SocketIOServer クラスを使用して WebSocket サーバーを作成します。接続が成功すると、接続成功のメッセージが出力されます。

次に、クライアントの接続時にリスナーを処理できるように、リスナーをサーバーに登録する必要があります。コードは次のとおりです。

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

このコード スニペットでは、「client_msg」という名前のイベントを登録し、受信したメッセージを処理する DataListener を追加します。

場合によっては、接続の認証も必要になることがあります。 SocketIO ライブラリは、認証を処理するために実装できる AuthorizationListener インターフェイスを提供します。サンプル コードは次のとおりです。

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

このコード スニペットでは、認証リクエストを処理するために AuthorizationListener を追加します。ここでのロジックは、すべての接続を認証することです。

最後に、WebSocket サーバーを起動し、接続が閉じるまで待つ必要があります。コードは次のとおりです。

// 启动服务器
server.start();

// 等待连接关闭
System.in.read();
server.stop();

これは単純な Java Websocket サーバーの実装ですが、大規模な同時接続を処理できません。次のセクションでは、netty-socketio ライブラリを使用して大規模な同時接続を処理する方法について説明します。

ネームスペースとルームを使用して同時接続を処理する

多数の同時接続を処理するには、接続をグループ化する必要があります。 netty-socketio ライブラリでは、グループ化に名前空間と部屋を使用できます。ネームスペースは、ルームのグループを含む論理チャネルです。ルームとは、ユーザーのグループが含まれる部屋です。

具体的な使用法は次のとおりです:

// 创建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<String>() {
    @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();

このコード セグメントでは、名前空間とルームを使用して接続を処理します。まず、「チャット」という論理チャネルを作成し、デフォルトのルームを追加しました。次に、クライアント接続を処理するときに、接続をデフォルト ルームに追加します。

クライアントからメッセージを受信すると、デフォルト ルーム内のすべてのユーザーにメッセージをブロードキャストします。ここでは getRoomOperations メソッドを使用して、ルーム内の操作オブジェクトを取得します。

このように、名前空間とルームを使用することで大規模な同時接続に対応できます。

パフォーマンスの最適化

大規模な同時接続下でパフォーマンスを確保するには、パフォーマンスの最適化を実行する必要があります。ここでは、いくつかの一般的な最適化方法をリストします。

  1. スレッド プールの使用

同時接続数が増加した場合、スレッド プールを使用してパフォーマンスを向上させることができます。 netty-socketio では、次の方法でスレッド プールを作成できます。

// 创建配置对象
Configuration config = new Configuration();
...
// 创建线程池
config.setWorkerThreads(100);
  1. キャッシュ データベース接続

データベース操作では、頻繁に作成されることを避けるために接続をキャッシュできます。接続する。 netty-socketio では、データベース接続を ConnectListener にキャッシュし、DataListener で使用できます。サンプル コードは次のとおりです。

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<String>() {
    @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");
        ...
    }
});

ここでは、SocketIOClient の set メソッドを使用してデータベース接続をキャッシュし、DataListener で使用します。

  1. キャッシュされたメッセージ キューを使用する

同時メッセージの量が多い場合、メッセージをキャッシュされたメッセージ キューに保存し、後続の処理を待つことができます。これにより、瞬間的な同時実行のプレッシャーを軽減できます。サンプル コードは次のとおりです。

private Queue<String> messageQueue = new ConcurrentLinkedDeque<>();

chatNamespace.addEventListener("client_msg", String.class, new DataListener<String>() {
    @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();

ここでは、メッセージを保存するための ConcurrentLinkedDeque キューを定義します。 DataListener で、メッセージをキューに入れます。処理スレッドでは、メッセージがキューから取得されて処理されます。過剰な CPU 使用率を避けるために、ここでスレッドのスリープ時間を設定する必要があることに注意してください。

概要

この記事では、netty-socketio を使用して大規模な同時接続を処理する方法を紹介しました。名前空間とルームを使用して接続をグループ化し、パフォーマンスを最適化すると、同期通信シナリオで多数の接続を処理するのに役立ちます。

さらに、WebSocket プロトコルは通常、リアルタイム通信シナリオで長時間接続を実装するために使用されますが、セキュリティ リスクも伴う可能性があることに注意してください。したがって、実際の使用においては、安全性を考慮して慎重に使用する必要があります。

以上がJava Websocket 開発の実践: 大規模な同時接続を処理する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
Apacheの.htaccess構成をNginxの構成に変換する方法は?Apacheの.htaccess構成をNginxの構成に変換する方法は?Apr 19, 2025 pm 05:09 PM

Apacheの.htaccess構成をプロジェクト開発でnginxに変換するための構成方法では、サーバーをApacheからNginxに移行する必要がある状況に遭遇することがよくあります。 AP ...

小規模なJavawebアプリケーションでは、DAOレイヤーがすべての人事エンティティクラスをキャッシュすることは実行可能ですか?小規模なJavawebアプリケーションでは、DAOレイヤーがすべての人事エンティティクラスをキャッシュすることは実行可能ですか?Apr 19, 2025 pm 05:06 PM

Javawebアプリケーションパフォーマンスの最適化:Javawebアプリケーション開発におけるDAOレベルのエンティティクラスキャッシュの実現可能性の調査、パフォーマンスの最適化は常に開発者の焦点でした。どちらか...

極座標における二重積分∫∫YDσ= 0の理由は何ですか?極座標における二重積分∫∫YDσ= 0の理由は何ですか?Apr 19, 2025 pm 05:03 PM

極座標系下での二重積分の解決この記事では、極座標の下での二重積分に関する質問に詳細に答えます。質問はポイントエリアを与え、組み込まれています...

高い並行性の下でアウトバウンドスクリプトタスクの独自性を確保し、リアルタイムで動作ステータスを監視する方法は?高い並行性の下でアウトバウンドスクリプトタスクの独自性を確保し、リアルタイムで動作ステータスを監視する方法は?Apr 19, 2025 pm 05:00 PM

スクリプトタスクの独自性を確保し、高い並行性環境での動作ステータスを監視する方法は?この記事では、クラスター環境でアウトバウンドフットを確保する方法について説明します...

サブクラスは、親クラスのSetNameメソッドを継承することにより、どのように私有地を設定しますか?サブクラスは、親クラスのSetNameメソッドを継承することにより、どのように私有地を設定しますか?Apr 19, 2025 pm 04:57 PM

サブクラスが親クラスのSetNameメソッドを継承することにより、私有地を設定する方法について。プログラミングでは、特にJava、サブクラス、...などのオブジェクト指向プログラミング言語で

Eclipse Pahoを使用してローカルEMQXに接続する際のユーザー名とパスワード認証の失敗の問題を解決する方法は?Eclipse Pahoを使用してローカルEMQXに接続する際のユーザー名とパスワード認証の失敗の問題を解決する方法は?Apr 19, 2025 pm 04:54 PM

eclipsepahoのmqttasyncclientを使用してローカルEMQXに接続する際のユーザー名とパスワード認証の障害の問題を解決する方法は? JavaとEclipseを使用して...

会社のセキュリティソフトウェアはアプリケーションの実行に失敗していますか?それをトラブルシューティングと解決する方法は?会社のセキュリティソフトウェアはアプリケーションの実行に失敗していますか?それをトラブルシューティングと解決する方法は?Apr 19, 2025 pm 04:51 PM

一部のアプリケーションが適切に機能しないようにする会社のセキュリティソフトウェアのトラブルシューティングとソリューション。多くの企業は、内部ネットワークセキュリティを確保するためにセキュリティソフトウェアを展開します。 ...

JavaのパラメーターQRコードを使用してWeChatアプレットを正しく生成して表示する方法は?JavaのパラメーターQRコードを使用してWeChatアプレットを正しく生成して表示する方法は?Apr 19, 2025 pm 04:48 PM

Javaにパラメーターを使用してWeChatアプレットQRコードを生成し、HTMLページに表示することは一般的な要件です。この記事では、Jの使用方法について詳しく説明します。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

SecLists

SecLists

SecLists は、セキュリティ テスターの究極の相棒です。これは、セキュリティ評価中に頻繁に使用されるさまざまな種類のリストを 1 か所にまとめたものです。 SecLists は、セキュリティ テスターが必要とする可能性のあるすべてのリストを便利に提供することで、セキュリティ テストをより効率的かつ生産的にするのに役立ちます。リストの種類には、ユーザー名、パスワード、URL、ファジング ペイロード、機密データ パターン、Web シェルなどが含まれます。テスターはこのリポジトリを新しいテスト マシンにプルするだけで、必要なあらゆる種類のリストにアクセスできるようになります。

EditPlus 中国語クラック版

EditPlus 中国語クラック版

サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

SublimeText3 英語版

SublimeText3 英語版

推奨: Win バージョン、コードプロンプトをサポート!

PhpStorm Mac バージョン

PhpStorm Mac バージョン

最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール