Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】WebSocket Support for Your Java Backend

2026年10月06日に「Dev.to」が公開したITニュース「WebSocket Support for Your Java Backend」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

JavaバックエンドでWebSocketが利用可能になった。Codename Oneフレームワークを使えば、サーバーとアプリ間で双方向通信を確立し、リアルタイムに情報を受け渡せる。これにより、アプリが頻繁にサーバーへ問い合わせる必要がなくなり、効率的なシステム構築が可能になる。接続管理には注意が必要だ。

出典: WebSocket Support for Your Java Backend | Dev.to公開日:

ITニュース解説

システム開発では、クライアント(スマートフォンのアプリやウェブブラウザ)とサーバー(情報を提供する側)が連携して動くのが一般的だ。これまでは、クライアントがサーバーに何か情報を要求する際に、主にHTTPという通信方法が使われてきた。HTTPは、クライアントが「リクエスト」を送り、サーバーが「レスポンス」を返す、という一方向のやり取りが基本だ。例えば、最新のニュースが欲しい時に、クライアントがサーバーに「新しいニュースある?」と定期的に問い合わせる(これをポーリングと呼ぶ)必要があった。しかし、これではサーバーに新しい情報がない場合でも無駄な通信が発生し、リアルタイムでの情報更新が難しいという課題があった。

そこで登場したのがWebSocketだ。WebSocketは、一度サーバーとクライアントの間で「接続」が確立されると、その接続をずっと維持し続けることができる。そして、この接続は双方向であり、サーバーからもクライアントへ、クライアントからもサーバーへ、いつでも自由にメッセージを送ることができる。これにより、クライアントが常にサーバーに問い合わせる必要がなくなり、サーバー側で何か新しいイベントが発生した時に、すぐにクライアントに通知を送れるようになる。まるで、お互いがいつでも話せる電話回線を常に開いているようなイメージだ。これにより、チャットアプリのメッセージ受信や、リアルタイムの株価更新、ゲームの対戦状況など、リアルタイム性が求められるアプリケーションの開発が非常に効率的になる。

今回のニュースは「Codename One」というフレームワークに関するものだ。Codename Oneは、JavaやKotlinというプログラミング言語を使って、スマートフォン向けのiOSアプリやAndroidアプリ、さらにはデスクトップアプリやウェブアプリまで、さまざまな種類のアプリケーションを一つのコードベースから開発できるオープンソースのフレームワークだ。通常、これらのプラットフォームごとに別々の言語やツールで開発する必要があるが、Codename Oneを使えば、JavaやKotlinの知識があれば、多くのプラットフォームに対応したアプリを効率的に作れるというメリットがある。

これまでCodename Oneでは、クライアント側からWebSocketを使ってサーバーと通信するための機能(クライアントAPI)は提供されていた。しかし、今回は「サーバー側」でWebSocket接続を受け入れ、処理するためのAPI(com.codename1.backend.WebSocket)が新しく追加されたことが大きなポイントだ。この新しい機能によって、Codename Oneのバックエンドを使って、サーバー側でリアルタイム通信を簡単に構築できるようになった。具体的には、国際標準であるRFC 6455に準拠したWebSocketプロトコルをサポートし、Javaのコールバック機能を使って、テキスト形式やバイナリ形式のメッセージを柔軟に処理できるようになっている。また、@WebSocketMappingという特殊な目印(アノテーションと呼ぶ)をコードに付けることで、どのURLパスでWebSocket接続を受け付けるかを簡単に設定できるようになった。

WebSocketサーバーをCodename Oneバックエンドで作るのは比較的シンプルだ。例えば、受け取ったメッセージをそのままクライアントに返す「エコー」機能を持つWebSocketサーバーを考えてみよう。まず、@WebSocketMapping("/echo")というアノテーションをクラスに付ける。これにより、サーバーは/echoというURLパスでWebSocket接続を待ち受けるようになる。次に、このクラスはWebSocketというインターフェースを実装する必要がある。このインターフェースには、WebSocket接続に関するいくつかの重要なメソッドが定義されている。onOpen(WebSocketSession session)は、クライアントからの接続が新しく確立された時に呼び出される。onText(WebSocketSession session, String message)は、クライアントからテキストメッセージが送られてきた時に呼び出される。onBinary(WebSocketSession session, byte[] data, int offset, int length)は、クライentからバイナリデータが送られてきた時に呼び出される。

これらのメソッドにはWebSocketSessionというオブジェクトが引数として渡される。このWebSocketSessionは、個々のクライアントとの接続に関する情報を保持するもので、このオブジェクトを使って特定のクライアントにメッセージを送信したり、接続ごとの固有の状態(例えば、そのクライアントがログインしているユーザーの情報など)を保存したりできる。重要なのは、WebSocketエンドポイントのインスタンスは、そのURLパスごとに一つだけ作られ、すべてのクライアント接続で共有されるということだ。そのため、クライアント固有のデータは、エンドポイントのクラスのフィールドに直接保存するのではなく、必ずWebSocketSessionのsetAttachmentなどの機能を使って保存するように設計する必要がある。

Codename Oneの開発チーム自身も、この新しいWebSocket機能を早速活用している。彼らは、アプリのテスト中にデバイスのスクリーンショットをサーバーに転送するためにこの機能を使っているのだ。具体的には、スクリーンショットの「メタデータ」(テキストメッセージ)と、実際の「画像データ」(バイナリメッセージ)を送信し、サーバーはこれらを受け取り、処理が完了したらクライアントに「受信完了」の確認メッセージを返す。この一連のプロセスは、テキストとバイナリの両方のメッセージタイプ、WebSocket接続のライフサイクル、そしてアプリケーションレベルでのメッセージの順序付けをしっかりとテストする良い機会となっている。

WebSocketは非常に便利な機能だが、従来のHTTPとは異なる特性を理解しておく必要がある。最も大きな違いは「リソースの保持期間」だ。HTTPでは、クライアントのリクエストに対してサーバーがレスポンスを返すと、その接続はすぐに閉じられ、サーバー側のリソースはすぐに解放される。しかし、WebSocketは一度接続が確立されると、クライアントが明示的に切断するか、タイムアウトになるまで接続を維持し続ける。これは、サーバーがアイドル状態のWebSocket接続を多数抱える可能性があり、その間、接続に関連するリソースが保持され続けることを意味する。

Codename Oneのバックエンドでは、この問題を軽減するために、Javaの仮想スレッドのような新しい技術を活用している。仮想スレッドを使えば、一つのOSスレッドが、複数のアイドル状態のWebSocket接続を効率的に管理できるため、物理的なリソースの消費を抑えることが可能になる。ただし、開発環境でのテストやTLS(暗号化通信)を利用する場合には、まだ従来のスレッドプールモードが使われることがあり、その場合は、一つの接続がアイドル状態でも一つのワーカー(スレッド)を占有する可能性があるため、リソース計画には注意が必要だ。

このようなリソース消費の違いを考慮し、WebSocket接続にはいくつかの制限を設定することが推奨される。例えば、CN1_WS_IDLE_TIMEOUT_MSという環境変数を設定することで、アイドル状態の接続がどれくらいの時間で自動的に切断されるかを指定できる(デフォルトは5分)。また、CN1_WS_MAX_MESSAGE_MBという変数で、サーバーが再構築する単一のメッセージの最大サイズを制限できる(デフォルトは2MB)。これらの設定は、アプリケーションの用途に合わせて適切に調整することが重要だ。また、サーバーのメトリクスを確認する際には、開いているWebSocket接続数がwebSocketConnectionsとして別途報告されるため、通常のHTTPリクエストとは区別して監視する必要がある。

WebSocketにおいて、サーバーがクライアントからのメッセージを受け取る際、断片化されたバイナリメッセージは完全に再構築され、テキストメッセージはUTF-8として正しくデコードされてから、onTextやonBinaryといったコールバックメソッドに渡される。onBinaryに渡されるバイト配列は、そのコールバックメソッドが完了するまでの間だけ有効なので、もし別の処理でそのデータを長く保持したい場合は、配列の内容をコピーする必要がある。また、これらのコールバックメソッドは、その接続を担当するスレッドで実行される。もしonTextやonBinaryの処理が非常に重く、時間がかかると、その接続からの次のメッセージの読み込みが停止してしまう。つまり、一つの遅い処理が、そのクライアントとの通信全体を滞らせる可能性があるのだ。

さらに、サーバーからクライアントへメッセージを送信する際、もしクライアント側が何らかの理由でメッセージの受信を停止してしまうと、サーバー側のsendメソッドがブロック(処理が一時停止)する可能性がある。これは「バックプレッシャー」と呼ばれる現象で、サーバーがクライアントの処理能力を超えてメッセージを送り続けることを防ぐための仕組みだ。しかし、もしサーバーが複数のクライアントに同時にメッセージをブロードキャスト(一斉送信)するような場合、たった一人の遅いクライアントによって、すべてのクライアントへのメッセージ送信が遅延してしまう可能性がある。このような事態を避けるためには、単にメッセージを送信し続けるのではなく、適切なサイズの「アプリケーションワークキュー」や、専用の「送信プール」を使って、送信処理を非同期的に行うなどの工夫が必要になる。

Codename OneのWebSocketサーバー実装は、彼ら自身のスクリーンショット転送という実際のユースケースでリアルな画像トラフィックを処理していることから、堅牢性が期待できる。しかし、この事実だけで「あらゆる悪意のある通信フレームにも対応できる」とか「本番環境で何万もの接続を処理できる」と結論づけるのは早計だ。そうした側面は、TLSの利用状況、サーバーの実行モード、メッセージサイズ、そして開発者が実装するビジネスロジックによって大きく左右されるため、別途詳細なテストが必要になる。

現在のCodename OneのWebSocketサーバーは、RFC 6455プロトコルをHTTP/1.1上でサポートしている。しかし、permessage-deflate(メッセージを圧縮して通信量を削減する機能)やHTTP/2 extended CONNECT(HTTP/2上でWebSocket接続を確立する機能)といった、より高度な機能はまだサポートされていない。これらの制約は、このWebSocketサーバーを導入する前に、既存のインフラストラクチャや要件と照らし合わせて確認すべき点となる。また、サーバーが正常に停止する際には、オープンしているWebSocket接続に対して1001 “going away”という特別なクローズコードを送信する。これは「サーバーが意図的に停止します」という通知であり、クライアント側はこの通知を受け取ったら、自身のポリシーに基づいて再接続を試みるなどの適切な対応を取ることができる。しかし、WebSocketサーバーが提供するのはあくまで通信の基盤であり、クライアントの認証や認可、あるいは通信が途絶えた際に漏れてしまったビジネスイベントをどうやって再送するかといった、より高レベルなアプリケーションロジックは、開発者が別途実装する必要がある。

関連コンテンツ

関連IT用語