2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

.NET をIBM Powerで動かしてみた話 #2

Last updated at Posted at 2022-12-20

本".NET をIBM Powerで動かしてみた話"シリーズは、.NET 7がLinux on Power環境で利用可能となった(IBM社のブログ : .NET 7 now includes support for Linux on Power!)ということで、以下のテーマで3つのブログを掲載予定としています。いずれのテーマも、Linux on Powerをご存知の方、もしくは触ったことがある方は今回のニュースを聞いて、抱かれた疑問ではないでしょうか。

1. 「本当に.NET 7は問題なく動くのか」
2. 「x86環境で作成された.NET アプリケーションはppc64le環境でもそのまま動くのか」
3. 「コンテナ環境でも利用できるのか」

今回は、2つ目のテーマである"「x86環境で作成された.NET アプリケーションはppc64le環境でもそのまま動くのか」" について記載していこうと思います。
なお、本記事で使用している環境は、上記の"1. 「本当に.NET 7は問題なく動くのか」"の記事で作成したものをそのまま使用しています。
まだ読まれていない方は、よろしければ本記事に入る前に以下の内容もご覧ください。

それでは、本題に入っていきたいと思います。

2. 「x86環境で作成された.NET アプリケーションはppc64le環境でもそのまま動くのか」

このテーマでは実際に.NETのサンプルコードを利用して、.NETアプリケーションの利用においてCPUアーキテクチャ(x86環境とPower環境)を意識することがあるのかを確認していきたいと思います。.NETの仕組み的に、サンプルコードレベルでの互換性はあると理解していますが、やはり実際に動かしてみたいと思ってしまいますよね。

ちなみにこれは参考情報ですが、.NET環境においても.NETアプリケーション内部で使用している.NETコンポーネントなどは、x86環境とPower環境とでの違いはあります。こちらはPower環境に対応した、対象の.NETコンポーネントが提供されているかどうかという部分になってきます。
このような形で、既存の.NETアプリケーションのコードが"全部・そのまま・必ず"動くかというとそうではありませんのでご注意ください。一度、評価環境などで動作をご確認いただくことをお勧めいたします。

(1) 作業環境の確認

今回使用しているLinux on Power環境は以下となります。
RHEL8.7 相当となるAlmaLinux 8.7 をインストールしています。

[root@dotnet-sample-alma87 ~]# uname -a
Linux dotnet-sample-alma87 4.18.0-425.3.1.el8.ppc64le #1 SMP Tue Nov 8 14:07:43 EST 2022 ppc64le ppc64le ppc64le GNU/Linux
[root@dotnet-sample-alma87 ~]# cat /etc/redhat-release 
AlmaLinux release 8.7 (Stone Smilodon)

(2) 使用するサンプルコード

以下のGitHubの内容をもとに動作を確認しています。
このGitHubの内容は、Blazorフレームワークをベースとしたサンプルコードとなっています。

この中から、以下のコンテンツの動作を確認していきます。
問題なく動作すれば、チャット機能やカウンター機能、天気情報の確認が可能なWebUIが起動してきます。

(3) サンプルコードの実行

まず初めに任意のディレクトリで上記のGitHubレポジトリをcloneします。
今回は、/rootディレクトリ配下にworkディレクトリを作成し、そちらにgit clone したいと思います。

/root/work ディレクトリの作成
[root@dotnet-sample-alma87 ~]# mkdir /root/work
[root@dotnet-sample-alma87 ~]# cd /root/work/
[root@dotnet-sample-alma87 work]# pwd
/root/work
git cloneの実施
[root@dotnet-sample-alma87 work]# git clone https://github.com/dotnet/blazor-samples.git
Cloning into 'blazor-samples'...
remote: Enumerating objects: 1939, done.
remote: Counting objects: 100% (139/139), done.
remote: Compressing objects: 100% (55/55), done.
remote: Total 1939 (delta 101), reused 95 (delta 84), pack-reused 1800
Receiving objects: 100% (1939/1939), 627.37 KiB | 169.00 KiB/s, done.
Resolving deltas: 100% (1270/1270), done.
[root@dotnet-sample-alma87 work]# ls
blazor-samples

続いて、今回利用する"BlazorServerSignalRApp"のディレクトリの中身を確認してみます。

blazor-samples/7.0/BlazorServerSignalRApp
[root@dotnet-sample-alma87 work]# cd blazor-samples/7.0/BlazorServerSignalRApp/
[root@dotnet-sample-alma87 BlazorServerSignalRApp]# ls
App.razor  BlazorServerSignalRApp.csproj  Data  Hubs  Pages  Program.cs  Properties  Shared  _Imports.razor  appsettings.Development.json  appsettings.json  wwwroot

次に、.NETアプリケーション起動時のアクセスIPアドレスの設定を変更します。デフォルトではlocalhostとなっていますが、今回は"Any IP"(対象のAlmaLinuxがもつ全てのIPアドレスでアクセス可能)の設定に変更したいと思います。

デフォルトの設定 : Properties/launchSettings.json
[root@dotnet-sample-alma87 BlazorServerSignalRApp]# cat Properties/launchSettings.json 
{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:55347",
      "sslPort": 44312
    }
  },
  "profiles": {
    "http": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "http://localhost:5098",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "https": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "https://localhost:7033;http://localhost:5098",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}
変更後 : Properties/launchSettings.json( "localhost -> * " に変更)
[root@dotnet-sample-alma87 BlazorServerSignalRApp]# cat Properties/launchSettings.json 
{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://*:55347",
      "sslPort": 44312
    }
  },
  "profiles": {
    "http": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "http://*:5098",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "https": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "https://*:7033;http://*:5098",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

それでは早速、起動してみましょう!

起動 : dotnet run
[root@dotnet-sample-alma87 BlazorServerSignalRApp]# pwd
/root/work/blazor-samples/7.0/BlazorServerSignalRApp
[root@dotnet-sample-alma87 BlazorServerSignalRApp]# dotnet run
ビルドしています...
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://[::]:5098
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: /root/work/blazor-samples/7.0/BlazorServerSignalRApp

エラーなく、起動してきました。
また先ほどの設定変更によって、.NETアプリケーションがListenしているURLが"http://[::]:5098" となっています。もし設定を実施しない場合は、"http://localhost:5098" となり、localhostからしかアクセスできなくなります。
今回は、"http://[::]:5098"としていますので、.NETアプリケーションが起動している環境がもつIPアドレスであれば、どのIPでもアクセスが可能となっています。

それでは実際にWebUIにアクセスしてみます。正常にアプリケーションが起動していれば、以下のような画面が表示されるはずです。
そしてここまで動作を確認ができれば、.NETのアプリケーションコードがCPUアーキテクチャに依存せず、そのまま利用できていることがわかります。

  • アクセスURL : http://<IPアドレス>:5098
    image.png

WebUI画面左側のタブをそれぞれクリックすると、各ページごとに作成された機能を確認できます。

  • Counter

"Click me"ボタンを押すと、Current countの値が増えていきます。
image.png

  • Fetch Data

dotnet run を実行した翌日以降の日付で天気予報が表示されます。今回は、12月20日に実行していますので、21日からの表示になっていますね。
image.png

(4) サンプルコードを変更してみよう!

ここからは、.NETアプリケーションのソースコード変更して、どこをどう変更するとWebUIに反映されるのかを確認してみました。
実施してみたことは以下の4点です。

(a) WebUIアクセス時の"Home"画面として、起動している環境のシステム情報を表示したい
(b) 左側のタブの"BlazorServerSignalRApp"を変更したい
(c) 左側のタブの表示順を変更したい
(d) 左側のタブのアイコンを変更したい

各項目を設定するための変更対象ファイルと内容は以下です。
変更後の"BlazorServerSignalRApp"アプリケーションコードは、以下のGitHubに公開しました。

それでは早速変更箇所を見ていきます。

まずは、以下のように"/root/work/blazor-samples/7.0/BlazorServerSignalRApp/Pages/"ディレクトリ配下に"Info.razor"というファイルを作成し、(a)のやりたいことであるHome画面として表示するWebページ用のコードを作ります。

/root/work/blazor-samples/7.0/BlazorServerSignalRApp/Pages/Info.razor を作成
@page "/"
@using System.Runtime.InteropServices
@using System.IO
@using System.Diagnostics
@{
    var hostName = System.Net.Dns.GetHostName();
    System.Diagnostics.Debug.WriteLine(hostName);

    const long Mebi = 1024 * 1024;
    const long Gibi = Mebi * 1024;

    GCMemoryInfo gcInfo = GC.GetGCMemoryInfo();
    string totalAvailableMemory = GetInBestUnit(gcInfo.TotalAvailableMemoryBytes);

    bool cgroup = RuntimeInformation.OSDescription.StartsWith("Linux") && Directory.Exists("/sys/fs/cgroup/memory");
    string memoryUsage = string.Empty;
    string memoryLimit = string.Empty;

    if (cgroup)
    {
        string usage = System.IO.File.ReadAllLines("/sys/fs/cgroup/memory/memory.usage_in_bytes")[0];
        string limit = System.IO.File.ReadAllLines("/sys/fs/cgroup/memory/memory.limit_in_bytes")[0];
        memoryUsage = GetInBestUnit(long.Parse(usage));
        memoryLimit = GetInBestUnit(long.Parse(limit));
    }

}

<div class="text-center">
    <h1>Hello! .NET on Power!</h1>
</div>
<br>

<font color="#0000cd"><b>今回の検証環境は、以下となります。</b></font><br>
<font color="#0000cd"><b>x86で作成されたサンプルコードをそのまま使用して、本日のセッション用にカスタマイズしています。</b></font><br>
<br>

<div align="center">
    <style>
	table td {
		background: #eee;
	}
    	table tr:nth-child(odd) td {
		background: #fff;
    	}
	table {
		border:3px solid #333;
	}
    </style>
    
    <table class="table table-striped table-hover">
        <tr>
            <td>.NET version</td>
            <td>@RuntimeInformation.FrameworkDescription</td>
        </tr>
        <tr>
            <td>Operating system</td>
            <td>@RuntimeInformation.OSDescription</td>
        </tr>
        <tr>
            <td>Processor architecture</td>
            <td>@RuntimeInformation.OSArchitecture</td>
        </tr>
        <tr>
            <td>CPU cores</td>
            <td>@Environment.ProcessorCount</td>
        </tr>
        <tr>
            <td>Containerized</td>
            <td>@(Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") is null ? "false" : "true")</td>
        </tr>
        <tr>
            <td>Memory, total available GC memory</td>
            <td>@totalAvailableMemory</td>
        </tr>
        @if (cgroup)
        {
            <tr>
                <td>cgroup memory usage</td>
                <td>@memoryUsage</td>
            </tr>
            <tr>
                <td>cgroup memory limit</td>
                <td>@memoryLimit</td>
            </tr>
        }
        <tr>
            <td>Host name</td>
            <td>@hostName</td>
        </tr>
    </table>
</div>

@{
    string GetInBestUnit(long size)
    {
        if (size < Mebi)
        {
            return $"{size} bytes";
        }
        else if (size < Gibi)
        {
            decimal mebibytes = Decimal.Divide(size, Mebi);
            return $"{mebibytes:F} MiB";
        }
        else
        {
            decimal gibibytes = Decimal.Divide(size, Gibi);
            return $"{gibibytes:F} GiB";
        }
    }
}

続いて、WebUIにアクセスした際に"Home"として、上記のWebページが表示されるように "BlazorServerSignalRApp/Shared/NavMenu.razor"ファイルを編集します。
またこのファイルでは、WebUI左側タブに表示されている文字やコンテンツの表示順、アイコンの変更(やりたいことの(b)-(d))も可能なため、併せて変更してしまいます。

(b) 左側のタブの"BlazorServerSignalRApp"を変更したい
(c) 左側のタブの表示順を変更したい
(d) 左側のタブのアイコンを変更したい

/root/work/blazor-samples/7.0/BlazorServerSignalRApp/Shared/NavMenu.razor を編集
<div class="top-row ps-3 navbar navbar-dark">
    <div class="container-fluid">
        <a class="navbar-brand" href="">.NET on IBM Power!!</a>
        <button title="Navigation menu" class="navbar-toggler" @onclick="ToggleNavMenu">
            <span class="navbar-toggler-icon"></span>
        </button>
    </div>
</div>

<div class="@NavMenuCssClass nav-scrollable" @onclick="ToggleNavMenu">
    <nav class="flex-column">
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="">
                <span class="oi oi-home" aria-hidden="true"></span> Home
            </NavLink>
        </div>
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="chat" Match="NavLinkMatch.All">
                <span class="oi oi-chat" aria-hidden="true"></span> Communication
            </NavLink>
        </div>
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="counter">
                <span class="oi oi-plus" aria-hidden="true"></span> Counter
            </NavLink>
        </div>
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="fetchdata">
                <span class="oi oi-cloudy" aria-hidden="true"></span> WeatherForecast
            </NavLink>
        </div>
    </nav>
</div>

@code {
    private bool collapseNavMenu = true;

    private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null;

    private void ToggleNavMenu()
    {
        collapseNavMenu = !collapseNavMenu;
    }
}

最後に、デフォルトのWebUIで"Home"画面として使用されていた"チャット画面"を"Communication"タブ(/chat)に変更するため、BlazorServerSignalRApp/Pages/Index.razor ファイルを変更します。

/root/work/blazor-samples/7.0/BlazorServerSignalRApp/Pages/Index.razor を編集
@page "/chat"
@using Microsoft.AspNetCore.SignalR.Client
@inject NavigationManager Navigation
@implements IAsyncDisposable

<PageTitle>Index</PageTitle>

<div class="form-group">
    <label>
        User:
        <input @bind="userInput" />
    </label>
</div>
<div class="form-group">
    <label>
        Message:
        <input @bind="messageInput" size="50" />
    </label>
</div>
<button @onclick="Send" disabled="@(!IsConnected)">Send</button>

<hr>

<ul id="messagesList">
    @foreach (var message in messages)
    {
        <li>@message</li>
    }
</ul>

@code {
    private HubConnection? hubConnection;
    private List<string> messages = new List<string>();
    private string? userInput;
    private string? messageInput;

    protected override async Task OnInitializedAsync()
    {
        hubConnection = new HubConnectionBuilder()
            .WithUrl(Navigation.ToAbsoluteUri("/chathub"))
            .Build();

        hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
        {
            var encodedMsg = $"{user}: {message}";
            messages.Add(encodedMsg);
            InvokeAsync(StateHasChanged);
        });

        await hubConnection.StartAsync();
    }

    private async Task Send()
	{
	    if (hubConnection is not null)
            {
                await hubConnection.SendAsync("SendMessage", userInput, messageInput);
            }
	}

    public bool IsConnected =>
        hubConnection?.State == HubConnectionState.Connected;

    public async ValueTask DisposeAsync()
    {
        if (hubConnection is not null)
        {
            await hubConnection.DisposeAsync();
        }
    }
}

以上で、サンプルコードの変更は終了です。
今一度アプリケーションを起動し、想定した内容となっているか確認してみましょう。また"dotnet run"実行のタイミングでエラーなどが表示されないかも併せて確認します。(もし表示された場合には、そのエラー箇所を修正しましょう。)

dotnet run 実行
[root@dotnet-sample-alma87 BlazorServerSignalRApp]# dotnet run
ビルドしています...
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://[::]:5098
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: /root/work/blazor-samples/7.0/BlazorServerSignalRApp

正常に上記の変更がされている場合、以下のようなWebページが表示されるはずです。
ちゃんと"Home"のページコンテンツとして、システム情報が表示されていますし、左側のタブ欄も変更が反映されていますね。

image.png

まとめ

今回は、前回の内容につづき、IBM Power上での.NET 7アプリケーションの稼働確認を行いました。この結果から、アプリケーションのソースコードは基本的にはCPUアーキテクチャに依存しないことが分かりました。
しかしながら冒頭に記載しましたように、.NETアプリケーション内部で使用している.NETコンポーネントなどは、x86環境とPower環境とでの違いはあります。これはPower環境に対応した、対象の.NETコンポーネントが提供されているかどうかという部分になってきます。
その為、既存の.NETアプリケーションのコードが"全部・そのまま・必ず"動くかというとそうではありませんのでご注意ください。一度、評価環境などで動作をご確認いただくことをお勧めいたします。

次回は最後のコンテンツとなる"3. 「コンテナ環境でも利用できるのか」" について記載しています。宜しければご覧ください。

今回の内容は以上となります。本記事が何かの参考となれば幸いです。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?