ClearDBから、Azure Database for MySQL(Preview) への移行

このブログを作ったときから、ClearDBを使い続けていましたが、今年になって、Azure としてMySQLのマネージドサービスが出た(Preview)ということで、マイグレーションしてみました。

参考にしたのはこの記事
(ほぼそのまま)

https://azure.microsoft.com/ja-jp/blog/cleardb-migration-to-azure-database-for-mysql/

やったこと

  1. リンクの「https://dev.mysql.com/downloads/workbench/」からworkbenchをダウンロードしてインストール
  2. Azureポータル上から、ClearDBの接続文字列を拾い集める。ホスト名、ユーザー名、パスワード。
  3. workbenchを起動して、接続先を登録しておく。テスト接続成功でOK
  4. Azureで作っておいた Azure Database for MySQL の接続文字列を取得。ホスト名、ユーザー名、パスワード。
  5. 同様にworkbenchで接続する。このときポータル上から作業している端末のIPアドレスを許可するように設定する。「+自分の IP を追加」を選ぶと早い。
    保存。
  6. あとは、最初の記事のようにマイグレーションウィザードと!
  7. しかし、途中クエリのタイムアウトエラーが起きたので、サーバーパラメーターの「long_query_time」を10から30に変更して何度かRetryして成功。
  8. WordPress側は、ルートにある「wp-config.php」を書き換えた
  9. しかし、SSL接続を強制しているため、接続エラーとなる。(一度Debugを有効にして確認した)
  10. そこで、「wp-config.php」に
    define('MYSQL_CLIENT_FLAGS', MYSQL_CLIENT_SSL);

を追加して無事に完了

レスポンスは気持ち早くなったような気がしている。

何よりこの記事の画像にしているように、パフォーマンスをメトリックで確認できるので、使っていく中で適切なスケールとかも見えてきそうなところ。

 

Paas上のDevOps というものを受講してみて

とあるきっかけからチャレンジ

Welcome to Microsoft’s Azure Paas上のDevOps!

結果からいうと、合格点70%に対して70%!
で、問題の翻訳の質があんまりよくないのもあったけど、
何を聞かれているのか全くわからないのもあった。。。(多分私のスキル不足)

ほかに受講できるもの「azure-skills」

とはいえ、コースの内容は面白いものでした。

5つのモジュールで構成されており、
最初のモジュールは、DevOpsとは、なぜ?といったような考え方から入り、
自動化するアプローチ、どうしていったらいいかとか。

そして中盤からツールの使い方へフォーカスして、
コードを用いた、ハンズオンまで用意されていました。
このとき、Azureのサブスクリプションや、Visual Studio 2015 が必要になりました。
コースや個人差があるとは思いますが、
全体で12時間以上かかっていたような気がします。補足資料もじっくり読むともっともっとかかりそう。

かかるということはそれだけ多くの内容を知ることができるので、
これはVirtual Academyとは比にならないくらい。

おすすめしたい!と思いますー

ハンズオン

一部内容が古いものがあって、今のAzureに当てはめたときに・・・という補完が必要でした。またビルドエラーになるものもあるので、そこを問題ないようにもっていくというのも一つの醍醐味かなぁと。コードはVS2015のASP.NET Coreであるために、xprojが採用されてます。これは既に古い存在なので、もしかしたら時間とともに動かなくなっていくかも…

Bad Request

何日にも分けてやってたりすると、途中Bad Requestが出るので、
プライベートモードにしたブラウザを使うか、クッキーや履歴を消してログインしなおすと大丈夫でした。
(ヘッダーサイズが大きすぎるぞと怒られるらしい)

認定書?

受講した人に聞くところ、私は最終試験70%だったために、特に何もなく終わったのですが、70%以上の成績をおさめると認定書?みたいなものがもらえるようです。
知識・経験不足…がんばろう

Azure Container Instances というサービスが・・・~blackjumbodog-dotnet-core

出てきたので、試してみました。

Fast and Easy Containers: Azure Container Instances

リンクは、公式のBlogです。

 

既に試しており、ざっくりまとめている方(しばやん)のを一読してみてください。

 

というわけで、OSC2017Hokkaidoでは、App Service on Linux でしたが、こちらはどうやら、Hyper-Vレベルで分離したcontainerのゲストインスタンスを利用可能になるサービスのようです。スケーリング等の機能はなく、IaaSに近いようなシンプルなコンテナといったところでしょうか。

実際に作ってみよう

Create your first container in Azure Container Instances

 

公式ではポータルのCLIを使ってとなってましたが、それっぽいテンプレートがポータルにあるのでそっちで試してみました。

イメージは、BlackJumboDog!
darkcrash/blackjumbodog-dotnet-core
ポートは3080をHTTPにしてるのでこれを!
こちら、Linuxベースのイメージになります。

しかしながら、色々試してて、リージョンは選択できるけどデプロイできないみたいな状態なので、今日現在ではおとなしくAzコマンドを使ったほうがいいのだろうと思いました。

加えて、ポータルで出来上がったものは、こんな感じで
あまり、というか情報がありませんでした。

そこで、コマンド

az container list -g [グループ名]
{
 "nextLink": null,
 "value": [
 {
 "containers": [
 {
 "command": null,
 "environmentVariables": [],
 "image": "darkcrash/blackjumbodog-dotnet-core",
 "instanceView": null,
 "name": "bjd-container4-XXXXXXX",
 "ports": [
 {
 "port": 3080
 }
 ],
 "resources": {
 "limits": null,
 "requests": {
 "cpu": 4.0,
 "memoryInGb": 4.0
 }
 },
 "volumeMounts": null
 }
 ],
 "id": "/subscriptions/XXXX/resourceGroups/bjd-container4/providers/Microsoft.ContainerInstance/containerGroups/bjd-container4-j6bvkbkaxarxy1",
 "imageRegistryCredentials": null,
 "ipAddress": {
 "ip": "13.93.166.22",
 "ports": [
 {
 "port": 3080,
 "protocol": "TCP"
 }
 ]
 },
 "location": "westus",
 "name": "bjd-container4-XXXXXXX",
 "osType": "Linux",
 "provisioningState": "Succeeded",
 "resourceGroup": "bjd-container4",
 "restartPolicy": null,
 "state": null,
 "tags": null,
 "type": "Microsoft.ContainerInstance/containerGroups",
 "volumes": null
 }
 ]
}

http://13.93.166.22:3080/

開いたー!ひゃっほー!
ただ、BlackJumboDogのコンソールログは見えないので、ちょっと実感は薄かったw

とはいえ、今までIaaS上にVMを上げてDockerHostを作り、そこにコンテナをのっけるのではなく、Hyper-Vに直接乗っかっているような状態なので、非常にシンプルでわかりやすくリソースの調整もポータル上からできるようになるというのであれば、VMっぽい感覚で、素早くコンテナ作れるってのはちょっとしたものを作る上ではいいんじゃないかと思いました。スケーリングはApp Service On LinuxがPaaSとして存在しているので、そんなすみわけがあるのかなぁと妄想したところでした。

これ、オーケストレーションももちろんだけど。
VNET接続とか、DNSまたはホスト名、LBとかいろいろできるようになったらまた違う可能性ありそうな気がしないでもない。ARMテンプレートとイメージだけでDevOpsとか。
ちょっと、●●ほしいなぁ、おしデプロイするかー!みたいなのも。

 

Azure Functions Runtime

Build 2017
の中でひそかに更新されたBlogがあった。

Introducing Azure Functions Runtime preview

なんというか、Runtime?ってどういうことだろうと思って開いてみたところ。

Azure Functionをオンプレミスでも動かせるようにできるものらしい。

 

最低要件とか

細かいドキュメントは、「Azure Functions Runtime Overview」あたりから

Windows Server 2016 or Windows 10 Creators Update with access to a SQL Server instance.

Windows Server 2016 または、Windows 10 Creators Updateとなっている。
このあたり、Windows Containerに依存している部分があるためと考えられそうだ。また、SQL Serverへの接続も必要と。

機能

このRuntimeが持つ機能は大きく二つ

「Azure Functions Management Role」
ポータルのような管理する機能を提供する

「Azure Functions Worker Role」
FunctionをWindows Containerに展開して実行する

ドキュメントでは、VisualStudio 2017からの直接デプロイもできるとはなっている。

ダウンロードは、Blog記事より下部にある

How do I get started?

Please download the Azure Functions Runtime installer.

からできた。

ちょっとだけ

以下、Windows Server 2016 へのインストールと、インストール後の画面
SQL Serverへの接続を構成しない限り動作しないようだ。
インストール後は再起動が必要となった。

スライドショーには JavaScript が必要です。

BlackJumboDog .NET Core 性能向上 メモ 2

これの続ぎ

リクエストを処理する中で、遅くなっているものは何か?
よく考えられるもは、ロジックの無駄な処理(処理する必要のないものを処理している)。リソースの使い方。
で、まずはロジックの無駄という意味では、意味のない処理は見つからず。
で、遅くなっているところというのを考えると
リソースの確保の部分。
new byte [ XX ];
これは、ある程度のサイズになったとき、Heapの確保が発生するので、場合によって、数msかかる。これが1か所ならまぁいいのですが、中の処理では、Socketの読み込みバッファから、エンコード用のバッファ、出力用のバッファまで広く使っており、1回のリクエストで、少なくとも5回以上は生成しておりました。

これを何とかできないか?と考えたのが、BufferPoolというクラスを作ることでした。

https://github.com/darkcrash/bjd5/blob/3212cf26eca2f1c90ee545df4b3307fc654abf73/Bjd.Common/Memory/BufferPool.cs

これの役目は・・・

  • byte配列の確保を毎回やらせないことで、GCのコストを抑える。Heapの確保と解放をあまり発生させない。
  • 一定数事前に配列を生成し、領域を確保することで生成のコストを抑える。
  • 必要なサイズに応じたものを返す。
  • 足りなければ、作る。
  • 足りなくて作ったものが、既定の確保しておく領域を上回る場合には、解放する。

これで得られる恩恵は、思ってた以上に大きく、リクエストあたり数ms減りました。

これに対して個人的な見解は・・・・
GCはリソースやメモリの再利用があるので、そこである程度同じことさせているときは、次第に早くなるのですが、HTTPリクエストやら、Socket通信などでは、同じリソースのサイズを要求しないことが多く、メモリの断片化が起きたり。GCが動くことで、CPUリソースを消費したりということではないかなぁと思ったりしたが、それを明確に確認できる方法は思いつかなかった。。。GCの呼び出し回数が減っているというくらいかな。

 

続く・・・

 

BlackJumboDog .NET Core 性能向上 メモ1

BlackJumboDog .NET Coreの性能を向上させようといろいろ模索する中での話。

今やっていた性能向上というのは、WebServerで、クライアントからの接続要求をどれくらい処理できるか?です。
具体的には、Fiddlerを使って、1000回~100000回のリクエストを処理させて、エラーがおきないように、そして500回あたりのリクエスト(FiddlerがTimelineをグラフ化してくれるサイズ)をどれくらい早くできるか?

そんなところで、比較対象がなければということで、MSのIIS(InternetInfomationService)を手っ取り早いところで、相手にしてみました。Hyper-VのゲストOSとして、Windows Server 2016 を。リソースは、4コアのメモリ4GBをあてました。検証で利用するファイルは、BJDの初期で入っているindex.htmlです。サイズは4Kb強

IIS on Windows Server 1

私が注目したのはまず、右上に出ている78msという時間。これはこのグラフ全体が78msということっぽいようで、500回のリクエストを80ms以内にすべて応答しているということです。グラフの色が出ているところが通信中の状態(HTTPリクエストからレスポンスが返るまで)で、空白が、何もしていない時間のようです。こうしてみたとき、空白の領域は多く、Fiddlerが遊んでる状態といいますか、サーバーとクライアントはKeepAliveによってただSocketがつながっているだけの状態。1リクエストは数msで処理されている状態。

 

対して、BlackJumboDog .NET Coreはというと・・・

全体が、500ms。グラフもぎりぎりまで密集しており、空白はほとんどない。リクエストからレスポンスまでの時間が長く、Fiddlerが待っている状態。

リクエスト数に対しての処理時間でいけば、単純に1msとなりますが、並列で動いているために、1リクエストは実際のところ10ms、20msとかそんな感じ。

一日に数回しかないような処理ならば、速いものですが、このリクエストはブラウザ一つで、ページの読み込み、スクリプトの読み込み、画像リソースの読み込みとか考えたとき、1ページ表示するのに重ければ、10回以上はあるでしょう。

これを考えたとき、静的なファイルはダウンロードさせずに、ブラウザにキャッシュ化したり、リクエスト数を減らすためにファイルを結合してみたりとか、トラフィックがネックであれば、GZIP圧縮をかけてみたりといったこともできます。

ですが・・・それでは面白くない。
実際、これだけの差があることを.NET Coreのせいにしてしまうというのも一つなのですが、.NET Coreでも、KestrelというASP.NET Coreを動かすシンプルなアプリケーションサーバーは、ものすごい勢いでリクエストを処理できたりします。(実際はアプリケーションの処理によってはそんなに早くならないですが)

https://github.com/aspnet/KestrelHttpServer

 

そこで、何とか早くならないかと模索してみた・・・つづく

dotnet publish [ProjectDirectory] -o [output] の出力先

project.jsonのものを置き換えていたところで気づいたのでメモ

dotnet publish [ProjectDirectory] -o [outputdirName]

とした場合、感覚としてdotnetコマンドを実行しているシェルのカレントディレクトリだろうと思っていたが、どうやら [ProjectDirectory] がカレントディレクトリになっているようだ。

なのでdotnetコマンド実行しているカレントディレクトリに配置したい場合は

dotnet publish [ProjectDirectory] -o ..\[outputdirName]

としないと予想しないところに出てしまうようだ。

追記 2017-03-11

dotnet pack [ProjectDirectory] -o [outputdirName]

でも同じことが起きた。
このことから、[ProjectDrectory]をカレントにしてしまっているような感じはする

 

xUnit fail of overload Testmethod on Visual Studio 2017 .NET Core

Visual Studio 2017 が出たぜー!というところで、さっそくBlackJumboDogもアップグレードしていったところ。

xUnitで謎のテストエラーが続発した・・・

System.InvalidOperatrionException
普通に考えたところで、メソッドの呼び出し方を間違えたとのことなのだが、型を動的にしているわけでもないので、あれま・・・とか思っていたところ。

よくよく見ていると、そのメソッドはオーバーロードしていた。

引数3つのTestメソッドと、引数2つのTestメソッドがいる状態
エラーメッセージは

メッセージ: System.InvalidOperationException : The test method expected 3 parameter values, but 2 parameter values were provided.

となっていて「引数が3つあるぞ、でも2つしかないぞ。」という困ったぞーという意味の例外。

なので・・・

オーバーロードをやめて名前を付けた。

というわけで、成功!

ひとまず回避策は見えたが、これが仕様なのか、不具合なのかは調べていない。。。

AppVeyorのテストでエラー

前回のログ出力をがっつり作り替えたところのそもそも理由

AppVeyor Bjd.SmtpServer.CoreCLR.Test  1.1.0-51

で、エラーとなっている部分があるんですが、
これはローカルのWin10、VS2015環境では問題なく通るテストなのです。
このテストケース。
実際にSocketサーバーが動いて、それにクライアントが接続にいって
Pop3クライアントとしてメールを受け取るタスクを検証しているのですが、
メインではなく、裏で動いているPop3サーバーにてメールを開いたときのサイズが変わってしまってました。

AppVeyor(抜粋)

[13:38:12.326][1400][151] Mail.Read C:\projects\bjd5-qqab7\Bjd.SmtpServer.CoreCLR.Test\bin\201702191338066076_9_1333341264_23264094\mailbox\user2\MF_00635026511425888292 300 byte.
[13:38:12.326][1400][151] 16189196 SockTcp.SendNoTrace 151
[13:38:12.935][1400][151] 16189196 SockTcp.SendNoTrace 55
[13:38:13.545][1400][151] 16189196 SockTcp.SendNoTrace 12
[13:38:13.951][1400][151] 16189196 SockTcp.SendNoTrace 38
[13:38:14.154][1400][151] 16189196 SockTcp.SendNoTrace 37
[13:38:14.560][1400][151] 16189196 SockTcp.SendNoTrace 1
[13:38:14.967][1400][151] 16189196 SockTcp.SendNoTrace 5
[13:38:15.576][1400][151] 16189196 SockTcp.SendNoTrace 1
[13:38:15.982][1400][151] 16189196 SockTcp.SendNoTrace 2
[13:38:16.388][1400][151] 16189196 SockTcp.Send 3

ローカル

[23:46:07.939][13628][ 26] Mail.Read C:\Users\[username]\Source\Repos\bjd5\Bjd.SmtpServer.CoreCLR.Test\bin\201702212346077840_5_1610115599_50579406\mailbox\user2\MF_00635026511425888292 308 byte.
[23:46:07.940][13628][ 26] 18701856 SockTcp.SendNoTrace 152
[23:46:07.940][13628][ 26] 18701856 SockTcp.SendNoTrace 56
[23:46:07.940][13628][ 26] 18701856 SockTcp.SendNoTrace 13
[23:46:07.940][13628][ 26] 18701856 SockTcp.SendNoTrace 39
[23:46:07.940][13628][ 26] 18701856 SockTcp.SendNoTrace 38
[23:46:07.940][13628][ 26] 18701856 SockTcp.SendNoTrace 2
[23:46:07.940][13628][ 26] 18701856 SockTcp.SendNoTrace 6
[23:46:07.940][13628][ 26] 18701856 SockTcp.SendNoTrace 2
[23:46:07.941][13628][ 26] 18701856 SockTcp.Send 3

トータル 300 byteに308 byte
さらに1行単位の送信では1バイトづつ違うー!
そして、送信してる行数も違う・・・

そもそも、単体テストを実行するような環境でSocketがっつりかましてるのどうなのか!というところもありますが。

おそらくは、改行コードじゃないかなぁ
・・・というところでここまでっ

How to output log for xUnit

ひさしぶりに BlackJumboDogをいじっていて、
ずーっと気になっていたことがあったので、思わずやってしまった・・・。

xUnitでは、並列テストを前提とした場合標準出力に対する出力をキャプチャしない仕様になっている。そのため、出力させるためには、独自のOutputHelperが必要になる。
※ Capturing Output

これやるにあたって、今のSystem.Diagnostics.Traceを全て置き換える必要が
あった。

なぜかというと、System.Diagnostics.Traceは、コンテキストを持たずアプリケーション内で静的に動作してしまうため、並列で動いたときはどのテストの結果であるかを知ることができない。

そのため、ちゃんとやるなら、System.Diagnostics.Traceを全て独自のものに置き換える必要があったが、それにはかなりの修正量になるのがあってためらっていた。

しかしながら、実際のところテストがエラーになったとき、単純なものであればよいが、複雑なものであれば、どこがどうなっているかというのを追いかける必要がある。そのためには、ログも実行された結果がそのまま出てくれているのが良く、関係のないところの情報が出ていることは、逆に紛らわしい。そのため単独で動かしてその結果が出てくれるならいいがそうではなかったりもする。まぁその時点でテストとしての精度が低いという問題もあるのだけれども。

そこで、ログもすべて自分の実装でコンテキスト化してしまおうというのをやってみた。

・ログは出力先が不特定多数(ファイル、コンソール、xUnit、その他)
・ログは気軽に出すことをできるようにしておき、必要に応じて出力できないようにする
・ログはルートのコンテキストに紐づける

といったような考えで挑んでみたところ。

悪くはないが、そのための影響が大きくやはりやりすぎだったか!と思いつつ、前に進んでいることで何かやる気が出てきている今日だった。

change internal architecture for log. 

独自で実装しておくことは、チューニングしやすくなるので、悪くはない。

もし、今後xUnitを用いた開発をするのであれば、ログを出力する機構を
テストごとにコンテキスト化できるような仕組みをお勧めしたいなぁと思った。