yasutomogのブログ

JavaScriptとAzure周りのメモ帳

PHP(Lumen)からAzure Storage Tableを使ったときのメモ3

内容

yasutomo.hatenablog.com

yasutomo.hatenablog.com

  • 上記2つの記事から、Azure SQLDatabaseとAzure Storage Tableを使って比較してみたメモ

処理概要

  • CSVから読み込んだデータをDBもしくはStorageに登録または更新
  • Azure SQLDatabaseのプランはS0(Standardの一番低いプラン)
  • Azure Storage Tableも通常プラン(上位版にはCosmosがある)
  • 自分のローカルPCから実施(AppService上で試すなどすると、また計測値が変わる可能性がある)

テスト内容

大量のInsert処理はAzure Storage Tableが早い

  • 10,000〜100,000件のCSVデータを使用してテスト
  • Azure SQLDatabaseへのInsert処理は1,000件単位にInsertして10,000件単位でcommitする(1000件単位でのInsertはSQLDatabaseの使用制限のため)
  • Azure Storage TableへのInsert処理は、Batchを使い100件単位にリクエス
  • 計測結果としては、CSV件数に関係なくAzure Storage Tableへの処理のほうが、Azure SQLDatabaseへの処理に比べて約5倍程の処理速度が出ることを確認

大量のupdate処理はAzure SQLDatabaseが早い

  • 1テーブル内の特定条件に紐づく複数レコードまたはエンティティを一括更新
  • 10,000件を一括更新するようなテスト
  • Azure SQLDatabaseへの更新処理は、update文を1文流すのみ
  • Azure Storage Tableへの更新処理は、更新対象データの判定に必要なデータを取得後、判定してから100件単位にBatchを使ってupdate処理をリクエス
  • 計測結果としては、Azure SQLDatabaseへの処理の方が約6倍近い速度がでることを確認。但し、どちらも数十秒で終わる処理なので、もっと大量なデータにならない限りはInsert処理に比べてほどのインパクトはなさそう。

結論

  • 大量のInsert処理が確実に必要になるのであれば、Azure Storage Tableは検討してみてもよさそう。
  • 今回の計測値は、Azure SQLDatabaseのプランはそこまで高くないので、そこを上げることで結果は変わってくる
  • 使用料金の観点でもみても、Azure Storage Tableのが安いので、その辺も踏まえて選定していく必要がある

PHP(Lumen)からAzure Storage Tableを使ったときのメモ2

内容

yasutomo.hatenablog.com

  • 上記ブログでAzure Storage TableにPHPからアクセスしたときにハマったポイントをまとめたメモ

処理概要

  • CSVから読み込んだデータをAzure Storage Tableに保持
  • CSVの1行がAzure Storage Tableの1Entityという構造
  • CSVのKey項目が存在しなければInsert(登録)、Key項目が存在すればUpdate(更新)する
  • CSVのKey項目でStorageから検索して、登録または更新を判定
  • Azure Storage TableのEntityのプロパティはすべて、String(文字列)の型を指定して、CSVの記載のまま登録したい

ハマったポイント1

Azure Storage Tableから取得した値が想定外!!?

  • 設定したときは、String(文字列)を指定
$entity->addProperty("hoge", EdmType::STRING, csvRec[0]);
  • プロパティから取得するときは、getValue関数を使用していた
$entity->getProperty("hoge")->getValue();
  • 設定した値のまま取得できることを想定していた。 基本的には想定通りの動作だったが、小数点付きの数値などの場合に設定値と異なることがあった
  • 設定値が "0001.0" の場合。getValueすると、 "1" で返されることを確認
  • azure-storage-tableのライブラリの中を確認
    • MicrosoftAzure\Storage\Table\Internal の JsonODataReaderWriter クラスでStorageから取得したEntityを変換している
    • 上記クラスのparseOneEntity(private関数)でEntityを生成してプロパティを1つずつ設定している
    • プロパティの型がStringの場合に、strvalした値をvalueに設定している
    • strval(0001.0)の戻り値は、1となるため、今回の現象になっている
  • Entityから以下のようにすると、想定通り、設定値と同様(0001.0)の値が取得できる
$entity->getProperty("hoge")->getRawValue();

ハマったポイント2

Entityを更新すると想定してプロパティの型が想定外!!?

  • entityを更新するときには、Storageから取得したentityを元に一部のプロパティを変更していた
$tableClient = TableRestProxy::createTableService($connectionString);
$entity = $tableClient->getEntity("mytable", "tasksSeattle", 1);
$entity->setPropertyValue("hoge", "fuga");
$tableClient->updateEntity("mytable", $entity);
  • 上記コード例のような場合、変更したプロパティは想定通りだったが、変更していないプロパティが元の型と別の型に自動的に変わっていることを確認
  • 上記コード例でentityに「weight」というプロパティに「60.5」という値が設定されていた場合、updateEntityされると元々はString型だったものがDouble型に自動で変換されている。また日付型データも同様の現象が発生することを確認
  • 取り急ぎの解決策として、Storageから取得したentityはそのまま使わないようにして、別途Entityを生成してaddPropertyすることで、すべてのプロパティをString型で保持するようにした

ハマったポイント3

getRawValueの値が想定外!!?

  • ハマったポイント1で書いたとおり、getRawValue関数を使うことで設定したときの値がそのまま返されることを確認していた
  • プロパティの型がString以外のときは、空文字が返されることを確認
  • これについてはライブラリの仕様だと思う。ライブラリのソースコードの中にも「//Store the raw value of the string representation.」というコメントが記載されており、あくまでも文字列型のときにのみ使用されるものという認識。

PHP(Lumen)からAzure Storage Tableを使ったときのメモ1

内容

  • Lumenで構築しているWebアプリケーションからAzure Storage Tableを使ったときのメモ
  • PHPからの接続は、MSの公開ライブラリを使用(以下の方法でライブラリ追加)
    • composer require microsoft/azure-storage-table

バージョン

github.com

前準備

ストレージアカウントを作成

  • 以下のリンクを参考にして、ストレージアカウントを作成し適当な名前でTableを新規作成

docs.microsoft.com

Azure Storage Tableを確認するためのツールをインストール

  • Azure Portalからは現時点ではTableが確認できてない
  • MSから公式のクライアントツールが提供されている(Mac版もある)

docs.microsoft.com

ライブラリの使用方法

  • 基本的には以下のリンクの方法でTable操作とEntity操作は問題なくいける

docs.microsoft.com

実装ポイント

Entityの検索処理

  • Key検索ではなくパーティションを条件に全件検索などするときに、1度に返される結果件数は1000件の制限がある
  • 検索結果が1000件より多い場合は、検索結果のcontinuationTokenを使用して次の1000件を取得するような実装が必要になる

サンプルコード

// SampleTableからの検索結果
$entities = [];
do {
    $result = $tableClient->queryEntities('SampleTable', $options);
    $entities = array_merge($entities, $result->getEntities());
    $options->setContinuationToken($result->getContinuationToken());
} while($result->getContinuationToken());

複数Entity操作処理

  • 複数行まとめて追加や更新などしたいときには、Batch処理としてまとめて処理することが可能
  • 1Entityごとに処理するよりもBatch処理を使用する方がパフォーマンス的にも良い
  • 但し、1Entityに対しての複数操作をBatchでまとめるのはやめてというのがドキュメントに記載されている

サンプルコード

$batchOperations = new BatchOperations();
foreach ($records as $rec) {
    $entity = new Entity();
    $entity->setPartitionKey('hoge');
    $entity->setRowKey('fuga');
    $entity->addProperty("propKey1", 'propVal1');
    $entity->addProperty("propKey2", 'propVal2');

    if (count($batchOperations->getOperations()) % 100 === 0) {
        $tableClient->batch($batchOperations);
        $batchOperations = new BatchOperations();

    }
}

if (count($batchOperations->getOperations()) % 100 !== 0) {
    $tableClient->batch($batchOperations);
}

Board APIのデータをChart表示するElectronアプリ(vue.js)

概要

  • ElectronとBoard APIを使ったサンプルアプリ作成(素振り)
  • Board APIで請求データと支払データを取得してChart表示
  • 基盤はelectron-vueを使用して実装
  • CSSフレームワークにはbuefyを使用
  • ストレージにnedbを使用

使用技術

  • electorn:2.0.2
  • vue:2.3.3
  • vue-electron:1.0.6
  • bignumber.js:7.0.1
  • buefy:0.6.5
  • chart.js:2.7.2
  • nedb:1.8.0

github.com

github.com

buefy.github.io

今回のソース

github.com

工夫したところ

  • API接続情報をストレージに保持
    • Board APIの接続に必要となるキーとトークンは都度設定する手間を省くために、nedbで保持できるように対応
  • APIから取得したデータをストレージに保持
    • Chartを表示するときに都度、APIアクセスするのは非効率なため、nedbで保持できるように対応
  • Board APIへのアクセス方法
    • Board APIはアクセス制限(3リクエスト / 秒)があるので、一定間隔をあけつつリクエストするように対応

使用方法

1. Board APIのキーとトークンの発行

  • Board APIについては、以下を参照

developers.the-board.jp

2. 設定画面でBoard API接続情報の設定

f:id:yasug:20180609002619p:plain

  • 1で発行した接続情報を入力して設定ボタンをクリック
  • 取得ボタンは、nedbに保持しているデータを取得して表示します

3. API接続ボタンをクリックしてデータ取得

f:id:yasug:20180609002622p:plain

  • APIに接続して請求データと支払データを直近1年分取得します
  • 内部的には、月ごとのデータを保持している
  • リクエストは意図的に間隔をあけているので、少し時間がかかります

4. 請求データ画面でChart表示

f:id:yasug:20180609002626p:plain

  • APIで取得したデータを元にChartを表示します

今後

基盤はできたので、あとは必要に応じてChartの種類を追加していきたい

Board APIの利用について

会社でWebサービスのBoardを利用していて、 API(ベータ版?)が公開されているので使ってみたメモ。

API仕様については、以下にまとまっていて KEYとトークンが発行できれば、あとは仕様に沿って リクエストするという流れ。

developers.the-board.jp

最初、curlコマンドで叩いていて、問題なくレスポンスが取れることが確認できた。

レスポンス結果を使って、適当にChart(jsで描画)を表示してみることを試してみようと思い ローカル環境のWebサーバに適当なhtmlとjsでページ作成し試したところ クロスドメインのエラーとなった。

Boardのサイトからチャットにて問い合わせしたところ、すぐに担当者に繋いで頂き 現時点では、セキュリティの関係上、ブラウザからの利用は想定していなく サーバからアクセスする流れとなる。 ※チャットで即座にご回答頂けたので、非常に助かりました。

とりあえず遊びで使ってみたかっただけなので今回はローカル環境に 以下のnode.jsのプロキシサーバを立てて対応して動かしました。

github.com

BoardのAPIはリクエスト数の制限が割りと厳しいので 真面目に作るなら、サーバ側でデータ保持するなど 何かしらのキャッシュ機構を作成する必要がありそうという印象。

CordovaのAndroidビルドエラーと環境構築

前提の環境

ビルドエラーについて

cordovaで開発するときに、Android用のビルドで以下のようなエラーが発生。

Starting 'cordova-with-build'...
(省略)
Error: Android SDK not found. Make sure that it is installed. If it is not at the default location, set the ANDROID_HOME environment variable.
'cordova-with-build' errored after 5.55 s

これだけ見ると「ANDROID_HOME」を設定すればいいように見えるが環境変数として、「ANDROID_HOME」に「~/Library/Android/sdk」を設定しても同様のエラーとなり解決せず。

確認

cordova requirementsコマンドでみると、以下のようにAndroid targetがnot installedになっている。

本来であれば、ここはAndroid StudioのSDKManagerでインストールした環境が表示されるはず。

$ cordova requirements android

Requirements check results for android:
Java JDK: installed .
Android SDK: installed
Android target: not installed
Android SDK not found. Make sure that it is installed. If it is not at the default location, set the ANDROID_HOME environment variable.
Gradle: not installed
Could not find gradle wrapper within Android SDK. Might need to update your Android SDK.

対応方法

・cordova platform rm android
・cordova platform add android

上記を試してた後に、改めてcordova requirementsコマンドを実行し、targetに正しく値が表示されていることを確認してOK

$ cordova requirements android

Requirements check results for android:
Java JDK: installed .
Android SDK: installed
Android target: installed android-21,android-22,android-23,android-24,android-25,android-26,android-27
Gradle: installed

iOSのPush通知(Apple Push Notification)のpemファイル作成

Push通知周りの証明書作成でいつもはまるのでメモ

現象

  • p12ファイル作成後、以下のようなopensslコマンドでpemファイルを生成
  • p12ファイルを生成するときに設定したパスワードを聞かれるので入力
  • Can't read Password というエラーが発生し、0バイトのpemファイルが作成される
openssl pkcs12 -in hoge.p12 -out fuga.pem -nodes -clcerts

解決策

  • iterm2を使って上記コマンドを叩くとエラーになるので、Macにデフォルトで入っているターミナルで全く同じコマンドを叩くことで正常にpemファイルが生成される