simplestarの技術ブログ

目的を書いて、思想と試行、結果と考察、そして具体的な手段を記録します。

Magic Onion:複数ポート番号のサーバーをdockerコンテナで

手順だけ記録しておきます。

基本
qiita.com

ここで Dockerfile を記述しているけど

FROM mcr.microsoft.com/dotnet/core/runtime:2.2
WORKDIR /app
COPY . .

とエントリポイントを削除

あとサーバー側の実装で引数一個目で port 番号を受け取って利用するようにしておく。

using Grpc.Core;
using MagicOnion.Hosting;
using MagicOnion.Server;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using System.Threading.Tasks;

namespace CubeWalk.Server
{
    class Program
    {
        static async Task Main(string[] args)
        {            
            if (1 > args.Length || !int.TryParse(args[0], out int port))
                return;

            GrpcEnvironment.SetLogger(new Grpc.Core.Logging.ConsoleLogger());

            // for SSL/TLS connection
            //var config = new ConfigurationBuilder().AddEnvironmentVariables().Build();
            //var certificates = new List<KeyCertificatePair> { new KeyCertificatePair(File.ReadAllText("server.crt"), File.ReadAllText("server.key")) };
            //var credential = new SslServerCredentials(certificates);

            await MagicOnionHost.CreateDefaultBuilder()
                .UseMagicOnion(
                    new MagicOnionOptions(isReturnExceptionStackTraceInErrorDetail: true),
                    new ServerPort("0.0.0.0", port, ServerCredentials.Insecure))
                    // for SSL/TLS Connection
                    //new ServerPort(config.GetValue<string>("MAGICONION_HOST", "127.0.0.1"), 12345, credential))
                .RunConsoleAsync();
        }
    }
}

out フォルダをカレントにイメージをビルドして

docker build . -t cubewalkroom:1.0

次の run コマンドで port フォワードして、とりあえず 12000 ポートでサーバーを立てます。

$ docker run -d --rm -p 12000-12100:12000-12100 --name cubewalkroom cubewalkroom:1.0 dotnet CubeWalkServer.dll 12000

続いて、ポートを一つずつ消費しながらサーバーを立てます。

$ docker exec -d cubewalkroom dotnet CubeWalkServer.dll 12001
$ docker exec -d cubewalkroom dotnet CubeWalkServer.dll 12002
$ docker exec -d cubewalkroom dotnet CubeWalkServer.dll 12003
.
.
.

それぞれの port に対して接続して利用することができました。

追記:
なんのためにポートを複数使う?
プロセスを分離できるので、分けたあとのお互いの影響 0 じゃん
と思っていたけど、内心パフォーマンスの分散にもなるかなって感じてました→原理的にむしろ悪くする

同じポートを使って詰まることはなく、ソケットを作ってお互い通信し、そのソケットにカーネルがパケットを振り分けるので
つまり、ポート一つに全アクセスが集中するのではなく、分散したソケット同士で通信するので、ポート一つでも分散できていたという話

こんな書式で複数ポートをフォワーディングできるという、ただそれだけの記事になったが
副次的にいろいろとポートとソケット、LinuxNIC, hard IRQ とか知ることができた