まだIT業界で消耗してるの? 😊ソフトウェア開発者のブログ

カテゴリー: クラウド・サーバー

ボットネットの脅威を考えたら Google Cloud を使うのがベストだ

2016年12月19日

これは Google Cloud Platform(2) Advent Calendar 2016 の19日目の記事です。

今年の11月に「Mirai」ボットネットが、Twitterなどの利用するDNSサービスへDDoS攻撃をしてサービスをダウンさせた事件があって、IoT ボットネットが話題になっています。先日、その IoT ボットネットから自分のWebサイトにもアクセスがありました。もちろん IoT ボットネットからという確証はありませんが、早朝から深夜までアクセスがあったので、常時電源の入っている機器には間違いありません。それだと普通のPCではないし、IP アドレスを調べるとモバイル回線からのアクセスはないのでスマートフォンでもなさそうです。

攻撃者は遊び程度だったようで、50台ぐらいのボットネットで、アクセスの間隔もかなり開いていました。それでもサーバーの CPU 負荷が普段より数倍になったので気がつきました。自分のWebサイトは時々スパイクアクセスがあるので、サーバーにかなり余裕をもたせていたので、今回は無事でした。

でも、もう少し攻撃が激しければ、システムがダウンしたと思います。そういうことを考えれば、サーバーはできるだけ増強したいのですが、その分サーバー料金がかさむのが痛いところです。

スパイクアクセスの場合は、同じページにアクセスが集中するので出力キャッシュが効果的なのですが、DDoS攻撃の場合はどういう攻撃されるか分からないので、現状だと、データベースの部分が弱いので、その能力のアップを急ごうと思っています。

現在、AWS を使っているので、DynamoDB だったら短時間でスループットを上げられるのかと調べてみると、よくある質問に以下のような回答がありました。スループットを増やすのに数分以上かかるようで、それだったらシステムはダウンしてしまいます。

Q: テーブルのプロビジョニングされたスループットレベルを変更するにはどのくらい時間がかかりますか?

通常、スループットを減らす場合は数秒から数分、増やす場合は数分から数時間かかります。

追加スループットが必要になった時点でスループットを増加したり増加のスケジュールを立てたりすることはお勧めできません。スループット容量のプロビジョニングは、必要なときに確実に容量を確保できるようかなり前から行っておくことをお勧めします。

それで Google Cloud Platform を調べたら、さすがに Google です。Cloud Datastore は、完全に自動スケールで、何も考える必要はありません。料金は以下のように完全に使っただけの料金になります。(以下東京リージョンの料金です)

  • データの保存 $0.18 GB/月
  • エンティティの読み込み数 $0.06 /10万エンティティ
  • エンティティの書き込み数 $0.18 /10万エンティティ
  • エンティティの削除数 $0.02 /10 万エンティティ

一方、AWS の DynamoDB の料金は以下のようになっています。

  • 書き込みスループット: $0.00742 :10 ユニットの書き込み容量あたり/1 時間 (1 時間あたり最大 36,000 回の書き込みを実行するために十分な容量)

  • 読み込みスループット: $0.00742 : 50 ユニットの読み込み容量あたり/1 時間 (1 時間あたり最大 180,000 回の強力な整合性のある読み込み、または最大 360,000 回の結果整合性のある読み込みを実行するために十分な容量)

こちらは、スループットで料金が決まります。この料金の記載だと、結果整合性のある読み込みだと、50ユニットの設定で、月2億5千万回のアクセスができ $5.34 で済みます。Google Cloud Datastore だったら $155 もかかると言いたいのでしょう。さすがに Amazon は商売上手です。

でも、公開用 Web サーバーの場合は、スパイクアクセスやDDoS攻撃のことを考えるとそんな単純な話ではありません。

価格を比較するため、公開用 Web サーバーで月1千万PVのWebサイトがあるとします。月1千万PVあれば Webサービスだとかなり楽に経営ができます。

Cloud Datastore の料金は、1pv に必要なデータベースへのリクエストを1エンティティとすると、料金は月 $6 になります。仮に 1pv当たり平均 10 エンティティが必要だとしても、月 $60 です。安い言い切るのは難しいかもしれませんがリーズナブルな料金です。

DynamoDB の場合は、容量をあらかじめ確保しておく必要があります。スパイクアクセスやDDos攻撃を考えると予測不可能で必要な容量の計算なんかできないですね。取りあえず1秒間に100pvのアクセスということにして、1pv で必要なデータベースへのアクセスが1ユニットだとすると、50ユニットが必要で月$5.34です。Cloud Datastore とほぼ同じ金額になります。

でも、ここでよく考えてみてください。DynamoDB は、全体のスループットではなくて、テーブル毎にスループットを設定する必要があります。ローカルセカンダリインデックスは、5個まででかつテーブルの作成のときに定義してやる必要がありそれ以降の変更はできないので、一つのテーブルに各種のデータを詰め込むのは無理で、それなりの数のテーブルが必要になると思います。DDos攻撃はどこが狙われるか分からないので、1秒間に100pvのアクセスに耐えるようにしようと思えば、すべてのテーブルにそにアクセスに耐えるだけのユニットを割り当てる必要があります。そしてさらに最悪なのが、1pv 当たりに必要なデータベースへのアクセスが平均では2ユニットであっても、あるページで50ユニット必要であれば、そのページが狙われるとダメなので、そのテーブルには50×50=2500ユニットも割り当てる必要がありそれだけで月$267になってしまいます。

1秒間に100pvというのは、どの程度かというと、今回のボットネットからの自分のサイトへのアクセスは、1台で1秒に15回以上のアクセスがありました。10台あれば150pvになるので100pvの容量だとエラーが多発するようになります。1秒間に100pvというのは、DDoS攻撃対策では、殆ど話にならないレベルです。

こう考えていくと、DynamoDB は、DDoS対策としては最悪でした。そして、通常の利用においても DynamoDB ファーストにするとテーブル数が多くなってコストが嵩みます。このことは、AWS もよく理解しているようで、Amazon AWSでユーザ数1100万以上にスケーリングするためのビギナーズ・ガイド という記事から引用します。

NoSQL データベースではなく、最初はSQLデータベースを使用しましょう。

  • まずはSQLデータベースの使用を推奨します。技術は確立されています。

  • 既存のコードやコミュニティ、サポートグループ、書籍やツールが多く存在します。

  • 最初の1000万ユーザでSQLデータベースが破壊されることはありません。(データベースが大規模でない限り)壊れることはないでしょう。

  • スケーラビリティの明確なパターンがあります。

NoSQL データベースが必要になるのはいつなのでしょうか。

  • 5TB以上のデータを初年に格納する必要がある場合や信じられないほどのデータベース集中型のワークロードの場合。

  • アプリケーションの要件が超低遅延である場合。

  • 高いスループットが必要な場合。読み込みや書き込みの際の出入力にかなり手を加える必要があります。

  • リレーショナルデータがない場合。

要するに DynamoDB は、アプリケーションを高速化するために、ごく少数のテーブルに対して使うべきもののようです。この影響で、業務系の人を中心に、NoSQL ファーストはダメだと思っている人が多いと思いますが、AWS の事情であって、本来はどちらがいいというものではなくて、アプリケーションの性格によって使うべきものです。

クラウドも AWS、Azure、Google Cloud のどれがいいのかという一般的な答えはないと思います。しかし、システムダウンしないWebサーバーにしようと思ったら、Cloud Datastore は殆どコストなしで無制限にスケールできるので Google Cloud を使った方がはるかにいいと思います。Google Cloud のアクセス集中に対する強さは、今年 Pokémon GO で実証されています。一方、AWS で、SQLデータベースをメインに使った場合、エンタープライズ向けの閉じたシステムだと、アクセス数はそれなりの精度で想定できるので問題はあまり生じないと思いますが、公開 Web サーバーで、DDoS攻撃 のことまで考えると非常に難しい問題になります。SQLデータベースではスケールさせるのにコストが非常に高くなるし、急激なアクセス増への対応も簡単ではないと思います。この点は、Azure も同じだと思います。

自分の Web サイトは、できれば DDoS攻撃に強いものにしていきたいので、サーバーを AWS から Google Cloud Platform に移そうと思っています。でも、Amazon EC2 のリザーブドインスタンスを買っているので、その期間が終了するまでは待ちます。リザーブドインスタンスは料金の割引は大きいのですが制約は厳しいと思います。google Compute Engine の方は、1ヶ月単位で自動的に継続割引が適用されます。何もしなくてもいいのには気に入りました。(計算してみたら AWSは3年の標準リザーブドインスタンスだとAmazon EC2 の料金が安いですが、3年縛りは厳しいし、値下げが適用されないのでリスクが高いです。コンバーティブルリザーブドインスタンスにすると google Compute Engine の継続割引後の料金とほぼ同じです。)

.NET Core で PostgreSQL を使ってみたら結構いけていたという話

2016年12月15日

これは PostgreSQL Advent Calendar 2016の15日目の記事です。

この Web サイトは、今年の4月から ASP.NET を Core の方に更新して Ubuntu サーバーで運用しています。実際に運用してみて、IIS よりも Nginx を使う方が便利だと思うようになってきたので、サーバーはすべて Linux サーバーにする予定です。

その際の問題は、データベースをどうするかということです。ASP.NET とはなんといっても SQL Server を使うのが定番です。それで、自分も SQL Server Express を使ってアプリを作っていました。しかし、残念なことに SQL Server が Linux に対応するのは来年の半ばということです。

最近、PostGIS を使いたいという思惑もあって、PostgreSQL を使ってみたら、結構いけていると感じたので、この記事を書くことにしました。まだ、使い始めて1ヶ月なので、今後問題が見つかるかもしれないので最終的どうなるかはわかりませんが、PostgreSQL を使っていこうと思っています。

Entity Framework Core で使う

.NET Core や .NET Framework から、PostgreSQL を使う場合は、Npgsql というデータプロバイダーを使用します。Npgsql には、Entity Framework Core(EF Core)用のプロバイダーもあるので、EF Core で使っている範囲では、SQL Server を使うのと違いは殆どありません。

参考 Npgsql の EF Core 用のドキュメント

例として、Visual Studio の ASP.NET Core の Web アプリケーションのテンプレートで認証を「個別のユーザーアカウント」にした場合に、EF Core が使用されているので、それを PostgreSQL を使うように修正してみます。

  1. Nuget パッケージ の追加 Npgsql.EntityFrameworkCore.PostgreSQL を追加します。

  2. Startup.cs の修正 以下のように、options.UseSqlServer と SQL Server を使う設定になっているので、

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
    services.AddIdentity<ApplicationUser, IdentityRole>()
       .AddEntityFrameworkStores<ApplicationDbContext>()
       .AddDefaultTokenProviders();
    ------ 以下省略
}

options.UseNpgsql に変更して、Npgsql を使うようにします。

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddDbContext<ApplicationDbContext>(options =>
                options.UseNpgsql(Configuration.GetConnectionString("DefaultConnection")));
    services.AddIdentity<ApplicationUser, IdentityRole>()
       .AddEntityFrameworkStores<ApplicationDbContext>()
       .AddDefaultTokenProviders();
    ------ 以下省略
}
  1. appsettings.json に記載してある接続文字列を修正します。
{
  "ConnectionStrings": {
    "DefaultConnection": "Server=localhost;Database=test;Username=postgres;Password=password"
  },
------ 以下省略
}

SQL Server から PostgreSQL を使うように変更するのはそれだけです。

接続文字列に設定したユーザーが、データベースを作成できる権限を持っているユーザーであれば、これでデータベースも勝手に作ります。もし、そうでなければ事前にデータベースを作っておきます。

ただし、それで Run して、ユーザーの登録をしようとするとエラーになります。Data ディレクトリに Migration フォルダーが作成されていて、SQL Server 用のものが事前に作られているためです。 それで、それらのファイルを削除してからするとちゃんとしたエラーメッセーが出ます。メーセージの通りにマイグレーションをしてやると正常に動くようになります。

A database operation failed while processing the request.
NpgsqlException: Exception while reading from stream 
IOException: Unable to read data from the transport connection: 既存の接続はリモート ホストに強制的に切断されました。. 
SocketException: 既存の接続はリモート ホストに強制的に切断されました。 
Use migrations to create the database for ApplicationDbContext
In Visual Studio, use the Package Manager Console to scaffold a new migration and apply it to the database:
PM> Add-Migration [migration name] 
PM> Update-Database
Alternatively, you can scaffold a new migration and apply it from a command prompt at your project directory:
> dotnet ef migrations add [migration name] 
> dotnet ef database update

コードファーストで開発する場合は、SQL Server なのか PostgreSQL なのかを気にしなくても開発できると思います。

細かい点でいうと作成されたテーブルをみると下の図のようにカラム名が Pascal ケースになっています。

AdWordのアカウントのリンクの画像

SQL Server では、カラム名の大文字小文字を区別しないのでPascalケースは便利なのですが、PostgreSQL では、列名の大文字小文字を区別し、SQL文の中の列名は小文字に変換されます。それで、カラム名が「AspNetUsers」だと SQL 文の中では、常に二重引用符でくくって "AspNetUsers" としないといけなくなって結構手間になります。そのまま Pascal ケースで使うのか、それとも fluent API か attributes を使ってスネークケースに変換して使うのか悩ましいところです。自分は EF Core で使うのが主で、生の SQL をあまり使わないので、Pascal ケースのままでもいいのではないかと思っています。

データベースファーストの場合も、SQL Server を使うのと殆ど違いはなく、Microsoft.EntityFrameworkCore.SqlServer.Design の代わりに Npgsql.EntityFrameworkCore.PostgreSQL.Design を追加し、

dotnet cli の場合は、

dotnet ef dbcontext scaffold "Host=localhost;Database=mydatabase;Username=myuser;Password=mypassword" Npgsql.EntityFrameworkCore.PostgreSQL

Powershell の場合は、

Scaffold-DbContext "Host=localhost;Database=mydatabase;Username=myuser;Password=mypassword" Npgsql.EntityFrameworkCore.PostgreSQL

というように、Microsoft.EntityFrameworkCore.SqlServerNpgsql.EntityFrameworkCore.PostgreSQL に置き換えてやれば、EF model を作成できます。

なお、DbContext のプロパティ名はカラム名を Pascal ケースに変換したものになります。

以上のように EF Core で使う限りにおいては、SQL Server を使うのと差はなく、実際に使っても今のところ大きな問題はでていません。

PostgreSQL を使うメリット、デメリット

SQL Server よりも便利な点としては、where 句で下のように正規表現を使うとサーバー側で処理をしてくれるという点です。( 参照 ドキュメント)

var customersStartingWithA = context.Customers.Where(c => Regex.IsMatch(c.CompanyName, "^A"));

まだ使っていませんが、circle 等の幾何データ型、配列型、JSONB型のマッピングは可能なようなので、EF Core でも、これらのデータの取得と更新は可能なようです。

ただし、PostgreSQL の独自の機能を本格的に使うためには、EF Core ではなくて、Npgsql を直接使う必要があり少し手間がかかります。

でも、少し調べてみると、.NET で PostgreSQL を Document Db として使うためのソフトとして Marten というソフトが開発されています。まだ使い始めたばかりですが、結構使いやすい感じです。

PostgreSQL のデメリットといえば、慣れの問題かも分かりませんが pgAdmin よりは、Visual Studio Management Studio の方が使いやすいという点です。

PostgreSQL にするか MySQL にするか

Linux で動作するオープンソースの RDB といえば、PostgreSQL よりも MySQL の方が有名です。

まず、.NET Core 対応という点で比較すると、PostgreSQL の方は、Npgsql の .NET Core 対応はアルファ版が出てもう1年以上になります。その後も開発が進められてきており、かなり安定してきていると思います。一方、MySQL の方は .NET Core に Connector/Net 7 で対応予定で現在開発版が公開されています。

最近の状況では、ZDNet Japan の「PostgreSQL」がスタートアップ企業に選ばれる理由という記事が参考になると思います。以下に最近のデータを載せておきます。

Hacker News Hiring Trends 2016年11月 Hacker News Hiring Trendsの画像

indeed Job Trends indeed Job Trendsのリンクの画像

ASP.NET Core を格安 VPS で使う

2016年10月1日

この Web サイトを Ubuntu サーバーで運用を始めて6ヶ月になりました。その間に特に問題はありませんでした。むしろ、Linux サーバーに慣れてきて、テキストベースの設定が結構便利だと思うようになりました。

それで、格安 VPS を使って、ASP.NET Core アプリを動かしてみました。使ったのは、「さくらの VPS」1G 月額972円で、Webサイトは pp22.net です。サイトの中身は、まだ、このサイトのコピーです。

さくらの VPS の設定及び ASP.NET Core アプリを Linux で公開する手順については以下のページにメモをしています。

pp22.net の Web サイトが動作し始めたので、WebPagetest を使ってスピードテストをしてみました。結果は殆ど差がなく、格安 VPS でも、Web アプリの作り方次第では十分使えることが分かりました。

creativeweb.jp creativeweb.jpのスピードテストの結果の図

pp22.net creativeweb.jpのスピードテストの結果の図

なお、pp22.net の方がロード時間が短いのは、下部に Google アドセンスの「関連コンテンツ ユニット」が付いていないことが影響していると思います。

格安 VPS を実際に使ってみて、ASP.NET Core を使う上での課題は、データベースをどうするかということです。このサイトは、ファイルベースなので問題なくインストールできたのですが、通常の Web アプリではデータベースが必須になる場合が多いと思います。

ASP.NET Core と親和性が高いのは SQL Sever Express ですが、Linux 版が出るのは来年の中頃です。Linux サーバー以外に Windows サーバーを立てて、そこに SQL Sever Express をインストールすれば動作に問題はないのですが、格安 VPS を使うという趣旨ではどうかと思います。

Linux で一番使われている RDB である MySQL の場合は、公式ドライバー MySQL Connector/NET がまだ開発中で安定性に問題があります。

そういうことで、現時点で格安にしようとすれば PostgreSQL ということになると思って現在テスト中です。PostgreSQL は、.NET Core への対応を積極的に行ってきたこと、また、JSONサポートも積極的に進めているのでスタートアップ向けにはいいのではないかと思っています。

RDB でなくててもいいのであれば、次のようなドライバーが .NET Core に対応しています。ただし、ServiceStack.Redis の方は、.NET Core 対応についてはアルファ版です。

また、クラウドのストレージを利用する場合は、次のようなツールが .NET Core に対応しているので、主なものは使えるようになっています。

ASP.NET 5 Beta 7 を Ubuntu Server で使ってみた

2015年9月12日

ASP.NET 5 Beta 7 が公開されましたが、公式ブログで Mono なしで動作するということだったので Ubuntu Server に実際にインストールしてみました。

Ubuntu Server につては、Microsoft Azure でイメージは Ubuntu Server 14.04 LTS を使用しています。

インストールについては、ASP.NET 5 の公式マニュアルの Installing ASP.NET 5 On Linux のページを見てしました。最初は、注意を読んでなくて dnvm をインストールすると、下の図のように「dnvm needs unzip to proceed.」というメッセージが出ました。マニュアルをちゃんと見ると note に dnvm のインストールには unzip が必要と言うことが書いてありました。

ubuntu01.png

DNX とlibuv については、マニュアルどおりにインストールしました。

実際の動作のテストは、VS 2015 で作成した ASP.NET 5 プレビューテンプレートの Web Application を使ったものを使用しました。修正点は、Kestrel サーバーが動作するように project.json に以下の項目を追加しました。

"dependencies" に追加
"Microsoft.AspNet.Server.Kestrel": "1.0.0-beta7"

"commands" に追加
"kestrel": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Kestrel --server.urls http://localhost:8000"

それで、「dnu restore」で依存パッケージを取得して、「dnx kestrel」で kestrel を起動するととアプリが動作しました。意外にあっけなく動作させることができました。

ubuntu02.png

Qiitaの「ASP.NET5 クロスプラットフォームでアプリケーションの動作環境を構築する」という記事では、「Ubuntuは、手順にある通りではうまくいきません。」と書かれていますが、それから比べると ASP.NET 5 の Linux 対応もかなり進んだと思います。

kestrel のポート番号を80に設定して起動するとチェックでエラーになります。本番環境での運用は、Nginx をリバースプロキシサーバーして使うようになるケースが多いような気もします。

コンソールアプリケーションの方もテストしてみました。ローカルディスクへの保存の処理を書いてみたのですが、このあたりは、DNX 4.5.1 と DNX Core 5.0 でライブラリーに変更があるのでコードの修正が必要になってきます。こういうケースでは、"frameworks"の設定は、VS だとどちらかでエラーがあるとコンパイルしないしエラーの表示もよく分からないものが表示されるので、使わない方の"framework"を削除しておいた方がいいようです。この関係を調べていて、.Net Core のドキュメントのページができているのに気がつきました。ただし、まだほとんどのページが作成中で使える状態にはなっていません。

以上テストをしてきて、ASP.NET 5 が Linux で実用的に使えるようになる日がかなり近づいていると感じました。

 

AWS が「さくらのクラウド」と同じ価格性能比になった?

2014年7月17日

「AWS は、さくらのクラウド、Azure より10倍価格性能比が悪い?」というブログを書いた後に、Amazon EC2 では、t2 インスタンスが提供されました。t2 インスタンスは、低価格帯のインスタンスでバースト機能をがあるのが特徴です。

そこで、t2 インスタンスを使って、前回と同じテストをしてみました。テストしたタイプは以下のとおりで、OSは Windows 2012-R2 です。今回は、価格的には「さくらのクラウド」とほぼ同じになっています。

  • さくらのクラウド:2コア, メモリ4GB, SSDプラン 100GB、石狩
  • Amazon EC2: t2.medium (2vCPU, 4GBメモリ), GP (SSD) 100GB、東京リージョン 

コスト(月あたり・円) データ転送量は80GBで計算

 
CPU
ディスク
データ転送
ディスク単価(GBあたり)
さくらのクラウド
5,500
3,500
0
9,000
20円、SSD 35円
Amazon EC2
5,626
1,260
1,688
8,574
8.4円、SSD 12.6円

※Amzon EC2 はドル建てなので 1ドル=105円で

テストの結果は、下の図のとおりで、Amazon EC2 の t2.medium の方が少し良くなっています。

t2 インスタンスについて考えてみると、確かに月100万PVのWebページは個人や中小企業のWebページとしてはかなりアクセス数が多い部類になるのですが、それでも平均すると1分間に23回のアクセスしかないので、1回の処理を1秒でできるように作ってあれば動作しているのは23秒だけで残りの37秒は遊んでいるということになります。実際は処理では特定の時間に集中することが多くそれにあわせて処理能力があるサーバーを選択するので、サーバーのCPUの稼働率というのは普段はかなり低いのが一般的です。そういう点ではバースト機能があるというのはコスト的に相当なメリットがあります。

さくらのクラウドにバースト機能があるかどうかは確認できていません。ただ、フェアシェアのようなCPUを共有する機能は使っていると思います。単価をみると 1Core-2GB 2,139円、2Core-4GB 4,860円、4Core-8GB 11,340円、8Core-16GB 24,300円とコア数が増えるとコア当たりの単価が上がっています。CPUをユーザー毎に完全に独立させているのであれば、Azureのようにコア当たりのコストは上がらないはずです。単価が上がるというのはコア数が多くなると共有が難しくなってくるという事情を考慮した単価設定だと思うのです。

いずれにしても、CPUの利用の仕方については、さくらのクラウドのほうが先進的であって、AWS が追いついたといえるでしょう。「国産クラウド」を代表する「さくらのクラウド」には今後も頑張って欲しいと思います。

Amazon EC2 t2.medium

image

さくらのクラウド

image