[アップデート] Amazon AppStream 2.0でUDPストリーミングがサポートされました

[アップデート] Amazon AppStream 2.0でUDPストリーミングがサポートされました

Clock Icon2022.07.24

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

しばたです。

すこし前の話ですがAmazon AppStream 2.0でUDPストリーミングがサポートされました。
AWSからのアナウンスはこちらになります。

https://aws.amazon.com/jp/about-aws/whats-new/2022/06/amazon-appstream-2-0-udp-streaming-windows-native-client/

基本的にはアナウンス通りの話なのですが、率直なところかなりアバウトな内容で不明点が結構あったので分かる範囲で調べてみました。

どういうことか?

通常AppStream 2.0の通信はHTTPS(TCP 443)で行われます。
AWSのアナウンスによれば通信環境が悪かったり通信が制限されている環境向けにUDP(UDP 8433[1])での通信もサポートしたとのことです。
UDP通信は現時点では最新バージョンのWindowsネイティブクライアントを使う場合のみサポートされ、UDP通信が使えない場合はTCP通信にフォールバックされます。

ここで一点疑問を解消できなかったのですが、AppStream 2.0の通信は大きく「認証」と「ストリーミング」の二系統あり両者ともHTTPS(TCP 443)を使います。

今回の更新は「UDPストリーミング」とのことなので、おそらくですがストリーミング通信のみUDPをサポートし、認証の通信は従来どおりHTTPSのみだと予測されます。

裏どりできる情報を見つけることが出来なかったので断言できないのですが、TCP無しでUDPオンリーという構成には出来ないでしょう。[2]

要件や制約

ここからはもう少し細かい要件について解説します。

通信要件

通信要件はこちらのドキュメントに記載されています。

こちらによれば、

  • UDPの通信はUDP 8433ポートを使用
  • 最新のWindowsネイティブクライアントでのみUDP通信可能

であり、加えて先述のアナウンスにある通りAWSのサービスエンドポイント(AWSのIP範囲)に対する疎通が必要です。
また、VPC Endpoint(PrivateLink)を利用する場合はUDP通信は非サポート(TCP通信のみ可能)なのでご注意ください。

サポートされるWindowsネイティブクライアントバージョン

ドキュメントでは「最新のWindowsネイティブクライアント」と表現されることが多かったのですが、より具体的にはVer.1.1.1025以降がサポート対象となります。

サポートされるベースイメージ

サーバー側の条件としてベースイメージがUDPをサポートするバージョンである必要があるそうです。

こちらは具体的なバージョン番号を見つけることができなかったのですが、ドキュメント上は「最新バージョンのイメージ」と記載されており、本日時点においては「2022年7月12日版」と「2022年6月20日版」が最新なのでこれらのバージョンのイメージを使えば問題ないと思います。

また、AWSがベースイメージを決めるElastic Fleetsにおいては既にサポート済みでありユーザーが気にする点はありません。

補足 : UDP通信の実装

Windowsクライアントのシステム要件を確認すると

The Windows native client supports UDP as well as the default TCP-based streaming over NICE DCV.
For more information about NICE DCV and UDP, see Enabling the QUIC UDP transport protocol.

とあり、UDP通信の実体はNICE DCVのUDP通信(QUIC)とのことです。
AppStream 2.0のストリーミングでNICE DCVを使っていることは公開されていますので、まあ、これは予想通りかなって感じですね。

ちなみにNICE DCVのUDP通信はデフォルトでUDP 8443ポートを使います。
Image Builderからサーバー側設定を見るとUDP 8300ポートを使う感じで最初に説明したUDP 8433とも異なっていました。
この点からおそらく、

  • ユーザー → (UDP 8433) → AppStream 2.0 UDPエンドポイント → (UDP 8300) → フリートインスタンス

と言う感じの通信をしていると推測されます。

確認してみた

ここからは実際に試していきます。

クライアント環境

クライアント環境は64bit版 Windows 10 Pro (21H1)に最新のWindowsネイティブクライアントをダウンロードしてインストール済みです。

インストール手順は画面の指示に従うだけなので割愛します。
バージョンは先述のVer.1.1.1025です。

サーバー環境

サーバー環境については以下としています。

  • 本日時点で最新の「AppStream-WinServer2019-07-12-2022」をベースにイメージを作成
    • バージョンは「2022年7月12日版」となります
  • On-Demandフリート環境をよしなに用意
  • テスト用スタックをよしなに用意

UDP通信をするためにはスタックの設定を変更する必要があります。

スタック設定に「Streaming Experience Settings」欄が新たに増えています。

「Edit」ボタンを押してこちらを編集すると下図の様な画面になりますので、優先プロトコルを「UDP」に変更して保存します。

内容が更新されればOKです。

更新後に新たに接続されるセッションからUDP通信が有効になります。

動作確認

これで準備ができたのでフリートを起動し、Windowsネイティブクライアントから接続してみます。

接続後もパッと見ではこれまでどおり何も変わりありません。

Streaming Modeで確認できる通信状況もプロトコルまでは表示しないため外部からはUDP通信しているのか判別する方法がありませんでした。

仕方ないのでWireSharkを使い通信を確認してみると、こんな感じでQUICの通信がされていることが確認できました。

ちなみにTCP通信の場合はこんな感じです。WebSocketで通信しています。

補足 : Windowsネイティブクライアントのデバッグログ

あくまで非公式な方法ですが、UDP通信を判別するもう一つの方法としてWindowsネイティブクライアントのデバッグログを取得する方法があります。

Windowsネイティブクライアントを調べてみると.NETのアプリケーションでログの取得にlog4netを使っていることがわかりました。
ログ出力の設定ファイルが

  • "ユーザープロファイル"\AppData\Local\AppStreamClient\app-"バージョン番号"\Log4Net.config

にあるので、テキストエディタでファイルを開き、以下のroot配下のログレベルをINFOからDEBUGに変えてやるとデバッグログを取得できます。

Log4Net.config
<log4net>

  // ・・・省略・・・

  <root>
    <level value="INFO" />
    <appender-ref ref="applicationLogsAppender" />
  </root>

</log4net>

アプリケーションログは以下のフォルダに起動毎に保存されます。

  • "ユーザープロファイル"\AppData\Local\Amazon\AppStreamClient\logs

AppStram 2.0がUDP通信をしている場合はログに以下の様な感じでQUIC関連のログが出力されます。

QUIC通信時のログ
# デバッグログを一部だけ抜粋
2022-07-24 04:35:28,344|[DEBUG] viewer.QuicConnection - New message, status: Complete, delivery: Reliable, proto size: 32
2022-07-24 04:35:28,344|[DEBUG] viewer.QuicConnection - Message received with 32 header and body size
2022-07-24 04:35:28,344|[DEBUG] viewer.QuicTransport - Body length 22, payload length 214
2022-07-24 04:35:28,344|[DEBUG] viewer.DisplayChannel - Read 214 bytes of payload
2022-07-24 04:35:28,344|[DEBUG] viewer.DisplayChannel - Received new tile for frame 2734 (Stream 3): { "x": 928, "y": 256, "width": 160, "height": 96 } [ ]
2022-07-24 04:35:28,344|[DEBUG] viewer.DisplayChannel - Message TileUpdate managed in 00:00:00.0000400
2022-07-24 04:35:28,344|[DEBUG] viewer.QuicTransport - <<< PROCESSED message in 00:00:00.0000613
2022-07-24 04:35:28,344|[DEBUG] viewer.DisplayChannel - Decompress task (lz4.3) frame 2734 starting
2022-07-24 04:35:28,344|[DEBUG] viewer.DisplayChannel - Successfully decompressed (lz4.3) for frame 2734
2022-07-24 04:35:28,344|[DEBUG] viewer.DisplayChannel - Decompress task (lz4.3) frame 2734 complete

代わりにTCP通信をしている場合はWebSocket通信のログが出力されます。

WebSocket通信時のログ
# デバッグログを一部だけ抜粋
2022-07-24 02:21:16,946|[DEBUG] viewer.WebSocketTransport - >>> Sending message...
2022-07-24 02:21:16,946|[DEBUG] viewer.WebSocketTransport - >>> SENT Header & body: body 16 (16), payload 0 (0)
2022-07-24 02:21:16,946|[DEBUG] viewer.WebSocketTransport - >>> Message sent in 00:00:00.0000811
2022-07-24 02:21:16,947|[DEBUG] viewer.DisplayChannel - >>> SENT Message ClientMessage in 00:00:00.0002989
2022-07-24 02:21:16,947|[DEBUG] viewer.DisplayChannel - Swap task frame 296 completed
2022-07-24 02:21:16,978|[DEBUG] viewer.WebSocketTransport - <<< RECEIVED Header: body 21 (24), payload 83 (88)
2022-07-24 02:21:16,978|[DEBUG] viewer.WebSocketTransport - <<< RECEIVED Body
2022-07-24 02:21:16,978|[DEBUG] viewer.WebSocketTransport - <<< RECEIVED Body padding
2022-07-24 02:21:16,978|[DEBUG] viewer.WebSocketTransport - <<< RECEIVED Payload: first byte: 1F, last: 0C
2022-07-24 02:21:16,978|[DEBUG] viewer.WebSocketTransport - <<< RECEIVED Payload padding
2022-07-24 02:21:16,978|[DEBUG] viewer.WebSocketTransport - <<< RECEIVED message in 00:00:00.0001231
2022-07-24 02:21:16,978|[DEBUG] viewer.DisplayChannel - Read 83 bytes of payload
2022-07-24 02:21:16,978|[DEBUG] viewer.DisplayChannel - Received new tile for frame 297 (Stream 6): { "x": 1120, "y": 352, "width": 96, "height": 64 } [ ]
2022-07-24 02:21:16,978|[DEBUG] viewer.DisplayChannel - Message TileUpdate managed in 00:00:00.0000943
2022-07-24 02:21:16,978|[DEBUG] viewer.WebSocketTransport - <<< PROCESSED message in 00:00:00.0001287

このほかにもAppStream 2.0ストリーミング接続先の違いで通信方法を判別することも可能です。

# UDP通信の接続先
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.amazonappstream.com:8433/streaming/yy-zzz/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/ws over Quic

# TCP通信の接続先
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.amazonappstream.com:443/streaming/yy-zzz/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/ws over WebSocket

なお、デバッグログは大量に発生するので動作確認が済んだ後は元に戻しておくことをお勧めします。

最後に

以上となります。

AppStream 2.0のUDP通信は利用者からすれば透過的であるため「今期待した通信をしているのか?」「自分の設定はこれで正しいのか?」を裏取りするのに非常に苦労しました...
せめてクライアントの画面上で「今どちらのプロトコルで通信してるか」くらいは判別できる様になると助かるのですが、こちらは今後の更新に期待したい感じです。

脚注
  1. 8443でなく 8433 なので注意! ↩︎

  2. 後述のWireSharkによる調査やデバッグログを見る分にはTCP + UDP通信でした ↩︎

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.