チュートリアル: Azure Relay を使用して、オンプレミスの WCF サービスをクラウドの Web アプリケーションに公開する
この記事では、Microsoft Azure と Visual Studio を使ってハイブリッド クラウド アプリケーションを作成する方法について説明します。 ここではクラウド内の複数の Azure リソースを使用するアプリケーションを作成します。 このチュートリアルでは、次のことについて説明します。
- Web ソリューションによって使用される Web サービスを作成、または既存の Web サービスを適合させる方法。
- Azure Windows Communication Foundation (WCF) Relay サービスを使用して、他の場所でホストされている Azure アプリケーションと Web サービスの間でデータを共有する方法。
このチュートリアルでは、次のタスクを行います。
- このチュートリアルの前提条件をインストールする。
- シナリオを確認する。
- 名前空間を作成する。
- オンプレミスのサーバーを作成する。
- ASP.NET アプリケーションを作成する。
- アプリをローカルで実行します。
- Web アプリを Azure にデプロイする。
- Azure でアプリを実行する。
前提条件
このチュートリアルを完了するには、次の前提条件を用意しておく必要があります。
- Azure サブスクリプション。 お持ちでない場合は、開始する前に無料アカウントを作成してください。
- Visual Studio 2015 またはそれ以降。 このチュートリアルの例では、Visual Studio 2019 を使用します。
- Azure SDK for .NET。 SDK のダウンロード ページからインストールします。
Azure Relay がハイブリッド ソリューションで役立つ理由
ビジネス ソリューションは、通常、カスタム コードと既存の機能の組み合わせで構成されます。 カスタム コードで、新しい独自のビジネス要件に対応します。 既に配置されているソリューションやシステムは、既存の機能を提供します。
ソリューション アーキテクトたちは、スケーラビリティが高く運用コストが低いクラウドを使い始めています。 その中で、ソリューションの構成要素として使用する既存のサービス資産は企業ファイアウォールの内部にあり、クラウド ソリューションからの到達が難しいということがわかってきました。 多くの内部サービスは、企業ネットワークと外部との境界で簡単に公開できるような方法では構築されたり、ホストされたりしていません。
Azure Relay では、既存の WCF Web サービスを利用し、企業ネットワーク インフラストラクチャに侵入的な変更を加えることなく、そのようなサービスから企業の境界の外側にあるソリューションに安全にアクセスできるようにします。 このような Relay サービスは既存の環境内でもホストされていますが、受信セッションや要求のリッスンは、クラウドでホストされている Relay サービスにデリゲートしています。 さらに Azure Relay は、Shared Access Signature (SAS) 認証を使用して、これらのサービスを未承認のアクセスから保護します。
シナリオを確認する
このチュートリアルでは、商品在庫ページに商品の一覧を表示する ASP.NET Web サイトを作成します。
このチュートリアルでは、既存のオンプレミスのシステムに商品情報が格納されているものとし、Azure Relay を使用してそのシステムにアクセスします。 単純なコンソール アプリケーションで実行される Web サービスで、この状況をシミュレートします。 これには、インメモリ セットの製品が含まれています。 このコンソール アプリケーションをユーザー自身のコンピューターで実行し、Web ロールを Azure にデプロイできます。 これにより、Azure データセンターで実行されている Web ロールがコンピューターを呼び出す方法を確認できます。 少なくとも 1 つのファイアウォールとネットワーク アドレス変換 (NAT) レイヤーの背後にコンピューターがほぼ確実に存在する場合でも、この呼び出しは発生します。
開発環境の設定
Azure アプリケーションの開発を開始する前に、ツールをダウンロードして、開発環境を設定します。
- SDK のダウンロード ページから、Azure SDK for .NET をインストールします。
- [.NET] 列で、使用している [Visual Studio] のバージョンを選択します。 このチュートリアルでは、Visual Studio 2019 を使用します。
- インストーラーの実行や保存を求めるメッセージが表示されたら、[実行] を選択します。
- [Web Platform Installer] ダイアログ ボックスで、[インストール] を選択してインストールを続行します。
インストールが完了すると、アプリの開発を開始するために必要なものがすべて揃います。 SDK には、Visual Studio で Azure アプリケーションを簡単に開発するためのツールが用意されています。
名前空間の作成
最初の手順として、名前空間を作成し、Shared Access Signature (SAS) キーを取得します。 名前空間により、リレー サービスが公開する各アプリケーションにアプリケーション境界が設けられます。 SAS キーは、サービスの名前空間が作成されると、システムによって自動的に生成されます。 サービス名前空間と SAS キーの組み合わせが、アプリケーションへのアクセスを Azure が認証する資格情報になります。
Azure portal にサインインします。
左側のメニューから、 [すべてのサービス] を選択します。 [統合] を選択し、[リレー] を検索し、[リレー] の上にマウス ポインターを移動して、[作成] を選択します。
[名前空間の作成] ページで、これらの手順を実行します。
名前空間を作成する Azure サブスクリプションを選択します。
[リソース グループ] で、名前空間を追加する既存のリソース グループを選択するか、新しいリソース グループを作成します。
リレー名前空間の名前を入力します。
名前空間をホストするリージョンを選択します。
ページ下部にある [確認と作成] を選択します。
[確認および作成] ページで、 [作成] を選択します。
数分後に、名前空間の [リレー] ページを確認します。
管理資格情報を取得する
[リレー] ページで、左側のメニューの [共有アクセス ポリシー] を選択します。
[共有アクセス ポリシー] ページで、 [RootManageSharedAccessKey] を選択します。
[SAS ポリシー:RootManageSharedAccessKey] の下で、 [プライマリ接続文字列] の横の [コピー] ボタンを選択します。 これで、後で使用できるように接続文字列がクリップボードにコピーされます。 この値をメモ帳などに一時的に貼り付けます。
前の手順を繰り返し、 [主キー] の値をコピーして、後で使用するために一時的な場所に貼り付けます。
オンプレミスのサーバーを作成する
まず、シミュレートするオンプレミスの商品カタログ システムを構築します。 このプロジェクトは Visual Studio コンソール アプリケーションです。Azure Service Bus NuGet パッケージを使用して、Service Bus ライブラリと構成設定を組み込みます。
Microsoft Visual Studio を管理者として起動します。 これを行うには、Visual Studio のプログラム アイコンを右クリックして [管理者として実行] を選択します。
Visual Studio で、 [新しいプロジェクトの作成] を選択します。
[新しいプロジェクトの作成] で、C# の [コンソール アプリ (.NET Framework)] を選択し、[次へ] を選択します。
プロジェクトに ProductsServer と名前を付け、[作成] を選択します。
ソリューション エクスプローラーで ProductsServer プロジェクトを右クリックし、[NuGet パッケージの管理] を選択します。
[参照] を選択し、WindowsAzure.ServiceBus を探して選択します。 [インストール] を選択して、使用条件に同意します。
これで、必要なクライアント アセンブリを参照できるようになりました。
商品のコントラクト用に新しいクラスを追加します。 ソリューション エクスプローラーで、ProductsServer プロジェクトを右クリックし、[追加]>[クラス] を選択します。
[名前] に ProductsContract.cs という名前を入力し、[追加] を選択します。
ソリューションに対して次のコード変更を行います。
ProductsContract.cs で、名前空間の定義を次のコードに置き換えます。このコードはサービスのコントラクトを定義します。
namespace ProductsServer { using System.Collections.Generic; using System.Runtime.Serialization; using System.ServiceModel; // Define the data contract for the service [DataContract] // Declare the serializable properties. public class ProductData { [DataMember] public string Id { get; set; } [DataMember] public string Name { get; set; } [DataMember] public string Quantity { get; set; } } // Define the service contract. [ServiceContract] interface IProducts { [OperationContract] IList<ProductData> GetProducts(); } interface IProductsChannel : IProducts, IClientChannel { } }
Program.cs で、名前空間の定義を次のコードに書き換えます。このコードは、プロファイル サービスとそのホストを追加します。
namespace ProductsServer { using System; using System.Linq; using System.Collections.Generic; using System.ServiceModel; // Implement the IProducts interface. class ProductsService : IProducts { // Populate array of products for display on website ProductData[] products = new [] { new ProductData{ Id = "1", Name = "Rock", Quantity = "1"}, new ProductData{ Id = "2", Name = "Paper", Quantity = "3"}, new ProductData{ Id = "3", Name = "Scissors", Quantity = "5"}, new ProductData{ Id = "4", Name = "Well", Quantity = "2500"}, }; // Display a message in the service console application // when the list of products is retrieved. public IList<ProductData> GetProducts() { Console.WriteLine("GetProducts called."); return products; } } class Program { // Define the Main() function in the service application. static void Main(string[] args) { var sh = new ServiceHost(typeof(ProductsService)); sh.Open(); Console.WriteLine("Press ENTER to close"); Console.ReadLine(); sh.Close(); } } }
ソリューション エクスプローラーで、App.config をダブルクリックして、Visual Studio エディターでそのファイルを開きます。
<system.ServiceModel>
要素の下 (ただし、<system.ServiceModel>
内) に、次の XML コードを追加します。重要
yourServiceNamespace
を名前空間の名前に、yourKey
を先ほどポータルから取得した SAS キーに置き換えてください。<services> <service name="ProductsServer.ProductsService"> <endpoint address="sb://yourServiceNamespace.servicebus.windows.net/products" binding="netTcpRelayBinding" contract="ProductsServer.IProducts" behaviorConfiguration="products"/> </service> </services> <behaviors> <endpointBehaviors> <behavior name="products"> <transportClientEndpointBehavior> <tokenProvider> <sharedAccessSignature keyName="RootManageSharedAccessKey" key="yourKey" /> </tokenProvider> </transportClientEndpointBehavior> </behavior> </endpointBehaviors> </behaviors>
Note
transportClientEndpointBehavior
が原因で発生するエラーは、この例では単に警告であり、障害となっている問題障害となっている問題ではありません。引き続き App.config 内で、
<appSettings>
要素内の接続文字列の値を、前の手順でポータルから取得した接続文字列に置き換えます。<appSettings> <!-- Service Bus specific app settings for messaging connections --> <add key="Microsoft.ServiceBus.ConnectionString" value="Endpoint=sb://yourNamespace.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=yourKey"/> </appSettings>
Ctrl + Shift + B キーを押すか [ビルド]>[ソリューションのビルド] を選択してアプリケーションをビルドし、これまでの作業が正確にできていることを確認します。
ASP.NET アプリケーションを作成する
このセクションでは、商品サービスから取得したデータを表示する単純な ASP.NET アプリケーションを構築します。
プロジェクトを作成する
Visual Studio が管理者として実行されていることを確認します。
Visual Studio で、 [新しいプロジェクトの作成] を選択します。
[新しいプロジェクトの作成] で、C# の [ASP.NET Web アプリケーション (.NET Framework)] を選択し、[次へ] を選択します。
プロジェクトに ProductsPortal と名前を付け、[作成] を選択します。
[新しい ASP.NET Web アプリケーションを作成する] で **[MVC] を選択し、[認証] で [変更] を選択します。
[認証の変更] で、[認証なし] を選択して、[OK] を選択します。 このチュートリアルでは、ユーザーがサインインする必要がないアプリケーションをデプロイします。
[新しい ASP.NET Web アプリケーションを作成する] に戻り、[作成] を選択して MVC アプリを作成します。
新しい Web アプリの Azure リソースを構成する Web アプリの発行の手順に従います。 その後、このチュートリアルに戻り、次の手順に進みます。
ソリューション エクスプローラーで [モデル] を右クリックし、[追加]>[クラス] を選択します。
クラスに Product.cs と名前を付け、[追加] を選択します。
Web アプリケーションを変更する
Visual Studio で、Product.cs ファイルの既存の名前空間定義を次のコードに書き換えます。
// Declare properties for the products inventory. namespace ProductsWeb.Models { public class Product { public string Id { get; set; } public string Name { get; set; } public string Quantity { get; set; } } }
ソリューション エクスプローラーで [コントローラー] を展開し、HomeController.cs をダブルクリックして Visual Studio でファイルを開きます。
HomeController.cs の既存の名前空間の定義を次のコードに書き換えます。
namespace ProductsWeb.Controllers { using System.Collections.Generic; using System.Web.Mvc; using Models; public class HomeController : Controller { // Return a view of the products inventory. public ActionResult Index(string Identifier, string ProductName) { var products = new List<Product> {new Product {Id = Identifier, Name = ProductName}}; return View(products); } } }
ソリューション エクスプローラーで、[表示]>[共有] を展開し、_Layout.cshtml をダブルクリックして Visual Studio エディターでファイルを開きます。
My ASP.NET Application
のすべての出現箇所を Northwind Traders Products に変更します。Home
、About
、およびContact
のリンクを削除します。 次の例では、強調表示されたコードを削除します。ソリューション エクスプローラーで [表示]>[ホーム] を展開し、Index.cshtml をダブルクリックして Visual Studio エディターでファイルを開きます。 ファイルの内容全体を次のコードに置き換えます。
@model IEnumerable<ProductsWeb.Models.Product> @{ ViewBag.Title = "Index"; } <h2>Prod Inventory</h2> <table> <tr> <th> @Html.DisplayNameFor(model => model.Name) </th> <th></th> <th> @Html.DisplayNameFor(model => model.Quantity) </th> </tr> @foreach (var item in Model) { <tr> <td> @Html.DisplayFor(modelItem => item.Name) </td> <td> @Html.DisplayFor(modelItem => item.Quantity) </td> </tr> } </table>
ここまでの作業が正確にできていることを確認するために、Ctrl + Shift + B キーを押してプロジェクトをビルドします。
アプリをローカルで実行する
アプリケーションを実行して、動作を確認します。
- ProductsPortal がアクティブなプロジェクトであることを確認します。 ソリューション エクスプローラーで、プロジェクト名を右クリックして [スタートアップ プロジェクトに設定] を選択します。
- Visual Studio で F5 キーを押します。
アプリケーションがブラウザーに表示され、実行されます。
統合する
次の手順では、オンプレミスの商品サーバーと ASP.NET アプリケーションを連結します。
まだ開いていない場合は、Visual Studio で、「ASP.NET アプリケーションを作成する」セクションで作成した ProductsPortal プロジェクトを開きます。
「オンプレミスのサーバーを作成する」に記載されている手順に従い、NuGet パッケージを Reference プロジェクトに追加します。 ソリューション エクスプローラーで ProductsPortal プロジェクトを右クリックし、[NuGet パッケージの管理] を選択します。
WindowsAzure.ServiceBus を検索し、[WindowsAzure.ServiceBus] 項目を選択します。 次に、インストールを完了し、このダイアログ ボックスを閉じます。
ソリューション エクスプローラーで、ProductsPortal プロジェクトを右クリックし、[追加]>[既存の項目] を選択します。
ProductsServer コンソール プロジェクトの ProductsContract.cs ファイルに移動します。 ProductsContract.cs を選択します。 [追加] の横にある下矢印を選択し、[リンクとして追加] を選択します。
次に、Visual Studio エディターで HomeController.cs ファイルを開き、名前空間定義を次のコードに置き換えます。
yourServiceNamespace
を実際のリレー名前空間の名前に、yourKey
を実際の SAS キーに置き換えてください。 このコードを使用すると、クライアントからオンプレミスのサービスを呼び出し、その結果を返すことができます。namespace ProductsWeb.Controllers { using System.Linq; using System.ServiceModel; using System.Web.Mvc; using Microsoft.ServiceBus; using Models; using ProductsServer; public class HomeController : Controller { // Declare the channel factory. static ChannelFactory<IProductsChannel> channelFactory; static HomeController() { // Create shared access signature token credentials for authentication. channelFactory = new ChannelFactory<IProductsChannel>(new NetTcpRelayBinding(), "sb://yourServiceNamespace.servicebus.windows.net/products"); channelFactory.Endpoint.Behaviors.Add(new TransportClientEndpointBehavior { TokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider( "RootManageSharedAccessKey", "yourKey") }); } public ActionResult Index() { using (IProductsChannel channel = channelFactory.CreateChannel()) { // Return a view of the products inventory. return this.View(from prod in channel.GetProducts() select new Product { Id = prod.Id, Name = prod.Name, Quantity = prod.Quantity }); } } } }
ソリューション エクスプローラーで ProductsPortal ソリューションを右クリックします。 プロジェクトではなく、ソリューションを右クリックしてください。 [追加]>[既存のプロジェクト] を選択します。
ProductsServer プロジェクトに移動し、ProductsServer.csproj ソリューション ファイルをダブルクリックして追加します。
ProductsPortal にデータを表示するには、ProductsServer が実行されている必要があります。 ソリューション エクスプローラーで ProductsPortal ソリューションを右クリックし、[プロパティ] を選択して [プロパティ ページ] を表示します。
[共通プロパティ]>[スタートアップ プロジェクト] の順に選択し、[マルチ スタートアップ プロジェクト] を選択します。 [ProductsServer] と [ProductsPortal] がこの順で表示されていることと、その両方の [アクション] が [開始] であることを確認します。
左側の [共通プロパティ]>[プロジェクトの依存関係] を選択します。
[プロジェクト] には [ProductsPortal] を選択します。 [ProductsServer] が選択されていることを確認してください。
[プロジェクト] には [ProductsServer] を選択します。 ProductsPortal が選択されていないことを確認してから、[OK] を選択して変更を保存します。
プロジェクトをローカルで実行する
アプリケーションをローカルでテストするには、Visual Studio で F5 キーを押します。 まず、オンプレミスのサーバー ProductsServer を起動し、次に ProductsPortal アプリケーションをブラウザー ウィンドウで起動する必要があります。 この時点で、オンプレミスのシステムの商品サービスから取得された商品在庫一覧データが表示されます。
[ProductsPortal] ページで [最新の情報に更新] を選択します。 ページを更新するたびに、ProductsServer から GetProducts()
が呼び出され、サーバー アプリにメッセージが表示されます。
次のセクションに進む前に、両方のアプリケーションを終了します。
Azure Web アプリに ProductsPortal プロジェクトをデプロイする
次の手順は、Azure Web アプリを ProductsPortal フロントエンドに再発行することです。
ソリューション エクスプローラーで [ProductsPortal] プロジェクトを右クリックし、[発行] を選択します。 [発行] ページで [発行] を選択します。
Note
デプロイの後で ProductsPortal Web プロジェクトが自動的に起動するとき、ブラウザー ウィンドウにエラー メッセージが表示されることがあります。 これは想定されたエラーです。ProductsServer アプリケーションがまだ実行されていないため、このようなエラーが発生します。
デプロイされた Web アプリの URL をコピーします。 この URL は後で必要になります。 この URL は、Visual Studio の [Azure App Service のアクティビティ] ウィンドウからも入手できます。
ブラウザー ウィンドウを閉じてアプリケーションの実行を停止します。
アプリケーションをクラウドで実行する前に、ProductsPortal が Visual Studio で Web アプリとして起動していることを確認する必要があります。
Visual Studio で [ProductsPortal] プロジェクトを右クリックし、[プロパティ] を選択します。
Web を選択します。 [開始アクション] で [URL の開始] を選択します。 以前にデプロイした Web アプリの URL (この例では
https://productsportal20190906122808.azurewebsites.net/
) を入力します。[ファイル]>[すべて保存] を選択します。
[ビルド]>[ソリューションのリビルド] を選択します。
アプリケーションの実行
F5 キーを押して、アプリケーションをビルドして実行します。 次のように、まず、オンプレミスのサーバー (ProductsServer コンソール アプリケーション) を起動し、次に ProductsPortal アプリケーションをブラウザー ウィンドウで起動する必要があります。
オンプレミスのシステムの商品サービスから取得された商品在庫一覧データが Web アプリ上に表示されます。 URL を確認し、ProductsPortal が Azure Web アプリとしてクラウドで実行されていることを確かめます。
重要
ProductsServer コンソール アプリケーションが実行されており、ProductsPortal アプリケーションにデータを提供できる状態になっている必要があります。 ブラウザーにエラーが表示された場合は、ProductsServer が次のメッセージを読み込んで表示するまで数秒待ってからブラウザーを更新してください。
ブラウザーで、[ProductsPortal] ページを更新します。 ページを更新するたびに、ProductsServer から GetProducts()
が呼び出され、サーバー アプリにメッセージが表示されます。
次のステップ
次のチュートリアルに進みます。