CosmosDBの接続モードについて(.NET)

Azure

.NETやjavaなどのSDKを利用することで、簡単にCosmosDBにアクセスできます。しかし、実際にどのようにCosmosDBと通信しているのかについては、普段意識することはないと思います。CosmosDBへの接続には2つのモードがあるため、今回はこの2モードについて調査た内容をまとめます。

結論

  • CosmosDBの接続モードは「Gatewayモード」と「Directモード」の2種類ある
  • 「Directモード」のほうがパフォーマンス効率がいい
  • .NET SDKでアクセスする際はデフォルトで「Directモード」に設定されている

接続モード

CosmosDBに接続する際は、「Gatewayモード」と「Directモード」の2種類があります。GatewayモードではGatewayノードを経由してCosmosDBに接続しますが、Directモードでは直接接続します。そのため、DirectモードはGatewayモードに比べてネットワークホップ数が少なく、パフォーマンスが向上します。

公式ドキュメントに記載されている図を見るとイメージが掴みやすいです。

引用:Azure Cosmos DB SQL SDK の接続モード

Directモードは.NETとJavaでサポートされています。.NET SDkから接続する際は、デフォルトでDirectモードに設定されています。

また、初回接続時にコンテナ情報やルーティング情報を取得します。これらの情報はSDK上でローカルにキャッシュされるため、以降の処理はキャッシュ情報を利用します。

引用:Azure Cosmos DB SQL SDK の接続モード

動作確認

2種類の接続モードについて概要が理解できたため、簡単なサンプルで動作確認をしてみたいと思います。CRUD処理を1回ずつ行うAzure Functionsを使用します。不要な個所は省略しています。

[Function("Test1")]
public async Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req)
{
    var id = "partitionKey";
    var name = "test1";
    var cosmosData = new CosmosEntity(id, name);

    var con = this._cosmosClient.GetContainer(containerName, colletionName);

    // Create new item
    var createResult = await con.CreateItemAsync<CosmosEntity>(cosmosData);

    // Read item
    var readResult = await con.ReadItemAsync<CosmosEntity>(id, new PartitionKey(id));

    // Update item
    cosmosData.name = "test2";
    var updateResult = await con.UpsertItemAsync<CosmosEntity>(cosmosData);

    // Delete item
    var deleteResult = await con.DeleteItemAsync<CosmosEntity>(id, new PartitionKey(id));
}

CosmosDBクライアントはDIで利用できるように設定します。

public static void Main()
{
    var host = new HostBuilder()
        .ConfigureFunctionsWorkerDefaults()
        .ConfigureServices(s =>
        {
            // CosmosDBクライアントの登録
            s.AddSingleton<CosmosClient>(serviceProvider =>
            {
                return new CosmosClient(endpoint, key, options);
            });
        })
        .Build();
    host.Run();
}

デフォルトの状態で実行した結果

まずはデフォルトの設定で実行して、CDBDataPlaneRequestsログを見てみます。CDBDataPlaneRequestsログにはCosmosDBへの読み書きリクエストが出力されます。

下記のログを確認すると、初めにCollectionに対するReadが記録されています。これは、CosmosDBのコンテナ(Collection)情報を取得していると思われます。Functionsを起動したまま複数回実行してみると、最初の1回しかCollectionのReadは記録されず、2回目以降はCRUDのみログに記録されていました。一方、毎回Functionsを起動し直して実行すると、必ず最初にCollectionに対するReadがログに記録されます。

CRUD(Create、Read、Upsert、Delete)についてはすべて設定どおりDirectモードで接続していることが分かります。

Gatewayモードに変更してみる

続いて、接続モードをGatewayに変更してみます。CosmosDBClientsOptionsを利用することで、様々な設定情報を変更できます。接続モードに関してはConnectionModeを使用します。

s.AddSingleton<CosmosClient>(serviceProvider =>
{
    var options = new CosmosClientOptions()
    {
        ConnectionMode = ConnectionMode.Gateway
    };
    return new CosmosClient(endpoint, key, options);
});

Gatewayに変更後、再度Functionsを起動して接続を行った結果のログを書きにしまします。CRUD処理がすべてGatewayモードで実行されていることがわかります。

まとめ

CosmosDBの接続には「Directモード」と「Gatewayモード」の2種類のモードが存在します。.NET SDKではデフォルトでパフォーマンスが高い「Gatewayモード」が使用されます。基本的にはデフォルトの設定のままで問題ないと思います。

しかし、企業のファイアウォールなどのネットワーク設定によってはDirectモードで必要な通信を許可できないこともあるかと思います。そのような時は、Gatewayモードが選択肢になるのではないでしょうか。

コメント