tubone

tubone

Boyaki makes a new world


 Recent posts  6 / 72

JanFebMarAprMayGatsby.jsで作ったBlogの投稿をGitHubの草にして表示させるWeb Developer Roadmap 2020を眺めながら今年の目標(Frontend)をだらだら考えるの会AWS X-RayでLambdaのトレースをしつつ、Datadog APMに連携するElixirでパラレルな負荷試験ツールを作るNEW GAME!から見る新入社員の心得その1NEW GAME!から見る新入社員の心得その2Jetson Nanoを触る報告 ~立派なタワーPCみたいだろ? 小型なんだぜ?~tiny_yolov2_onnx_camを使って物体検知するJetson nano + SainSmart IMX219でアニメ風自撮り動画を作るStyleGANとStyleGAN2を使って美少女キャラを無限増殖させるRaspberry PIを使って植物の水やり監視システムを作る2020年のデスクトップはこれだ!かっこいいあつもりを始めてしまいましたクロスルート証明書について考えてみるMonWedFri
クロスルート証明書について考えてみるあつもりを始めてしまいました2020年のデスクトップはこれだ!かっこいいRaspberry PIを使って植物の水やり監視システムを作るStyleGANとStyleGAN2を使って美少女キャラを無限増殖させるJetson nano + SainSmart IMX219でアニメ風自撮り動画を作る


 SearchBox

Search your interesting by Algolia in this blog.


この記事は60文字約5分で読めます

Elixirを使ってAPIの負荷試験ツールを作りましたな話です。

Table of Contents

負荷試験について本気出して考えてみた

業務の中で、負荷試験について考える機会が多かった年始明けでしたので、せっかくなのでよりいい負荷試験ツールを自作してみようかと思いました。

負荷といえば並列なリクエスト、並列といえばやっぱジャイアンツElixirということで、Elixirで実装することにしました。

ElixirでHttpリクエストをするならHttpoison

HTTPoisonはElixirで使えるHTTPクライアントです。

使い方もとっても簡単で、GET、POSTは下記のように実施できます。

# GET
HTTPoison.get!("http://example.com",[],[{:timeout, :infinity}, {:recv_timeout, :infinity}])

# POST
payload = Poison.encode!(%{"contentType" => "image/png", "key" => "value"})

ret = HTTPoison.post!("http://example.com", payload, [],[{:timeout, :infinity}, {:recv_timeout, :infinity}])

upload_id = Poison.decode!(ret.body)["upload_id"]

GETはHTTPoison.get()、POSTはHTTPoison.post!() で実施できます。簡単ですね。

! がついているかついていないかは例外を上げるか上げないかの違いです。

ナオキ「例外あ、あげますね・・・。」

1つ目の引数はURLですね。

Payloadは2つ目の引数。Posion.encode!() にMapでKVを入れれば実現できます。これも簡単ですね!!残念ながら、GETのbodyは許容しません。

3つ目はHeader。今回は使いませんね。

4つ目はOptions。Timeoutなどを設定します。

Timeoutは:recv_timeout:timeoutの2つを指定します。 負荷試験なので、Infinityにしておきます。

ResponseがJsonの場合はPoison.decode!()でKVでアクセスできます。簡単ですね!!

Elixirで並列処理するならTask.asyncでしょ

正直ここらへんはElixirのHttpoisonでAPI負荷検証ツールをつくったを参考にしてます。

  def send_requests_parallel(process_num,count) do
    time_total = Enum.map(1..process_num, &Task.async(fn ->
      &1
      send_requests(@url)
    end))
                 |> Enum.map(fn(task) -> Task.await(task,1000_000) end)
                 |> Enum.reduce(0, fn x,total -> total + x end)
    IO.inspect "#{count}, average_time: #{time_total / process_num / 1000} ms, time_total: #{time_total / 1000} ms"
  end

とやることで、並列処理&返ってきた実行時間をreduceで集計することができます。すごいすごい。

CSVに出力

こちらも超簡単。CSVという便利なライブラリをmixから落とせば簡単に実現できます。

 def write_csv() do
    file = File.open!("response.csv", [:append, :utf8])
    table_data = [["aaa","bbb", "ccc", "ddd"]]
    table_data |> CSV.encode(headers: false) |> Enum.each(&IO.write(file, &1))
  end

簡単ですね!

完成

完成しました。

elixirperformancetool

ついでにElixirのドキュメントツールex_docを使ってドキュメントも作ってみました。

Ebook Homebrew: ElixirPerformanceTool

Elixirとっつきにくいかなぁと思いましたが、意外に簡単でした。

こんな感じでAPIのレスポンスタイムを取得できました。

iex> ElixirPerformanceTool.run(10,10)
"0, average_time: 1422.0 ms, time_total: 1422.0 ms"
"2, average_time: 843.0 ms, time_total: 843.0 ms"
"1, average_time: 1969.0 ms, time_total: 1969.0 ms"
"3, average_time: 844.0 ms, time_total: 844.0 ms"
"4, average_time: 844.0 ms, time_total: 844.0 ms"
˚