Quantcast
Channel: プログラミング
Viewing all articles
Browse latest Browse all 8051

WCF サービスを Azure App Service の Web App for Containers でホストする - present

$
0
0

はじめに

Azure App Service の Web App for Containers は、Windowsコンテナをサポートしているみたい。.NET Framework + WCFのサービスを動かせるかも。

試してみた。

WCFサービスとクライアント

サービスコントラクトとデータコントラクト

using System;
using System.Runtime.Serialization;
using System.ServiceModel;

namespace NetHttpSample.Shared
{
    [ServiceContract]
    publicinterface ISampleService
    {
        [OperationContract]
        ServerInfo GetServerInfo();
    }

    [DataContract]
    publicclassServerInfo
    {
        [DataMember]
        publicstring MachineName { get; set; }

        [DataMember]
        publicstring HostName { get; set; }

        [DataMember]
        publicstring[] IPAddresses { get; set; }
    }
}

WCFサービス

サービス側は NetHttpBinding を使う。Web App for Containers だとフロントで TLSが終端されるみたいなので、コンテナ側では HTTP で待ち受ける。

using System;
using System.Linq;
using System.Net;
using System.ServiceModel;
using System.Threading;
using NetHttpSample.Shared;

namespace NetHttpSample.Server
{
    internalclassProgram
    {
        staticvoid Main(string[] args)
        {
            var host =new ServiceHost(
                typeof(SampleService),
                new Uri("http://localhost:80"));

            try
            {
                var binding =new NetHttpBinding();
                host.AddServiceEndpoint(
                    typeof(ISampleService),
                    binding,
                    "/SampleService");

                host.Open();

                foreach (var endpoint in host.Description.Endpoints)
                {
                    Console.WriteLine(endpoint.ListenUri);
                }

                Thread.Sleep(-1);
            }
            catch
            {
                host.Close();
            }
        }
    }

    [ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]
    publicclassSampleService : ISampleService
    {
        public ServerInfo GetServerInfo()
        {
            var hostName = Dns.GetHostName();
            var ipAddresses = Dns.GetHostAddresses(hostName);
            returnnew ServerInfo
            {
                MachineName = Environment.MachineName,
                HostName = hostName,
                IPAddresses = ipAddresses.Select(x => x.ToString()).ToArray(),
            };
        }
    }
}

Dockerfile

# ベースイメージとして公式の .NET Framework ランタイムイメージを使用
FROM mcr.microsoft.com/dotnet/framework/runtime:4.8-windowsservercore-ltsc2019

# アプリケーションのディレクトリを作成
WORKDIR /app

# WCF サービスのバイナリをコンテナにコピー
COPY ./bin/Debug/ /app

# 必要なポートを公開
EXPOSE 80# サービスを起動するためのエントリーポイント
ENTRYPOINT ["/app/NetHttpSample.Server.exe"]

WCFクライアント

クライアント側は NetHttpsBinding を使う。アドレス違うし、バインディングも違うから通信できるか心配だったけど、特に問題なかった。

using System;
using System.Net;
using System.Net.Security;
using System.ServiceModel;
using System.ServiceModel.Channels;
using NetHttpSample.Shared;

namespace NetHttpSample.Client
{
    internal class Program
    {
        static void Main(string[] args){
            string host;if (args.Length >0){
                host = args[0];}else{
                Console.Write("ホスト[localhost]:");
                host = Console.ReadLine();if (string.IsNullOrEmpty(host)){
                    host ="localhost";}}

            ServicePointManager.ServerCertificateValidationCallback =new RemoteCertificateValidationCallback((a, b, c, d) => true);

            for (var z =0; z <3; z++)
            {
                var binding = new NetHttpsBinding
                {
                    AllowCookies =true,
                    UseDefaultWebProxy =false,
                };
                var factory = new ChannelFactory<ISampleService>(
                    binding,
                    new EndpointAddress(
                        new Uri($"https://{host}:443/SampleService"),
                        EndpointIdentity.CreateDnsIdentity("azurewebsites.net")));
                factory.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None;for(var y =0; y <3; y++){
                    var channel = factory.CreateChannel();for(var x =0; x <10; x++){
                        var result = channel.GetServerInfo();
                        Console.WriteLine($"{nameof(result.MachineName)}: {result.MachineName}");}((IChannel)channel).Close();
                    Console.WriteLine("----------");
                }
                factory.Close();
                Console.WriteLine("====================");
            }

            Console.WriteLine("Enter で終了");
            Console.ReadLine();
        }
    }
}

デプロイ

  1. Azure ポータルでリソースグループ作成
  2. Azure ポータルでコンテナレジストリ作成
    • アクセスキーの管理者ユーザーを ON にする
  3. コンテナイメージ作成 sh docker build -t nethttpsample:1.0.0 .
  4. コンテナイメージをコンテナレジストリにプッシュ sh az acr login -n <コンテナレジストリ名> docker tag nethttpsample:1.0.0 <コンテナレジストリ名>.azurecr.io/nethttpsample:1.0.0 docker push <コンテナレジストリ名>.azurecr.io/nethttpsample:1.0.0
  5. App Service の Web App for Containers を作成

実行

Web App for Containers のインスタンスを 3 つに増やしてクライアントを実行したら、channel はオープンしている間、同じサーバーにアクセスし続けた。 channel を作り直した場合でも、作成元の ChannelFactory が同じなら、同じサーバーにアクセスし続けた。 ChannelFactory を作り直したら、違うサーバーにアクセスした。

NetTcpBinding と同じで、ChannelFactory が同じなら、channel は同じサーバーに接続し続けることを確認。期待通りの結果だ。

おわりに

レガシーな WCFサービスをどうにかしてモダンなインフラで動かしたいので、Web App for Containers というのはかなりアリだと思った。.NET Frameworkから .NETに移行するのがベストなのは理解している。ただ、あまりにも工数がかかり過ぎるのでね。


Viewing all articles
Browse latest Browse all 8051