2017年のPaaS/SaaS周りを振り返って – フルマネージドDBサービス発展の年

2017年も終わりを迎えようとしておりますが、2017年はPaaS/SaaSにとって非常にインパクトの大きい一年でした。

このエントリでは、PaaS/SaaS利用者の観点から、2017年を振り返ってみようと思います。

なお、私は主にMicrosoft Azureを利用しているため、内容の濃さなどの面でどうしてもMicrosoft Azure寄りとなりますことをあらかじめご了承ください。

フルマネージドDBサービス発展の年

2017年は、フルマネージドDBサービスの利便性が大変向上した一年だったと思います。

特に「DBインスタンス」という考え方から脱却したサービスが登場し、本格的に利用された年だったと言えるのではないでしょうか。

アプリケーション開発者からすると、インスタンスのことを気にするのは本質的ではありません。そのような本質的ではないことについて一切触れる必要なく、DBをサービスとして利用することは、2017年で一気に身近になってきたことだと思います。

また、料金体系的にも「トランザクションごとに課金」というパターンが浸透してきたのも2017年の特徴ではないでしょうか。これによって、真に「利用した分だけ支払う」ことが現実のものとなったと思えます。

Azure Cosmos DB

スキーマレスなNoSQL DBとして利用でき、各リージョン間でデータレプリケーションが可能なDBaaSです。

もともとAzure Cosmos DBの源流として、Azure DocumentDBというサービスが2010年から提供されていたのですが、Build 2017にて名称をAzure Cosmos DBとし、以下のようなAPIへと対応しました。

料金体系についてはRU(Request Unit)と呼ばれる単位で計上されることになっており、インスタンスベースの課金体系ではないことが非常に重要です。

Azure Database for MySQL/PostgreSQL (プレビュー)

Azure SQL Databaseで培われてきたフルマネージドDBサービスの堅牢性とスケーラビリティが、MySQLおよびPostgreSQLのインターフェースで利用できるようになったものです。これもBuild 2017で発表されました。

従来であればMySQL/PostgreSQLともにVMを立ち上げ(あるいはオンプレミスのリソースを用意して)そこにインストールし、パフォーマンスモニタリングに気を使いながら、自力で運用するものでした。

このサービスは現時点ではまだプレビューですので、手放しで本番に投入して良いものかどうかは微妙だと思いますが、上記のような運用から解放される道筋が示されていることについて、将来十分に考慮に値することだと思います。

こちらの料金体系は、時間課金のコンピューティングユニットとデータ容量課金のストレージの合算値となり、やはりインスタンスベースの料金体系ではありません。

Amazon DynamoDB

Amazon DynamoDBは、フルマネージドDBサービスの中でも元祖と言えるでしょう。2012年にサービス提供が開始され、2013年に東京リージョンで利用可能となりました。

リージョン間でのレプリケーション(クロスリージョンレプリケーション)にも対応しており、課金体系もデータ量とスループットに基づいたものとなっています。

これらのことは、近代的なフルマネージドDBサービスの基礎となっており、Amazon DynamoDBがサービスを通して示したビジョンは大変重要なものと言えるでしょう。

フルマネージドDBサービスは開発者をより開発に集中させる

上記で紹介したサービスはいずれも、開発者からDBの管理という手間をなくそうという方向性のサービスです。自力でDBの管理を行う場合にかかるコストと、上記サービスを利用した場合のコストは、性質的に全く異なるものです。

また、自力でDBの管理を行う場合は、どうしても人間そのものがボトルネックになってしまいます(腰痛や風邪などの体調不良、冠婚葬祭に伴う休暇など)。速く移動するという本質で見た時に馬車から自動車へと変遷していった歴史があるように、DBの管理やスケーリングについてもより利便性の高い手段を検討していくことが肝要なのではないでしょうか。

そして、開発者がより開発に集中できるようにし、生産性の向上に繋げていくことが、最終的な競争力に寄与するのだろうと私は思います。

Azure Functions CosmosDB input bindingsを使う上でのコツ – バインド変数編

さて、今度はバインド変数に関する躓きを共有します。

クエリエクスプローラとFunctions経由との間でクエリの結果が異なる???

例えば以下のようなクエリをCosmosDBに投げるとします。

SELECT c.id FROM c WHERE CEILING(c.age / 10) * 10 = 30

クエリエクスプローラでは以下のような結果が得られました。

[
    {
        "id": "user-123"
    },
    {
        "id": "user-124"
    },
    {
        "id": "user-133"
    }
]

今度はクエリの30に当たる箇所を{generation}として、sqlQueryに設定します。

SELECT c.id FROM c WHERE CEILING(c.age / 10) * 10 = {generation}

こんな感じですね。そしてFunctions側でQueue Storageトリガーを使って以下のようなジョブを受け取ります。

{"generation": 30}

この時、Functionsで受け取れるCosmosDB inout bindingsの結果は以下のようなものとなります。

[]

すっからかんですね。。。一体どういうことでしょう。

理由

初めて知った時には非常に驚きましたが、どうやら各bindingsにわたってくる値は文字列としてキャストされてしまうっぽいということです。

本当は以下のように展開してほしいのですが。。。

SELECT c.id FROM c WHERE CEILING(c.age / 10) * 10 = 30

こんな感じになってしまうということです。

SELECT c.id FROM c WHERE CEILING(c.age / 10) * 10 = "30"

これは厄介ですね。。。。

対処

これを回避するには、クエリの方で強制的に数値に置き換えてやればよいのですが、CosmosDBのビルトイン関数には数値へのキャストをしてくれるものがありません。

そこで登場するのがユーザ定義関数(User Defined Function/UDF)です。

CosmosDBでは、javascriptを使ってユーザが関数を定義することができるのです。

CosmosDBのブレードにあるスクリプトエクスプローラというメニューから、UDFの定義ができます。

UDF開発画面

上記画像のような関数を定義してやり、sqlQuery側を以下のように変更すると、無事に期待した結果が得られます。

SELECT c.id FROM c WHERE CEILING(c.age / 10) * 10 = udf.ConvertToNumber({generation})

このほか、時刻にまつわる関数などもCosmosDBにはビルトインでは存在しませんが、このようなUDFを作って対応することが可能です。

CosmosDBのUDFは非常に強力な機能ですので、是非とも有効に活用していきたいものですね。

元ネタ:https://stackoverflow.com/questions/44916811/difference-among-the-azure-cosmosdb-query-explorers-results-and-the-azure-funct/44918767#44918767

Azure Functions CosmosDB input bindingsを使う上でのコツ – 余剰演算子編

先日あたりからAzure FunctionsのCosmosDB input bindingsを使っていて、いくつかはまりどころのような挙動に出くわしましたので、その説明と対処法を紹介していきます。

sqlQueryで剰余演算子(Modulation Symbol)がそのまま使えない

例えば以下のようなQueryをCosmosDBに投げるとします。

SELECT c.id FROM c WHERE c.level % 20

このクエリを直接クエリエクスプローラで実行する場合、期待する結果が得られます。

ところがこのクエリをAzure FunctionsのCosmosDB input bindingsにsqlQueryとして指定した場合、以下のようなエラーがでてしまい、期待した動作をしません。

2017-07-05T16:45:43.113 Exception while executing function: Functions.MyFunction. Microsoft.Azure.WebJobs.Host: The '%' at position 34 does not have a closing '%'.

理由

実はsqlQueryの仕様として、%というのはアプリケーション設定の値を参照するために使う記号でして、%myappSetting%のような感じで使うものだったんですね。

そのため、単独で%が登場すること自体があってはならない、と、そういうことが理由となっています。

対処

対処法の一つとして、アプリケーション設定値に%を設定して、それを使えばよい、というものがあります。

アプリケーション設定から値を設定する

上記画像のように、例えばmodulationsymbolというアプリケーション設定値を定義しておき、sqlQuery側では以下のように%%modulationsymbol%に置き換えることで、期待通りの結果を得ることができます。

SELECT c.id FROM c WHERE c.level %modulationsymbol% 20

あまりカッコよくはないですが、致し方がない感じはしますね。

元ネタ:https://stackoverflow.com/questions/44903632/sqlquery-of-documentdb-input-bindings-with-modulation-symbol-makes-functions-fa

Azure Functions Cosmos DB Bindingsの新機能sqlQueryを試してみた

Cosmos DB Binding

Azure Functions Cosmos DB bindingsというドキュメントが公開されていることに最近気がついたのですが、その中でも個人的に以前から密かに待望していた機能であるsqlQueryについて、とうとう公式に明記されました。

大変便利と思われるこの機能を早速試してみましたので、本エントリで紹介していきます。

なお、本エントリの前提知識として、以下のエントリを読んでおくことをお勧めします。

Azure DocumentDB inputを設定する

今回私が作った関数のfunction.jsonですが、DocumentDB inputの設定は以下のようになっております。よく見ると、sqlQueryに見慣れたSQLが記述されていますね。

これを標準エディタで見てみますと、以下のようになります。

sqlQueryの仕様

テーブル名を必ず指定する必要がある(ただし何でもOK)

気をつけなければいけない点として、フィールド名を指定する場合はテーブル名を指定する必要があるということです。

function.jsonでコレクション名を指定してあるため、テーブル名そのものは何でもOKであり、特に何らかの影響を与えるわけではありません。このため、慣例的にテーブル名をcとすることが多いようです。そのため、フィールド名nameを指定するためにはc.nameとする必要があります。

クエリバインド変数の指定方法

httpバインディングで受け付ける関数の場合、sqlQueryに対して{name}などとすることでクエリバインド変数を利用することが可能です。

例えば SELECT c.id FROM c WHERE c.type={type}というsqlQueryを指定した場合、getパラメータにtype=imageのように指定することで、typeimageであるドキュメントを全て持ってくることができます。

今回使ったデータ

今回の検証のために、あらかじめ別の関数を使ってCosmos DBに以下のようなドキュメントデータをいくつか登録しておきました。

関数のコーディング

普段ですとPerlやBashでコードを書いたりするのですが、今回はPHP7での実装事例を紹介します。

中身はこれしかありませんが、一応おさらいも兼ねて解説していきます。

1行目ですが、このコードはphpで動作するコードですので、Functionと言えど <?phpで開始する必要があります。

2行目ではfunction.jsonで指定したsqlQueryの結果を$messageに格納する処理を行っています。

getenvの引数に指定する文字列は、function.jsonで指定したnameと同じものを指定します。これによりgetenvはCosmos DBから取得したJSONデータを内包した一時ファイルのパスを返します。あとはfile_get_contentsで中身を取り出し、json_decodestdClassに復元してやることで、phpで自在に操作可能となります。

3行目はレスポンス処理を行っています。getenvでレスポンス用の一時ファイルパスを取得し、そこにjson_encodeしたデータをfile_put_contentsで書き込んでやるだけです。

実際にアクセスしてみる

以下は、GETパラメータにname=tagoをつけてリクエストを投げてみた結果です。

任意の絞り込みを行った結果を取得できていることがわかると思います。

まとめ

今回の検証で、Azure Functions + Cosmos DBを使ったSQLライクな問い合わせができることがわかりました。

ちなみにCosmos DBに対するクエリとして、既に一部の集計関数がサポートされています。ただし、GROUP BY句は現時点ではサポートしていません(かなりアツい要望は多数あるようです。私も欲しい)。

Azure DocumentDB が Azure Cosmos DB に名称変更したようです

Azure Functionsと共に利用すると便利なフルマネージドNoSQLサービスである「Azure DocumentDB」が名称変更して「Azure Cosmon DB」になったようです。

以下、Azure Portal上の説明を引用します。

Azure Cosmos DB is a fully managed, globally-distributed, horizontally scalable in storage and throughput, multi-model database service backed up by comprehensive SLAs. Azure Cosmos DB is the next generation of Azure DocumentDB. Cosmos DB was built from the ground up with global distribution and horizontal scale at its core – it offers turn-key global distribution across any number of Azure regions by transparently scaling and replicating your data wherever your users are. You can elastically scale throughput and storage worldwide and pay only for the throughput and storage you need. Cosmos DB guarantees single-digit millisecond latencies at the 99th percentile anywhere in the world, offers multiple well-defined consistency models to fine-tune for performance and guaranteed high availability with multi-homing capabilities – all backed by industry leading service level agreements (SLAs).

Cosmos DB is truly schema-agnostic – it automatically indexes all the data without requiring you to deal with schema and index management. Cosmos DB is multi-model – it natively supports document, key-value, graph and columnar data models. With Cosmos DB, you can access your data using NoSQL APIs of your choice – DocumentDB SQL (document), MongoDB (document), Azure Table Storage (key-value), and Gremlin (graph), are all natively supported. Cosmos DB is a fully managed, enterprise ready and trustworthy service. All your data is fully and transparently encrypted and secure by default. Cosmos DB is ISO, FedRAMP, EU, HIPAA, and PCI compliant as well.

委細について、本日深夜(日本時間)に開催される Build 2017 での発表が気になるところです。

なお、ライブビューイングがストリーミング配信される様ですので、そちらも見ておくと良いと思われます。