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

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 7877

Trending Articles