Liberent-Dev’s blog

株式会社リベル・エンタテインメントのテックブログです。

DFrameを試してみる

こんにちは!
システム開発部のK.Mです。

今回の記事の経緯

以前こちらの記事にてMemoryPackの記事を書きましたが、サーバがC#で動いておりMemoryPackでリクエストとレスポンスをやり取りする形になっていると、MemoryPackを扱うためにどうしてもC#が必要になってきます。

その場合に少し困るのが負荷テストです。
LocustやGatling、JMeterを使用する場合、C#でテストシナリオが書けないので、一時的にリクエストとレスポンスをJson形式にして負荷テストすることになるのですが、その場合だとMemoryPackを含めた本番想定の負荷テストが出来ない状況になってしまいます。

そのため、C#にてテストシナリオを書けてMemoryPackでのやり取りが出来るものを検討する必要があります。
その際の検討段階に上がってきたのが、DFrameとなります。
(neuecc氏の術中にはまっていっている感じがしますが・・・)

neuecc氏が書いたDFrameの記事はこちら
githubこちら

確認環境

OS:Mac
開発環境:VisualStudio
DFrame:1.1.1

負荷かける先のAPIサーバの用意

ローカル環境で確認するため、C#にてMemoryPackでレスポンスを返すAPIサーバが必要になります。
以前の記事で用意したAPIサーバ用のプロジェクトを使っていきますので詳細は以前の記事をご確認ください。

DFrameの準備

こちらも、以前の記事で用意したAPIを叩く側のWebアプリ用のプロジェクトを使いまわします。

プロジェクトを開いて、NuGetでDFrameをインストールしていきます。
VisualStudio(以降、VS)の「ツール」→「NuGetパッケージの管理...」を選択します。

選択後、NuGetパッケージソリューションが開くので、右上の検索欄に「DFrame」を入力します。
検索結果が表示されるので、下記画像のように4点チェックボックスを選択して、「パッケージを追加」ボタンを選択します。

プロジェクトの選択が開くので、追加先のプロジェクトが選択されていることを確認して、「OK」ボタンを選択します。

NuGetで正常にインストースされるとVSのパッケージコンソールに下記のようなログが表示されます。

DFrameの追加完了後はgithub上にあるReadMeに記載されているgetting-startedを参考にしてコードを追加していきます。

using DFramme;  // ADD

public class Program
{
    public static void Main(string[] args)
    {
        DFrameApp.Run(7312, 7313);

        // これ以降の元々あったソースは不要のため削除
    }
}

ただし、このままだとDFrameの初期ページのindexが既存のindexと被ってエラーが発生するので、既存の下記ファイルを修正(または削除)しておきます。

  • index.cshtml
  • index.cshtml.cs

修正する場合はファイル名の変更とモデル名の変更が必要になります。

ファイル名変更

  • index.cshtmlindex2.cshtmlに変更
  • index.cshtml.csindex2.cshtml.csに変更
    index.cshtmlのファイル名を変更すれば自動的に変更されます。)

モデル名変更

  • index2.cshtml
    @model IndexModelとなっている箇所を@model Index2Modelに変更します。

  • index2.cshtml.cs
    IndexModelとなっている箇所をIndex2Modelに変更します。

もし上記の修正を行わずに実行した場合は、このようなエラー画面が表示されます。

DFrameの起動

修正を行った上でVS上で実行し、ブラウザでhttp://localhost:7312へアクセスします。
正常に動作していれば、下記のような画面表示となります。

テストシナリオのWorkloadを定義していないため、現状では動作しませんので続いてはテストシナリオを書いていきます。

テストシナリオの書き方

まずは、ReadMe通りに簡単なシナリオを作成するために新規ファイルを追加してコードを書きます。
VSから新規ファイル追加を選択してWorkloadTestというファイル名にします。

WorkloadTest.csを下記にように書き直します。

using System;
using DFrame;

namespace プロジェクト名
{
    public class WorkloadTest : Workload
    {
        public override async Task ExecuteAsync(WorkloadContext context)
        {
            Console.WriteLine($"Hello {context.WorkloadId}"); 
        }
    }
}

WorkloadTest.csを書き直した後、VSで実行後にブラウザでアクセスすると下記のように、Workloadを継承したクラスの名前が表示されているのでそのまま「EXECUTE」ボタンを押して実行します。

実行するとブラウザ上では下記のようになります。

VSのアプリケーション出力ではConsole.WriteLine($"Hello {context.WorkloadId}");の出力結果が表示されているのでWorkloadTestが動いているのを確認出来ました。

次は、APIにアクセスする処理を入れていきます。
(9月1日追記:HttpClientで良くない実装をしていたため、修正部分があります。詳しくは下記の記事を参照してください。) tech.liberent.co.jp

using System;
using System.Net.Http.Headers;
using DFrame;
using MemoryPack;

namespace TestMemoryPackWeb
{
    public class WorkloadTest : Workload
    {
        HttpClient? client;
        public string ScreenMessage { get; private set; } = "";

        public override async Task SetupAsync(WorkloadContext context)
        {
            // 初期化
            Console.WriteLine("SetupAsync!!");
            client = new();
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-memorypack"));
        }

        public override async Task ExecuteAsync(WorkloadContext context)
        {
            // 実行
            Console.WriteLine("ExecuteAsync!!");

            var resString = await client.GetByteArrayAsync("http://localhost:8080/WeatherForecast2");

            var resVal = MemoryPackSerializer.Deserialize<WeatherForecast[]>(resString);
            foreach (WeatherForecast w in resVal)
            {
                ScreenMessage += w.Date.ToString() + ":" + w.TemperatureC + ":" + w.TemperatureF + ":" + w.Summary + "  ";
            }

            Console.WriteLine($"{ScreenMessage}");
        }

        public override async Task TeardownAsync(WorkloadContext context)
        {
            // 後片付け
            Console.WriteLine("TeardownAsync!!");
            client?.Dispose();
        }
    }
}

上記のように修正後、VSにて実行してブラウザでアクセスして「EXECUTE」ボタンを押して実行します。
ブラウザ上で結果が表示されるのと、VSのコンソールログにて受け取ったレスポンスが表示されていることが確認出来ます。

まとめ

まだ、深くまで触れていないのですが、グラフなど視覚的に分かりやすい出力がDFrameだけで出るようであれば使い勝手が良くなりそうな気がしてます。

サーバがc#でかつMemoryPackを使用している場合ですと、MemoryPackが使用出来るのと、Unity側の実装(Unity依存の処理を取り省く手間はありますが)やサーバ側の実装が使えるため、Pythonなどの異なる言語でシナリオを作るのと比べると断然楽になるのではと考えています。


リベル・エンタテインメントでは、このような最新技術などの取り組みに興味のある方を募集しています。
もしご興味を持たれましたら下記サイトにアクセスしてみてください。
https://liberent.co.jp/recruit/