tag:blogger.com,1999:blog-53060572095915128282024-03-06T14:32:05.804+09:00株式会社ジェニシス 技術開発事業部ブログ株式会社ジェニシス技術開発事業部エンジニアによる技術系情報を中心としたブログです。ながみねhttp://www.blogger.com/profile/03714491902349624938noreply@blogger.comBlogger130125tag:blogger.com,1999:blog-5306057209591512828.post-54098804642694884422018-07-13T16:27:00.002+09:002018-07-13T16:28:28.588+09:00【AWS Lambda】API Gateway の疎通確認株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。<br />
<br />
最近、AWSをフル活用して社内システムを作ったので、そのノウハウのご紹介を行っています。<br />
<br />
ただいま、Lambdaで関数作りを頑張っています。<br />
<br />
<h2>
試しに繋いでみるか</h2>
<div>
前回「<a href="https://genesis-tdsg.blogspot.com/2018/07/aws-lambdaweb.html" target="">【AWS Lambda】Webリクエストの受付</a>」でひとまずAPI Gatewayをトリガーにくっつけました。</div>
<div>
<br /></div>
<div>
これでもうURLが存在しているのでアクセスしてみましょう。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-xUbY_HNiZWU/W0hPi69zfaI/AAAAAAAADNM/UutOqxLNWF8yA_q6zd4RdfOgpME50xsNACLcBGAs/s1600/WS000052.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="305" data-original-width="1047" height="186" src="https://3.bp.blogspot.com/-xUbY_HNiZWU/W0hPi69zfaI/AAAAAAAADNM/UutOqxLNWF8yA_q6zd4RdfOgpME50xsNACLcBGAs/s640/WS000052.JPG" width="640" /></a></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-cyJ8koMyNUQ/W0hP4B7kCtI/AAAAAAAADNU/0GbAVwbgYzEPscGkohGVWZdU2Dm_I2C8ACLcBGAs/s1600/WS000053.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="209" data-original-width="579" src="https://3.bp.blogspot.com/-cyJ8koMyNUQ/W0hP4B7kCtI/AAAAAAAADNU/0GbAVwbgYzEPscGkohGVWZdU2Dm_I2C8ACLcBGAs/s1600/WS000053.JPG" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<ul>
<li><span style="color: red;">{"message": "Internal server error"}</span></li>
</ul>
</div>
<div>
<br /></div>
<div>
Internal server error!!</div>
<div>
<br /></div>
<div>
初期状態では動かない!!</div>
<div>
<br /></div>
<div>
<h2>
テストでは正常</h2>
</div>
<div>
しかしですね、Lambdaのテストでは正常なんですよ。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-oFkbpZrfTyk/W0hQesbQp_I/AAAAAAAADNc/w_c1mKHRMeclrVI_7VIOpUDAlyCcJOuSQCLcBGAs/s1600/WS000054.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="490" data-original-width="1600" height="194" src="https://2.bp.blogspot.com/-oFkbpZrfTyk/W0hQesbQp_I/AAAAAAAADNc/w_c1mKHRMeclrVI_7VIOpUDAlyCcJOuSQCLcBGAs/s640/WS000054.JPG" width="640" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<span style="color: red; font-size: x-large;">テストでは正常なのに、実際にアクセスするとエラー。</span></div>
<div>
<br /></div>
<div>
ここで躓く人って結構多いんじゃないでしょうか?</div>
<div>
<br /></div>
<div>
私も苦労しました。</div>
<div>
<br /></div>
<div>
<h2>
原因</h2>
</div>
<div>
実はですね、Lambdaのテストは「ラムダ関数だけ」のテストで、API Gatewayは関係無いんですよ。</div>
<div>
<br /></div>
<div>
つまり、上記の状況は</div>
<div>
<br /></div>
<div>
<ul>
<li>ラムダ関数は正常である。</li>
<li>API Gatewayでエラーを起こしている。</li>
</ul>
</div>
<div>
<br /></div>
<div>
という状況なのです。</div>
<div>
<br /></div>
<div>
<h2>
API Gatewayエラーの原因</h2>
</div>
<div>
API Gateway がエラーになる原因。</div>
<div>
<br /></div>
<div>
<span style="color: red;"><b>ログとかそういうの一切出ないですから!!</b></span></div>
<div>
<br /></div>
<div>
ネット調査で特定しました。</div>
<div>
<br /></div>
<div>
<ul>
<li><a href="https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html" target="_blank">API Gateway の Lambda プロキシ統合をセットアップする</a></li>
</ul>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-z5JOSwaQv_s/W0hSiGug-5I/AAAAAAAADNo/Bwcf21UIg4AztIEmCeJZeEW-WRUEWdrJgCLcBGAs/s1600/WS000055.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="192" data-original-width="1279" height="96" src="https://1.bp.blogspot.com/-z5JOSwaQv_s/W0hSiGug-5I/AAAAAAAADNo/Bwcf21UIg4AztIEmCeJZeEW-WRUEWdrJgCLcBGAs/s640/WS000055.JPG" width="640" /></a></div>
<div>
<br />
API Gatewayでは、以下の形式でレスポンスを返さなければいけないと書かれています。<br />
<br /></div>
<div>
<pre class="prettyprint linenums"><code>{
"isBase64Encoded": true|false,
"statusCode": httpStatusCode,
"headers": { "headerName": "headerValue", ... },
"body": "..."
}</code></pre>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<h2>
関数</h2>
</div>
<div>
つまり、API Gatewayを通せるようにLambda関数を書かねばなりませんから。</div>
<div>
<br /></div>
<div>
<pre class="prettyprint linenums"><code class="language-py">def lambda_handler(event, context):
# TODO implement
return 'Hello from Lambda'
</code></pre>
</div>
<div>
<br /></div>
<div>
これを</div>
<div>
<br /></div>
<div>
<pre class="prettyprint linenums"><code class="language-py">def lambda_handler(event, context):
# TODO implement
return {
"isBase64Encoded": False,
"statusCode": 200,
"headers": {},
"body": "Hello from Lambda"
}</code></pre>
</div>
<div>
<br /></div>
<div>
こうする!!</div>
<div>
<br /></div>
<div>
<h2>
結果</h2>
</div>
<div>
無事に表示されました。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-auo8Cy6mTgc/W0hTy9OoayI/AAAAAAAADOA/bdfTuTgjQ4E0bjMoerUdyBJ-dMFnHHUmQCLcBGAs/s1600/WS000056.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="214" data-original-width="574" src="https://3.bp.blogspot.com/-auo8Cy6mTgc/W0hTy9OoayI/AAAAAAAADOA/bdfTuTgjQ4E0bjMoerUdyBJ-dMFnHHUmQCLcBGAs/s1600/WS000056.JPG" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
これ、知らなけれ本当に意味分からないので、ここで躓かないよう注意して下さい。<br />
<br /></div>
<div>
<h2>
続く</h2>
</div>
<div>
引き続きエAPI Gatewayの掘り下げを進みます。</div>
Anonymousnoreply@blogger.com9tag:blogger.com,1999:blog-5306057209591512828.post-34101988605260597162018-07-06T14:13:00.001+09:002018-07-06T14:14:43.470+09:00【AWS Lambda】Webリクエストの受付株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。<br />
<br />
最近、AWSをフル活用して社内システムを作ったので、そのノウハウのご紹介を行っています。<br />
<br />
ただいま、Lambdaで関数作りを頑張っています。<br />
<br />
<h2>
Webからのリクエストを受け付けたい!!</h2>
<div>
Lambda というのは実に色々な長所を持つ優れたアーキテクトですが、私が一番好きなのは、その<b><span style="color: blue;">可用性の高さ</span></b>です。<br />
<br />
処理不可に応じて凄く<b><span style="color: blue;">細かい単位で柔軟にスケールアウト</span></b>して行ってくれます。<br />
<br />
この細かい単位でスケールアウトという性質が最も効果を発揮するのは、やはりWebだと思います。<br />
<br />
Webというのは人気が無い時はアクセスゼロなのに、どこかで祭りが発生すると一気に数百万ヒットにまで到達することがあるくらいアクセス数が劇的に増減します。<br />
<br />
<br />
<ul>
<li>Lambda はアクセス数の増減に最強である。</li>
</ul>
<br />
<br />
これが最大の長所だと思います。<br />
<br />
と言うわけで、HTTPリクエストのトリガーを司る機能「ApiGateway」を見ていきましょう。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-mEwDToHx6T0/Wz7uW4oZzYI/AAAAAAAADK0/s_5CglvNJFk2JtDJgy8fsrIJrN-RW226QCLcBGAs/s1600/WS000018.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="70" data-original-width="621" src="https://2.bp.blogspot.com/-mEwDToHx6T0/Wz7uW4oZzYI/AAAAAAAADK0/s_5CglvNJFk2JtDJgy8fsrIJrN-RW226QCLcBGAs/s1600/WS000018.JPG" /></a></div>
<br />
<br />
<h2>
Amazon API Gateway概要</h2>
Amazon API Gateway は、正確にはLambdaの一部ではなく、Lambdaと連結するAWSの別サービスです。<br />
<br />
<a href="https://aws.amazon.com/jp/api-gateway/" target="_blank">公式サイト</a>では以下のように宣伝されています。<br />
<br />
<br />
<ul>
<li>どのようなスケールであっても、簡単に API の作成、配布、保守、監視、保護が行えます。</li>
<li>バックエンドからのデータ、ビジネスロジック、機能にアクセスする、アプリケーションの玄関として振る舞う API を作成できます。</li>
<li>最大数十万個の同時 API 呼び出しの受け入れと処理に伴うすべてのタスクを取り扱います。</li>
</ul>
<br />
<br />
が、この表現はどうにも分かり辛いです。AWSのサイトって何かピンと来ない言い回しをされていることが多いんですよね。<br />
<br />
<br />
早い話、私はこの機能は<b><span style="color: blue;">「WebAPIのURLを疎結合に管理するサービス」</span></b>だと理解しています。<br />
<br />
例えばですね、WebAPIとして「https://www.genesis.com/user/get」というURLがあったとしますよね。<br />
<br />
これ、最近はもうデファクトスタンダードになっているRails系規約で考えますと、このURLに相当する処理は「userクラスのgetメソッド」なんですよ。<br />
<br />
<br />
<ul>
<li><b>クラス名+メソッド名 = URL</b></li>
</ul>
<br />
<br />
これが<b><span style="color: blue;">命名規約</span></b>なんです。<br />
<br />
でも悪い言い方をすれば、<b><span style="color: red;">「クラス名・メソッド名とURLが密結合になっている」</span></b>とも言えます。<br />
<br />
内部の実装として都合の良い命名と、人様に向けて公開するURLのネーミングが同じとは限りません。<br />
<br />
<br />
<ul>
<li>本番系はこのURL</li>
<li>テスト系はこっちのURL</li>
</ul>
<br />
<br />
とか、<br />
<br />
<ul>
<li>URLの変更に伴ってクラス名を変えなきゃいけなくなっちゃった。⇒大規模リファクタリング</li>
</ul>
<br />
みたいな要件、状況はあり得ますからね。<br />
まあ、規約に頼らず手動でURLとクラスの紐づけを行うという手もありますが、それはそれでデザインパターンとして汚い。<br />
<br />
だ・か・ら、<br />
<br />
<br />
<ul>
<li>実装チームは実装チームで、Lambdaの中で都合の良いように作ってください。</li>
<li>公開するURLは別途、Amazon API Gatewayで設定します。</li>
</ul>
<br />
<br />
ということが可能な<b><span style="color: blue;">疎結合アーキテクト</span></b>を実現する。<br />
<br />
そこにAmazon API Gatewayの美しさがあると私は感じています。<br />
<br />
まあ、APIの規模が小さい場合は「実装名=URL」で十分なので疎結合性の利点を感じられないのですが、いずれにせよ<span style="color: red;">API Gatewayを使わなければWebからLambdaを呼べない</span>のだから、覚えるしかありません。<br />
<br />
<br />
<h2>
Lambda で API Gateway の設定</h2>
<div>
では、Lamda と API Gateway を繋げる設定をしていきましょう。</div>
<div>
<br /></div>
<h3>
トリガー追加</h3>
<div>
まず、Lambdaのコンソール画面からトリガーで API Gateway を追加します。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-em7u_A2JwOs/Wz70mXRJV1I/AAAAAAAADLM/BJPc63GC4_MJXbg5f5cEjdrfcRkjMVJoQCLcBGAs/s1600/WS000019.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="790" data-original-width="1600" height="314" src="https://1.bp.blogspot.com/-em7u_A2JwOs/Wz70mXRJV1I/AAAAAAAADLM/BJPc63GC4_MJXbg5f5cEjdrfcRkjMVJoQCLcBGAs/s640/WS000019.JPG" width="640" /></a></div>
<div>
<br /></div>
<div>
<h3>
トリガー設定</h3>
</div>
<div>
トリガーを追加するとすぐ下に設定項目が出てきます。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-KwEOp4EiYL0/Wz71FjjzpKI/AAAAAAAADLU/zntLP51-wqkvMKfaMMiYcg8FkW5SbIFKgCLcBGAs/s1600/WS000020.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="630" data-original-width="1600" height="250" src="https://3.bp.blogspot.com/-KwEOp4EiYL0/Wz71FjjzpKI/AAAAAAAADLU/zntLP51-wqkvMKfaMMiYcg8FkW5SbIFKgCLcBGAs/s640/WS000020.JPG" width="640" /></a></div>
<div>
<br /></div>
<div>
それぞれの意味はこちら。</div>
<div>
<br /></div>
<div>
<ul>
<li>API 名:API を一意にする為の名前。URLに含まれる。今回は「ApiGatewayTest」</li>
<li>デプロイされるステージ:APIを展開するステージ。URLに含まれる。今回は「prod」</li>
<li>セキュリティ:必要に応じて権限を付与。今回は全開放であるオープンで。</li>
</ul>
</div>
<div>
<br /></div>
<div>
これで追加ボタンを押せば完了です。</div>
<div>
<br /></div>
<div>
結果、URLは以下のようになります。</div>
<div>
<br /></div>
<div>
<ul>
<li>https://xxxxx.amazonaws.com/prod/ApiGatewayTest</li>
</ul>
</div>
<div>
<br /></div>
<h3>
ステージ</h3>
<div>
ここで少し分かり辛いのは「ステージ」とは何かということです。</div>
<div>
<br /></div>
<div>
URLにも含まれていますね。</div>
<div>
これはAPIのバージョン管理や、本番系とテスト系の切り分けに使うものです。</div>
<div>
<br /></div>
<div>
例えば、同じAPIでも「本番用」「総合テスト用」「結合テスト用」を分けて実行したい時、ステージの設定を分けることで簡単に制御出来るわけです。</div>
<div>
<br /></div>
<div>
<ul>
<li>prod ← productionの意</li>
<li>staging</li>
<li>test</li>
</ul>
</div>
<div>
<br /></div>
<div>
と設定すれば、</div>
<div>
<br /></div>
<div>
<ul>
<li>https://xxxxx.amazonaws.com/prod/ApiGatewayTest</li>
<li>https://xxxxx.amazonaws.com/staging/ApiGatewayTest</li>
<li>https://xxxxx.amazonaws.com/test/ApiGatewayTest</li>
</ul>
</div>
<div>
<br /></div>
<div>
となる。</div>
<div>
<br /></div>
<div>
分かり易いでしょ?</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<h3>
ステージが不要な場合</h3>
</div>
<div>
「ステージなんていらないから少しでもURLを短くしたい」と、ステージを省略したいというケースもあると思います。</div>
<div>
<br /></div>
<div>
「prod」なんてのは開発者視点のURLであって、一般ユーザから見れば本番以外に無いわけですから。</div>
<div>
出来れば消したい。</div>
<div>
<br /></div>
<div>
しかしながら、これは<b><span style="color: red;">出来ない</span></b>んじゃないかと思います。</div>
<div>
調査しましたが、出来そうな雰囲気が無い。。。</div>
<div>
<br /></div>
<div>
これはステージ名のネーミングセンスで乗り切るしか無いんじゃないかな……。</div>
<div>
<br /></div>
<div>
<div>
<ul>
<li>api</li>
</ul>
</div>
<div>
<br />
と設定すれば、</div>
<div>
<br /></div>
<div>
<ul>
<li>https://xxxxx.amazonaws.com/api/ApiGatewayTest</li>
</ul>
</div>
<div>
<br /></div>
<div>
となるので、一見するとステージ名が露出しているのようには見えないでしょ?<br />
<br />
セコい手ですが。。。</div>
</div>
</div>
<div>
<br /></div>
<div>
<h2>
続く</h2>
</div>
<div>
今回はここまで。</div>
<div>
API Gatewayはバージョン管理とかの機能もあるみたいなので、掘り下げていきたいと思います。</div>
Anonymousnoreply@blogger.com0tag:blogger.com,1999:blog-5306057209591512828.post-56945220072695426302018-06-22T17:12:00.001+09:002018-06-22T17:12:07.046+09:00AWS Lambda で環境変数を使用 暗号化と復号株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。<br />
<br />
最近、AWSをフル活用して社内システムを作ったので、そのノウハウのご紹介を行っています。<br />
<br />
ただいま、Lambdaで関数作りを頑張っています。<br />
<br />
<h2>
環境変数を使用する</h2>
<div>
Lambda には環境変数をセットする項目があります。</div>
<div>
<br /></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-OxI-BvdVs7w/Wyyijh_tdCI/AAAAAAAADHI/AgQnHHeds0cNUfrYg3jVVUB5T9vMsvRrACLcBGAs/s1600/WS000050.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="227" data-original-width="973" height="92" src="https://3.bp.blogspot.com/-OxI-BvdVs7w/Wyyijh_tdCI/AAAAAAAADHI/AgQnHHeds0cNUfrYg3jVVUB5T9vMsvRrACLcBGAs/s400/WS000050.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
環境変数を使用する用途としては、例えばソースにコミットするわけにはいかないパラメータの取り扱いですね。</div>
<div>
<br /></div>
<div>
WebAPIを使用するためのパスワードとかがそれに当たりますが、ソースや設定ファイルにパスワードを書いてコミットしておくとソースをチェックアウトする開発者全員にバレてしまいますから、環境変数にセットしておいておくことでソースには含めないわけです。</div>
<div>
<br /></div>
<div>
他には、私は「実行環境の場所」を判別するのにも便利です。</div>
<div>
<br /></div>
<div>
「ローカルで動作確認する時はこっち」「Lamda上でテストする時はこっち」「本番実行する時はこっち」と今、自分がどのモードで動いているのかを判別する材料として環境変数をセットしておくわけです。</div>
<div>
<br /></div>
<div>
デプロイ時にパラメータを切り替えると切り替え忘れたりしますが、環境変数にセットしておけばそんなことは心配無用ですからね。</div>
<div>
<br /></div>
<div>
その他、ログレベルを動的に変えるとか、使い方は色々。</div>
<div>
<br /></div>
<div>
<b><span style="color: blue;">サーバレスだからこそ、環境変数を便利に使うのがコツ</span></b>と言えると思います。</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<h2>
環境変数をセットして読み取り</h2>
</div>
<div>
では、実際に環境変数をセットしてみましょう。</div>
<div>
セットは簡単。</div>
<div>
<br /></div>
<div>
キーと値をセットして終わり。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-qpzhH7EQDfw/WyyljdQ4JRI/AAAAAAAADHg/iFrpQ0C6s5gKxq_QqjegB9vwcYm3QLoggCLcBGAs/s1600/WS000051.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="279" data-original-width="848" height="131" src="https://2.bp.blogspot.com/-qpzhH7EQDfw/WyyljdQ4JRI/AAAAAAAADHg/iFrpQ0C6s5gKxq_QqjegB9vwcYm3QLoggCLcBGAs/s400/WS000051.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
読み取る時は、その言語標準の方式で読み取ればOKです。</div>
<div>
Pythonだとこうなります。</div>
<br />
<pre class="prettyprint linenums"><code class="language-py">import os
def lambda_handler(event, context):
param = os.getenv("test")
# Tacy
print(param)</code></pre>
<br />
<br />
<div>
簡単ですね。<br />
<br />
<h2>
暗号化</h2>
</div>
<div>
環境変数は暗号化することも出来ます。</div>
<div>
暗号化したパラメータは後で復号することも可能です。</div>
<div>
<br /></div>
<h3>
キーの作成と暗号化</h3>
<div>
まず、IAMのマネージメントコンソールから鍵を作成します。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-BW7wAgvXsDw/WyysXBa31_I/AAAAAAAADH4/rUW-bZRe8-Aqbbt3vkVosMVipwgI2bMvQCLcBGAs/s1600/WS000052.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="603" data-original-width="1111" height="216" src="https://1.bp.blogspot.com/-BW7wAgvXsDw/WyysXBa31_I/AAAAAAAADH4/rUW-bZRe8-Aqbbt3vkVosMVipwgI2bMvQCLcBGAs/s400/WS000052.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
そしてLambdaのコンソールから鍵をセットすると、何やら「暗号化」という項目が出てきましたね。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-f57X-PnH3Dk/Wyys8yQg3cI/AAAAAAAADIA/_UqGRcK81ycPB71mHq-e_xXTS9wGUhRnwCLcBGAs/s1600/WS000053.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="524" data-original-width="1163" height="180" src="https://1.bp.blogspot.com/-f57X-PnH3Dk/Wyys8yQg3cI/AAAAAAAADIA/_UqGRcK81ycPB71mHq-e_xXTS9wGUhRnwCLcBGAs/s400/WS000053.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
暗号化ボタンを押すと、もうどんな値が入っていたかは見えなくなります。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-PkznftoXVUo/WyytN3MoasI/AAAAAAAADII/jzTkrkbx44wxKaKLEzuIvS54OGcWzNxtACLcBGAs/s1600/WS000054.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="519" data-original-width="1093" height="188" src="https://2.bp.blogspot.com/-PkznftoXVUo/WyytN3MoasI/AAAAAAAADII/jzTkrkbx44wxKaKLEzuIvS54OGcWzNxtACLcBGAs/s400/WS000054.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
さて、後はこれをどうやって復号するかですが、実は「暗号」ボタンのすぐ右の「コード」というボタンを押すとすぐにサンプルソースが出てくるんですよ。</div>
<div>
<br /></div>
<h3>
シークレットスニペットの復号</h3>
<pre class="prettyprint linenums"><code class="language-py">import boto3
import os
from base64 import b64decode
ENCRYPTED = os.environ['test']
# Decrypt code should run once and variables stored outside of the function
# handler so that these are decrypted once per container
DECRYPTED = boto3.client('kms').decrypt(CiphertextBlob=b64decode(ENCRYPTED))['Plaintext']
def lambda_handler(event, context):
# TODO handle the event here</code></pre>
<div>
<br /></div>
<div>
親切で助かりますね。</div>
<div>
<br />
では、動作確認してみましょう。</div>
<div>
<br /></div>
<div>
<h3>
動作確認ソース</h3>
</div>
<div>
<pre class="prettyprint linenums"><code class="language-py">import boto3
import os
from base64 import b64decode
def lambda_handler(event, context):
ENCRYPTED = os.environ['test']
# 390c9aa7-75f3-11e8-abe0-656e318945ae
print(ENCRYPTED)
DECRYPTED = boto3.client('kms').decrypt(CiphertextBlob=b64decode(ENCRYPTED))['Plaintext']
# Tacy
print(DECRYPTED.decode())</code></pre>
</div>
<div>
</div>
<div>
<br /></div>
<div>
無事に出力されました。<br />
特に問題は無さそうですね。</div>
<div>
<br /></div>
<div>
<h2>
終わりに</h2>
</div>
<div>
案外簡単でした。<br />
ただ、この環境変数って昔は無かったそうです。<br />
<br />
2016年くらいにリリースされたみたいですね。<br />
<br />
Lambdaはまだまだリアルタイムで進化形のサービスなのかもしれませんね。</div>
Anonymousnoreply@blogger.com0tag:blogger.com,1999:blog-5306057209591512828.post-70127166613822332372018-06-14T12:01:00.002+09:002018-06-14T12:03:28.781+09:00【AWS Lambda】Lambda コスト節約論株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。<br />
<br />
最近、AWSをフル活用して社内システムを作ったので、そのノウハウのご紹介を行っています。<br />
<br />
今回は気になるニュースを見たので雑談です。<br />
<div>
<br /></div>
<h2>
ダイソーで予算超過危機が発生したらしい</h2>
<div>
ダイソーでLambdaを使ったら年間数千万円のコスト超過に陥るピンチになったらしいですね。</div>
<div>
<br /></div>
<div>
<ul>
<li><a href="http://tech.nikkeibp.co.jp/atcl/nxt/column/18/00001/00579/" target="_blank">AWS移行で予算超過のリスク判明、ダイソーの回避策</a></li>
</ul>
<div>
<br /></div>
</div>
<div>
<br /></div>
<div>
原因は Amazon DynamoDB だそうな。</div>
<div>
<br /></div>
<h2>
Lambda と DynamoDB のコスト面での違い</h2>
<div>
記事を読むと、リスクの原因はLambdaとDynamoDBではコスト面の思想が違うことがキモであるようですね。</div>
<div>
<br /></div>
<div>
<h3>
Lambdaは従量課金制</h3>
</div>
<div>
私がLambdaに着目する最大の理由ですが、Lambdaは使った分だけ支払う従量課金制です。</div>
<div>
<br /></div>
<div>
Lambdaではない通常のレンタルサーバの場合、サーバを丸ごと一台を借りて占有してしまうわけですから、使っていてもいなくても占有リソースは一定、従って料金は一定です。</div>
<div>
つまり、<b><span style="color: red;">夜中とか誰も使っていない時間帯でも金はそのまま取られている</span></b>ってことですよ。</div>
<div>
<br /></div>
<div>
想定される処理の最大負荷が8と仮定して、それに備えてサーバには10のリソースを割いているとします。</div>
<div>
すると、サーバリソースは以下のように消費されます。</div>
<div>
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://3.bp.blogspot.com/-GvDB9tbe0LY/WyHHwxkcWyI/AAAAAAAADEk/Ijb2ujXCPUseSXRI3T-4tZEogxD0bA8ggCLcBGAs/s1600/WS000047.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="レンタルサーバの場合のリソース無駄使い" border="0" data-original-height="483" data-original-width="933" height="328" src="https://3.bp.blogspot.com/-GvDB9tbe0LY/WyHHwxkcWyI/AAAAAAAADEk/Ijb2ujXCPUseSXRI3T-4tZEogxD0bA8ggCLcBGAs/s640/WS000047.JPG" title="レンタルサーバの場合のリソース無駄使い" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">レンタルサーバの場合のリソース無駄使い</td></tr>
</tbody></table>
<div>
<br /></div>
<div>
水色の部分が実際に必要なリソース。</div>
<div>
グレーの部分は<span style="color: red;"><b>お金をドブに捨てている</b></span>部分です。</div>
<div>
<br /></div>
<div>
負荷の最大/最小の差が大きいほど、このグレーゾーンは大きくなります。</div>
<div>
<b>「日中しか使わない社内システム」</b>とか<b>「人気ゲームの発売日直後だけ忙しくなる攻略Wiki」</b>とか、かなり勿体ない使い方をしていると思います。</div>
<div>
<br /></div>
<div>
対して、Lambdaの場合はこんな感じ。</div>
<div>
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://3.bp.blogspot.com/-a7dH-VE_qqw/WyHJF1JPo2I/AAAAAAAADEw/cWcYrSyayUItNtofiMBuexscAmaxRENHgCLcBGAs/s1600/WS000048.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="485" data-original-width="935" height="331" src="https://3.bp.blogspot.com/-a7dH-VE_qqw/WyHJF1JPo2I/AAAAAAAADEw/cWcYrSyayUItNtofiMBuexscAmaxRENHgCLcBGAs/s640/WS000048.JPG" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Lambdaの場合は無駄遣いが殆ど無い</td></tr>
</tbody></table>
<div>
<br /></div>
<div>
グレーゾーンが殆どありません。</div>
<div>
<br /></div>
<div>
全く無いとは言いませんが、かなり細かい粒度で節約してくれるわけです。</div>
<div>
素晴らしい。</div>
<div>
<br /></div>
<div>
<h3>
DynamoDBは性能ベース</h3>
</div>
<div>
DynamoDBは「プロビジョニングベース」と言いまして、プロビジョニングとは何なのかはさておき、話の趣旨としては要するにこういうことです。</div>
<div>
<br /></div>
<div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td><a href="https://3.bp.blogspot.com/-GvDB9tbe0LY/WyHHwxkcWyI/AAAAAAAADEk/Ijb2ujXCPUseSXRI3T-4tZEogxD0bA8ggCLcBGAs/s1600/WS000047.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="レンタルサーバの場合のリソース無駄使い" border="0" data-original-height="483" data-original-width="933" height="328" src="https://3.bp.blogspot.com/-GvDB9tbe0LY/WyHHwxkcWyI/AAAAAAAADEk/Ijb2ujXCPUseSXRI3T-4tZEogxD0bA8ggCLcBGAs/s640/WS000047.JPG" title="レンタルサーバの場合のリソース無駄使い" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="font-size: 12.8px;">DynamoDBの場合のリソース無駄使い</td></tr>
</tbody></table>
</div>
<div>
<b>DynamoDBは従量課金制ではない。</b></div>
<div>
<br /></div>
<div>
つまり、</div>
<div>
<br /></div>
<div>
<ul>
<li><b><span style="color: red;">APサーバであるLambdaは従量課金制かもしれないが、DBサーバであるDynamoDBは従量課金制ではない。</span></b></li>
<li><b><span style="color: red;">ダイソーのレジは「忙しい時間帯」と「暇な時間帯」があって、DynamoDBは暇な時間帯でも忙しい時間帯と同じ料金を取られる。</span></b></li>
<li><b><span style="color: red;">だから</span></b><b><span style="color: red;">DynamoDBがコスト超過に陥る。</span></b></li>
</ul>
</div>
<div>
<br /></div>
<div>
なんてこった。</div>
<div>
<br /></div>
<div>
<h2>
どうすれば良いのか?</h2>
</div>
<h3>
ダイソーの場合</h3>
<div>
<b><span style="color: blue;">クラウドの面白い所であるが欠点でもある</span></b>という所だと思いますが、クラウド環境ってこういう<b>従来方式であれば考えなくて良い制約</b>ってものがあるんですよ。</div>
<div>
<br /></div>
<div>
それを克服出来るかどうかがエンジニアの腕の見せ所。</div>
<div>
<br /></div>
<div>
記事を見ると、ダイソーの場合は<b><span style="color: blue;">Lambdaを遅延させることでDynamoDBの最大負荷を下げて解決した</span></b>ようです。</div>
<div>
<br /></div>
<div>
リアルタイム性が必要無いのであれば、そのようなキュー方式を採用するのも一つのアイデアですね。</div>
<div>
<br /></div>
<div>
勉強になります。</div>
<div>
<br /></div>
<div>
<h3>
S3を使ってはどうか?</h3>
</div>
<div>
ダイソーのキュー方式作戦は一つの正解だったと思いますが、要点はこういうことですよね。</div>
<div>
<br /></div>
<div>
<ul>
<li><b><span style="color: blue;">出来る限りDynamoDBの負荷を下げなければならない。</span></b></li>
</ul>
</div>
<div>
<br /></div>
<div>
核心部分としては、<b><span style="color: blue;">DBサーバの負荷を下げる為のプログラムチューニング</span></b>なわけですよ。</div>
<div>
<br /></div>
<div>
この記事を見た時は、私は直観で<b>「DBを節約したいなら、ファイルでやればどうか?」</b>と思いましたね。</div>
<div>
<br /></div>
<div>
昔、クラウドではないオンプレミス環境のシステムを作った頃の経験なんですけど、私は<b>大量データ収集配布処理</b>を作ったことがあるんですよ。</div>
<div>
あの時は「DBで持つ情報」と「ファイルで持つ情報」を分類して管理していました。</div>
<div>
<br /></div>
<div>
<ul>
<li><b><span style="font-size: x-large;">データはDBではなくファイルで持つ。</span></b></li>
</ul>
</div>
<div>
<br /></div>
<div>
この作戦です。</div>
<div>
<br /></div>
<div>
<b>ファイルサーバに相当するAmazon S3は従量課金制だから、DynamoDBみたいボトルネックにはなりません。</b></div>
<div>
<br /></div>
<h3>
ファイルで持つ情報</h3>
<div>
ファイルで情報を持つ大前提は「ファイルパスが一意キーである」ことです。</div>
<div>
<br /></div>
<div>
DBの用語で表現をするならば、<b><span style="color: blue;">主キー検索だけでしかアクセスしない情報はファイルで持てば良い</span></b>のです。</div>
<div>
<br /></div>
<div>
<h3>
DBで持つ情報</h3>
</div>
<div>
DBで持つ必要のある情報は、SQLですね。</div>
<div>
「検索フォームから条件を入れて検索したい」とか「group by したい」みたいなSQLの機能があってこそ実現可能な要件のあるデータはDBで持つしかありません。<br />
<br />
まあDynamoDBはNoSQLなのでちょっと違いますが、いずれにせよDynamoDBの中になければ使えない機能が必要なのであれば、DynamoDBに持つしかないです。<br />
<br />
ダイソーはきっとこっちだったのでしょうね。</div>
<div>
<br /></div>
<div>
<h3>
冗長に持つ</h3>
</div>
<div>
これは褒められた手段ではありませんが、状況によっては「殆ど主キー検索で使用するデータだけど、ちょっとだけgroup by したい時もある」みたいなケースもあります。</div>
<div>
<br /></div>
<div>
そういう時は、もう腹をくくって同じデータをファイルとDBの二重で持つのも一つの判断です。</div>
<div>
データの不整合の余地を残すという弱点が生まれてしまいますが、チューニングには何かを犠牲にするという判断が必要になる時もあります。</div>
<div>
<br /></div>
<div>
<h2>
ディスク使用量は問題ではない</h2>
</div>
<div>
私の経験則を一つ。</div>
<div>
負荷という面において<b><span style="color: blue;">「ディスク使用量」というのは問題にはならん</span></b>ですよ。</div>
<div>
<br /></div>
<div>
あくまで一般論ですが、システムにおいて「ディスクスペース」ってのは安くて余裕があるものなのです。</div>
<div>
だから<b>ディスクスペースを無駄遣いする代わりに別の部分を高速化する</b>という手法は常套手段としてよく使います。</div>
<div>
<br /></div>
<div>
Amazonの場合もそうで、ファイルスペースであるS3に巨大データが居座っていることは問題にならんです。</div>
<div>
<br /></div>
<div>
<ul>
<li>0.023USD/GB</li>
</ul>
</div>
<div>
<br /></div>
<div>
<b><span style="color: blue;">1TB使って月23ドル</span></b>。</div>
<div>
プロジェクト全体の予算から考えればゴミみたいなものでしょう?</div>
<div>
低アクセス領域におけばもっと安い。</div>
<div>
<br /></div>
<div>
チューニングにおいては「どこがクリティカルなのか?」ということを分かっていなければなりません。</div>
<div>
<br /></div>
<div>
注意点ですが、<b><span style="color: red;">ネットワーク転送量は別の話</span></b>です。</div>
<div>
<br /></div>
<div>
大量データをS3に置いておくだけなら易いですが、それを無数のユーザにダウンロードさせるようなことをすると、ネットワーク料金がかさんで破産します。</div>
<div>
だからダウンロード用データはAmazonではなく別の定額制の場所に置くとか、CDN(コンテンツデリバリネットワーク)を使うとかいった工夫が必要になります。</div>
<div>
<br /></div>
<div>
まあ、そこまで話が伸びるとキリが無いのでここで終わり。</div>
<div>
<br /></div>
<h2>
まとめ</h2>
<div>
ここまで書いて思うこととしては、</div>
<div>
<br /></div>
<div>
<ul>
<li>クラウドはロジック効率がコストに跳ね返ってくる。</li>
</ul>
</div>
<div>
<br /></div>
<div>
ということですね。</div>
<div>
<br /></div>
<div>
丸ごとドーンとサーバを貰っちゃってるオンプレミスとは条件が違いますから、処理効率を考案するアーキテクトの力量が非常に重要です。</div>
<div>
<br /></div>
<div>
ありとあらゆる創意工夫を総動員して総合的に効率的なシステムを構築しなければなりません。</div>
<div>
<br /></div>
<div>
となると、「実装が出来るだけ」みたいなドカタが背負えるようなものでは到底なくて、実装・DB・ネットワーク・AWS特性など色々な側面を平行して考慮出来る<b><span style="color: blue;">フルスタックエンジニア</span></b>が求められてくるという……。</div>
<div>
<br /></div>
<div>
全く、IT業界は楽じゃないですね。</div>
Anonymousnoreply@blogger.com0tag:blogger.com,1999:blog-5306057209591512828.post-85307631717848565712018-06-01T13:59:00.001+09:002018-06-01T13:59:20.611+09:00【AWS Lambda】関数作成4株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。<br />
<br />
最近、AWSをフル活用して社内システムを作ったので、そのノウハウのご紹介を行っています。<br />
<br />
現在はAWS Lambdaの使い方を紹介中です。<br />
<br />
<a href="https://genesis-tdsg.blogspot.com/2018/05/aws-lambda_24.html" target="_blank">前回</a>からまだまだ続いてLambda関数のコンソール画面を調査中です。<br />
<br />
<h2>
ネットワーク</h2>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-Ut-E0PjMesM/WxDKdQRZ5jI/AAAAAAAADBY/2CTy5LuqvrIAZ8FTOzrJ9HdjeSrcBcWOQCLcBGAs/s1600/WS000031.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="285" data-original-width="759" height="150" src="https://1.bp.blogspot.com/-Ut-E0PjMesM/WxDKdQRZ5jI/AAAAAAAADBY/2CTy5LuqvrIAZ8FTOzrJ9HdjeSrcBcWOQCLcBGAs/s400/WS000031.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
ネットワークは、関数が置かれるネットワークの場所を指定する項目で、VPCを選択することが出来ます。</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<b>「VPCって何だ?」</b>というところが問題ですね。</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
VPCは「Virtual Private Cloud」の略称です。<b><span style="color: red;">プライベートクラウド</span></b>です。</div>
<div>
<br /></div>
<div>
要するに、普通にAWSを使っている時、それは<b><span style="color: blue;">パブリッククラウド</span></b>なのですよ。</div>
<div>
インターネット上に存在しているAWSには世界中のどこからでも自由にアクセスして処理することが出来ます。</div>
<div>
<br /></div>
<div>
プライベートクラウドは、例えば「自社の中からしか接続できない」みたいに特定の場所からしかアクセスしか出来ないようにすることで、自分達専用のクラウド空間を実現するということです。</div>
<div>
<br /></div>
<div>
あくまでも仮想的にプライベート化するだけで、物理的には同じサーバに載っていますのでご注意を。</div>
<div>
<br /></div>
<div>
このVPCの設定は、どのネットワーク上に置くのか、ということを選択する項目です。</div>
<div>
「非VPC」は普通のインターネットからアクセス可能という意味です。</div>
<div>
<br /></div>
<h2>
デバッグとエラー処理</h2>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-TCepmfglrXE/WxDMICRcpvI/AAAAAAAADBo/MaM8BXfabcsG0HVwieuZ78bH4q_g3tTQwCLcBGAs/s1600/WS000032.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="282" data-original-width="751" height="150" src="https://3.bp.blogspot.com/-TCepmfglrXE/WxDMICRcpvI/AAAAAAAADBo/MaM8BXfabcsG0HVwieuZ78bH4q_g3tTQwCLcBGAs/s400/WS000032.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
デバッグとエラー処理は、Lamdaがコケた時の通知です。</div>
<div>
以下の二つを選択可能です。</div>
<div>
<br /></div>
<div>
<ul>
<li>SNS:Amazon Simple Notification Service</li>
<li>SQL:Amazon Simple Queue Service</li>
</ul>
</div>
<div>
<br /></div>
<div>
<span style="color: red;"><b>SNSはFaceBookとかそういうのではないのでお間違え無く。</b></span></div>
<div>
<br /></div>
<div>
Lamdaはコケると再実行されるようですが、リトライが一定回数を超えた場合、上記のどちらかのサービスにメッセージを送ります。</div>
<div>
これで保守担当に連絡が行って、障害を検知できるという機能ですね。</div>
<div>
<br /></div>
<div>
アクティブトレースとは、「AWS X-Ray」というサービスを活用してより詳細なログを追いかける機能の模様です。 </div>
<div>
<br /></div>
<div>
<h2>
同時実行数</h2>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-uWZhgN1zorY/WxDP4oofRhI/AAAAAAAADB0/-K_i3ehhfAMyySTU0PZrw1BCECoUzClegCLcBGAs/s1600/WS000033.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="234" data-original-width="755" height="123" src="https://2.bp.blogspot.com/-uWZhgN1zorY/WxDP4oofRhI/AAAAAAAADB0/-K_i3ehhfAMyySTU0PZrw1BCECoUzClegCLcBGAs/s400/WS000033.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
これは少し驚きでした。</div>
<div>
AWS Lambdaは際限なくスケールアウトしていくものと思っていましたが、実際には同実行数1000という上限が設けられているそうです。</div>
<div>
<br /></div>
<div>
「予約されていないアカウントの同時実行の使用」と「同時実行の予約」という言葉がありますが、これはこういうことです。</div>
<div>
<br /></div>
<div>
まず、対象リージョンの対象アカウント毎に同時実行数は「1000」という閾値があり、Lambda関数を100コ作っても200コ作ってもこの同時実行数を消費して処理します。</div>
<div>
<br /></div>
<div>
何も設定しなければ<b><span style="color: blue;">1000ある椅子を早い者勝ち</span></b>で取っていくわけですが、関数に依っては「大事だから確実に実行したい処理」とか「激増する可能性があるから限度を設けて締めておきたい」とかいう需要もあるかもしれません。</div>
<div>
<br /></div>
<div>
そのな時は、同時実行の値を100とか入れておきます。</div>
<div>
<br /></div>
<div>
すると、その処理の為に椅子が100コ確保されて、その処理はその100の中だけで行います。</div>
<div>
他の処理は残り900を共有して行う。</div>
<div>
<br /></div>
<div>
こういう処理です。</div>
<div>
<br /></div>
<div>
よほどの大量アクセスが見込まれない限りはフリーで良いと思いますが、特別な事情がある時は使うことになりそうです。</div>
<div>
<br /></div>
<div>
<h2>
監査とコンプライアンス</h2>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-OfCpF8K2NyE/WxDR3sdnbpI/AAAAAAAADCA/GmHfi3BDD1w59a0vR8dMTVFBJ9pl26uxACLcBGAs/s1600/WS000034.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="233" data-original-width="757" height="122" src="https://3.bp.blogspot.com/-OfCpF8K2NyE/WxDR3sdnbpI/AAAAAAAADCA/GmHfi3BDD1w59a0vR8dMTVFBJ9pl26uxACLcBGAs/s400/WS000034.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
単なる注意書き。</div>
<div>
Lambdaでは、監査やコンプライアンスの為に、その関数に対していつ誰が何をしたという証跡を「CloudTrail」という所に保存しているようです。</div>
<div>
<br /></div>
<div>
これにより「誰か知らんうちに何か変なことしやがった!!」って時に犯人を特定できるわけです。</div>
<div>
<br /></div>
<div>
<h2>
終わり</h2>
</div>
<div>
これでザッと一通り目を通せました。</div>
<div>
<br /></div>
<div>
色々ありましたが、一つ一つはそんなに難しいわけでもなく、使いやすい良いサービスだと思います。</div>
<div>
<br /></div>
<div>
引き続き関数作りを進めていきます。</div>
Anonymousnoreply@blogger.com0tag:blogger.com,1999:blog-5306057209591512828.post-37633453444140601062018-05-24T12:01:00.003+09:002018-05-24T12:01:51.645+09:00【AWS Lambda】関数作成3株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。<br />
<br />
最近、AWSをフル活用して社内システムを作ったので、そのノウハウのご紹介を行っています。<br />
<br />
現在はAWS Lambdaの使い方を紹介中です。<br />
<br />
<a href="https://genesis-tdsg.blogspot.jp/2018/05/aws-lambda_18.html" target="_blank">前回</a>からまだまだ続いてLambda関数のコンソール画面を調査中です。<br />
<br />
<h2>
関数コード</h2>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-5FquY89y2jU/WwYiKYxu9NI/AAAAAAAAC-g/ntb0H5GYvK0NU-lWu9AYjsLbBo0bjsEhQCLcBGAs/s1600/WS000025.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="862" data-original-width="1375" height="250" src="https://4.bp.blogspot.com/-5FquY89y2jU/WwYiKYxu9NI/AAAAAAAAC-g/ntb0H5GYvK0NU-lWu9AYjsLbBo0bjsEhQCLcBGAs/s400/WS000025.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
関数コードは、Lamda関数を実行した時に叩くロジックの管理です。</div>
<div>
<br /></div>
<div>
リッチエディター形式になっていますが、<b><span style="color: red;">こんな所で実装する人いるのかしら?</span></b></div>
<div>
普通はローカルで開発してアップロードでしょ。。。</div>
<div>
<br /></div>
<div>
基本は手元で開発したソースをzipファイル等の形式に圧縮してアップロードすることで展開することになります。</div>
<div>
アップロードはコツがいるみたいなので、後日検証。</div>
<div>
<br /></div>
<div>
「ハンドラ」という項目がありますが、これは「実行した時に最初にどのメソッドを叩くの?」ということを設定する所です。</div>
<div>
これについても後日検証。</div>
<div>
<br /></div>
<div>
<h2>
環境変数</h2>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-GGyjpyHTkX4/WwYkaORaAjI/AAAAAAAAC-s/tpe1nhu4scoU4h44xXrWY0mbSEnJWSVfgCLcBGAs/s1600/WS000027.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="448" data-original-width="977" height="182" src="https://1.bp.blogspot.com/-GGyjpyHTkX4/WwYkaORaAjI/AAAAAAAAC-s/tpe1nhu4scoU4h44xXrWY0mbSEnJWSVfgCLcBGAs/s400/WS000027.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
環境変数は、その名の通り環境変数。</div>
<div>
実行環境に応じてパラメータを変えたい時に使用すると便利なものです。</div>
<div>
<br /></div>
<div>
代表的なものとして、<b><span style="color: red;">秘密情報</span></b>でしょうか。</div>
<div>
<br /></div>
<div>
例えば<b><span style="color: red;">「本番環境用のDB接続用パスワード」をGitHubにブチ混んでいてはマズい</span></b>わけですよ。</div>
<div>
<br /></div>
<div>
そういう時はパスワードは環境変数から取得することで、ローカルではローカルの設定でDB接続し、本番では本番環境変数でDB接続出来ます。</div>
<div>
コミットファイル中にはパスワードが存在しないので安心ということです。</div>
<div>
<br /></div>
<div>
項目「暗号化の設定」は、それを更に推し進めたもののようです。</div>
<div>
<br /></div>
<div>
<b><span style="color: red;">「Lambdaの画面開いたらパスワード丸見えなんだけど?」</span></b>というのを避けるため、<b><span style="color: blue;">Lambdaコンソールから見える文字列も暗号化しておいてくれる</span></b>という物です。</div>
<div>
<br /></div>
<div>
そしてソース中で復元する時は、ちゃんと元の文字列になっています。</div>
<div>
<br /></div>
<div>
当然ですが、パスワードをログ出力していたらブチ怖しなのでご注意を。</div>
<div>
<br /></div>
<div>
<span style="background-color: #fafafa; color: #16191f; font-family: "amazon ember" , "helvetica neue" , "roboto" , "arial" , sans-serif; font-size: 18px; font-weight: 700;">タグ</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-7SQMfnazhME/WwYmGnPGe0I/AAAAAAAAC_E/aqL4E9M4K0ENLusNJeh_pHpGytv2hN4zACLcBGAs/s1600/WS000028.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="189" data-original-width="971" height="77" src="https://2.bp.blogspot.com/-7SQMfnazhME/WwYmGnPGe0I/AAAAAAAAC_E/aqL4E9M4K0ENLusNJeh_pHpGytv2hN4zACLcBGAs/s400/WS000028.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
タグは、Lambda関数の目印です。</div>
<div>
「メールのフォルダ分け」と似たようなもので、Lambda関数が増えてくると探すのが大変になるから、タグをつけて整理出来るようにしておくというものです。</div>
<div>
<br /></div>
<div>
<span style="color: #16191f; font-family: "amazon ember" , "helvetica neue" , "roboto" , "arial" , sans-serif;"><span style="background-color: #fafafa; font-size: 18px;"><b>実行ロール</b></span></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-1WPDG5Mx-44/WwYm4xq8ChI/AAAAAAAAC_Y/e6eiVUezc08trukkMRGDSEZe1NShfKx2wCLcBGAs/s1600/WS000029.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="393" data-original-width="485" height="259" src="https://1.bp.blogspot.com/-1WPDG5Mx-44/WwYm4xq8ChI/AAAAAAAAC_Y/e6eiVUezc08trukkMRGDSEZe1NShfKx2wCLcBGAs/s320/WS000029.JPG" width="320" /></a></div>
<div>
<span style="color: #16191f; font-family: "amazon ember" , "helvetica neue" , "roboto" , "arial" , sans-serif;"><span style="background-color: #fafafa; font-size: 18px;"><b><br />
</b></span></span></div>
<div>
<div>
ロールとは権限を管理する機能です。</div>
<div>
<br /></div>
<div>
つまり<b>「この関数はS3にアクセスして良い」</b>というような実行権限を付与するための項目です。</div>
<div>
正しく設定しなければもちろん動きません。</div>
<div>
<br /></div>
</div>
<div>
関数が増えてくると、こういう所もキチンと整備し、必要最小限の権限のみを付与することで、システムの保守性が上がるわけです。</div>
<div>
<br /></div>
<div>
<b style="color: #16191f; font-family: "Amazon Ember", "Helvetica Neue", Roboto, Arial, sans-serif; font-size: 18px;">基本設定</b></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-LhCdqhLG7zQ/WwYnehOlkVI/AAAAAAAAC_k/qg-LxAbgZxgpBYIUJL-GUZf8t6f--9voACLcBGAs/s1600/WS000030.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="394" data-original-width="485" height="259" src="https://3.bp.blogspot.com/-LhCdqhLG7zQ/WwYnehOlkVI/AAAAAAAAC_k/qg-LxAbgZxgpBYIUJL-GUZf8t6f--9voACLcBGAs/s320/WS000030.JPG" width="320" /></a></div>
<div>
<br /></div>
<div>
「基本設定」は寄せ集め項目なので、適当なネーミングにしたのでしょうね。。。</div>
<div>
<br /></div>
<h4>
説明</h4>
<div>
関数についてコメントを書いておくもの。</div>
<div>
<br /></div>
<h4>
メモリ</h4>
<div>
<b><span style="color: blue;">重要項目。</span></b></div>
<div>
<br /></div>
<div>
Lambdaではメモリを関数に任意でセットします。</div>
<div>
ここで設定している<b><span style="color: red;">メモリを2倍にしたら、コストも2倍</span></b>というシビアな項目です。</div>
<div>
<br /></div>
<div>
従って、<b><span style="color: blue;">Lambda関数はメモリ節約こそが大正義</span></b>ということを意味します。</div>
<div>
<br /></div>
<div>
最近はサーバの性能が上がってメモリも十分に搭載されており、メモリの使用量なんか全く気にしなくてOKという開発が増えてきました。</div>
<div>
しかしLambdaでそれは通用しません。</div>
<div>
<br /></div>
<div>
コスト削減のため、<b><span style="color: blue;">「メモリ節約」「処理速度向上」は極限まで追求しなければならない</span></b>のです。</div>
<div>
<br /></div>
<div>
最小は128MB、最大は3GB。</div>
<div>
<br /></div>
<div>
<h4>
タイムアウト</h4>
</div>
<div>
関数が開始から終了までに許容する時間です。</div>
<div>
現状だと5分が上限です。</div>
<div>
<br /></div>
<div>
Lambdaは小さい処理を大量実行するモデルなので、<b><span style="color: red;">一回の実行に何時間もかかるようなバッチは思想と合っていない</span></b>ので使用できません。</div>
<div>
<br /></div>
<div>
そういう時はLambdaを使わないという選択肢もありますが、私はデータの範囲を分けて関数を複数起動するなど、あくまで<b><span style="color: blue;">小さなバッチの集積体</span></b>という思想に従った方が保守性の高いシステムになると思います。</div>
<div>
<br /></div>
<div>
なお、この画面で設定する値の値は5分ですが、ここで設定する値はLambdaのタイムアウト時間で、HTTPリクエストに対応するAPI Gatewayトリガーの最大時間は90秒だったりします。</div>
<div>
<br /></div>
<div>
なので、</div>
<div>
<br /></div>
<div>
<span style="color: red;"><b>「あれ??? タイムアウト時間を5分に設定しているのに、90秒でエラーになっちまうぞ!?」</b></span></div>
<div>
<br /></div>
<div>
ということが起きるんですよ。</div>
<div>
<br /></div>
<div>
これは罠です。</div>
<div>
<br /></div>
<div>
<h2>
続く</h2>
</div>
<div>
関数のパラメータ解説はもう少し続きます。</div>
Anonymousnoreply@blogger.com0tag:blogger.com,1999:blog-5306057209591512828.post-75925063625144348572018-05-18T10:48:00.002+09:002018-05-18T10:48:38.287+09:00【AWS Lambda】関数作成2株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。<br />
<br />
最近、AWSをフル活用して社内システムを作ったので、そのノウハウのご紹介を行っています。<br />
<br />
現在はAWS Lambdaの使い方を紹介中です。<br />
<br />
<h2>
コンソール画面</h2>
<a href="https://genesis-tdsg.blogspot.jp/2018/05/aws-lambda.html" target="_blank">前回</a>からの続きでコンソール画面を見ていきたいと思います。<br />
<br />
画面の上の方から行きます。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-yCnxwuSXFNE/Wv4iT5NKldI/AAAAAAAAC8k/-0VifNoaKmgoY_uuWU74PIPHgbhBE4E2gCLcBGAs/s1600/WS000023.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="806" data-original-width="1469" height="218" src="https://2.bp.blogspot.com/-yCnxwuSXFNE/Wv4iT5NKldI/AAAAAAAAC8k/-0VifNoaKmgoY_uuWU74PIPHgbhBE4E2gCLcBGAs/s400/WS000023.JPG" width="400" /></a></div>
<br />
<br />
一番上に「アクション」とかボタンが並んでいますが、この辺りは作った関数をキックしたりする部分です。<br />
これについては後続の記事で書きますので、次に進みます。<br />
<br />
<h3>
デザイナー</h3>
デザイナーは、Lambda関数を頂点に、それ以外のAWSサービスを紐づけるための機能です。<br />
<br />
初期状態では以下二つがぶら下がっています。<br />
<br />
<ul>
<li>Amazon CloudWatch Logs</li>
<li>Amazon DynamoDB</li>
</ul>
<br />
<h4>
<br /></h4>
<h4>
Amazon CloudWatch Logs</h4>
Amazon CloudWatch Logsは、Lambdaのログを出力するサービスです。<br />
<br />
通常のシステムの場合、ログはログファイルに吐き出してローテーションするものですが、Lambdaのようなサーバレスのサービスの場合、無意識に使えるディスクスペースは基本ありません。<br />
なので「ディスクスペースに吐き出す」みたいな簡単な処理に工夫が必要になってきます。<br />
<br />
ディスクスペースの代わりにログを吐き出す先、それがAmazon CloudWatch Logsです。<br />
<br />
イメージとしては、恐らくNoSQL型のDBにログを保存しているのだろうと思います。<br />
そしてCloudWatchの画面でそれを参照する、というカラクリです。<br />
<br />
CloudWatchの画面イメージはこちら。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-4kko6yUznaM/Wv4kow2SMoI/AAAAAAAAC88/gZqx6ppCHPQP5V44ihEJmzMPaP3XJlrhgCLcBGAs/s1600/WS000024.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="806" data-original-width="1469" height="218" src="https://4.bp.blogspot.com/-4kko6yUznaM/Wv4kow2SMoI/AAAAAAAAC88/gZqx6ppCHPQP5V44ihEJmzMPaP3XJlrhgCLcBGAs/s400/WS000024.JPG" width="400" /></a></div>
<br />
CloudWatchにログを出力するための実装方法は後日の記事にします。<br />
<br />
<h3>
Amazon DynamoDB</h3>
Amazon DynamoDBは、アマゾン自慢のNoSQLです。<br />
<br />
<a href="https://genesis-tdsg.blogspot.jp/2018/04/aws-lambdardbms.html" target="_blank">【AWS Lambda】帳票出力API開発 その2~RDBMSを使うな~</a><br />
<br />
で書きましたとおり、Lambdaと通常のRDBMSの組み合わせは基本、無いです。<br />
代わりにNoSQLを使用します。<br />
<br />
Lambda最大の制約はココ、NoSQLを使うしか無いう点でしょう。<br />
<br />
でも性能的には最強なんです。<br />
最近、私はずっと<b>「既存システムをNoSQLに置き換えることは出来ないか?」</b>ということばかり考えています。<br />
<br />
例えば、<b>掲示板</b>とかならイケるんですよ。<br />
<br />
5ちゃんねる(旧2ちゃんねる)という掲示板がありますけど、あれってサーバ側にはテキストファイルが置いてあるだけでDBは使ってませんからね。<br />
<br />
テキスト出力だけでやっている処理はNoSQLに置き換え可能です。<br />
<br />
また、<b>PukiWiki</b>という有名なWikiツールがありますけど、あれもテキスト出力だけで実現しています。<br />
<br />
<b><span style="color: blue;">Lamdaと</span></b><span style="color: blue;"><b>DynamoDB</b></span><b><span style="color: blue;">で実現するNoSQL・サーバレス</span></b><b><span style="color: blue;">型のWiki&掲示板</span></b>というのは負荷の激烈増減というサービスの性質を考えると相性最強のはず。<br />
<br />
何とかして自分で開発出来ないかと考えています。<br />
<br />
<br />
<h3>
トリガー</h3>
さて、最初からぶら下がっている二つは上記のとおりとして、気になるのは左側の「トリガー」です。<br />
<br />
これは<b>「何をキッカケとして、Lambda関数をキックするか?」</b>ということを決定するための機能です。<br />
<br />
例えば、<br />
<br />
<br />
<ul>
<li>API Gateway:HTTPリクエストをトリガーとしてのキック</li>
</ul>
<br />
<br />
などですね。<br />
<br />
以下のラインナップはあります。<br />
<br />
<br />
<ul>
<li>API Gateway</li>
<li>AWS IoT</li>
<li>Alexa Skills Kit</li>
<li>Alexa Smart Home</li>
<li>CloudWatch Events</li>
<li>CloudWatch Logs</li>
<li>CodeCommit</li>
<li>Cognito Sync Trigger</li>
<li>DynamoDB</li>
<li>Kinesis</li>
<li>S3</li>
<li>SNS</li>
</ul>
<br />
<br />
すいません。<br />
私が作ったシステムだと「API Gateway」か検証していなくて他は未検証なのですが、断片的に調査した情報だと以下の機能だと理解しています。<br />
<br />
<h4>
AWS IoT</h4>
AWS IoTというサービスと連動するもの。<br />
例えば「目覚まし時計を叩いたら起動」とか、そういう用途が可能と思われます。<br />
<br />
<h4>
Alexa Skills Kit・Alexa Smart Home</h4>
噂のAI製品「Alexa」と連動するもの。<br />
<br />
例えば「Alexa! 会議室は空いているか!?」とか話しかけると起動し、Lamdaの処理を経由して会議室予約システムとかと照合し、最終的には「C会議室が開いています」みたいな返事をするとか、<br />
そういう用途が可能になると予想。<br />
<br />
<h4>
CloudWatch Events・CloudWatch Logs</h4>
ログ回り。<br />
例えば「ログの中にFATAL」という文字が出現したらキックし、社員に緊急出勤させるような処理のためのもの。<br />
<br />
<h4>
CodeCommit</h4>
AWS CodeCommitというGitHubみたいなサービスがあるそうです。<br />
プッシュ通知とか出せるのでしょう。<br />
<br />
<h4>
Cognito</h4>
Cognitoはシングルサインオンを管轄する機能です。<br />
「ユーザがログインしたら起動」とか出来るものと予想。<br />
<br />
<h4>
DynamoDB</h4>
DynamoDBは上記のとおりのNoSQL。<br />
テーブルの更新を察知することが出来ます。<br />
<br />
RDBMSにも「トリガー」という機能がありますが、あれと似たような機能のようです。<br />
<br />
<h4>
Kinesis</h4>
Amazon Kinesis Data Streamsというストリーミング処理と連携。<br />
<br />
例えば「動画の15分の所でCMを挟む」とかの用途と予想。<br />
<br />
<h4>
S3</h4>
S3はAWSの最初期からある伝統のディスクストレージ。<br />
<br />
「特定フォルダにファイルがアップロードされたらキック」<br />
<br />
<h4>
SNS</h4>
<div>
<span style="color: red;"><b>SNS? FeceBookみたいな? と思ったら違いました</b></span><b style="color: red;">。</b></div>
<div>
<br /></div>
<div>
Amazon Simple Notification Serviceという、プッシュ通知を行ってくれるサービスがあるそうで。</div>
<div>
プッシュ通知の中身をLambdaを使って構築しているのかな?</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
以上のとおり、沢山あります。</div>
<div>
<br /></div>
<div>
これらから分かるとおり、LambdaはAWS製品を使う上での基幹部分に位置する超重要サービスだと言えます。</div>
<div>
<br /></div>
<div>
AWSに関わっていくなら、Lambdaへの理解は必要不可欠と言って良いでしょう。</div>
<div>
<br /></div>
<div>
<br /></div>
<h2>
続く</h2>
<div>
引き続きLambdaの関数設定について調査していきます。</div>
Anonymousnoreply@blogger.com0tag:blogger.com,1999:blog-5306057209591512828.post-69995574513658498042018-05-11T10:30:00.001+09:002018-05-11T10:34:32.615+09:00【AWS Lambda】関数作成1株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。<br />
<br />
最近、AWSをフル活用して社内システムを作ったので、そのノウハウのご紹介を行っています。<br />
<br />
今回はAWS Lambdaで関数を作成するところまで行ってみましょう。<br />
<br />
<h2>
ログイン</h2>
<div>
ログインするためにはもちろんID登録をする必要があり、ID登録だけにも権限とか注意点があるのですが、そこは割愛。</div>
<div>
<br /></div>
<div>
ログインした所からスタートします。</div>
<div>
<br /></div>
<div>
以下が私のLambdaのコンソール画面です。</div>
<div>
<br /></div>
<div>
https://ap-northeast-1.console.aws.amazon.com/lambda/home?region=ap-northeast-1#/functions</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-69EVraOZElo/WvTlY_SEmWI/AAAAAAAAC5c/aLh5fu4NGKE_F8FKx8m3xduSKarb-P3jACLcBGAs/s1600/WS000013.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="782" data-original-width="1442" height="216" src="https://4.bp.blogspot.com/-69EVraOZElo/WvTlY_SEmWI/AAAAAAAAC5c/aLh5fu4NGKE_F8FKx8m3xduSKarb-P3jACLcBGAs/s400/WS000013.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
既に関数を作って稼働させているのでメニューに一つ関数があります。</div>
<div>
<br /></div>
<div>
ブログのストーリー進行の都合上、もう一個関数を作りたいと思います。</div>
<div>
<br /></div>
<h2>
関数作成</h2>
<div>
右上にあるオレンジ色のボタン「関数の作成」をクリックします。</div>
<div>
<br /></div>
<div>
すると以下の画面に遷移します。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-tO5mOW2CNXU/WvTmPbbZg-I/AAAAAAAAC5k/6_0Dg9XCxEoIFA4qnd8H2rzCwBrI5sILwCLcBGAs/s1600/WS000014.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="923" data-original-width="1469" height="250" src="https://4.bp.blogspot.com/-tO5mOW2CNXU/WvTmPbbZg-I/AAAAAAAAC5k/6_0Dg9XCxEoIFA4qnd8H2rzCwBrI5sILwCLcBGAs/s400/WS000014.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
メニューが三つあります。</div>
<div>
<br /></div>
<h3>
一から作成</h3>
<div>
説明文にあるように「Hello World」を出力するという、最小空っぽ構成でスタートするというものです。</div>
<div>
一から全部自分で構築します。</div>
<div>
<br /></div>
<div>
<h3>
設計図</h3>
</div>
<div>
メニューから選択し、最初からある程度構成された状態でスタートするものです。</div>
<div>
<br /></div>
<div>
初心者の自分としては「ゼロから構築するのは難しいし、最初からそこそこ動くなら便利そうだな」と思って私はこれを選択しました。</div>
<div>
<br /></div>
<div>
が、ハッキリ言って<span style="color: red;"><b>動かねえ!!</b></span></div>
<div>
<br /></div>
<div>
これね、確かに最初から多少なりともセットアップされた状態でスタート出来るのですけど、恐らくセキュリティとかの都合だと思うんですけど、とにかく<span style="color: blue;"><b>疎通しない状態からスタートしやがる</b></span>んですよ。<br />
<br />
いや、とりあえず「テスト」とかやれば動くんですけど、「HTTPリクエストの受付」とか肝心なところになると全然ダメ。</div>
<div>
<br /></div>
<div>
初心者の自分には動かない原因なんて分からないですからね。</div>
<div>
結局、一個一個理解してようやく動かすに至りました。</div>
<div>
<br /></div>
<div>
まあ、どんなもんかと思ってとりあえず設計図を選ぶと分かることもありますが、結局は一から作成するのと同じくらい理解に時間を費やす覚悟が必要です。</div>
<div>
<br /></div>
<div>
<h3>
サーバレスアプリケーションのリポジトリ</h3>
</div>
<div>
これは私も未調査ですが、どうやら世界中のエンジニアが「私もAWSの関数を作ってみました。ぜひ使ってください」というのを公開しているようですね。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-M0CZdDeZEqk/WvTpCExRHuI/AAAAAAAAC6A/k1JAVidKzhAEDxTF2uM_l91JXw9E3da0wCLcBGAs/s1600/WS000015.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="291" data-original-width="322" height="289" src="https://1.bp.blogspot.com/-M0CZdDeZEqk/WvTpCExRHuI/AAAAAAAAC6A/k1JAVidKzhAEDxTF2uM_l91JXw9E3da0wCLcBGAs/s320/WS000015.JPG" width="320" /></a></div>
<div>
<br /></div>
<div>
Yuji Nishimura.</div>
<div>
西村 祐司さん? 日本人の方もいらっしゃるようです。</div>
<div>
<br /></div>
<div>
コメントを見る限り「挙動確認の為に試しに公開してみた」という物に見えます。結構フリーに公開出来る環境なようです。</div>
<div>
<br /></div>
<div>
探せば何か面白い関数が眠っているかもしれませんね。</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
さて、今回は「一から作成」で進んでいきたいと思います。</div>
<div>
<br /></div>
<div>
<h2>
ランタイム</h2>
</div>
<div>
関数名は適当に「TacyBlogSample」として、次にランタイム。</div>
<div>
実行言語を選択します。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-BUWlFfK_xGU/WvTrVJ42p5I/AAAAAAAAC6M/89ujzlDjQPQ85QBcAPNRhBWircvTFbm-gCLcBGAs/s1600/WS000016.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="329" data-original-width="851" height="153" src="https://2.bp.blogspot.com/-BUWlFfK_xGU/WvTrVJ42p5I/AAAAAAAAC6M/89ujzlDjQPQ85QBcAPNRhBWircvTFbm-gCLcBGAs/s400/WS000016.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
2018年現在だと以下のラインナップです。</div>
<div>
<br /></div>
<div>
<ul>
<li>C# (.NET Core 1.0)</li>
<li>C# (.NET Core 2.0)</li>
<li>Go 1.x</li>
<li>Java 8</li>
<li>Node.js 4.3</li>
<li>Node.js 6.10</li>
<li>Node.js 8.10</li>
<li>Python 2.7</li>
<li>Python 3.6</li>
</ul>
</div>
<div>
<br /></div>
<div>
え? <b><span style="color: blue;">「PHPとかRubyとか無いんだけど? 俺こんな言語知らないよ?」</span></b>って?</div>
<div>
あなた、<b><span style="color: red;">時代に乗り遅れてます</span></b>よ!!</div>
<div>
<br /></div>
<div>
と言うのも、Lambdaのようなサーバレス環境は言語が固定されており、メニューの中に入っている言語しか使用出来ません。</div>
<div>
<br /></div>
<div>
どの言語をサポートするかはクラウド業者が決めますから、クラウド業者から見て評価の高い言語しか使用出来ないということです。</div>
<div>
<br /></div>
<div>
つまり、AWS様は<b>「PHPとRubyなんでどうてもええわ」</b>と思っているってことなわけですよ。見放されています。</div>
<div>
<br /></div>
<div>
今後クラウドを使っていきたい人はクラウド界で人気のある言語を習得するという<b>スキルセット戦略</b>を持つ必要があります。</div>
<div>
<br /></div>
<div>
私のオススメは断然「Python」です。</div>
<div>
いくつかクラウドサービスを見てみましたが、Pythonは必ず優先的にサポートされています。</div>
<div>
<br /></div>
<div>
皆さんもぜひPythonを習得して下さい。</div>
<div>
<br /></div>
<div>
と言うわけで、とりあえずPython3.6を選択。</div>
<div>
<br /></div>
<div>
<h3>
ロール</h3>
</div>
<div>
ロールというのは、権限設定です。</div>
<div>
<br /></div>
<div>
「この関数はファイルサーバに書き込みが出来る」</div>
<div>
「この関数はログ出力が出来る」</div>
<div>
<br /></div>
<div>
とかそういうのです。</div>
<div>
<br /></div>
<div>
私は一人で小規模なアプリを開発しただけなので余り権限を意識していませんが、複数人で大規模なアプリを開発するとなると、権限を適切に割り振る設計も重要になってくるのでしょう。</div>
<div>
<br /></div>
<div>
余り気にしていないと言っても、</div>
<div>
<br /></div>
<div>
<ul>
<li>「あれ? 動かないぞ?」 ⇒ 権限が無かった。</li>
</ul>
</div>
<div>
<br /></div>
<div>
というのは都度都度発生しますので、重要です。</div>
<div>
<br /></div>
<div>
ともかく、今は適当に新規で作って先に進みます。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-b_y9-ZD_718/WvTw57Gx5rI/AAAAAAAAC60/fgGbBurkVUkoattkyIo7D_WErqENLu_5wCLcBGAs/s1600/WS000017.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="791" data-original-width="1600" height="197" src="https://1.bp.blogspot.com/-b_y9-ZD_718/WvTw57Gx5rI/AAAAAAAAC60/fgGbBurkVUkoattkyIo7D_WErqENLu_5wCLcBGAs/s400/WS000017.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
出来上がりました。</div>
<div>
<br /></div>
<div>
<h2>
続く</h2>
</div>
<div>
今日のところはここまで。</div>
<div>
<br /></div>
<div>
次回から関数コンソールの中身を見ていきましょう。</div>
Anonymousnoreply@blogger.com0tag:blogger.com,1999:blog-5306057209591512828.post-8186849778863679532018-04-20T14:18:00.004+09:002018-04-20T14:19:26.552+09:00【AWS Lambda】課金体系解説【無料枠】株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。<br />
<br />
最近、AWSをフル活用して社内システムを作ったので、そのノウハウのご紹介を行っています。<br />
<br />
今回はAWS Lambdaの料金解説です。<br />
<div>
<br />
<h2>
手始め</h2>
<div>
クラウド環境を使う人が真っ先に気にするのは、やはり<b><span style="color: blue;">料金</span></b>ではないでしょうか?</div>
<div>
<br /></div>
<div>
クラウド環境が活用される理由の第一はやっぱり<span style="color: blue;"><b>コスト</b></span>で、コストパフォーマンス良くランニングしたい人の為のサービスですから。</div>
<div>
<br /></div>
<div>
しかしながら、クラウド環境のコストは千差万別。</div>
<div>
普通のレンタルサーバの場合は月々いくらの定額制が多いですが、クラウド環境は従量課金制であることが多く、<span style="color: blue;"><b>「従量課金ってのは、具体的にどういう計算になるの?」</b></span>という所が非常に難しいです。</div>
<div>
<br /></div>
<div>
特にAWSは数あるクラウド環境の中でも課金体系が複雑な方だと言われており、これはAWSの<span style="color: red;"><b>欠点</b></span>の一つだと言えるでしょう。</div>
<div>
<br /></div>
<div>
ともかく今回はLambda部分の課金についてご説明です。<br />
<br /></div>
<h2>
GB-秒課金</h2>
<div>
こちらがLambdaの料金の公式ページです。</div>
<br />
<ul>
<li><a href="https://aws.amazon.com/jp/lambda/pricing/" target="_blank">https://aws.amazon.com/jp/lambda/pricing/</a></li>
</ul>
<div>
<br /></div>
そこにはこう書かれています。</div>
<div>
<br /></div>
<blockquote class="tr_bq">
Lambda では 1 か月に 1,000,000 件の無料リクエストおよび 400,000 GB-秒のコンピューティング時間が無料利用枠となっています。</blockquote>
<div>
<br /></div>
<div>
<b><span style="color: blue;">400,000 GB-秒のコンピューティング時間って何ぞや???</span></b></div>
<div>
<br /></div>
<div>
普段は余り耳にしない独特の単語が出てきました。</div>
<div>
<br /></div>
<div>
<ul>
<li>GB-秒</li>
<li>コンピューティング時間</li>
</ul>
</div>
<div>
<br /></div>
<div>
これを分かり易い言葉に置き換えると、こういうことなんです。</div>
<div>
<br /></div>
<div>
<ul>
<li>インスタンスのメモリ×実行時間</li>
</ul>
<div>
<br /></div>
</div>
<div>
つまり<b><span style="color: blue;">「AWS内のメモリを累計でどれだけ消費したか?」</span></b>で課金されるという意味になります。</div>
<div>
以下の青色の面積が課金対象です。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-sHojBHYXKE0/WtlsLnVr7kI/AAAAAAAAC2A/i0q7A_2c0g8KLYBCwayixT2H02oSSZFeACLcBGAs/s1600/WS000008.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="434" data-original-width="780" height="222" src="https://3.bp.blogspot.com/-sHojBHYXKE0/WtlsLnVr7kI/AAAAAAAAC2A/i0q7A_2c0g8KLYBCwayixT2H02oSSZFeACLcBGAs/s400/WS000008.JPG" width="400" /></a></div>
<div>
</div>
<br />
<h2>
インスタンスのメモリ</h2>
<div>
「インスタンスのメモリって何のこっちゃ?」という方もいらっしゃるかもしれないので、Lambdaの画面の一部を切り抜いてお見せしましょう。</div>
<div>
<br /></div>
<div>
以下のように、Lambdaコンソールの「基本設定」蘭にメモリを指定する項目があります。これがインスタンスの設定メモリです。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-xSX_hKN1qF8/Wtlt3Q4vAFI/AAAAAAAAC2U/TrMFuuGYcis4X6WBe6W-NLxrR9VfMpi0wCLcBGAs/s1600/WS000010.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="384" data-original-width="812" height="151" src="https://1.bp.blogspot.com/-xSX_hKN1qF8/Wtlt3Q4vAFI/AAAAAAAAC2U/TrMFuuGYcis4X6WBe6W-NLxrR9VfMpi0wCLcBGAs/s320/WS000010.JPG" width="320" /></a></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-q-i6nALC9ps/WtlsjSytURI/AAAAAAAAC2E/vXemDvYGHNcU3HIlvgWZ9r3xneojoHeZQCLcBGAs/s1600/WS000009.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="100" data-original-width="420" height="76" src="https://1.bp.blogspot.com/-q-i6nALC9ps/WtlsjSytURI/AAAAAAAAC2E/vXemDvYGHNcU3HIlvgWZ9r3xneojoHeZQCLcBGAs/s320/WS000009.JPG" width="320" /></a></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div>
一番小さい設定で128MB、一番大きい設定で3008MBになります。</div>
<div>
(何故3008MBなどという中途半端な値なのかは不明)</div>
<div>
<br /></div>
<div>
課金基準は「インスタンスのメモリ×実行時間」なので、この<span style="color: red;"><b>メモリのサイズに正比例して料金が上がっていく</b></span>ことになりますね。</div>
<div>
<br /></div>
<div>
ここでお分かりになると思いますが、Lambdaは<span style="color: blue;"><b>メモリが小さいほど正義</b></span>なインフラという意味になります。</div>
<div>
<br /></div>
<div>
通常のサーバの場合、「メモリが8GBなら8GBをフルに使わないと勿体ない」という発想で、<span style="color: blue;"><b>積んであるメモリをキッチリ使い切ることが芸術</b></span>です。</div>
<div>
<br /></div>
<div>
そこがLambdaは全然違って、メモリの正比例でお金がかかっていきますから、可能か限りメモリを少なく済ませることが財布に直結するという、<b><span style="color: blue;">プログラマーの腕の見せ所</span></b>なインフラなのです。</div>
<div>
<br /></div>
<div>
従って、採用する言語もメモリを余り使わない言語の方が優れているということになり、<span style="color: red;">メモリを大量消費する言語であるJavaはLambdaとの相性が最悪</span>です。</div>
<div>
<br /></div>
<div>
私のエンジニアとしての経歴はJavaを起点にしていますが、来るべきクラウド時代を考えるとJavaのみしか使えないエンジニアは活躍の場所が限られると考えています。</div>
<div>
<br /></div>
<div>
<b>「Javaエンジニアは、主力言語はJavaのままでも良いが、補助としてもう一つ言語を覚えるべき」</b></div>
<div>
<br /></div>
<div>
という私の持論はここに起因しているわけです。</div>
<div>
<br /></div>
<div>
<h2>
インスタンスの実行時間</h2>
</div>
<div>
インスタンスの実行時間はそのまま、処理が開始されてから終了されるまでの時間です。</div>
<div>
<br /></div>
<div>
<ul>
<li>1秒で処理が完了したら、1秒を課金。</li>
<li>3秒で処理が完了したら、3秒を課金。</li>
</ul>
</div>
<div>
<br /></div>
<div>
プログラムの速さが料金に直結してくるという、やはり<b><span style="color: blue;">プログラマーの腕の見せ所</span></b>なインフラなのです。</div>
<div>
<br /></div>
<div>
課金は秒単位で行われます。</div>
<div>
どういう意味かと言いますと、昔は</div>
<div>
<br /></div>
<div>
<ul>
<li>課金は時間課金。</li>
<li>インスタンスを30分使っても課金は1時間。</li>
<li>1秒使っても1時間分の金を払いやがれ!!</li>
</ul>
</div>
<div>
<br /></div>
<div>
という<span style="color: red;"><b>カツアゲ</b></span>みたいな課金体系でしたが、クラウド黎明期はこれでも凄いことだと言われていたそうです。</div>
<div>
今は1秒単位なので、随分効率が良くなりましたね。</div>
<div>
<br /></div>
<div>
しかし、プログラマーとしては結構キツいなぁ。</div>
<div>
<br /></div>
<div>
<span style="color: red;"><b>「この処理、今は3秒かかっているけど、工夫すれば2秒になるんじゃない?」</b></span></div>
<div>
<br /></div>
<div>
とか言われちゃうってことでしょ?</div>
<div>
キッツ~。</div>
<div>
<br /></div>
<div>
あと、当たり前ですが、アクセスが殺到してインスタンスが複数立ち上がったら、その正比例でコンピューティング時間に追加されていきます。</div>
<div>
<br /></div>
<div>
<h2>
無料範囲</h2>
</div>
<div>
こう考えると「400,000 GB-秒のコンピューティング時間が無料利用枠」という意味も分かってきますね。</div>
<div>
<br /></div>
<div>
メモリが128MBの場合、</div>
<div>
<br /></div>
<div>
<ul>
<li>400,000(GB・秒) ÷ 128(MB) = 3,125,000(秒) = 868時間 = 36 日</li>
</ul>
</div>
<div>
<br /></div>
<div>
という計算になりますね。</div>
<div>
だから、立ち上がるインスタンスが1コならずっとタダで使えるってことになります。</div>
<div>
<br /></div>
<div>
しかし、処理の都合でメモリは最低でも1280MBは欲しいとなってくると、この場合だと3.6日ということになります。</div>
<div>
<br /></div>
<div>
短いような気もしますが、ここで忘れてはいけないのは、あくまで「処理時間」ということです。</div>
<div>
アクセスが来ていない時間帯は処理していませんので料金は発生しません。</div>
<div>
Lambdaは、</div>
<div>
<br /></div>
<div>
<ul>
<li>アクセスが来ていない時は寝ている。</li>
<li>アクセスが来たら起きて処理して終わったらまた寝る。</li>
</ul>
</div>
<div>
<br /></div>
<div>
という挙動ですからね。</div>
<div>
<br /></div>
<div>
サービスとしては24時間立ち上がっていても、サーバとして処理している時間が短いシステムであれば、3.6日というのはまあまあの無料枠を貰えていると考えて良いのではないでしょうか?</div>
<div>
<br /></div>
<div>
なかなかお得なインフラです。</div>
<div>
<br /></div>
<div>
<h2>
手始め</h2>
</div>
<div>
引き続きLambdaの連載を継続します。</div>
Anonymousnoreply@blogger.com0tag:blogger.com,1999:blog-5306057209591512828.post-32349756194747621372018-04-11T14:48:00.001+09:002018-04-11T15:02:10.006+09:00【AWS Lambda】帳票出力API開発 その2~RDBMSを使うな~株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。<br />
<br />
最近、AWSをフル活用して社内システムを作ったので、そのノウハウのご紹介を行っています。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-zGtPKZANxGY/Wq8t7uIeWsI/AAAAAAAACqU/-PHZEyYaWWITKg6RoM4o3dGR4Yvu0GogQCPcBGAYYCw/s1600/WS000000.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="794" data-original-width="1406" height="225" src="https://3.bp.blogspot.com/-zGtPKZANxGY/Wq8t7uIeWsI/AAAAAAAACqU/-PHZEyYaWWITKg6RoM4o3dGR4Yvu0GogQCPcBGAYYCw/s400/WS000000.JPG" width="400" /></a></div>
<br />
<a href="https://genesis-tdsg.blogspot.jp/2018/04/aws-lambda.html" target="_blank">前回</a>に引き続き、AWS Lambdaのご紹介です。<br />
<div>
<br /></div>
<div>
<h2>
特徴3:RDBMSを使うな</h2>
<div>
特徴3は重大です。</div>
<div>
<br /></div>
<div>
<ul>
<li><b><span style="color: red;">RDBMSを使ってはならぬ。</span></b></li>
</ul>
</div>
<div>
<br /></div>
<div>
とだけ言うと語弊があるので、ここは詳しく説明していきましょう。</div>
<div>
<br /></div>
<h3>
RDBMSとは</h3>
<div>
RDBMSが何かということは、各自でwikipediaでも見て貰えば十分かと。</div>
<div>
リレーショナルデータベースマネジメントシステム、つまり<b><span style="color: blue;">普通のDB</span></b>です。</div>
<div>
<br /></div>
<div>
<ul>
<li>Oracle</li>
<li>MySQL</li>
<li>PostgreSQL</li>
</ul>
</div>
<div>
<br /></div>
<div>
これを使うな、とは過激な話です。</div>
<div>
<br /></div>
<div>
<b><span style="color: red;">「DBを使えないシステムなんて実質役に立たないだろ!!」</span></b></div>
<div>
<br /></div>
<div>
と思う人も多いはず。</div>
<div>
これには理由があるんです。</div>
<div>
<br /></div>
<div>
それは<span style="color: blue;">「コネクション」</span>です。</div>
<div>
<br /></div>
<h3>
コネクションの概念</h3>
<div>
通常のWebシステムの場合、まずWebシステムのインスタンスが起動し、そこからRDBMSに対してコネクションを張ります。</div>
<div>
<br /></div>
<div>
この時、「SQLを発行する都度、コネクションを張る」という挙動をするシステムは基本無いです。</div>
<div>
(大昔のへっぽこシステムなら分かりませんが)</div>
<div>
<br /></div>
<div>
<ul>
<li>Webシステム起動時に一定数のコネクションを確保し、それを使い回す。</li>
</ul>
</div>
<div>
<br /></div>
<div>
これが基本……と言うか、これ以外選択肢は無いと思います。</div>
<div>
<br /></div>
<div>
コネクションをいくつ取るかはアプリ側に任されていて、RDBMSは<span style="color: red;">上限数までは</span>要求されるだけ張るようになっています。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-CKvjW583tsM/Ws2OqjD1xNI/AAAAAAAACzU/ai7o4F0OMNw7bf6Dxlg3YoMdXboRTvScgCLcBGAs/s1600/WS000001.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="340" data-original-width="877" height="155" src="https://3.bp.blogspot.com/-CKvjW583tsM/Ws2OqjD1xNI/AAAAAAAACzU/ai7o4F0OMNw7bf6Dxlg3YoMdXboRTvScgCLcBGAs/s400/WS000001.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
上の図はコネクション数5をイメージしています。</div>
<div>
<br /></div>
<div>
これはつまり、同時にSQLを実行できるのは5つまで。</div>
<div>
6つ以上のSQLが発生した場合、5つに収まらない分は<span style="color: red;"><b>待ち</b></span>になります。</div>
<div>
<br /></div>
<div>
よくある障害発生のパターンとして、SQLがコネクションを使ってそのまま開放しないというものがあります。</div>
<div>
これをやられるとシステム全体のSQLが止まってしまうので、インスタンスの緊急再起動をさせることでコネクションを切って張りなおすことで回復させるのが常套手段です。<br />
<span style="color: #cccccc;">(DBまで再起動する羽目になったら目も当てられませんが)</span></div>
<div>
<br /></div>
<div>
上の図はインスタンスが一台のイメージでした。</div>
<div>
では、ロードバランサーとかを使って、APサーバが2台ある構成のイメージを見てみましょう。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-ZEPIN1FW4Hw/Ws2QBKhdE1I/AAAAAAAACzg/CxSfvxD3InUTqhMm8XX5DJC7su2GsSnxwCLcBGAs/s1600/WS000002.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="388" data-original-width="1326" height="116" src="https://1.bp.blogspot.com/-ZEPIN1FW4Hw/Ws2QBKhdE1I/AAAAAAAACzg/CxSfvxD3InUTqhMm8XX5DJC7su2GsSnxwCLcBGAs/s400/WS000002.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
はい。</div>
<div>
説明するまでも無いと思いますが、コネクションが2倍に増えました。</div>
<div>
<br /></div>
<div>
<ul>
<li>インスタンス毎にコネクションを確保する。</li>
</ul>
</div>
<div>
<br /></div>
<div>
それがシステムの基本です。</div>
<div>
ここに<b><span style="color: red;">Lambdaの罠</span></b>があります。</div>
<div>
<br /></div>
<div>
<h3>
Lambdaの特徴</h3>
</div>
<div>
Lambdaは以下が特徴のサービスです。</div>
<div>
<br /></div>
<div>
<ul>
<li>処理が無い時はインスタンスが寝る。</li>
<li>処理が増えた時はインスタンスが増える。</li>
<li><b><span style="color: red;">処理が激増した時はインスタンスがガンガン増える。</span></b></li>
</ul>
</div>
<div>
<br /></div>
<div>
そろそろお分かりになってきたでしょうか。</div>
<div>
<br /></div>
<div>
<span style="color: blue;"><b>Lambdaはインスタンスの動的増減に価値を持っているサービスです。</b></span></div>
<div>
<br /></div>
<div>
しかし、インスタンス毎にコネクションを張るという物理的な制約は変わらない。<br />
つまり、<span style="color: red; font-weight: bold;">コネクション数が無限に増える</span>という仕様なのです。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-nD16tMVKYVQ/Ws2Sl7oRg_I/AAAAAAAAC0E/bQDwZuln2JEfOTm46F7mbRmH5fDXMwtNgCLcBGAs/s1600/WS000003.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="463" data-original-width="1085" height="170" src="https://1.bp.blogspot.com/-nD16tMVKYVQ/Ws2Sl7oRg_I/AAAAAAAAC0E/bQDwZuln2JEfOTm46F7mbRmH5fDXMwtNgCLcBGAs/s400/WS000003.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
この有様です。</div>
<div>
<b><span style="color: red;">イナゴ</span></b>としか言いようがありません。</div>
<div>
<br /></div>
<div>
<ul>
<li><b>LambdaとRDBMSは相性が悪い。</b></li>
</ul>
</div>
<div>
<br /></div>
<div>
これは覚えておかなければなりません。必須知識です。</div>
<div>
<br /></div>
<div>
<h3>
使って良い場合</h3>
</div>
<div>
でも、カラクリが分かれば使えるシチュエーションもあることも分かるでしょう。</div>
<div>
<br /></div>
<div>
「インスタンスが無限に増えた時にRDBMSがボトルネックになる」が問題の核心部分ですから、インスタンスの数が制御されていれば問題にはなりません。</div>
<div>
<br /></div>
<div>
<ul>
<li>Webリクエストをトリガーとしてインスタンスを起動する場合はインスタンスがどれだけ増えるか分からないから絶対に使ってはいけない。</li>
<li>定期バッチのように、インスタンス数がコントロールされている場合は使える。</li>
</ul>
</div>
<div>
<br /></div>
<div>
これは大変重要な部分です。</div>
<div>
覚えておいてください。</div>
<div>
<br /></div>
<div>
<h3>
本システムの場合</h3>
</div>
<div>
本システムでは、Lambdaは帳票出力APIとして使用しています。</div>
<div>
帳票出力に<b><span style="color: blue;">必要な情報は外部から全部JSONで貰う</span></b>という仕様にしました。</div>
<div>
DBにはアクセスしていません。</div>
<div>
<br /></div>
<div>
これが解決策なのです。<br />
<br />
<br />
<ul>
<li><b>必要な全データをリクエストから取得し、そのままDBを使用すること無く処理が完了する機能には最強!!</b></li>
</ul>
<br />
<br />
帳票出力APIにLambdaをチョイスしたのは我ながら名案です。<br />
<br /></div>
<div>
<h3>
オマケ:それでもDBを使いたい</h3>
</div>
<div>
そんな制約がありながらも、それでもLambdaの拡張性や効率は魅力的です。</div>
<div>
<br /></div>
<div>
<ul>
<li>アクセスが少ないシステムの場合は、インスタンスが寝ているからタダで使える。</li>
<li>アクセスが増えても自動拡張してくれる。</li>
</ul>
</div>
<div>
<br /></div>
<div>
この安定性とコストパフォーマンスは捨て難いです。</div>
<div>
そんな人はNoSQLに活路を見出してみましょう。</div>
<div>
<br /></div>
<div>
<ul>
<li><a href="https://aws.amazon.com/jp/dynamodb/" target="_blank">Amazon DynamoDB</a></li>
</ul>
</div>
<div>
<br /></div>
<div>
AmazonのNoSQLであるDynamoDBは、GoogleのBigTableと並んで世界一有名なNoSQLです。</div>
<div>
<br /></div>
<div>
<span style="color: #999999;">っていうか、LambdaもDynamoDBもGoogleのパクリとしか思え……ゲホゲホ</span></div>
<div>
<br /></div>
<div>
DynamoDBはクラウド型DBを名乗るだけあって、Lambdaのインスタンス激増から来るアクセス急増にも耐えられるように設計されています。</div>
<div>
<br /></div>
<div>
耐久性の秘密は分散にあります。</div>
<div>
だから「保存したデータが別の場所からは見えない(伝搬してないから)」という現象が起きたりとか、RDBMSとはまるで別物。</div>
<div>
<br /></div>
<div>
分散を実現する為に「リレーション」というものが無く、従ってテーブル間結合も出来ないとか、<b><span style="color: red;">DBをRDBMSからDynamoDBに差し替えれば使えるみたいな単純な話ではないところが厄介</span></b>ですが、ちゃんと勉強して使いどころを見極めれば非常に心強い味方になってくれるでしょう。</div>
<div>
<br /></div>
<div>
<h2>
終わりに</h2>
</div>
<div>
引き続きLambdaの話を続けます。</div>
<div>
</div>
</div>
Anonymousnoreply@blogger.com0tag:blogger.com,1999:blog-5306057209591512828.post-21346078182874459062018-04-02T12:05:00.000+09:002018-04-11T14:49:05.750+09:00【AWS Lambda】帳票出力API開発 その1株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。<br />
<br />
<br />
<ul>
<li><a href="https://genesis-tdsg.blogspot.jp/2018/03/python.html" target="_blank">Pythonで社内システムを作ってみた~序章~</a></li>
</ul>
<div>
<br /></div>
<div>
上記に記載したとおり、最近覚えたPythonをメインに使用して社内用のWebシステムを作ってみました。</div>
<div>
システム構成はこんな感じです。</div>
<div>
<br /></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-zGtPKZANxGY/Wq8t7uIeWsI/AAAAAAAACqU/-PHZEyYaWWITKg6RoM4o3dGR4Yvu0GogQCPcBGAYYCw/s1600/WS000000.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="794" data-original-width="1406" height="225" src="https://3.bp.blogspot.com/-zGtPKZANxGY/Wq8t7uIeWsI/AAAAAAAACqU/-PHZEyYaWWITKg6RoM4o3dGR4Yvu0GogQCPcBGAYYCw/s400/WS000000.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
複数のアーキテクトから構成されるシステムですので、このブログでは分解して連載して行きたいと思います。</div>
<div>
<br /></div>
<div>
最初はAWS Lambdaで稼働する帳票出力APIです。</div>
<div>
<br /></div>
<h2>
AWS Lambda</h2>
<div>
AWS Lambdaは、Lambdaが提供するコード実行環境です。</div>
<div>
公式サイトはこちら。</div>
<div>
<br /></div>
<div>
<ul>
<li><a href="https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/welcome.html" target="_blank">https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/welcome.html</a></li>
</ul>
</div>
<div>
<br /></div>
<div>
公式サイトにはこのように書かれていますね。</div>
<div>
<br /></div>
<blockquote class="tr_bq">
AWS Lambda はサーバーをプロビジョニングしたり管理しなくてもコードを実行できるコンピューティングサービスです。AWS Lambda は必要に応じてコードを実行し、1 日あたり数個のリクエストから 1 秒あたり数千のリクエストまで自動的にスケーリングします。使用したコンピューティング時間に対してのみお支払いいただきます- コードが実行中でなければ料金はかかりません。AWS Lambda によって、実質どのようなタイプのアプリケーションやバックエンドサービスでも、管理なしでコードを実行できます。</blockquote>
<div>
<br /></div>
<div>
でもこれ、初めてLambdaに触れる人には何言ってるのかチンプンカンプンだと思います。<br />
そこでまずはLambdaの導入編として、その使い方や長所、短所といった解説から行ってみましょう。<br />
<br />
<h2>
特徴1:サーバレス環境である</h2>
サーバレス環境、サーバレスアーキテクチャ……。<br />
最近のクラウド界で流行のキーワードです。<br />
<br />
サーバレスとは直訳すれば「サーバが無い」という意味になりますが、実際のところ、<b><span style="color: blue;">サーバはあります。</span></b><br />
<br />
あくまで我々利用者がサーバの細かい設定を意識しなくて良い、利用者目線でサーバが無いかのように見える、という概念的な話です。<br />
<br />
概念的な話なのでぼんやりとしてしまいがちですが、この画面を見るとピンと来ると思います。<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-pZOy10_Q9DU/WsGU97haKCI/AAAAAAAACto/KezGC0UH4OkUNXf6AOJV2rfU1eYSrBK_QCLcBGAs/s1600/WS000000.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="288" data-original-width="971" height="117" src="https://3.bp.blogspot.com/-pZOy10_Q9DU/WsGU97haKCI/AAAAAAAACto/KezGC0UH4OkUNXf6AOJV2rfU1eYSrBK_QCLcBGAs/s400/WS000000.JPG" width="400" /></a></div>
<br />
<br />
これはLambdaの管理画面で、ソースをアップロードする項目です。<br />
<br />
画面からお察しのとおり、<b><span style="color: blue;">Zipで圧縮したソースをアップロードするだけで実行可能な状態になります。</span></b><br />
<br />
ソースをサーバのどこどこに配置して、そこにパスを通し、Webリクエストを受ける為にapacheやロードバランサの設定も……とか、そういうのは不要です。<br />
<br />
Zipファイルをドンと載せるだけで実行可能。サーバ構築不要。<br />
それが「サーバレス」という言葉の意味です。<br />
<br />
ちなみにですが、前述のとおり、我々がサーバを意識しないだけで、実際にはサーバはあるんです。<br />
大企業などでは「インフラ担当」「リリース担当」「開発担当」が完全に分かれている場合、開発担当は作ったソースをリリース担当に渡せばそのうちリリースしておいて貰えるという体制が構築されていることがありますが、<br />
この場合、開発担当の視点ではサーバレスということになります。<br />
<br />
従来は「インフラ担当」「リリース担当」がやってくれていた作業を自動でやってくれる。<br />
それがLambdaです。<br />
<br />
今まで出来なかったことが可能になるわけではありませんが、今までやっていたことが楽に出来るようになります。<br />
<br />
一方、人を介在させず全自動でやるために「制約」も色々ありますが、それは徐々に勉強していきましょう。<br />
<br />
<h2>
特徴2:コンピューティング時間課金</h2>
特徴その2は、コンピューティング時間課金であること。<br />
<br />
普通のレンタルサーバを借りる場合、月3000円でサーバ1台をレンタル、とかそういう課金方式です。<br />
<br />
Lambdaはソースが動いた時間で課金されるので、ソース実行時間が1秒だったら1秒だけ課金されるという方式です。<br />
<br />
「じゃあ、1日1度、夜間に3秒で終わるファイルクリーンアップバッチを実行したい場合、1日3秒。月90秒の時間だけお金払えば良いってこと?」<br />
<br />
と問われれば、そのとおりです。<br />
そういうところで長所を発揮するサービスです。<br />
<br />
軽微な処理の為にサーバを1台占拠したり、既に動いているサーバの隅っこにこっそり置かせて貰ったりとか、そういうのは必要ありません。<br />
<br />
軽微な処理だけの為の独立した環境が手に入るという、疎結合という観点でも優れたシステム設計を実現出来ます。<br />
<br />
しかし、それ故の欠点もあります。<br />
<br />
何故「処理が動いた時間だけ課金」という事が可能なのかというと、それは動いていない時間帯は裏側にあるインスタンス(=サーバ)が寝ているからなのです。<br />
<br />
ずっと起きっぱなしだったらAWS側のリソースを食ってしまいますので、無課金というわけにはいきません。<br />
使っていない時間帯は寝ているからリソースを食わない。従って、寝ている間はタダでOK。<br />
そういうカラクリなのです。<br />
<br />
だから、寝ぼけた状態から起きる為のコスト、<span style="color: red;"><b>「スタートアップ時間」</b></span>が発生します。<br />
<br />
これが決定的に向かないのがJavaです。<br />
Javaは初期起動でJavaVMを展開するコストが重く、その後もクラスロードが重いと、とにかく<span style="color: red;"><b>最初が重い言語</b></span>です。<br />
<br />
最初が重い言語であるにも関わらず、Lambdaでは起きる度にスタートアップを要求される。<br />
<span style="color: red;"><b>致命的に相反する</b></span>性質です。<br />
<br />
でも実は、今回開発した帳票出力APIはJavaで作ってしまいました。<br />
何故Javaなのか?<br />
それは<span style="color: blue;"><b>Javaのライブラリを使わなきゃ実現出来なかったからです。(泣)</b></span><br />
<br />
事情は後の連載で明らかになりますが、私は好きでLambdaにJavaを展開したわけじゃないってことはご理解下さい。<br />
<br />
ちなみに、元々はJavaエンジニアである私が最近Pythonに手を伸ばした理由の一つとして、コレがあります。<br />
<br />
<br />
<ul>
<li><b><span style="color: blue;">スタートアップが遅いJavaでは、これからのクラウド時代に適合し切れない</span></b></li>
</ul>
<br />
<br />
と、私は考えています。<br />
<br />
Java自体は良い言語で、今後もずーっと使われていく絶対的安全牌の言語だと思います。<br />
しかし、<span style="color: red;"><b>Javaしか出来ないってエンジニアはヤバい。</b></span><br />
Javaの欠点を補える性質を持った言語を身につけておかないと、使い回しの効かないエンジニアが出来上がる危険性があると思います。<br />
<br />
そういうわけで、今までJavaだけやってきたエンジニアは、これからの時代の変化に対応する為にPythonを勉強していくことがオススメです。<br />
<br />
<h2>
続く</h2>
Lambdaで紹介することはまだまだあります。<br />
次回に続きます。</div>
Anonymousnoreply@blogger.com0tag:blogger.com,1999:blog-5306057209591512828.post-11547180373022520712018-03-26T13:01:00.001+09:002018-03-26T17:58:14.346+09:00code-prettifyで技術ブログの可読性アップ株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。<br />
<br />
今回はちょっと臨時番外編をお送ります。<br />
<br />
<h2>サイトが見辛い</h2>最近は<a href="https://qiita.com/" target="_blank">Qiita</a>という技術交流SNSが注目を集めていますよね。<br />
私も技術調査を行っている時にQiitaに掲載されている記事にお世話になることが多いです。<br />
<br />
それを見ていて思うのが、何かこのブログって掲載しているブログが見辛いなぁ。。。<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-Sw6YY7M1Zh0/WrhmMYaa57I/AAAAAAAACsA/_byRJ0ABMuoi8_gaBJk_Exp79yJzQpALQCLcBGAs/s1600/WS000000.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="729" data-original-width="768" height="303" src="https://4.bp.blogspot.com/-Sw6YY7M1Zh0/WrhmMYaa57I/AAAAAAAACsA/_byRJ0ABMuoi8_gaBJk_Exp79yJzQpALQCLcBGAs/s320/WS000000.JPG" width="320" /></a></div><br />
<br />
このブログを始めた2013年当時、私はGoogleが提供してくれているコード掲載用ライブラリである「code-prettify」を導入したのですが、<br />
今となっては<span style="color: red;"><b>明らかにQiitaとか他の技術ブログより見辛い</b></span>ぞ。<br />
<br />
一体どうなってんの???<br />
<br />
と言うことで、現状に甘んずることなく、ブログの品質向上を目指して見直しを行うことにしました。<br />
<br />
何か良いライブラリ無いかな。。。<br />
<br />
<h2>code-prettifyだった</h2><div>そして調査して分かりましたが、私のやりたいことは「code-prettify」で出来るんですね。</div><div><br />
</div><div>code-prettify自身が2013年当時から進化していて、最新版を持って来れば良いんですよ。</div><div><br />
</div><div>2013年の頃はGoogle本家に置いてあったと記憶しているcode-prettifyも、今はGitHubに引っ越ししているようです。</div><div><br />
</div><div><ul><li><a href="https://github.com/google/code-prettify" target="_blank">https://github.com/google/code-prettify</a></li>
</ul></div><br />
今まで使っているcode-prettifyを消して、新しいのを入れなおしてみましょう。<br />
<br />
<h2>run_prettify</h2>run_prettifyはAjaxライブラリの一種なので、HTMLのヘッダーで宣言が必要です。<br />
<br />
以下のようにCDN(コンテンツデリバリネットワーク)の以下を宣言して下さい。<br />
<br />
<div class="scroll"><pre class="prettyprint linenums"><code class="language-python"><script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>
</code></pre></div><br />
<br />
CDN……。<br />
要するに、Googleの親サイトに直接繋いでJSファイルを読み込むわけです。<br />
<br />
便利である一方、Googleのサイトが落ちたり、無くなっちゃったりすると死んでしまうわけですが、run_prettifyはCDNを使った方が良いと思います。<br />
<br />
容易な変更が許されない業務システムで使うライブラリであれば、そのシステムをリリースした時のバージョンを維持する為にJSファイルをローカルにダウンロードしてシステム内部で保持する必要があります。<br />
でも、このブログって業務システムではないですし、何より新しさが重要ですから。<br />
<br />
CDNが無くなったり、引っ越ししたりしたら、それに合わせてブログを更新するべきだと思います。<br />
更新が遅い技術ブログなんて役に立たないっしょ?<br />
<br />
何年も前に取得した古いライブラリを維持するとかは業務系システムで考えるべきことで、こういうブログは目新しさを求めてCDNを呼べば良いと思います。<br />
<br />
さて、「run_prettify.js」ですが、これで描画に必要なスタイルシートとかも全部読み込んでくれています。<br />
<br />
ですが、読み込む際にオプションを指定することが出来ます。<br />
<br />
<br />
<ul><li><a href="https://github.com/google/code-prettify/blob/master/docs/getting_started.md" target="_blank">https://github.com/google/code-prettify/blob/master/docs/getting_started.md</a></li>
</ul><br />
<br />
いくつかありますが、気になった所を挙げてみましょう。<br />
<br />
<br />
<ul><li>autorun:自動実行。画面のonLoad時に自動実行することで、デフォルトはtrueです。どうも昔は自動実行が無くて、自分でonLoad実行しなきゃいけなかったようですが、今はこのとおり、自動実行でラクチンです。</li>
<li>lang:プログラミング言語の指定。code-prettifyは「Java表示モード」「Python表示モード」みたいに、言語毎にグラフィックを変えてくれるというIDEみたいな凄い技をやってくれます。そのデフォルト言語ですね。デフォルト言語をPythonにしておけば、何もしなければPythonモードで表示され、その上でJavaにしたい時はHTMLの中のclassにJavaを指定すればそこだけJavaモードになります。</li>
<li>skin:スキンの指定。後述。</li>
</ul><br />
大事なのは「skin」かな。<br />
<br />
<br />
<ul><li><a href="https://rawgit.com/google/code-prettify/master/styles/index.html" target="_blank">https://rawgit.com/google/code-prettify/master/styles/index.html</a></li>
</ul><br />
<br />
上記のページにあるスキンからお好みのものを選ぶことは出来ます。<br />
当ブログは長らくdefaltでしたが、今回を期に「Sons-Of-Obsidian」に変更します。<br />
<br />
<br />
<br />
<pre class="prettyprint linenums"><div class="scroll"><script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js?skin=sons-of-obsidian"></script></div></pre><br />
<br />
<br />
これで宣言完了。<br />
<br />
<h2>書く</h2><div>ここから先の使い方は簡単です。</div><div>例えばPythonのコードを載せたい時は、以下のようにHTMLを書けばOK。</div><br />
<pre class="prettyprint linenums"><pre class="prettyprint linenums"><code class="language-python">...コード...</code></pre>
</pre><br />
「linenums」とは行数を表示するオプションです。<br />
特に理由が無い限りは常につけておいた方が良いでしょう。<br />
<br />
実際、このやり方で上記の画像の状況だったソースを掲載すると以下になります。<br />
<br />
<br />
<pre class="prettyprint linenums"><code class="language-python">import os
import json
dirPath = 'C:/MyMail_result'
files = os.listdir(dirPath)
#連想配列を作成
map = {}
#ファイルを全部読み込み
for file in files:
f = open(os.path.join(dirPath,file))
data = json.load(f)
f.close()
#name毎にsalienceを集計
for entity in data['entities']:
name = entity['name']
if name in map:
map[name] = map[name] + entity['salience']
else:
map[name] = entity['salience']
#集計結果をソート
resultList = reversed(sorted(map.items(), key=lambda x:x[1]))
#出力
for data in resultList:
print(data[0] + '\t' + str(data[1]))
</code></pre><br />
これこれ。<br />
これをやりたかったんですよ。<br />
<br />
今の時代なら絶対コレしか無い!!<br />
<br />
<h2>終わりに</h2><div>よっしゃ。これで綺麗になったぞ。</div><div>やっぱね、5年も同じブログを続けていると時代遅れになっている部分があったとしても、どうしても「これでいいや」って気分になりがちなんですよね。</div><div>今までそれでやって来ているわけですから。</div><div><br />
</div><div>でも、偶にで良いので振り返って、「いやいや、今ならもっと良いやり方があるぞ」という所を見つけたら、改善を決行しなければなりません。</div><div><br />
</div><div><span style="color: red;"><b>「今までそれでやって来た」というだけで改善を行わないという怠慢!!</b></span></div><div><br />
</div><div>ブログ運営に限らず、業務を行う上では常に気を付けていきたいものです。</div>Anonymousnoreply@blogger.com0tag:blogger.com,1999:blog-5306057209591512828.post-15784796226299403762018-03-19T12:40:00.001+09:002018-03-23T17:44:18.767+09:00Pythonで社内システムを作ってみた~序章~株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。<br />
<br />
先週まで勉強を兼ねて、PythonとGoogleの機械学習API「CLOUD NATURAL LANGUAGE API」の連載を行っていましたが、<br />
おかげ様で何とか感触を掴めてきました。<br />
<br />
しかし「勉強の為の勉強」だと、どうもピントがぼやけた調査になってしまうのが現実のところ。<br />
そこで「社内システムの開発」を想定して、ちょっくらPythonで社内で使えそうなシステムを作ってみようと考えるに至り、ようやくある程度の形になってきたところです。<br />
<br />
そこで、今回より新シリーズ「Pythonで社内システムを作ってみた」を始めていきたいと思います。<br />
<br />
<h2>
着想</h2>
<div>
テーマとして選んだのはSEならみんなお馴染みの、<b>「業務経歴書」</b>です。</div>
<div>
<br /></div>
<div>
弊社の業務経歴書はIT界で悪名高い神エクセルの類です。<br />
<br />
エクエルに各自書き込むという方式なので記述粒度が人によって合ってなかったり、印刷してみると微妙に見切れちゃってたり、<br />
とか細々とした問題が多いという感覚が現場の実感としてありました。<br />
<br />
私の業務経歴書はこんな感じ。(ちょっとだけお見せします)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/--i_dnUQZ6Io/Wq8gKzcbVHI/AAAAAAAACpw/F6N5lybyqBkZZt-aVeKUT94UEQ90zSsjQCLcBGAs/s1600/WS000001.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="776" data-original-width="963" height="257" src="https://4.bp.blogspot.com/--i_dnUQZ6Io/Wq8gKzcbVHI/AAAAAAAACpw/F6N5lybyqBkZZt-aVeKUT94UEQ90zSsjQCLcBGAs/s320/WS000001.JPG" width="320" /></a></div>
<br />
<br />
一見すると綺麗ですが、これがエクセルで、実は問題もあるんですよ。<br />
<br />
デザインの改善点の指摘もあるのですが、何せ全員が各自個別にエクセルファイルを持っている形ですから、<br />
デザイン変更したくても全員が同じようにレイアウト変更作業をやるのは大変だから二の足を踏んだりとか、<br />
やっぱり「個別管理」「エクセル形式」というのは、手っ取り早いのは良いですけど長期的管理体制には不向き。<br />
<br />
そこで私は「これをWebシステム化して一元管理したら業務改善になるんじゃないかな?」と考えるに至ったわけです。<br />
<br />
<h2>
課題</h2>
<div>
「Webシステム化する」と言うだけなら簡単ですが、それをソリューションとしてビルドアップするのは中々ハードルが高いです。</div>
<div>
開発進行過程で課題になった点をご紹介しましょう。</div>
<div>
<br /></div>
<h3>
言語はPython</h3>
<div>
これは課題と言うより「前提」ですが、言語は最初からPythonにしようと思っていました。</div>
<div>
そもそもはPythonの勉強から始まっている、というのも大きいですが、もう一つの理由としては「優遇」があります。</div>
<div>
<br /></div>
<div>
プログラミング視点では「小規模Webシステムなんてどんな言語使っても対して変わらん」というのが実際のところですが、環境面だと意外にそうでもないです。</div>
<div>
<br /></div>
<div>
<a href="http://genesis-tdsg.blogspot.jp/2013/12/gaegoogle-app-engine.html" target="_blank">過去の連載</a>で私はGoogleAppEngineを使用し、ネタバレになりますが今回はAWSを使用しましたが、その所感として<b><span style="color: blue;">Pythonはクラウド界で優遇されています。</span></b></div>
<div>
<br /></div>
<div>
クラウドサービスは言語を指定されている製品がありまして、「この製品はPythonは使えるけでRubyは未対応」など、クラウド製品の都合で言語が縛られるケースがあります。</div>
<div>
そんな中、Pythonは常に対応していました。</div>
<div>
<br /></div>
<div>
<ul>
<li>とりあえずPythonならばクラウドはOK</li>
</ul>
</div>
<div>
<br /></div>
<div>
私は<b>寄らば大樹の陰</b>という主義のエンジニアですが、Pythonは寄って安心の大樹だと思います。</div>
<div>
<br /></div>
<div>
<h3>
基盤</h3>
</div>
<div>
基盤は「クラウド+サーバレス(従量課金制)」しか無いと最初から思っていました。</div>
<div>
<br /></div>
<div>
この業務経歴書管理システムは、その性質上、業務経歴が書き換わるタイミングしか出番が来ないものです。</div>
<div>
個人単位だと数ヶ月~数年に一度しか使いません。</div>
<div>
<br /></div>
<div>
そんなシステムの為にサーバを常駐させておくなんてのはコスト的にあり得なくて、システムを使うときだけ費用が発生する従量課金制のクラウド・サーバレスサービスしか無いというのは自明の理でした。</div>
<div>
<br /></div>
<div>
サーバレスサービスは、やはり以前に連載していた<a href="http://genesis-tdsg.blogspot.jp/2013/12/gaegoogle-app-engine.html" target="_blank">GoogleAppEngine</a>が業界代表格でしょう。</div>
<div>
この連載の中で別のシステムを作っていましたから、「サーバレスとはどういうものか?」「どういう時に出番が来るのか?」という知見はありました。</div>
<div>
<br /></div>
<div>
今回は同じサーバレスでも別製品、AWSのサーバレスを使うことにしました。</div>
<div>
GoogleではなくAWSにした理由は、弊社の方針ですね。</div>
<div>
今後、弊社ではAWSに力を入れていこうという方針があるので、そこに乗っかることにしました。</div>
<div>
<br /></div>
<div>
特にAWSの方がGoogleより向いている何かがあったわけではありません。</div>
<div>
しかし、あっちこっちの技術に手を伸ばしていると片手落ちになってしまうので、合わせられる部分は合わせよう、とAWSにすることにしました。<br />
<br /></div>
<div>
<h3>
Webシステム・フレームワーク</h3>
</div>
<div>
「PythonでWebシステムを作るとしたら、フレームワークはどうしよう?」と思いました。</div>
<div>
調べてみると「django(ジャンゴ)」というフレームワークが見つかったのでコレにしました。</div>
<div>
<br /></div>
<div>
と言うか、PythonのWebシステム界ではdjangoが支配的地位です。</div>
<div>
django以外の選択肢なんかありません。</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<h3>
帳票出力</h3>
</div>
<div>
<span style="color: red;"><b>最大の問題点。</b></span></div>
<div>
業務経歴書は印刷して面談に持って行くという<b><span style="color: red;">紙媒体</span></b>が運用上絶対に外せない要件です。</div>
<div>
<br /></div>
<div>
<ul>
<li>Webだけなら誰でも出来る。</li>
<li>印刷はどうすりゃいいんだ!?</li>
</ul>
</div>
<div>
<br /></div>
<div>
帳票出力は技術的最大のハードルです。</div>
<div>
<br /></div>
<div>
<ul>
<li>Yahooの時刻表印刷みたいにWeb画面を印刷する。</li>
<li>現在と同じくExcelを出力する。</li>
<li>PDFで出力する。</li>
</ul>
</div>
<div>
<br /></div>
<div>
色々考えて検証しましたが、これらにはそれぞれ問題点があって解消出来ませんでした。</div>
<div>
<br /></div>
<div>
<ul>
<li>Web画面印刷⇒ブラウザ依存でどうしても微妙に見栄えが変わってしまう。</li>
<li>Excel印刷⇒印刷時の見切れに対応出来ない。</li>
<li>PDF⇒柔軟性が無さ過ぎる。例えば営業が「ちょっと急ぎ手直ししたい」という状況が発生した時に書き換えられない。</li>
</ul>
</div>
<div>
<br /></div>
<div>
これらを踏まえて、最終的に「Wordで出力する」という仕様に結論付けました。</div>
<div>
<br /></div>
<div>
Word出力もこれはこれで難しくて。。。</div>
<div>
最初はPythonでやろうとしましたが、どうしても実現不可能なケースがあったので、Pythonは諦めてココだけJavaでやることにしました。</div>
<div>
<br /></div>
<div>
Word出力の奮闘記は後の連載でご紹介します。</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<h2>
システム構成</h2>
</div>
<div>
そんなこんなで試行錯誤した結果、以下のようなシステム構成図でまとまりました。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-zGtPKZANxGY/Wq8t7uIeWsI/AAAAAAAACqQ/HtOb0qxszrsKv8ifyYqaSTNvjmVfyx-dwCLcBGAs/s1600/WS000000.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="794" data-original-width="1406" height="225" src="https://4.bp.blogspot.com/-zGtPKZANxGY/Wq8t7uIeWsI/AAAAAAAACqQ/HtOb0qxszrsKv8ifyYqaSTNvjmVfyx-dwCLcBGAs/s400/WS000000.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
大きく「Webシステム」と「帳票出力API」に二分割されています。</div>
<div>
<br /></div>
<div>
<h2>
終わりに</h2>
</div>
今後はシステム構築に至るまでの過程やノウハウの連載を始めていきたいと思います。<br />
<br />
<br />
<ul>
<li>Webシステム実装:Python&Django編</li>
<li>Webシステムインフラ:AWS Elastic Beanstalk編</li>
<li>帳票出力API実装:Apache POI編</li>
<li>帳票出力APIインフラ:AWS Lambda編</li>
</ul>
<br />
<br />
システム全体としては色々と詰め込まれていますが、それぞれ非常に疎結合となっています。<br />
<br />
「ベンダーロックオン」と言いまして、クラウドの話をすると以後ずっとそのクラウドから抜け出せなくなることを気にされるケースがありますが、作ってみたところ、別にそんなことは無さそうでした。<br />
<br />
ログ出力の設定とか多少のことはありますが、「作ったアプリのインフラを別のところに引っ越したいんだけど?」となった場合でも、特に問題にはならない規模です。<br />
<br />
従って、連載を進めていく上で「インフラ編を読んだ後じゃないと実装編の意味が分からない」とかにもならないと思います。<br />
<br />
連載は、システム規模が<br />
<br />
<br />
<ul>
<li>Webシステム>>>帳票出力API</li>
</ul>
<br />
<br />
なので、まずは手短な帳票出力API編から始めていきたいと思います。</div>
Anonymousnoreply@blogger.com0tag:blogger.com,1999:blog-5306057209591512828.post-34059383414468082822018-02-28T19:03:00.003+09:002018-03-23T17:45:49.689+09:00【Googleクラウド・機械学習編】日報解析バッチ作成中4~集計~株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。<br />
<br />
最近は機械学習について勉強中です。<br />
現在はGoogleの機械学習API「CLOUD NATURAL LANGUAGE API」の検証と、Pythonの勉強を並行して進行しています。<br />
<br />
初心者の勉強として、簡単なバッチを作っている最中です。<br />
大した内容はありませんが、お付き合いください。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-3YUURn_N7UA/Wm17dFnUkNI/AAAAAAAACdE/ysNQ2GpfyRslybcuvlLAvUfJDV0kU2VYQCLcBGAs/s1600/WS000000.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="848" data-original-width="904" height="300" src="https://4.bp.blogspot.com/-3YUURn_N7UA/Wm17dFnUkNI/AAAAAAAACdE/ysNQ2GpfyRslybcuvlLAvUfJDV0kU2VYQCLcBGAs/s320/WS000000.JPG" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<h2>
集計へ</h2>
<div>
<a href="https://genesis-tdsg.blogspot.jp/2018/02/google_19.html" target="_blank">前回</a>にて、何とか自分の日報メールをAPIに食わせて、結果ファイルを取得するところまで成功しました。</div>
<div>
現状、以下のようにJSONファイルがズラリとローカルに保管されております。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-lZiJTfi6RUY/WpZxFSnD0qI/AAAAAAAAClw/xm3XSKjjIUYJaETp6yvgPlDqKrdq5WAYgCLcBGAs/s1600/WS000000.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="504" data-original-width="1190" height="168" src="https://1.bp.blogspot.com/-lZiJTfi6RUY/WpZxFSnD0qI/AAAAAAAAClw/xm3XSKjjIUYJaETp6yvgPlDqKrdq5WAYgCLcBGAs/s400/WS000000.JPG" width="400" /></a></div>
<div>
<br />
一個一個のファイルの中身は、以下のようにJSON文字列が入っています。<br />
<br /></div>
<pre class="linenums">{
"entities": [
{
"name": "日報",
"type": "OTHER",
"metadata": {},
"salience": 0.20918807,
"mentions": [
{
"text": {
"content": "日報",
"beginOffset": 21
},
"type": "COMMON"
}
]
},
{
"name": "結合テスト項目書",
"type": "OTHER",
"metadata": {},
"salience": 0.113717824,
"mentions": [
{
"text": {
"content": "結合テスト項目書",
"beginOffset": 169
},
"type": "COMMON"
},
{
"text": {
"content": "結合テスト項目書",
"beginOffset": 203
},
"type": "COMMON"
}
]
},
{
"name": "稼働時間",
"type": "OTHER",
"metadata": {},
"salience": 0.111668386,
"mentions": [
{
"text": {
"content": "稼働時間",
"beginOffset": 53
},
"type": "COMMON"
}
]
},
……続く
</pre>
<div>
<br /></div>
<div>
<br /></div>
<div>
ファイルには<br />
<br />
<br />
<ul>
<li>"name": "結合テスト項目書"</li>
<li>"salience": 0.113717824</li>
</ul>
<div>
<br /></div>
<div>
のように「キーとなる単語」と、その重要度が数値でセットされています。</div>
<div>
つまり、単語毎にグルーピングして集計すれば、私の日報の中から頻出する重要キーワードが浮かび上がる、と。</div>
<div>
こういう段取りなわけです。</div>
<div>
<br /></div>
<div>
では、集計バッチを作ってみましょう。</div>
<div>
<br /></div>
<div>
</div>
<br />
<h2>
集計バッチ</h2>
</div>
<div>
こんなものを作りました。</div>
<div>
<br /></div>
<pre class="prettyprint linenums">import os
import json
dirPath = 'C:/MyMail_result'
files = os.listdir(dirPath)
#連想配列を作成
map = {}
#ファイルを全部読み込み
for file in files:
f = open(os.path.join(dirPath,file))
data = json.load(f)
f.close()
#name毎にsalienceを集計
for entity in data['entities']:
name = entity['name']
if name in map:
map[name] = map[name] + entity['salience']
else:
map[name] = entity['salience']
#集計結果をソート
resultList = reversed(sorted(map.items(), key=lambda x:x[1]))
#出力
for data in resultList:
print(data[0] + '\t' + str(data[1]))
</pre>
<div>
<br /></div>
それほど大したバッチではありませんが、特徴は連想配列かな?<br />
<br />
<br />
<ul>
<li>map = {}</li>
</ul>
<div>
<br /></div>
<div>
PythonではこれでHashMapを作ったことと同じ事になります。</div>
<div>
<br /></div>
<div>
私の好みの部分もありますが、オブジェクト指向において、Mapというのはちと問題児だと思います。</div>
<div>
基本的には「型」を定義して、そこに突っ込むのがオブジェクト指向であって、その「型」は厳密に定められているものです。</div>
<div>
<br /></div>
<div>
Mapは何でもぶっこめるので型も何もあったもんじゃない。</div>
<div>
ソースがグジャグジャになる原因の一つだと思います。</div>
<div>
<br /></div>
<div>
しかしですね、ここで考慮しなければならないのが、Pythonが動的型付け言語であるということです。</div>
<div>
<br /></div>
<div>
Mapに何でもぶっこんでおいても、Pythonが動的に型を合わせてくれますので。</div>
<div>
静的型付け言語で、必要に応じてキャストまでしなければならないJavaとは大きく違う部分です。</div>
<div>
<br /></div>
<div>
つまり、Pythonはむしろ、気軽にMapを使ってパッパと開発していく、そういう用途の為の言語であると言えるでしょう。</div>
<div>
<br /></div>
<div>
だから今回みたいに、ちょっとした計算バッチはパッパとMapで済ませてしまえばOK。</div>
<div>
<br /></div>
<div>
前も書きましたが、Pythonは「ちょっとした計算の集合体」に向く言語です。</div>
<div>
Javaは「定められた一貫性」に優れる言語です。</div>
<div>
<br /></div>
<div>
見方を変えれば、</div>
<div>
HTTPリクエストやJSONファイルみたいに、どんな内容でも自由に突っ込まれてくる情報の取り扱いは、Pythonが優れる。</div>
<div>
RDBMSみたいに、「このテーブルのこのカラムはVARCHAR2」とガッチリ決まっていて不動の所はJavaが優れる。</div>
<div>
<br /></div>
<div>
ならば、<span style="color: blue;"><b>「WebシステムでDBに保存する処理はどっちの言語が良いの?」</b></span>と問われれば、</div>
<div>
これが悩ましいです。</div>
<div>
<br /></div>
<div>
MVCモデルのうち、コントロール部はPython、モデル部はJavaに軍配が上がると思います。(ビュー部はHTMLだから関係無い)</div>
<div>
<br /></div>
<div>
従って、私がここ最近Pythonを触ってみた感触としては、こういう感想です。</div>
<div>
<br /></div>
<div>
<ul>
<li>テーブルの数が多いシステムはJava。</li>
<li>テーブルの数が少ないシステムはPython。</li>
</ul>
</div>
<div>
<br /></div>
<div>
指標値とするべきはテーブルの数!!</div>
<div>
<br /></div>
<div>
「テーブルの数が多い=STEP数も多い=画面数も多い」となりがちなので、STEP数や画面数を指標としても同じような判断に落ち着く事も多いと思いますが、</div>
<div>
<span style="color: blue;"><b>テーブル数主眼が本質</b></span>という考え方はアリだと思います。</div>
<div>
<br /></div>
<div>
「多い/少ない」の分かれ目は、これも感覚的なものですが……、20コくらいが上限じゃないでしょうか?</div>
<div>
一つのシステムで20テーブルを超えたら、もう大規模システムの領域だと思います。</div>
<div>
Pythonで似たようなことをやりたいなら、システムを2つに分割して10テーブルの小さなシステムを2つ作るとか、</div>
<div>
サービスデザインを見直すべきところでしょう。</div>
<div>
<br /></div>
<div>
<h2>
集計結果</h2>
</div>
<div>
ともかく、これで集計出来ました。</div>
<div>
さあ、私の日報の分析結果は如何に。<br />
<br /></div>
<div>
<pre class="linenums">日報 30.935778224999996
稼働時間 17.395398603999993
概要 7.594298239
詳細 4.874361350999999
作成 4.006452768100001
打ち合わせ 2.7061136348
提案書作成作業 1.90614234
ネットワーク接続作業 1.6254301270000004
プロパー 1.5154260646000002
作業 1.4572377554000002
ジェニシス 1.4317204425000003
見積もり 1.4068984159999998
稼働 1.245910729
事 1.1966940003
技術調査 1.1899960548
ソース解析 1.07680666
人 1.0335532006
予定 1.002557445
気づき 0.9903137190000001
帳票 0.9701202919999999
サンプル 0.9039525214999999
構築方針書 0.8930587449999999
マネージャー 0.8877154268999999
連絡事項 0.8676672089
システム 0.8229978675000001
プロジェクト 0.8194439760000002
話 0.8187522889000002
資料 0.8143453079000003
Java 0.7839326217000001
客先 0.7562989093
こと 0.7256286095000003
準備 0.6499679165000001
画面 0.6439224732000001
BI 0.6338003121
サンプルHTML 0.6266641692999999
Oracle 0.6084089060000001
GCOM 0.5797013178999999
検討 0.5605384631
機能 0.5536394495999999
パッケージ 0.5513561149999999
調査 0.5406491108
現場 0.5338922546000001
プラン 0.5171976732
方針 0.4683039328
要件定義 0.4537456172
単体テスト 0.44251170900000003
部分 0.4377159611
設計書 0.4054884552
内部 0.3879731024
方 0.3855670599999999
ビジネスフロー 0.384925288
クラウド基盤 0.3830445173
要件定義工程 0.3821089
開発 0.3820660644
結合テスト項目書 0.37300472500000004
チームミーティング 0.36438519610000003
放置状態 0.363936127
STEP数 0.35657688679999994
ビジネスフロー作成フェーズ 0.3412589773
ソースレビュー 0.338786632
BIプラン 0.337376835
提案書 0.32983535729999996
画面構成検討 0.32272407500000005
提案書作成作業:08:00h 0.31764615100000004
ございませ 0.30836847
構成 0.30728194200000003
帰社 0.30420098119999994
レビュー 0.3030037097
状況 0.3007273611
支援 0.29845437710000006
ソース解析:08:00h 0.293045449
もの 0.29084775009999997
待機 0.28608122
調整 0.285563885
チャンス 0.27885413449999996
合宿 0.2785616205
結合テスト 0.277871993
リリース 0.263083156
感じ 0.25053776079999995
問題 0.25040119800000005
導入 0.24158003300000003
勉強会 0.2364971065
画面構成検討:08:00h 0.235985352
案件 0.2346195449
承認 0.2288930412
Oracleクラウド 0.22463897
インターネット 0.22296365950000002
★個人名につき秘密★ 0.22103915889999995
時間 0.21647127900000002
構築方針書作成:08:00h 0.213250314
処理 0.212900709
HTML 0.2093946756
見積もり作業 0.20597136
客先打ち合わせ 0.204712169
内部調整:08:00h 0.204112792
プロジェクト構築検討:08:00h 0.202727818
課題 0.20266155249999998
結合テスト項目書作成:08:00h 0.197733019
ソース解析作業 0.19659552349999998
</pre>
</div>
<div>
</div>
<div>
<br />
全部で2000行もあるのでTOP100だけ載せますが……。</div>
<div>
<br /></div>
<div>
ん、ん~……。<br />
<span style="color: red;"><b><br /></b></span>
<span style="color: red;"><b>何も読み取れないというのが正直なところ。</b></span><br />
<br />
とは言え、<span style="color: blue;"><b>「あっ、この人、SEだ!!」</b></span>ということは伝わってきますよね。<br />
<br />
私だと使い道が思い浮かばなくても、広告業とかやっている人には使い道がありそうな気もしますね。<br />
<br />
断定的な処理を行う材料には使えなくて、ヤマを張る為の参考情報くらいが使い道なようです。<br />
<br />
例えば、<br />
<br />
<br />
<ul>
<li>客先打ち合わせ<span style="white-space: pre;"> </span>0.204712169</li>
</ul>
<div>
<br />
<br /></div>
<div>
「打ち合わせ」というキーワードで引っ掛けて、その数字が0.5を超えたら、それだけ日報に多数の「打ち合わせ」という単語が登場しているということですから、</div>
<div>
<br /></div>
<div>
<span style="color: blue;">「コイツは打ち合わせばっかりやっている可能性がある。不要な会議をやっていないか確認して、必要であればテコ入れしろ!!」</span></div>
<div>
<br /></div>
<div>
とアラートを出すとか、ね。</div>
<div>
<br /></div>
<div>
具体的な実用化案までは考えられませんか、どういうシロモノかという感覚は理解出来た気がします。</div>
<div>
<br /></div>
<h2>
終わりに</h2>
</div>
<div>
興味本位で始めた連載でしたが、なかなか面白かったと思います。</div>
<div>
自分の業務で即刻役に立つものではありませんが、見分を広めるという意味では良かったかな、と思います。</div>
<div>
<br /></div>
<div>
ネットで記事を読むだけと、ショボくても良いから自分で作ってみるのは、結構違うものです。</div>
<div>
<br /></div>
<div>
今後も色々と調べていきたいですね。</div>
Anonymousnoreply@blogger.com0tag:blogger.com,1999:blog-5306057209591512828.post-57046915248586682702018-02-19T21:34:00.000+09:002018-03-23T17:19:40.249+09:00【Googleクラウド・機械学習編】日報解析バッチ作成中3~リクエスト送信~株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。<br />
<br />
最近は機械学習について勉強中です。<br />
現在はGoogleの機械学習API「CLOUD NATURAL LANGUAGE API」の検証と、Pythonの勉強を並行して進行しています。<br />
<br />
初心者の勉強として、簡単なバッチを作っている最中です。<br />
大した内容はありませんが、お付き合いください。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-3YUURn_N7UA/Wm17dFnUkNI/AAAAAAAACdE/ysNQ2GpfyRslybcuvlLAvUfJDV0kU2VYQCLcBGAs/s1600/WS000000.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="848" data-original-width="904" height="300" src="https://4.bp.blogspot.com/-3YUURn_N7UA/Wm17dFnUkNI/AAAAAAAACdE/ysNQ2GpfyRslybcuvlLAvUfJDV0kU2VYQCLcBGAs/s320/WS000000.JPG" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<h2>
リクエスト送信</h2>
<div>
<a href="https://genesis-tdsg.blogspot.jp/2018/02/google.html" target="_blank">前回</a>の作業にて、ファイルを読み込むところまでは確認出来ました。<br />
今度はこれをAPIに送り込まなければなりません。<br />
<br />
最難関となるリクエスト送信処理そのものは<a href="https://genesis-tdsg.blogspot.jp/2018/01/googlepython3jsonpost_22.html" target="_blank">もっと前</a>に検証して解決しているので、今回行うのは簡単なテキスト加工ですね。<br />
<br />
<h3>
テキスト</h3>
<div>
私の日報は必ず以下のような形式になっています。</div>
<div>
<br /></div>
<br />
<blockquote>
Delivered-To: endo@genesis-net.co.jp<br />
Received: by 10.60.116.6 with SMTP id js6csp2150228oeb;<br />
Tue, 28 Jul 2015 06:16:25 -0700 (PDT)<br />
X-Received: by 10.60.142.234 with SMTP id rz10mr33362752oeb.4.1438089385353;<br />
Tue, 28 Jul 2015 06:16:25 -0700 (PDT)<br />
Return-Path: <3qIC3VRMJBDsdbkbpfp-dXb-pbosfZbdjXfi.Zljbkaldbkbpfp-kbq.Zl.gm@2uix4h7xygsz66weerlq.apphosting.bounces.google.com><br />
Received: from mail-pd0-f197.google.com (mail-pd0-f197.google.com. [209.85.192.197])<br />
by mx.google.com with ESMTPS id ma3si53036429pdb.163.2015.07.28.06.16.24<br />
for <endo@genesis-net.co.jp><br />
(version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);<br />
Tue, 28 Jul 2015 06:16:25 -0700 (PDT)<br />
Received-SPF: pass (google.com: domain of 3qIC3VRMJBDsdbkbpfp-dXb-pbosfZbdjXfi.Zljbkaldbkbpfp-kbq.Zl.gm@2uix4h7xygsz66weerlq.apphosting.bounces.google.com designates 209.85.192.197 as permitted sender) client-ip=209.85.192.197;<br />
Authentication-Results: mx.google.com;<br />
spf=pass (google.com: domain of 3qIC3VRMJBDsdbkbpfp-dXb-pbosfZbdjXfi.Zljbkaldbkbpfp-kbq.Zl.gm@2uix4h7xygsz66weerlq.apphosting.bounces.google.com designates 209.85.192.197 as permitted sender) smtp.mail=3qIC3VRMJBDsdbkbpfp-dXb-pbosfZbdjXfi.Zljbkaldbkbpfp-kbq.Zl.gm@2uix4h7xygsz66weerlq.apphosting.bounces.google.com<br />
Received: by pdbpo3 with SMTP id po3so221230738pdb.1<br />
for <endo@genesis-net.co.jp>; Tue, 28 Jul 2015 06:16:24 -0700 (PDT)<br />
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;<br />
d=1e100.net; s=20130820;<br />
h=mime-version:reply-to:message-id:date:subject:from:to:content-type<br />
:content-transfer-encoding;<br />
bh=449+r7RRDqf7+TpVrGlImqmP3nYBDuppv9kcCar1VM8=;<br />
b=Ex7Z3fWrUdO//VwmvJl4tECF79NZGChauQzCEd5f4uCZ3YIC6m02Damyzwxg+W1pmO<br />
96vdBP56t3on+zNqYbjXdE50MnZlbq41s+rhfmpN3744ow7ce/ocruBueluTNlMQuHZO<br />
Ct0+vALQ7aTtyC0UNE+RnNU1oGDcA0hTUueL8e93SFbJVcCPtgg+bvn8zx3zhj0l5Da0<br />
axnU9Figlz+M/Vazvy95mppTOlBzCQobqXZkeobBupWkFaYLxny0/bKXjkiq16sa5EZ1<br />
Vp2BYtR/7lc5eHQcg3NHK+dtiR6QU4UsM98P1B8b1jQrWm8MfVJKEcUDP6ls6YROZMDk<br />
pSoQ==<br />
MIME-Version: 1.0<br />
X-Received: by 10.66.146.227 with SMTP id tf3mr36223044pab.21.1438089384636;<br />
Tue, 28 Jul 2015 06:16:24 -0700 (PDT)<br />
Reply-To: "endo@genesis-net.co.jp" <endo@genesis-net.co.jp><br />
X-Google-Appengine-App-Id: s~genesis-gae-service<br />
X-Google-Appengine-App-Id-Alias: genesis-gae-service<br />
Message-ID: <047d7b6dc768ed3c29051bef4663@google.com><br />
Date: Tue, 28 Jul 2015 13:16:24 +0000<br />
Subject: =?ISO-2022-JP?B?GyRCIVpGfEpzIVsxc0YjGyhCXzIwMTUwNzI4?=<br />
From: "endo@genesis-net.co.jp" <endo@genesis-net.co.jp><br />
To: "HIMITSU@genesis-net.co.jp" <HIMITSU@genesis-net.co.jp><br />
Content-Type: text/plain; charset=ISO-2022-JP; format=flowed; delsp=yes<br />
Content-Transfer-Encoding: 7bit<br />
○○ さん<br />
お疲れ様です。遠藤です。<br />
<span style="color: red;">2015年07月28日の日報を送付します。</span><span style="color: red;"><br /></span><span style="color: red;">【稼働時間】</span><span style="color: red;">・09:00~18:00 (08:00h)</span><span style="color: red;"><br /></span><span style="color: red;">【概要】</span><span style="color: red;">・実装:08:00h</span><span style="color: red;"><br /></span><span style="color: red;">【詳細】</span><span style="color: red;"> 報告内容がズラズラっと。</span><span style="color: red;"><br /></span><span style="color: red;">【連絡事項】</span><span style="color: red;">・7/31(金):帰社</span><span style="color: red;"><br /></span><span style="color: red;">以上、よろしくお願いします。</span><br />
--<br />
================================================<br />
遠藤 太志郎<br />
株式会社ジェニシス技術開発事業部@春日<br />
Mail:endo@genesis-net.co.jp<br />
歯科医院予約管理システムDentNet facebook<br />
http://www.facebook.com/dentnet.genesis<br />
株式会社ジェニシス技術開発事業部ブログ<br />
http://genesis-tdsg.blogspot.jp/<br />
================================================</blockquote>
</div>
<div>
<br /></div>
<div>
解析が必要な部分は赤文字の部分だけです。従って、</div>
<div>
<br /></div>
<div>
<ul>
<li>お疲れ様です。</li>
<li>以上、よろしくお願いします。</li>
</ul>
</div>
<div>
<br /></div>
<div>
この2つのキーワードを「開始」と「終了」の目印として使うことが出来そうです。</div>
<div>
<br /></div>
<div>
まあ、私のメールだからこんなやり方でフィルタリングできますが、もっと形態不明なメールを解析するのであれば、違う目印が必要になるでしょうね。</div>
<div>
<br /></div>
<div>
今はテキストベースでやっていますからこういうやり方ですが、ちゃんと環境を整えれば「ヘッダー」と「ボディ」を見分けるくらい出来ると思います。<br />
<br />
その条件で、ファイルの文中から解析したい部分だけを切り取るロジックがこちら。</div>
<div>
<br /></div>
<div>
<pre class="prettyprint linenums">def read_content(file):
flg = False;
content = ''
for line in open(os.path.join(dirPath, file), 'r', encoding='ISO-2022-JP'):
if line.find('以上、よろしくお願いします。') == 0:
flg = False
if flg:
content = content + line
else:
if line.find("お疲れ様です。") == 0:
flg = True
return content
</pre>
</div>
<div>
<br /></div>
<div>
特筆することはありません。<br />
<br />
ただ、こういう文字列加工って<span style="color: red;">チョコチョコチョコチョコ</span>作業するものなんですよね。<br />
Pythonというのは、この<span style="color: blue;">チョコチョコ作業に向いている</span>性質があると思います。<br />
<br />
言語の向き、不向きを肌感触で知っていることは重要だと思いますね。<br />
<br />
文字列が構築出来ましたら、後はそれをJSONに組み込んで送り込むだけです。<br />
<br />
<pre class="prettyprint linenums">def send_request(content, file):
# 送信先URL
url = "https://language.googleapis.com/v1/documents:analyzeEntities?key=himitsu"
# 送信するJSONパラメータ
body = {
'document': {
'type': 'PLAIN_TEXT',
'content': content
},
'encodingType': 'UTF8'
}
body = json.dumps(body).encode("utf-8")
# リクエストヘッダー
header = {
"content-type": "application/json"
}
# リクエストメソッド
method = "POST"
try:
# 送信実行
request = urllib.request.Request(url, data=body, headers=header)
with urllib.request.urlopen(request) as response:
# 結果を出力
response_body = response.read().decode("utf-8")
print("レスポンスを受信しました。")
print(response_body)
f = open(os.path.join(exportPath, file + '.json'), 'w') # 書き込みモードで開く
f.writelines(response_body)
f.close()
except urllib.error.HTTPError as e:
# エラーだった場合、エラー原因を出力
print('ERROR!!')
print(e.code)
print(e.read())
</pre>
<br />
<br />
特筆するべきは、JSONの構築箇所です。<br />
<br />
<pre class="prettyprint linenums"> # 送信するJSONパラメータ
body = {
'document': {
'type': 'PLAIN_TEXT',
'content': <span style="color: red;">content</span>
},
'encodingType': 'UTF8'
}
</pre>
<br />
これ。
<br />
<span style="color: red;">content</span>が上記で構築した変数ですが、このように、JSONの構造が見える状態で形成することが出来ました。</div>
<div>
<br /></div>
<div>
<ul>
<li>"body = {" + {\'document\': {" + "\'content' + content ……</li>
</ul>
<br />
みたいな<b><span style="color: blue;">エスケープ文字の羅列だと読めないですからね!!</span></b></div>
<div>
このようにJSONをJSONとして取り扱い出来ることが大変すばらしいです。</div>
<div>
<br /></div>
<div>
後はリクエストを送り、受領したレスポンスをファイルに一時保存すれば終わり。<br />
<br />
<pre class="prettyprint linenums">f = open(os.path.join(exportPath, file + '.json'), 'w') # 書き込みモードで開く
f.writelines(response_body)
f.close()
</pre>
<br />
ファイルの書き込みはこれでOKです。<br />
<br />
<h2>
終わりに</h2>
これでズラーッと解析結果を取得出来ました。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-7LBHkGmpHV0/WopsG8VF0II/AAAAAAAACiA/AFNxENoIlQMJrOleFXpSSYciDK5RpQC7gCLcBGAs/s1600/WS000000.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="305" data-original-width="825" height="147" src="https://2.bp.blogspot.com/-7LBHkGmpHV0/WopsG8VF0II/AAAAAAAACiA/AFNxENoIlQMJrOleFXpSSYciDK5RpQC7gCLcBGAs/s400/WS000000.JPG" width="400" /></a></div>
<br />
後は、この結果ファイル一覧を読み込んで、どんなデータが入っているか見てみようと思います。<br />
<br /></div>
Anonymousnoreply@blogger.com0tag:blogger.com,1999:blog-5306057209591512828.post-27320549421224882442018-02-05T19:01:00.000+09:002018-03-23T17:46:17.040+09:00【Googleクラウド・機械学習編】日報解析バッチ作成中2~ファイル読み込み~株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。<br />
<br />
最近は機械学習について勉強中です。<br />
現在はGoogleの機械学習API「CLOUD NATURAL LANGUAGE API」の検証と、Pythonの勉強を並行して進行しています。<br />
<br />
初心者の勉強として、簡単なバッチを作っていきたいと思います。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-3YUURn_N7UA/Wm17dFnUkNI/AAAAAAAACdE/ysNQ2GpfyRslybcuvlLAvUfJDV0kU2VYQCLcBGAs/s1600/WS000000.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="848" data-original-width="904" height="300" src="https://4.bp.blogspot.com/-3YUURn_N7UA/Wm17dFnUkNI/AAAAAAAACdE/ysNQ2GpfyRslybcuvlLAvUfJDV0kU2VYQCLcBGAs/s320/WS000000.JPG" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<h2>
ファイル読み込み</h2>
<div>
今回はローカルPC内に置いたファイルを読み込むところまで進めたいと思います。</div>
<div>
<br /></div>
<div>
まず、メールをローカルPCに置きます。</div>
<div>
<br /></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-Sxu88UxfR1o/WngdfkmWkcI/AAAAAAAACe4/w6ITmg75bMAUXB2WawLpvBWs74bDIUPpACLcBGAs/s1600/WS000000.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="757" data-original-width="1258" height="192" src="https://1.bp.blogspot.com/-Sxu88UxfR1o/WngdfkmWkcI/AAAAAAAACe4/w6ITmg75bMAUXB2WawLpvBWs74bDIUPpACLcBGAs/s320/WS000000.JPG" width="320" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
「C:/MyMail/【日報】遠藤_20160201 - 'endo@genesis-net.co.jp' (endo@genesis-net.co.jp) - 2016-02-02 0650.eml」</div>
<div>
<br /></div>
<div>
こんなようなパスのファイルが沢山置かれました。</div>
<div>
<br /></div>
<div>
では、まずはファイル1コを読み込んでみましょう。</div>
<div>
<br /></div>
<h3>
ファイル読み込み:1コ</h3>
<div>
このファイルを読み込むソースはコレです。<br />
<br /></div>
<pre class="prettyprint linenums">filePath = "C:/MyMail/【日報】遠藤_20160201 - 'endo@genesis-net.co.jp' (endo@genesis-net.co.jp) - 2016-02-02 0650.eml"
for line in open(filePath, 'r',encoding='ISO-2022-JP'):
print(line)
</pre>
<br />
<span style="color: blue;">この簡単さよ。
</span><br />
<span style="color: blue;"><br /></span>
実質2行でファイルを全部開けます。<br />
<br />
調べたところ、上記の書き方はCLOSE処理も自動的に行ってくれているようですね。<br />
意識的にクローズしたい場合は、こちら。<br />
<br />
<pre class="prettyprint linenums">filePath = "C:/MyMail/【日報】遠藤_20160201 - 'endo@genesis-net.co.jp' (endo@genesis-net.co.jp) - 2016-02-02 0650.eml"
f = open(filePath, 'r',encoding='ISO-2022-JP')
for line in f:
print(line)
f.close()
</pre>
<br />
たぶん、読み込み処理だったら上記の書き方だけで大概は解決するんじゃないかな?<br />
ファイルを読む時って、特別な理由が無い限りは頭からお尻まで全部読み込んでしまうものですからね。<br />
<br />
今回は登場しませんが、書き込み処理だったら自分でクローズする必要がありそうです。<br />
<br />
<span style="color: blue;"><b>ファイルを開くことよりもクローズすることを気にする</b></span>辺りに、私の玄人ぶりを察して頂ければと思います。<br />
<br />
「r」とは、読み込みモードで開くという意味です。<br />
「書き込みモード」「追加書き込みモード」「読み書き両用モード」などいくつかあるようですね。<br />
<br />
「読み書き両用モード」というのは、何が起きるか分からないので私はオススメ出来ませんが。<br />
同じファイルを読み書きしたいのであれば、専用モードで毎回開きなおすのが正しいと思いますが、必要なシチュエーションもあるのかもしれませんね。<br />
<br />
「encoding='ISO-2022-JP'」は、もちろん文字エンコーディングです。<br />
デフォルトはUTF-8なので、何も指定しなければもちろん文字化けします。<br />
<br />
<br />
ファイル読み込みについては以上です。<br />
実に簡単でしたね。<br />
<br />
<h3>
ファイル読み込み:全部</h3>
次に、フォルダ内のファイル全部読み込みに行ってみましょう。<br />
<br />
<pre class="prettyprint linenums">import os
dirPath = 'C:/MyMail'
files = os.listdir(dirPath)
for file in files:
for line in open(os.path.join(dirPath,file), 'r',encoding='ISO-2022-JP'):
print(line)
</pre>
<br />
まず、以下の部分が特定フォルダ配下の<b><span style="color: blue;">ファイル名</span></b>の一覧を取得する処理です。<br />
<br />
<ul>
<li>files = os.listdir(dirPath)</li>
</ul>
<div>
<br /></div>
<div>
ここで一つ気になったのは、Javaで言うところの「File型」とかそういうのではなく、単にファイル名の文字列が配列でぶっこまれているだけということですね。</div>
<div>
<br /></div>
<div>
だから、配列をループで回して読み込む際は、以下のようにファイルを絶対パスに直さなければならないのです。<br />
それが「join」です。</div>
<div>
<br />
<ul>
<li>os.path.join(dirPath,file)</li>
</ul>
<div>
<br /></div>
<div>
要するに「ディレクトリパス」+「/」+「ファイル名」という結合を行っているのですが、「/」の部分はOSで差があったりしますからね。</div>
<div>
その辺をクールに処理してくれるのが「join」なのです。</div>
<div>
<br /></div>
<div>
では、「毎回joinしてフルパスを構築せねばならんのか?」と言いますと、それとは別にglobという書き方があります。</div>
<div>
<br /></div>
<div>
<pre class="prettyprint linenums">import glob
dirPath = 'C:/MyMail/*'
files = glob.glob(dirPath)
for file in files:
for line in open(file, 'r',encoding='ISO-2022-JP'):
print(line)
</pre>
</div>
</div>
<br />
dirPathを正規表現で記載することで、ファイルを絶対パスで一覧取得する機能です。<br />
どちらが良いかはお好みで良いでしょう。<br />
<br />
いずれにせよ、取得するのは「File型」ではなく「パス文字列」という点に、私は着目します。<br />
<span style="color: blue;">処理が軽量</span>なんですね。<br />
<br />
Pythonは処理速度が速いことが一つの売りですが、その鱗片がこういうところに垣間見えます。<br />
<br />
ともかく、後は取得した一覧をグルーッと回していくだけです。<br />
<br />
<br />
<pre class="prettyprint linenums">for file in files:
for line in open(os.path.join(dirPath,file), 'r',encoding='ISO-2022-JP'):
print(line)</pre>
<br />
<br />
Pythonはこのように処理の開始と終了を{}ではなくてインデントで表現するのが特徴です。<br />
こんな書き方をする理由としては、例えばfor文一つを書くだけでも、<br />
<br />
<pre class="prettyprint linenums">for(){
</pre>
<br />
<pre class="prettyprint linenums">for()
{
</pre>
<br />
と「{」が同じ行にあるか違う行にあるかどうかで<b><span style="color: red;">宗教戦争</span></b>が起きてしまうことを回避する為の作戦だそうです。<br />
<b><span style="color: blue;">誰が書いても似たようなソースになる</span></b>ということを目指した結果です。<br />
<br />
しかし、<br />
<br />
<b><span style="color: red;">「いくら理由があるにしたって、インデントで表現するかよ、普通?」</span></b><br />
<br />
って思いますよね?<br />
思ってたんですけど、<span style="color: blue;"><b>実装してみると全然気になりません。</b></span><br />
<br />
むしろ見易いとさえ思います。<br />
目からウロコが落ちました。<br />
<br />
可読性の高い言語だ、という実感があります。<br />
良い言語です。<br />
<br />
<h2>
終わりに</h2>
<div>
今回は単にファイルを開くだけという簡単な内容でしたが、Pythonの入門としては上々の滑り出しだと感じています。</div>
<div>
<br /></div>
<div>
最初はみんな初心者ですからね。</div>
<div>
簡単なところから慣れ親しんでいきたいと思います。</div>
Anonymousnoreply@blogger.com0tag:blogger.com,1999:blog-5306057209591512828.post-31353553536544832672018-01-29T18:23:00.000+09:002018-03-23T17:46:40.234+09:00【Googleクラウド・機械学習編】日報解析バッチ作成中1株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。<br />
<br />
最近は機械学習について勉強中です。<br />
現在はGoogleの機械学習API「CLOUD NATURAL LANGUAGE API」の検証と、Pythonの勉強を並行して進行しています。<br />
<br />
<h2>
現状</h2>
「CLOUD NATURAL LANGUAGE API」の「analyzeEntities」は、文章の構文解析です。<br />
<div>
文章中から特徴のあるキーワードを抽出することが可能です。</div>
<div>
<br /></div>
<div>
前にちょっと実験してみた結果がこちらに載っています。</div>
<div>
<br /></div>
<div>
<ul>
<li><a href="https://genesis-tdsg.blogspot.jp/2017/12/googlecloud-natural-language-api.html" target="_blank">https://genesis-tdsg.blogspot.jp/2017/12/googlecloud-natural-language-api.html</a></li>
</ul>
<div>
<br /></div>
</div>
<div>
しかしこれ、現状だと何の役にも立ちません。</div>
<div>
<br /></div>
<div>
新技術全般によくあることなのですが、</div>
<div>
<br /></div>
<div>
「技術的な意味は分かった。」</div>
<div>
<span style="color: red;"><b>「それが一体何の役に立つのか?」</b></span></div>
<div>
<br /></div>
<div>
という状況に陥ってしまいます。<br />
<br /></div>
<div>
通常の業務だとこうです。</div>
<div>
<br /></div>
<div>
<ul>
<li>先に案件が存在する。⇒それに必要な技術を習得する。</li>
</ul>
</div>
<div>
<br /></div>
<div>
しかし、新技術の領域だと「案件」なんかありませんので、こうなります。</div>
<div>
<br /></div>
<div>
<ul>
<li>とりあえず技術だけ覚える。⇒後で何か使い道が無いか考える。</li>
</ul>
</div>
<div>
<br />
<span style="color: red;"><b>使い道は自分で考えなければなりません。</b></span><br />
過酷な道ですが、そこは楽しくやっていきましょう。</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<h2>
使い道探し</h2>
</div>
<div>
そして使い道を考えてみました。</div>
<div>
このAPIは「文章解析」ですから、インプットとなる文章を調達することが最初の課題となります。</div>
<div>
<br /></div>
<div>
一番の大本命は、弊社サービスのDentNet(デントネット)</div>
<div>
<br /></div>
<div>
<ul>
<li><a href="http://www.dentnet.org/" target="_blank">http://www.dentnet.org/</a></li>
</ul>
</div>
<div>
<br /></div>
<div>
歯科医院向けのWebシステムでして、「歯科医院からのアンケート」とか「電話サポートの記録」とか、そういうのを入手して解析を行うのが一番の使い道です。</div>
<div>
<br /></div>
<div>
しかし、それを行う場合、本来の仕事をしている営業チームやサポートチームの時間を割いて貰わなければならなくなってしまうので、話が大きくなり過ぎます。</div>
<div>
<br /></div>
<div>
もっと手元にある情報で、かつ文章形式の情報が望ましいです。</div>
<div>
<br /></div>
<div>
ありますね。</div>
<div>
<br /></div>
<div>
サラリーマンの必需品、<b><span style="color: red;">メール</span></b>です。</div>
<div>
<br /></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-Aesx7TWqo_g/Wm12il27KwI/AAAAAAAACco/eWrlG1lqBecySdiA9MUN8lfDtawvybjTACLcBGAs/s1600/%25E6%2597%25A5%25E5%25A0%25B1.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="501" data-original-width="1294" height="153" src="https://3.bp.blogspot.com/-Aesx7TWqo_g/Wm12il27KwI/AAAAAAAACco/eWrlG1lqBecySdiA9MUN8lfDtawvybjTACLcBGAs/s400/%25E6%2597%25A5%25E5%25A0%25B1.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
私の所属する技術開発事業部は<b><span style="color: blue;">「日報」</span></b>という形式で毎日の終わりに上長に業務報告を行います。</div>
<div>
(宛先は上長ですが、メールは全員に届きます。)</div>
<div>
<br /></div>
<div>
日報の形式はフリーフォーマットの文章でして、報告する人が報告したい内容を書く運用になっています。</div>
<div>
<br /></div>
<div>
部員はそれを見て、「ああ、あの人はそんな仕事をやっているんだな」「アイツ、最近忙しそうだな」みたいな事を思うわけですね。</div>
<div>
<br /></div>
<div>
今のところは日報は<b><span style="color: blue;">今日の話を見るだけ</span></b>の運用ですが、構文解析APIを実行して過去に遡って大量データを解析すると、<span style="color: blue;"><b>頻出登場単語</b></span>とかが浮かび上がってくるかもしれません。</div>
<div>
<br /></div>
<div>
日報という不定形の文章を、何とか定量化して、数値根拠のある指標に転換することが出来ないだろうか……。</div>
<div>
<br /></div>
<div>
そう考えまして、私はこれから<span style="color: blue;"><b>「日報解析バッチ」</b></span>を作ろうと思います。</div>
<div>
<br /></div>
<div>
<h2>
実現イメージ</h2>
</div>
<div>
日報解析バッチの実現イメージはこちらです。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-3YUURn_N7UA/Wm17dFnUkNI/AAAAAAAACdE/ysNQ2GpfyRslybcuvlLAvUfJDV0kU2VYQCLcBGAs/s1600/WS000000.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="848" data-original-width="904" height="300" src="https://4.bp.blogspot.com/-3YUURn_N7UA/Wm17dFnUkNI/AAAAAAAACdE/ysNQ2GpfyRslybcuvlLAvUfJDV0kU2VYQCLcBGAs/s320/WS000000.JPG" width="320" /></a></div>
<div>
<br /></div>
<h4>
1.メールの取得</h4>
<div>
メールサーバから解析対象のメールをテキストファイルとして手動ダウンロードします。</div>
<div>
バッチ自体が通信してメールを取得する機能は省略します。</div>
<div>
(高機能を言い出したらキリが無い。最小限の機能で形を作ります)</div>
<div>
<br /></div>
<div>
<h4>
2.リクエスト実行</h4>
</div>
<div>
日報解析バッチにて実現。メールを構文解析APIに送り込みます。</div>
<div>
「ローカルフォルダの中に置いてあるテキスト形式のメールを全部送る」という形で、まとまった単位で送信したいと思います。</div>
<div>
<br /></div>
<div>
<h4>
3.レスポンス取得</h4>
</div>
<div>
日報解析バッチにて実現。構文解析APIからのレスポンスを受信します。</div>
<div>
レスポンスはJSON形式になっていますが、JSONだけベロッと出されても意味不明ですので、</div>
<div>
バッチにて正規化して意味が読み取れる形に整形します。</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<b>4.ドキュメント化</b></div>
<div>
<br /></div>
<div>
最後に、人様にお見せ出来るよう表形式に整えて完了です。</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
日報解析バッチはPythonで作ります。</div>
<div>
Python初心者の学習記録も兼ねていきたいと思います。</div>
<div>
<br /></div>
<h2>
次回</h2>
<div>
次回から実装に入っていきます。</div>
<div>
最初は「ローカルフォルダの中に置いてあるテキスト形式のメールを読み込む」というファイルIOからです。</div>
<div>
<br /></div>
<div>
ソースは既に手元にありますが、Pythonならではの簡略で綺麗なソースに仕上がっています。</div>
Anonymousnoreply@blogger.com0tag:blogger.com,1999:blog-5306057209591512828.post-58580604958727169502018-01-22T12:19:00.000+09:002018-03-23T17:47:01.296+09:00【Googleクラウド・機械学習編】Python3でJSONパラメータをpost送信する2株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。<br />
<br />
最近流行の機械学習について勉強中です。<br />
<br />
今回は<a href="https://www.blogger.com/blogger.g?blogID=5306057209591512828&pli=1#editor/target=post;postID=1782030579003689544;onPublishedMenu=allposts;onClosedMenu=allposts;postNum=0;src=postname" target="_blank">前回</a>の後編として、<span id="goog_253727683"></span>Googleクラウドの「CLOUD NATURAL LANGUAGE API」にPythonでリクエストを送りたいと思います。<br />
<br />
<h2>
ソース</h2>
<div>
結論から行きますと、このソースでリクエスト送信に成功しました。</div>
<pre class="prettyprint linenums">import urllib.request
import urllib.parse
import json
#送信先URL
url="https://language.googleapis.com/v1/documents:analyzeEntities?key={My_API_KEY}"
#送信するJSONパラメータ
body = {
'document': {
'type': 'PLAIN_TEXT',
'content': '株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。\n\n仕事はシステムエンジニア。\n特技は空手道初段です。\n\n家族は妻が一名ほどいます。\n\n好きなお酒はウイスキーです。\n\n仲良くして下さい。'
},
'encodingType': 'UTF8'
}
#JSONパラメータをバイト変換
body = json.dumps(body).encode("utf-8")
#リクエストヘッダー
header = {
"content-type": "application/json"
}
try:
#送信実行
request = urllib.request.Request(url, data=body, headers=header)
with urllib.request.urlopen(request) as response:
#結果を出力
response_body = response.read().decode("utf-8")
print(response_body)
except urllib.error.HTTPError as e:
#エラーだった場合、エラー原因を出力
print('ERROR!!')
print(e.code)
print(e.read())
</pre>
<h2>
解説</h2>
<div>
これが私の初めてのPythonでしたが、ふむ、確かに最近注目を集めるだけのパワーがあるものだと思います。</div>
<div>
<br /></div>
<div>
イチオシの点を上げていきます。</div>
<div>
<br /></div>
<h3>
リクエスト送信の簡単さ</h3>
<div>
この処理の中でリクエスト送信を行っている箇所はここです。<br />
<br /></div>
<pre class="prettyprint linenums"> #送信実行
request = urllib.request.Request(url, data=body, headers=header)
</pre>
<div>
<br /></div>
<div>
<br /></div>
<div>
headerやbodyの加工という前処理は別ですが、送信実行するだけなら僅か1行。<br />
<br />
これをJavaで表現すると、大体こんな感じ。</div>
<pre class="prettyprint linenums"> URL url = new URL(urlstr);
HttpURLConnection connection = null;
DataOutputStream dos = null;
try {
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoInput(true);
connection.setDoOutput(true);
dos = new DataOutputStream(connection.getOutputStream());
Map<string string=""> postParamMap = getPostParamMap();
StringBuilder buls = new StringBuilder();
if (postParamMap != null) {
for (String key : postParamMap.keySet()) {
buls.append(key);
buls.append("=");
buls.append(postParamMap.get(key));
buls.append("&");
}
}
dos.writeBytes(buls.substring(0, buls.length() - 1));
StringBuilder bul = new StringBuilder();
try (InputStreamReader isr = new InputStreamReader(
connection.getInputStream(), StandardCharsets.UTF_8);
BufferedReader reader = new BufferedReader(isr)) {
String line;
while ((line = reader.readLine()) != null) {
bul.append(line);
bul.append(System.lineSeparator());
}
return bul.toString();
}
} finally {
if (dos != null) {
dos.close();
}
if (connection != null) {
connection.disconnect();
}
}
</string></pre>
<div>
<br />
DataOutputStreamとかBufferedReaderとかConnectionとか、最後にclose?<br />
ハッキリ言って<span style="color: red;"><b>「知らんわ!!」</b></span>としか言いようが無い宣言の嵐。<br />
<br /></div>
<div>
比べて「request = urllib.request.Request(url, data=body, headers=header)」で済むこのPythonの簡潔さは特筆するべきものと言えるでしょう。<br />
<br />
私はWebAPIこそがWebシステムの理想形だと考えています。<br />
<br />
インターネット=パソコンだった昔と違い、今ではスマホやタブレットなど様々な端末から参照出来ることが求められている時代ですからね。<br />
<br />
MVCモデル(モデル、ビュー、コントローラ)のうち、モデルとコントローラを完全に切り離してWebAPIに設置し、ビュー側は、「パソコン用」「スマホ用」「タブレット用」など、個別に開発する。<br />
<br />
これが今の時代に求められる<span style="color: blue;"><b>マルチ端末対応</b></span>の最適解です。<br />
<br />
つまり、WebAPIへのリクエスト送信に強い言語は、即ち時代の覇者であるのです。<br />
Pythonはその点を良く分かっている言語と言えるでしょう。<br />
<br />
<h3>
JSON定義</h3>
Pythonが便利な点はまだあります。<br />
<br />
<pre class="prettyprint linenums">body = {
'document': {
'type': 'PLAIN_TEXT',
'content': '株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。\n\n仕事はシステムエンジニア。\n特技は空手道初段です。\n\n家族は妻が一名ほどいます。\n\n好きなお酒はウイスキーです。\n\n仲良くして下さい。'
},
'encodingType': 'UTF8'
}
</pre>
<b><br /></b>
<span style="color: blue;"><b>JSONが直接定義出来る。</b></span><br />
<br />
良いですか?<br />
「JSON形式の文字列を読み込む」じゃないです。<br />
JSONそのものを定義しているのです。<br />
<br />
「JSON形式の文字列を読み込む」だったらこう書くことになります。<br />
<br />
<pre class="prettyprint linenums">body = "{
\'document\': {
\'type\': \'PLAIN_TEXT\',
\'content\': \'株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。\n\n仕事はシステムエンジニア。\n特技は空手道初段です。\n\n家族は妻が一名ほどいます。\n\n好きなお酒はウイスキーです。\n\n仲良くして下さい。\'
},
\'encodingType\': \'UTF8\'
}"
</pre>
<br />
<b><span style="color: red;">「エスケープ文字「\」が邪魔くせえ」</span></b>という地味だけど面倒な問題点がPytonでは解消されているのです。<br />
<br />
可読性が大変高くなっています。<br />
データ定義にJSONを使うのは今や常識。<br />
<br />
<div>
Pythonは良く分かっていますね。</div>
<div>
<br /></div>
<h3>
JSONバイト変換</h3>
<div>
実装中にハマってしまったのがココです。</div>
<div>
<pre class="prettyprint linenums">#JSONパラメータをバイト変換
body = json.dumps(body).encode("utf-8")
</pre>
<br />
HTTPリクエストを送り込む前に、JSONをバイト変換しなければならない。<br />
当然と言えば当然なのですが、ネット上に情報が錯綜していましてね、エラーの原因が分からず非常に苦労しました。<br />
<br />
エラーハンドリングの奮闘記を記載させて頂きましょう。<br />
<br />
まず、バイト変換しない場合です。<br />
上記の「json.dumps(body).encode("utf-8")」を消すと、以下のようになエラーが出てしまいます。<br />
<br />
<pre class="prettyprint linenums">Traceback (most recent call last):
File "C:/Users/endo/PycharmProjects/Test/postjson.py", line 30, in <module>
with urllib.request.urlopen(request) as response:
File "C:\Python\Python36-32\Lib\urllib\request.py", line 223, in urlopen
return opener.open(url, data, timeout)
File "C:\Python\Python36-32\Lib\urllib\request.py", line 526, in open
response = self._open(req, data)
File "C:\Python\Python36-32\Lib\urllib\request.py", line 544, in _open
'_open', req)
File "C:\Python\Python36-32\Lib\urllib\request.py", line 504, in _call_chain
result = func(*args)
File "C:\Python\Python36-32\Lib\urllib\request.py", line 1361, in https_open
context=self._context, check_hostname=self._check_hostname)
File "C:\Python\Python36-32\Lib\urllib\request.py", line 1318, in do_open
encode_chunked=req.has_header('Transfer-encoding'))
File "C:\Python\Python36-32\Lib\http\client.py", line 1239, in request
self._send_request(method, url, body, headers, encode_chunked)
File "C:\Python\Python36-32\Lib\http\client.py", line 1285, in _send_request
self.endheaders(body, encode_chunked=encode_chunked)
File "C:\Python\Python36-32\Lib\http\client.py", line 1234, in endheaders
self._send_output(message_body, encode_chunked=encode_chunked)
File "C:\Python\Python36-32\Lib\http\client.py", line 1064, in _send_output
+ b'\r\n'
TypeError: can't concat str to bytes
</module></pre>
<br />
<br />
<br />
<ul>
<li>can't concat str to bytes</li>
</ul>
<br />
<br />
<span style="color: blue;"><b>「文字列をバイトに変換してからじゃないとHTTP送信出来ねえよ」</b></span>というエラーログが出ます。<br />
当たり前ですね。<br />
<br />
次の罠がこちら。<br />
<br />
<pre class="prettyprint linenums">#JSONパラメータの間違った変換
body = urllib.parse.urlencode(body).encode(encoding='utf-8')
</pre>
<br />
これ。
<br />
<br />
<ul>
<li>urllib.parse.urlencode(body).encode(encoding='utf-8')
</li>
</ul>
<br />
「urllib.parse.urlencode(body).encode(encoding='utf-8')」はNGです。<br />
<br />
「urllib.parse.urlencode(body).encode(encoding='utf-8')」は、どうやらJSONをJSONではなく「普通の文字列」としてエンコードしてしまうみたいなんですよ。<br />
<br />
<span style="color: red;"><b>urllib.parse.urlencode(body).encode(encoding='utf-8')<span style="color: red;">した瞬間に、JSONはJSONではなく、単なる変な文字列になってしまう。</span></b></span><br />
<br />
なのでWebサーバ側のバリデーションチェックでエラーになってしまう。<br />
<br />
<pre class="prettyprint linenums">ERROR!!
400
b'{\n "error": {\n "code": 400,\n "message": "Invalid JSON payload received. Unexpected token.\\ndocument=%7B%27type%\\n^",\n "status": "INVALID_ARGUMENT"\n }\n}\n'
</pre>
<br />
<br />
だから、JSONのエンコードはこっち。<br />
<br />
<br />
<ul>
<li>json.dumps(body).encode("utf-8")</li>
</ul>
<br />
<br />
JSONではない汎用エンコードはこっち。<br />
<br />
<ul>
<li>urllib.parse.urlencode(body).encode(encoding='utf-8')</li>
</ul>
</div>
<br /></div>
<div>
私が調べた限り、現在のネット情報だと「JSONのPOST送信とそれ以外のPOST送信は違いますよ」ってことがハッキリ書いている所が見つからなかったです。<br />
理解した今となっては分かりますが、最初は両者の違いが分かりませんでした。<br />
<br />
だから後者の汎用エンコードのサイトを見ていると「あれ? ちゃんとエンコードしているのにエラーになる。変だなぁ?」とハマッてしまう。<br />
これは要注意です。<br />
<br />
<span style="color: red;"><b>Pytonでは、JSONのPOST送信とそれ以外のPOST送信ではエンコードのやり方が違います。</b></span><br />
<br />
要注意です。<br />
<br /></div>
<div>
<h2>
終わりに</h2>
</div>
<div>
ともかく、これでWebAPIの一番の難関である<b><span style="color: blue;">「疎通確認」</span></b>は成功しました。</div>
<div>
<br /></div>
<div>
ここから先は色々なデータを流し込んで「CLOUD NATURAL LANGUAGE API」の能力を見てみたいと思います。</div>
Anonymousnoreply@blogger.com0tag:blogger.com,1999:blog-5306057209591512828.post-17820305790036895442018-01-09T12:46:00.000+09:002018-03-23T17:19:20.285+09:00【Googleクラウド・機械学習編】Python3でJSONパラメータをpostする株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。
<br />
<br />
2018年になりました。本年も宜しくお願いします。
<br />
<br />
さて、2017年から引き続き、最近流行の機械学習について勉強中です。<br />
<br />
<h2>
リクエスト送信プログラム作成</h2>
<div>
<br /></div>
<div>
さて、現在はGoogleクラウドの「CLOUD NATURAL LANGUAGE API」を検証中なわけですが、</div>
<div>
その為には<b><span style="color: red;">「リクエスト送信プログラム」</span></b>を作らなければなりません。</div>
<div>
<br /></div>
<div>
ちょっと実行するだけならネット上に転がっているリクエスト送信支援ツールを使えば良いですが、</div>
<div>
手元の大量データを送り込んだりとか、独自のカスタマイズを施す為には自前開発が必要不可欠です。</div>
<div>
<br /></div>
<div>
私はJavaエンジニアですので、プログラムもJavaで作るのが一番簡単な道です。</div>
<div>
アンドロイドアプリでWebAPIのリクエストプログラムとか作ったこともありますし。</div>
<div>
しかし、新年も始まったことですし、ここは<span style="color: blue;"><b>志を高く</b></span>持って<span style="color: magenta;"><b>Python</b></span>で作ることにチャレンジしていきたいと思います。</div>
<div>
<br /></div>
<div>
<h2>
作成プログラム</h2>
</div>
<div>
<br /></div>
<h3>
目標</h3>
<div>
<br /></div>
<div>
CLOUD NATURAL LANGUAGE APIに対する最も基本的な疎通確認レベルのPOST送信。</div>
<div>
<br /></div>
<div>
<h3>
条件</h3>
</div>
<div>
<br /></div>
<div>
言語はPythonとする。バージョンは3。</div>
<div>
<br /></div>
<div>
結論を言いますと、<span style="color: red;"><b>もの凄く苦労しました。</b></span></div>
<div>
この記事はJavaだったら30分で作れたはずのプログラムを6時間も悪戦苦闘した奮闘記となります。</div>
<div>
<br /></div>
<div>
<h2>
Python開発の困難点</h2>
</div>
<div>
<br /></div>
<h3>
1.Python2の情報が混ざっている</h3>
<div>
<br /></div>
<div>
前の記事で書きましたが、Pythonは<b><span style="color: red;">「Python2」と「Python3」で互換性がありません。</span></b></div>
<div>
<br /></div>
<div>
JavaだったらJava1.5で書いたソースは概ねJava8でも動作します。</div>
<div>
(完全互換ではないのはミソ。以前に予約後の問題でJavaのバージョンを上げたら動かなくなったことがありました。とはいえ、殆どOKなので苦労はしません)</div>
<div>
<br /></div>
<div>
Pythonの場合は全然ダメです。</div>
「バージョン間で互換性」は、まあハッキリ言って程度問題でして、「完全互換を保証するものではないが、大体は流用OK」くらいの言語が多いです。<br />
<br />
<div>
でも、Python2とPython3は<b><span style="color: blue;">雰囲気が似ているだけの別物</span></b>というくらい全然動きません。</div>
<div>
そして、伝統的にはPython2が長く使われており、Python3は最新鋭です。</div>
<div>
<br /></div>
<div>
よって、「Python post送信」とかで検索すると、Python2とPython3の情報が混ざって出てくるんです。</div>
<div>
私が必要としているのはPython3ですから、Python2の情報は罠でしか無い。</div>
<div>
これが厄介です。</div>
<div>
<br /></div>
<div>
ちなみに調べている中で偶然知ったのですが、<b><span style="color: magenta;">「Perlは互換性に強い」</span></b>そうですね。</div>
<div>
<br /></div>
<div>
Perl...<br />
相当古くから根付いている言語ですが、Perlは互換性が強い故に、何十年も前からサーバを引っ越ししつつ代々引き継がれているようなソースでも問題無く動くそうな。</div>
<div>
<br /></div>
<div>
「何十年も維持するプログラムだったらPerlが良い」</div>
<div>
<br /></div>
<div>
という記事を見ました。</div>
<div>
<br /></div>
<div>
なるほど。</div>
<div>
こういうブログをやっていると最新情報ばかりに目が行ってしまいますが、業務系システムでは恒久的保守をどう行っていくかも重要な能力です。<br />
<br /></div>
<div>
「古い技術であっても侮ってはならない」という教訓になりました。<br />
<br /></div>
<div>
<h3>
2.情報が少ない</h3>
</div>
<div>
<br /></div>
<div>
やっぱりですね、少ないですよ、情報が。</div>
<div>
無くは無いですが。</div>
<div>
<br /></div>
<div>
まず日本語の情報だけでは全然足りないので、<b><span style="color: blue;">英語情報に手を伸ばすことは当然</span></b>。</div>
<div>
しかし、英語情報も踏まえても、イマイチ必要な情報が見つからない。</div>
<div>
<br /></div>
<div>
JavaとかPHPとか、長年の蓄積がある言語と比べると、ネット上における情報量の差というものを肌で感じます。</div>
<div>
これは大きなリスクです。</div>
<div>
<br /></div>
<div>
仮に会社の案件としてPythonを採用したとすると、体制を構築するのは至難でしょう。</div>
<div>
<br /></div>
<div>
JavaとかPHPだともうネット上に情報が溢れているので誰でも何とかなるのですが、Pythonはそうは行きません。</div>
<div>
強力な少数精鋭の体制以外では対応出来ないと思います。</div>
<div>
<br /></div>
<div>
これをチャンスと見るか、リスクと見るかは見解が分かれる所だと思います。</div>
<div>
<br /></div>
<div>
<h3>
3.デタラメ</h3>
</div>
<div>
<br /></div>
<div>
これが一番厄介!!<br />
<br /></div>
<div>
ネットに<b><span style="color: red;">嘘が書いてある!!</span></b></div>
<div>
<br /></div>
<div>
嘘ではないにしても説明不足だったりとか、肝心な情報が抜けている記事が多い。</div>
<div>
(もしくは、昔はそのソースで動いたのかもしれませんが、今では動かないとか)<br />
<br />
情報源の少なさ故に淘汰されていないからなのでしょう。</div>
<div>
ネットの技術情報は<b><span style="color: blue;">量が質を生む</span></b>ものです。</div>
<div>
大量の情報が溢れかえって切磋琢磨し淘汰された結果、役に立つ情報が検索結果の上の方に来るのがネット界。</div>
<div>
<br /></div>
<div>
現在のPythonはまだ発展途上で、その段階に到っていません。<br />
ノイズでしかない情報が溢れている。</div>
<div>
これも大きなリスクです。</div>
<div>
<br /></div>
<div>
<h2>
成果物ソース</h2>
</div>
<div>
<br /></div>
そんなこんなで苦労しましたが、ひとまずリクエストの正常送信までは確認出来ております。<br />
<br />
<pre class="prettyprint linenums">import urllib.request
import urllib.parse
import json
#送信先URL
url="https://language.googleapis.com/v1/documents:analyzeEntities?key={My_API_KEY}"
#送信するJSONパラメータ
body = {
'document': {
'type': 'PLAIN_TEXT',
'content': '株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。\n\n仕事はシステムエンジニア。\n特技は空手道初段です。\n\n家族は妻が一名ほどいます。\n\n好きなお酒はウイスキーです。\n\n仲良くして下さい。'
},
'encodingType': 'UTF8'
}
#JSONパラメータをバイト変換
body = json.dumps(body).encode("utf-8")
#リクエストヘッダー
header = {
"content-type": "application/json"
}
try:
#送信実行
request = urllib.request.Request(url, data=body, headers=header)
with urllib.request.urlopen(request) as response:
#結果を出力
response_body = response.read().decode("utf-8")
print(response_body)
except urllib.error.HTTPError as e:
#エラーだった場合、エラー原因を出力
print('ERROR!!')
print(e.code)
print(e.read())
</pre>
どうです?<br />
私はこれを見ると「あっ、綺麗だな💛」と思います。<br />
<br />
Javaだったらもっとゴチャゴチャですもん。<br />
InputStreamだとか、OutputStreamだとか、close処理とか……。<br />
<br />
比べて、要は<br />
<br />
<br />
<ul>
<li>urllib.request.Request.urlopen(url, data=body, headers=header)</li>
</ul>
<br />
<br />
で完結するPythonは如何に綺麗か。<br />
<br />
確かによく洗練された言語だと思います。<br />
<br />
私はまだ使い始めたばかりですが、慣れれば確かに他の言語より使い勝手が良いんじゃないかな、という感触は感じられましたね。<br />
<br />
まとめますと、<br />
<br />
<br />
<ul>
<li>言語そのものが持つパフォーマンスは優れている。</li>
<li>枯れておらず、情報がまだ少ないのがリスク。</li>
</ul>
<br />
<br />
というのが私の所感です。<br />
<br />
なので、<br />
<br />
<br />
<ul>
<li>プロジェクトのメイン言語として採用するのはハイリスク過ぎる。</li>
<li>社内用のちょっとしたツール開発用なら、生産性も高くノウハウ蓄積にも適している。</li>
</ul>
<br />
<br />
こういう使い方でスキルアップしていきたいなぁ、と思うところです。<br />
<br />
<h2>
次回</h2>
<div>
<br /></div>
次回は上記ソースの解説と、作成過程で蹴躓いた箇所の説明、デバック解説です。<br />
<br />
同じ原因でハマっている人が検索から飛んできてくれたら嬉しいですね。Anonymousnoreply@blogger.com0tag:blogger.com,1999:blog-5306057209591512828.post-37375322981145014042017-12-25T12:27:00.003+09:002018-03-23T17:47:34.912+09:00【AndroidStudio】日本語化再び【完全版】株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。<br />
<br />
今回は臨時投稿。<br />
以前に連載していたAndroidStudioについて更新が発生したのでご連絡です。<br />
<br />
<h2>
【AndroidStudio】インストール&日本語化</h2>
<div>
2015年の記事「<a href="https://genesis-tdsg.blogspot.jp/2015/11/androidstudio_95.html" target="_blank">AndroidStudio】インストール&日本語化</a>」で、<br />
AndroidStudioの日本語化について試行錯誤しましたが、</div>
<div>
結論はと言うと<b><span style="color: red;">ダメ</span></b>でした。</div>
<div>
<br /></div>
<div>
AndroidStudioの日本語化は不完全。。。</div>
<div>
下手に日本語化するより英語でやった方がマシ。。。</div>
<div>
<br /></div>
<div>
と思っていましたが、いつの間にか日本語対応が完成していました。</div>
<div>
<br /></div>
<div>
<ul>
<li><a href="https://www.willbrains.jp/page/4" target="_blank">https://www.willbrains.jp/page/4</a></li>
</ul>
<div>
<br /></div>
</div>
<div>
日本の誇る日本語化アプリ「Pleiades」が対応して下さったようです。</div>
<div>
対応時期はどうやら<b>2017年6月末</b>だったの模様。</div>
<div>
<br /></div>
<div>
かなりの大幅アップデートだったようで、私が知っていたPleadesから相当な進化を遂げております。</div>
<div>
<br /></div>
<div>
日本語化手順は公式サイトを見れば分かるかと思いますが、一応、当ブログでもご紹介させて頂きたいと思います。</div>
<div>
<br /></div>
<div>
<h2>
【AndroidStudio】日本語化手順</h2>
</div>
<h3>
1.AndroidStudioのインストール</h3>
<div>
事前のAndroidStudioのインストールは省略します。</div>
<div>
普通にインストールして下さい。</div>
<div>
<h3>
2.Pleadesの取得</h3>
</div>
<div>
Pleadesの公式サイトよりプラグインをダウンロードします。</div>
<div>
<br /></div>
<div>
<ul>
<li><a href="http://mergedoc.osdn.jp/" target="_blank">http://mergedoc.osdn.jp/</a></li>
</ul>
</div>
<div>
<br /></div>
<div>
ここで注意ですが、ダウンロードするのは上にある「Pleiades All in One」ではなく、下にあるプラグインの方です。</div>
<div>
<br /></div>
<div>
ここがPleiadesの凄い所なのですが、Pleiadesは<b><span style="color: blue;">元々は</span><span style="color: blue;">Eclipse用に作られた日本語化ツールですが、AndroidStudioなどのIntelliJ系にも適応出来る</span></b>のです。</div>
<div>
<br /></div>
<div>
「AOP (横断的関心事を解決するテクノロジー)」 と言うそうです。<br />
「Java クラスローダーをフックし、クラスをバイトコードレベルで動的に書き換え……」とのことですが、完全に<b><span style="color: purple;">黒魔術</span></b>。<br />
私は性能測定ツールやモックツール等で<span style="color: purple;"><b>メタ領域</b></span>に突っ込んだ製品を見たことがあるので概念はある程度理解する所ですが、実装イメージが沸くほどには到底及びません。<br />
特殊技術の領域です。<br />
<br />
とは言え、使うだけなら単なるツールなので簡単です。</div>
<div>
<br /></div>
<div>
早速プラグインをダウンロードしてみましょう。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-qOSXaE7nZ2A/Wjj3y6iy1RI/AAAAAAAACTY/BP3yHxn0-LkUNI8BIsacIAbtVtEaubt6QCLcBGAs/s1600/WS000000.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="829" data-original-width="1600" height="206" src="https://4.bp.blogspot.com/-qOSXaE7nZ2A/Wjj3y6iy1RI/AAAAAAAACTY/BP3yHxn0-LkUNI8BIsacIAbtVtEaubt6QCLcBGAs/s400/WS000000.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<h3>
3.解凍</h3>
</div>
<div>
ダウンロードしたプラグインを解凍します。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-p1EaoAYcVWg/Wjj5rDc1X0I/AAAAAAAACTk/wJH0VB9q2WYlfSbXafzfrrSQllLUBlTNwCLcBGAs/s1600/WS000001.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="301" data-original-width="883" height="136" src="https://4.bp.blogspot.com/-p1EaoAYcVWg/Wjj5rDc1X0I/AAAAAAAACTk/wJH0VB9q2WYlfSbXafzfrrSQllLUBlTNwCLcBGAs/s400/WS000001.JPG" width="400" /></a></div>
<div>
<br />
昔は「features」と「plugins」しか無かったのですが、色々と増えました。<br />
これは<span style="color: red;"><b>革命的</b></span>なことです。<br />
Eclipseのプラグインなんてどれもこれも「features」と「plugins」だけがチョロっと入っているだけのチープなものばかりなんです。<br />
それ以外が含まれた豪華なパッケージなんて初めて見ました。<br />
<br /></div>
<div>
この中の「setup.exe」をダブルクリックして実行します。</div>
<div>
<br /></div>
<div>
<h3>
4.セットアップ</h3>
</div>
<div>
セットアップ実行直後の画面は以下です。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-fc9H7qSdLy8/Wjj6I-NO7_I/AAAAAAAACTo/d6kqxytvdRoqKKo_-OsyQfEiUuji0jsvwCLcBGAs/s1600/WS000002.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="630" data-original-width="860" height="292" src="https://4.bp.blogspot.com/-fc9H7qSdLy8/Wjj6I-NO7_I/AAAAAAAACTo/d6kqxytvdRoqKKo_-OsyQfEiUuji0jsvwCLcBGAs/s400/WS000002.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
「日本語化するアプリケーション」の選択ボタンを押下します。</div>
<div>
実行ファイルの選択ダイアログが表示されますので、日本語化したいアプリの実行ファイルを選んで下さい。</div>
<div>
<br /></div>
<div>
私の場合はAndroidStudioの64bit版を日本語化したいので、「studio64.exe」を選びます。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-zIH6rwJYzN0/Wjj6jEugDrI/AAAAAAAACTw/XHaGtmT1dmYEIE3u_gIV3s6S4wcqoXkOQCLcBGAs/s1600/WS000003.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="540" data-original-width="960" height="225" src="https://1.bp.blogspot.com/-zIH6rwJYzN0/Wjj6jEugDrI/AAAAAAAACTw/XHaGtmT1dmYEIE3u_gIV3s6S4wcqoXkOQCLcBGAs/s400/WS000003.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
後はもう、スルスルっと設定が行われ、以下の状態になります。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-mq65U2utNRY/Wjj6-YB7GlI/AAAAAAAACT4/Ge6JecnvP1gqAbwIs6-fQepF0zy7XnbEACLcBGAs/s1600/WS000004.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="630" data-original-width="860" height="292" src="https://1.bp.blogspot.com/-mq65U2utNRY/Wjj6-YB7GlI/AAAAAAAACT4/Ge6JecnvP1gqAbwIs6-fQepF0zy7XnbEACLcBGAs/s400/WS000004.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
「日本語化する」のボタンを押下して下さい。</div>
<div>
<br /></div>
<div>
これで日本語化完了です。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-XuFFCXRvP10/Wjj7KrhcgEI/AAAAAAAACUA/7-ugSgTcMic492-TtyLxEWgR3b0k4NaYQCLcBGAs/s1600/WS000005.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="130" data-original-width="562" height="92" src="https://1.bp.blogspot.com/-XuFFCXRvP10/Wjj7KrhcgEI/AAAAAAAACUA/7-ugSgTcMic492-TtyLxEWgR3b0k4NaYQCLcBGAs/s400/WS000005.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<h3>
5.起動</h3>
</div>
<div>
では、期待を込めてAndroidStudioを起動してみましょう。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-AXF7z7NMYOw/Wjj8y0GHWvI/AAAAAAAACUM/OrdN0XPMlIEuhyQ6B2Lpxyt0g1IObpV7QCLcBGAs/s1600/WS000006.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="746" data-original-width="1385" height="215" src="https://3.bp.blogspot.com/-AXF7z7NMYOw/Wjj8y0GHWvI/AAAAAAAACUM/OrdN0XPMlIEuhyQ6B2Lpxyt0g1IObpV7QCLcBGAs/s400/WS000006.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
バッチリです!!</div>
<div>
<br /></div>
<div>
<h3>
終わりに</h3>
</div>
<div>
いやぁ、流石はレジェンドアプリのPleadesですね。<br />
<br />
昔は「自分でパスを通せ」みたいな、実に技術者向けのそっけないツールだったのですが、今や完全GUI対応。<br />
この進化は普通ではありません。<br />
<br />
「AndroidStudioを普及させたい勢力が手伝った」とかあるんじゃないかな?<br />
それくらい特別なアップデートが成されています。</div>
<div>
<br />
日本Android界全体に影響を与える大改修と言って良いでしょう。</div>
<div>
<br /></div>
<div>
しかし、最近はIntelliJベース製品の攻勢が著しいですね。</div>
<div>
<br /></div>
<div>
Android開発はAndroidStudioが正式採用。</div>
<div>
Python開発はPyCharmが世界最強と評価されています。</div>
<div>
<br /></div>
<div>
Javaは長年の間、Eclipseが支配的地位を占めてきましたが、</div>
<div>
<b><span style="color: blue;"><br /></span></b></div>
<div>
<b><span style="color: blue;">「AndroidはAndroidStudioなのにJavaはEclipseかよ?」</span></b></div>
<div>
<br /></div>
<div>
というのは誰もが思っていることでしょう。</div>
<div>
<br /></div>
<div>
私は伝統的JavaエンジニアなのでEclipseに最も慣れ親しんでいます。<br />
しかし、IntelliJの活躍を見ると、慣れたEclipseを離れて新しい環境に挑戦していかなければならないと、最近強く思いますね。<br />
<br />
今年度の更新はこれが最後です。<br />
また来年も宜しくお願いします。</div>
Anonymousnoreply@blogger.com0tag:blogger.com,1999:blog-5306057209591512828.post-80658880096691442112017-12-18T12:46:00.000+09:002018-03-23T17:48:01.219+09:00【Googleクラウド・機械学習編】CLOUD NATURAL LANGUAGE API その2株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。<br />
<br />
最近流行の機械学習について勉強中です。<br />
<br />
<a href="https://www.blogger.com/blogger.g?blogID=5306057209591512828#editor/target=post;postID=7487665282389714865;onPublishedMenu=allposts;onClosedMenu=allposts;postNum=0;src=postname" target="_blank">前回</a>に引き続き、「CLOUD NATURAL LANGUAGE API」の実行を目指していきます。<br />
<br />
<h2>
前回まで</h2>
<div>
前回までで、ひとまずAPIの有効化と共に<span style="color: red;">課金</span>許可まで行いました。</div>
<div>
<br /></div>
<h2>
認証ID取得</h2>
<div>
API管選択画面から「管理」のボタンを押して認証情報の取得画面に進みます。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-kNcang97qXQ/WjYT_hCFICI/AAAAAAAACSI/XVbsswoQfOUYY71YOodZ3JqAXxqP7vMZgCLcBGAs/s1600/WS000000.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="489" data-original-width="895" height="217" src="https://3.bp.blogspot.com/-kNcang97qXQ/WjYT_hCFICI/AAAAAAAACSI/XVbsswoQfOUYY71YOodZ3JqAXxqP7vMZgCLcBGAs/s400/WS000000.JPG" width="400" /></a></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-nnDUKVbbUYs/WjYUCxxxoTI/AAAAAAAACSM/qJTaOPkjG_QbO3E3vY1DJUCajZJX7UCDwCLcBGAs/s1600/WS000001.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="721" data-original-width="1411" height="203" src="https://3.bp.blogspot.com/-nnDUKVbbUYs/WjYUCxxxoTI/AAAAAAAACSM/qJTaOPkjG_QbO3E3vY1DJUCajZJX7UCDwCLcBGAs/s400/WS000001.JPG" width="400" /></a></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-ykl502cQzOU/WjYUScSg3WI/AAAAAAAACSQ/-VrDcbXO4xQzzkIrzgDehW040xeXBA7tQCLcBGAs/s1600/WS000002.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="437" data-original-width="572" height="303" src="https://3.bp.blogspot.com/-ykl502cQzOU/WjYUScSg3WI/AAAAAAAACSQ/-VrDcbXO4xQzzkIrzgDehW040xeXBA7tQCLcBGAs/s400/WS000002.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
選択肢が出てきました。</div>
<div>
<br /></div>
<div>
<ul>
<li>APIキー</li>
<li>OAuthクライアントID</li>
<li>サービスアカウントキー</li>
</ul>
</div>
<div>
<br /></div>
<div>
このうち、単純に実行したい場合に必要なのはAPIキーです。<br />
それ以外のキーは未調査。<br />
<br />
APIキーを選択します。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/--8xjQsl1ujU/WjYVyYnsYuI/AAAAAAAACSc/GPwvQKksYbwmJKpFtLB_0yKH59XzDonHwCLcBGAs/s1600/WS000004.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="292" data-original-width="520" height="179" src="https://4.bp.blogspot.com/--8xjQsl1ujU/WjYVyYnsYuI/AAAAAAAACSc/GPwvQKksYbwmJKpFtLB_0yKH59XzDonHwCLcBGAs/s320/WS000004.JPG" width="320" /></a></div>
<div>
<br /></div>
<div>
無事に生成されました。</div>
<div>
<br /></div>
<div>
ここで注意事項ですが、APIキーは他人に漏らしてはいけません。</div>
<div>
<br /></div>
<div>
APIキーで個人を識別する仕様ですので、<span style="color: red;"><b>APIキーが漏れることは、ログインID/パスワードやクレジットカード番号が漏れることと同レベルの危機</b></span>です。</div>
<div>
<br /></div>
<div>
ちなみに今は私が自分で検証しているだけなので考慮不要ですが、もし業務で本格的に使う事になったらAPIキー秘匿の為の策も練る必要があります。</div>
<div>
<br /></div>
<div>
外部への流出対策は言うまでもありませんが、内部に対する秘匿も課題になるでしょう。</div>
<div>
<br /></div>
<div>
例えば、</div>
<div>
<br /></div>
<div>
<ul>
<li>ログにHTTPリクエストのクエリが表示されている。</li>
<li>クエリの中にはAPIキーも含まれている。</li>
<li>ログは内部の人間ならば誰でも見れる。</li>
</ul>
</div>
<div>
<br /></div>
<div>
なんてコンボをやらかしたら、もう完全にダダ漏れですよね。</div>
<div>
こういうのを一つ一つ見落とさないように防いでいくことはなかなか難しいと思います。</div>
<div>
<br /></div>
<div>
クラウドにはクラウドのリスクがありますので、その辺りも理解する必要があります。</div>
<div>
<br /></div>
<div>
ともかくこれで無事に取得出来ました。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-hK2_N0YlWb8/WjYcoWUDCeI/AAAAAAAACSs/-WSouS2EqGI4ayWihGGfXmAyIl0ULhZqACLcBGAs/s1600/WS000007.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="332" data-original-width="1056" height="125" src="https://2.bp.blogspot.com/-hK2_N0YlWb8/WjYcoWUDCeI/AAAAAAAACSs/-WSouS2EqGI4ayWihGGfXmAyIl0ULhZqACLcBGAs/s400/WS000007.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
ちなみに今、<b><span style="color: red;">「取得したけど一覧に何も出ない」</span></b>という挙動しました。</div>
<div>
F5を押したら表示されましたが。</div>
<div>
<br /></div>
<div>
ちょっとGoogleさん、<span style="color: red;">画面リフレッシュの実装漏れみたいなバグ</span>がありませんか、これ?</div>
<div>
<br /></div>
<div>
Googleって、<b>些細なバグは後回し</b>にするような所がありますからね。</div>
<div>
ユーザーも些細な事は気にしないのがお付き合いするコツです。</div>
<div>
<br /></div>
<div>
<h2>
実行</h2>
</div>
<div>
さて、これで実行に必要な素材は全部揃ったはずなのですが。</div>
<div>
ここからが難関。</div>
<div>
<br /></div>
<div>
API仕様書を読み込んで行かなければなりません。</div>
<div>
<br /></div>
<div>
<ul>
<li><a href="https://cloud.google.com/natural-language/docs/reference/rest/?hl=ja" target="_blank">https://cloud.google.com/natural-language/docs/reference/rest/?hl=ja</a></li>
</ul>
</div>
<div>
<br /></div>
<div>
また、HTTPリクエストを作るプログラムも実装しなきゃいけないなど、大変な作業が待っています。</div>
<div>
しかし、親切な事にGoogleには「APIエクスプローラ」という動作確認用の機能があります。</div>
<div>
<br /></div>
<div>
<ul>
<li><a href="https://developers.google.com/apis-explorer/?hl=ja#p/language/v1/" target="_blank">https://developers.google.com/apis-explorer/?hl=ja#p/language/v1/</a></li>
</ul>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
これを使ってちょっと動作確認をしてみましょう。</div>
<div>
<br /></div>
<div>
<h3>
文章</h3>
</div>
<div>
<div>
テキトーに考えた私の自己紹介を送り込んでみます。</div>
<div>
<br /></div>
<div>
======================================</div>
<div>
株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。</div>
<div>
<br /></div>
<div>
仕事はシステムエンジニア。</div>
<div>
特技は空手道初段です。</div>
<div>
<br /></div>
<div>
家族は妻が一名ほどいます。</div>
<div>
<br /></div>
<div>
好きなお酒はウイスキーです。</div>
<div>
<br /></div>
<div>
仲良くして下さい。</div>
</div>
<div>
======================================</div>
<div>
<br /></div>
<div>
<h3>
使用する機能</h3>
</div>
<div>
analyzeEntities。</div>
<div>
エンティティ解析です。</div>
<div>
<br /></div>
<div>
エンティティとは、「特徴的な単語」と解釈すれば良いでしょう。</div>
<div>
<br /></div>
<h2>
結果</h2>
以下のようなリクエストを送り込みます。
<br />
<pre class="prettyprint">POST https://language.googleapis.com/v1/documents:analyzeEntities?key={YOUR_API_KEY}
{
"document": {
"content": "株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。\n\n仕事はシステムエンジニア。\n特技は空手道初段です。\n\n家族は妻が一名ほどいます。\n\n好きなお酒はウイスキーです。\n\n仲良くして下さい。",
"type": "PLAIN_TEXT"
},
"encodingType": "NONE"
}
</pre>
すると、こんな結果が戻ってきました。
<br />
<pre class="prettyprint">200
- Show headers -
{
"entities": [
{
"name": "株式会社ジェニシス 技術開発事業部",
"type": "ORGANIZATION",
"metadata": {
},
"salience": 0.22330247,
"mentions": [
{
"text": {
"content": "株式会社ジェニシス 技術開発事業部",
"beginOffset": -1
},
"type": "PROPER"
}
]
},
{
"name": "遠藤 太志郎",
"type": "PERSON",
"metadata": {
},
"salience": 0.19125123,
"mentions": [
{
"text": {
"content": "遠藤 太志郎",
"beginOffset": -1
},
"type": "PROPER"
}
]
},
{
"name": "Tacy",
"type": "OTHER",
"metadata": {
},
"salience": 0.19125123,
"mentions": [
{
"text": {
"content": "Tacy",
"beginOffset": -1
},
"type": "PROPER"
}
]
},
{
"name": "仕事",
"type": "OTHER",
"metadata": {
},
"salience": 0.07422842,
"mentions": [
{
"text": {
"content": "仕事",
"beginOffset": -1
},
"type": "COMMON"
}
]
},
{
"name": "システムエンジニア",
"type": "OTHER",
"metadata": {
},
"salience": 0.07422842,
"mentions": [
{
"text": {
"content": "システムエンジニア",
"beginOffset": -1
},
"type": "COMMON"
}
]
},
{
"name": "特技",
"type": "OTHER",
"metadata": {
},
"salience": 0.05605998,
"mentions": [
{
"text": {
"content": "特技",
"beginOffset": -1
},
"type": "COMMON"
}
]
},
{
"name": "空手道初段",
"type": "OTHER",
"metadata": {
},
"salience": 0.05605998,
"mentions": [
{
"text": {
"content": "空手道初段",
"beginOffset": -1
},
"type": "COMMON"
}
]
},
{
"name": "酒",
"type": "CONSUMER_GOOD",
"metadata": {
},
"salience": 0.03795014,
"mentions": [
{
"text": {
"content": "酒",
"beginOffset": -1
},
"type": "COMMON"
}
]
},
{
"name": "ウイスキー",
"type": "OTHER",
"metadata": {
},
"salience": 0.03795014,
"mentions": [
{
"text": {
"content": "ウイスキー",
"beginOffset": -1
},
"type": "COMMON"
}
]
},
{
"name": "家族",
"type": "PERSON",
"metadata": {
},
"salience": 0.028858999,
"mentions": [
{
"text": {
"content": "家族",
"beginOffset": -1
},
"type": "COMMON"
}
]
},
{
"name": "妻",
"type": "PERSON",
"metadata": {
},
"salience": 0.028858999,
"mentions": [
{
"text": {
"content": "妻",
"beginOffset": -1
},
"type": "COMMON"
}
]
}
],
"language": "ja"
}
</pre>
<br />
<h2>
考察</h2>
ほえ~。<br />
<div>
<br />
「salience」とは突出率という意味で、この数字が高いほど特徴的で、<br />
低いほどありふれた単語、という意味のようです。<br />
<br />
<br />
<ul>
<li>株式会社ジェニシス 技術開発事業部</li>
</ul>
<br />
<br />
これで一つの単語として認識されています。<br />
<br />
TYPE:ORGANIZATION<br />
<br />
しかし、「株式会社ジェニシス」が会社名で「技術開発事業部」が部署名であることまでの粒度には到っていません。<br />
<br />
<ul>
<li>遠藤 太志郎</li>
</ul>
<br />
私の名前も抽出出来ています。<br />
<br />
TYPE:PERSON<br />
<br />
ジェニシスの方は「TYPE:ORGANIZATION」で私の名前は「TYPE:PERSON」ですから、それが人間の名前なのか組織の名前なのかを識別出来るようです。<br />
<br />
なるほどなるほど。<br />
機能のイメージは沸いてきますね。<br />
問題はこれをどう役立てるかということですが、試していくには元となるデータが沢山必要ですね。<br />
<br />
<b style="color: red;">同僚の日報</b>とか解析してみると面白いかもしれません。<br />
<br />
<h2>
終わりに</h2>
</div>
<div>
引き続きCLOUD NATURAL LANGUAGE APIの検証を進めていこうと思います。</div>
Anonymousnoreply@blogger.com0tag:blogger.com,1999:blog-5306057209591512828.post-74876652823897148652017-12-11T12:28:00.002+09:002018-03-23T17:48:20.998+09:00【Googleクラウド・機械学習編】CLOUD NATURAL LANGUAGE API その1株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。<br />
<br />
最近流行の機械学習について勉強中です。<br />
<br />
今回からGoogleクラウドAPIを使い始めていきます。<br />
最初は「CLOUD NATURAL LANGUAGE API」です。<br />
<br />
<h2>
始め方</h2>
<div>
何事も最初が一番難しい。</div>
<div>
「CLOUD NATURAL LANGUAGE APIってどこにあるのよ?」でまず躓きます。</div>
<div>
<br /></div>
<div>
GoogleクラウドAPI全般に言えることですが、APIは管理コンソールの中にあります。</div>
<div>
<br /></div>
<div>
コンソールの中に「APIとサービス」という項目があります。</div>
<div>
これを選択して下さい。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-bmgrQx9ATOc/WizWzTUTWrI/AAAAAAAACOA/EtrISIdKcf8SD93G2FUZpDa-Zs4BSQvigCLcBGAs/s1600/WS000001.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="381" data-original-width="546" height="223" src="https://3.bp.blogspot.com/-bmgrQx9ATOc/WizWzTUTWrI/AAAAAAAACOA/EtrISIdKcf8SD93G2FUZpDa-Zs4BSQvigCLcBGAs/s320/WS000001.JPG" width="320" /></a></div>
<div>
<br /></div>
<div>
その中に「ライブラリ」があります。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-ZRmPlsf_xNY/WizXdqQmYuI/AAAAAAAACOM/3Nv8WmDJnfkEwSRptt2Enewul6BNl4BoQCLcBGAs/s1600/WS000000.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="253" data-original-width="273" src="https://2.bp.blogspot.com/-ZRmPlsf_xNY/WizXdqQmYuI/AAAAAAAACOM/3Nv8WmDJnfkEwSRptt2Enewul6BNl4BoQCLcBGAs/s1600/WS000000.JPG" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div>
ライブラリを選択すると、お待ちかねのライブラリページが表示されます。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-fLPbgI7VBgs/WizXuzuVZRI/AAAAAAAACOQ/7AksYokUap4JxnUUMm6XGHDyneQDOdIRQCLcBGAs/s1600/WS000001.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="791" data-original-width="1600" height="197" src="https://2.bp.blogspot.com/-fLPbgI7VBgs/WizXuzuVZRI/AAAAAAAACOQ/7AksYokUap4JxnUUMm6XGHDyneQDOdIRQCLcBGAs/s400/WS000001.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<span style="color: red;"><b>沢山あります!!</b></span></div>
<div>
<br /></div>
<div>
このライブラリページはGoogleクラウドの全機能が集結しています。</div>
<div>
<br /></div>
<div>
「CLOUD NATURAL LANGUAGE API」に限らず、「GMail」とか、「Googleカレンダー」とか、果ては「Youtube」まで。</div>
<div>
<br /></div>
<div>
Webで実現出来る機能は全部この中に投入されており、この中からお好きなものを選んで使用して下さい、とそういう形態なわけですね。</div>
<div>
そして機能毎に使用回数とか伝送データ量とかが計測されており、それに応じてお金を払うという従量課金制で進行しております。</div>
<div>
<br /></div>
<div>
では、目当ての「CLOUD NATURAL LANGUAGE API」を検索しましょう。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-nTVGa_wTnsY/WizanWYkBNI/AAAAAAAACOc/BZujS1ykfMMKONxDaMKQ4rl_DMQX3yK6wCLcBGAs/s1600/WS000002.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="702" data-original-width="1108" height="252" src="https://2.bp.blogspot.com/-nTVGa_wTnsY/WizanWYkBNI/AAAAAAAACOc/BZujS1ykfMMKONxDaMKQ4rl_DMQX3yK6wCLcBGAs/s400/WS000002.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
出てきましたね。</div>
<div>
これを選択するお、「有効にする」のボタンがある画面が表示されます。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-MVk2-deSP-s/Wiza-LYIbmI/AAAAAAAACOg/Mqm7WaF-0aEs31Ptc6UOAmb-MftsuqLewCLcBGAs/s1600/WS000003.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="665" data-original-width="1108" height="240" src="https://3.bp.blogspot.com/-MVk2-deSP-s/Wiza-LYIbmI/AAAAAAAACOg/Mqm7WaF-0aEs31Ptc6UOAmb-MftsuqLewCLcBGAs/s400/WS000003.JPG" width="400" /></a></div>
<div>
<br /></div>
<div>
さっそく有効にして……。おっと。</div>
<div>
<br /></div>
<div>
<span style="color: red;"><b>課金しろ、と出てきてしまいました!!</b></span></div>
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-fTJ-Ka7ZQ9I/Wizf0boWHfI/AAAAAAAACOw/EqCF_boyeQIkELa4thvoLm5bKFQ89JlQQCLcBGAs/s1600/WS000004.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="791" data-original-width="1600" height="197" src="https://3.bp.blogspot.com/-fTJ-Ka7ZQ9I/Wizf0boWHfI/AAAAAAAACOw/EqCF_boyeQIkELa4thvoLm5bKFQ89JlQQCLcBGAs/s400/WS000004.JPG" width="400" /></a></div>
<br /></div>
<div>
<h2>
課金体系</h2>
</div>
<div>
私は一年間の無料お試しクレジットを貰っているので、当面は課金はされないはず。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-ZZNNQpcqQHM/WizgLpnNduI/AAAAAAAACO0/oivHtPfxpx8i02GVdsk5hxjRJjro9dwqQCLcBGAs/s1600/WS000005.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="165" data-original-width="591" src="https://1.bp.blogspot.com/-ZZNNQpcqQHM/WizgLpnNduI/AAAAAAAACO0/oivHtPfxpx8i02GVdsk5hxjRJjro9dwqQCLcBGAs/s1600/WS000005.JPG" /></a></div>
<br />
とは言え何かミスって爆死したら困るので先に予算体系も調べました。<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-25YlTACV-EE/Wizl9h4XYbI/AAAAAAAACPE/qOff8iJGiFIxsB6OJXxepVRpgEPR0wwxQCLcBGAs/s1600/WS000006.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="269" data-original-width="880" height="121" src="https://4.bp.blogspot.com/-25YlTACV-EE/Wizl9h4XYbI/AAAAAAAACPE/qOff8iJGiFIxsB6OJXxepVRpgEPR0wwxQCLcBGAs/s400/WS000006.JPG" width="400" /></a></div>
<br />
<br />
<br />
<ul>
<li><a href="https://cloud.google.com/natural-language/pricing?hl=ja" target="_blank">https://cloud.google.com/natural-language/pricing?hl=ja</a></li>
</ul>
<br />
<br />
要約すると、<br />
<br />
<br />
<ul>
<li>5,000件までは無料</li>
<li>それ以降、1,000件辺り1ドルが必要</li>
<li>大量使用ユーザは1000件辺り0.25ドルまで値下げOK</li>
</ul>
<br />
<br />
とのことです。<br />
<br />
この「件」というのは、HTTPリクエストの送信回数のことです。<br />
またCLOUD NATURAL LANGUAGE APIは一回当たりの送信文字数が1,000文字毎にも一件という閾値となっています。<br />
<br />
そして1ヶ月毎にクリアされていきます。<br />
<br />
つまり、<br />
<br />
<br />
<ul>
<li>1,000文字のHTTPリクエストを1回送る。⇒1件</li>
<li>1,000文字のHTTPリクエストを2回送る。⇒2件</li>
<li>999文字のHTTPリクエストを1回送る。⇒1件</li>
<li>1,001文字のHTTPリクエストを1回送る。⇒2件</li>
<li>1,001文字のHTTPリクエストを2回送る。⇒4件</li>
</ul>
<br />
<br />
こういう計算です。<br />
<br />
<b><span style="color: red;">月々</span><span style="color: red;">5,000件までは無料</span></b>というのは、私がチョコチョコと検証している限りは無料と言ってしまっても良いでしょう。<br />
<br />
このように、<br />
<br />
<ul>
<li>大規模ユーザにはそれなりのお金を払って貰う。</li>
<li>小規模ユーザには、少々のお金を払って貰う。</li>
<li>個人がちょっと見てるくらいは無料。</li>
</ul>
<br />
クラウド環境は小規模スタートしたい時に有利と言われますが、全くその通りです。<br />
<br />
ちなみに夏目漱石の「こころ」は、大体23万文字です。<br />
対して、5,000件× 1,000文字 = 500万ですから、<span style="color: red;"><b>月々文庫本20冊くらいのバイト数は負荷のうちに入らない</b></span>と見なされるくらいの大量データ処理を想定していることが分かります。<br />
<br />
<b><span style="color: blue;">ビッグデータ解析</span></b>という側面も持ち合わせたサービスなのですね。<br />
<br />
<h2>
有効化</h2>
これで無事にAPIの有効化に成功しました。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-3kEnPztarew/WizqPKQJKlI/AAAAAAAACPQ/eTdRWIT-r6IZ4sLmIu9m_W8yp7Gm9oKCQCLcBGAs/s1600/WS000000.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="849" data-original-width="1411" height="240" src="https://3.bp.blogspot.com/-3kEnPztarew/WizqPKQJKlI/AAAAAAAACPQ/eTdRWIT-r6IZ4sLmIu9m_W8yp7Gm9oKCQCLcBGAs/s400/WS000000.JPG" width="400" /></a></div>
<div>
<br /></div>
ここから先は実際にHTTPリクエストを送り込むフェーズになります。<br />
<br />
HTTPリクエスト送信時には、認証IDという送信者を一意に認識するキーをリクエスト中に埋め込む必要があります。<br />
次回は認証ID取得から始まります。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-her30SySrXw/WizqnWH6tiI/AAAAAAAACPU/vf5y12jAkB8xIkGjn5BD7MK8Bz90z-66wCLcBGAs/s1600/WS000001.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="849" data-original-width="1411" height="240" src="https://4.bp.blogspot.com/-her30SySrXw/WizqnWH6tiI/AAAAAAAACPU/vf5y12jAkB8xIkGjn5BD7MK8Bz90z-66wCLcBGAs/s400/WS000001.JPG" width="400" /></a></div>
<br />
<h2>
続く</h2>
</div>
<div>
結構長い道のりです。<br />
しかしGoogle系のAPIはみんな同じ要領なので、一度経験しておけば二回目以降はスピーディーに作業出来ると思います。</div>
Anonymousnoreply@blogger.com0tag:blogger.com,1999:blog-5306057209591512828.post-34854193243898897452017-12-04T21:32:00.000+09:002018-03-23T17:48:51.104+09:00【Googleクラウド・機械学習編】機能のご紹介株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。<br />
<br />
最近流行の機械学習について勉強中です。<br />
<br />
今までは「人工知能調査」と銘打って記事のタイトルとしていましたが、調査対象をGoogleクラウドの機械学習APIに絞り込んだことから、記事のタイトルも合わせて絞り込んだものにしてみました。<br />
<br />
では、早速機械学習APIの中に入っていきましょう。<br />
<br />
<h2>
何が出来るのか?</h2>
ご存じ無い方だと、「機械学習のAPI? 何のこっちゃ?」という印象かと思います。<br />
以下の例を見ればすぐイメージが沸くでしょう。<br />
<br />
<h3>
CLOUD NATURAL LANGUAGE API</h3>
<ul>
<li><a href="https://cloud.google.com/natural-language/" target="_blank">https://cloud.google.com/natural-language/</a></li>
</ul>
<div>
<br /></div>
「非構造化テキストから分析情報を得る」とのこと。<br />
「非構造化テキスト」とは、例えばこのブログの記事のようなフリー文章のことです。<br />
<br />
フリー文章をこのAPIに食わせると、「機械学習」「人工知能」みたいな<b><span style="color: red;">要点となる単語をピックアップ</span></b>してきたり、そこに含まれている<span style="color: red;"><b>感情をピックアップ</b></span>してきたりするものです。<br />
<br />
例えば自社サービスのユーザからアンケートを収拾してきて、それを食わせると、<br />
<br />
<br />
<ul>
<li>「高い」</li>
<li>「障害」</li>
<li>「対応」</li>
<li>「値段」</li>
</ul>
<br />
<br />
みたいな、特徴的な単語が抽出されてきます。<br />
加えて、「怒り:20%」「不満:30%」「良好:50%」みたいな感情も数値化されて出てきます。<br />
<br />
こういう情報を見て、<br />
<br />
「ああ、利用者はウチのサービスに対して値段の高さ、障害発生率、ヘルプデスクの対応、この辺りを気にしているんだなぁ。値下げは出来ないけど、障害発生率、ヘルプデスクは気になる。これは新機能の追加より、現在のサービスの安定性向上にリソースを割いた方が良いってことなのかなぁ」<br />
<br />
という判断材料に使えるわけですね。<br />
<br />
このAPIは<span style="color: blue;"><b>「ユーザからの声を数値化するサービス」</b></span>と言えるでしょう。<br />
上手く使えば経営者の目がキラキラするかもしれません。<br />
<br />
補足ですが、「ビッグデータ解析と似たようなもんだな」という印象を抱く方もいると思います。<br />
私は「似たような物ではなく、同じ物だ」と解釈しています。<br />
<br />
機械学習とビッグデータ解析は技術領域が被っていますので、両者の境界線は曖昧です。<br />
<br />
<h3>
CLOUD SPEECH API</h3>
<div>
<ul>
<li><a href="https://cloud.google.com/speech/" target="_blank">https://cloud.google.com/speech/</a></li>
</ul>
</div>
<br />
<br />
音声をテキスト変換するAPIです。日本語にも対応していることを確認済み。<br />
<br />
最近のスマホは「近所の居酒屋まで道案内してや」と話し掛けるだけでGoogleマップが起動したりしますが、恐らくはこの技術を使っているものと推測されます。<br />
<br />
私は業務系エンジニアであるため、このAPIの使い道は真っ先に以下を思いつきました。<br />
<br />
<ul>
<li>議事録のテキスト化</li>
</ul>
<br />
<span style="color: blue;"><b>会議の内容を手持ちのスマホで録音して、戻ってからAPIに食わせてテキスト化出来るんじゃないか!?</b></span><br />
<br />
これは期待大です。<br />
<br />
<h3>
CLOUD TRANSLATION API</h3>
<div>
<ul>
<li><a href="https://cloud.google.com/translate/" target="_blank">https://cloud.google.com/translate/</a></li>
</ul>
<div>
<br /></div>
</div>
言わずと知れたGoogle伝統の翻訳APIです。<br />
<br />
最高に素晴らしい機能ではありますが、公式のGoogle翻訳以上のものを自分で作るのは難しいんじゃないかな?<br />
<br />
自分のアプリの中にGoogle翻訳を組み込みたいようなケースがあれば、活躍するのかもしれません。<br />
<br />
<h3>
CLOUD VISION API</h3>
<div>
<ul>
<li><a href="https://cloud.google.com/vision/" target="_blank">https://cloud.google.com/vision/</a></li>
</ul>
</div>
<br />
画像を解析するAPIです。<br />
画像から様々な情報を抽出します。<br />
<br />
<br />
<ul>
<li>ラベル検出</li>
<li>不適切なコンテンツの検出</li>
<li>ロゴ検出</li>
<li>ランドマーク検出</li>
<li>光学式文字認識(OCR)</li>
<li>顔検出</li>
<li>画像属性</li>
</ul>
<br />
<br />
「光学式文字認識(OCR)」とは、画像の中に書かれた文字をテキスト抽出することです。<br />
名刺画像を食わせれば名前を抽出出来る、とかそういう機能ですね。<br />
<br />
それ以外は何のこっちゃ???<br />
<br />
これ、使ってみれば感覚が分かります。<br />
以下、私の写真を食わせてみました。<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-7h3SQBONGLM/WiOumESk4VI/AAAAAAAACMo/pRVjQkSnrIQp4WOhuPe6K0TD84f0CEbjwCLcBGAs/s1600/WS000002.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="453" data-original-width="1015" height="284" src="https://2.bp.blogspot.com/-7h3SQBONGLM/WiOumESk4VI/AAAAAAAACMo/pRVjQkSnrIQp4WOhuPe6K0TD84f0CEbjwCLcBGAs/s640/WS000002.JPG" width="640" /></a></div>
<br />
JOY:■■■■■<br />
<br />
とか出ていますね。<br />
<br />
<span style="color: blue;"><b>「これ、お前が遊びに出かけた時の写真だろ!!」</b></span>と、断定してきているわけですね。<br />
服装のポップな感じから見極めていると思われます。<br />
<br />
人間の思考回路と同じ。<br />
実に人工知能らしい機能じゃありませんか。<br />
<br />
<h2>
その他の機能</h2>
上記を見ると、「ああ、あのサービスのあの機能はコレだったんだ」と思う方も多いと思います。<br />
何か、どこかで見たことがあるような機能です。<br />
<br />
あの機能を自分で作るとなると途方も無い労力です。<br />
しかしWebAPIを使えば簡単に実現出来ます。<br />
<br />
それが機械学習APIなわけですね。<br />
<br />
最後に、私が気になるAPIをご紹介。<br />
<br />
<h3>
CLOUD JOBS API</h3>
<br />
<ul>
<li><a href="https://cloud.google.com/jobs-api/" target="_blank">https://cloud.google.com/jobs-api/</a></li>
</ul>
<br />
<br />
<br />
限定公開アルファ版。<br />
<br />
<span style="color: blue;"><b>「求職者がもっと簡単に職を探せるようにするという幅広い取り組みの一環」</b></span><br />
<br />
とのことです。<br />
<br />
要するに、「求職者のスキル」と「企業の求めている人材像」を分析してマッチングする機能ということでしょう。<br />
リクルートとかが関心を寄せそうな話です。<br />
<br />
これを弊社ジェニシスに置き換えた場合、弊社では「マッチング営業」という業務が存在します。<br />
SEを派遣する時の仲介となる業務です。<br />
<br />
この業務は「行う仕事と、派遣された人材のスキルが合わない」というスキルミスマッチが大問題に発展します。<br />
もちろん、念入りに面談して技術力も見極めればそんなことは起きるはずは無いのですが、「忙しくて面談の時間が30分しか取れない」とか「技術力を見極める力量のある人が忙しいので動員出来ない」とか、大人の事情で万全な体制が取れないケースがあります。<br />
<br />
しかし、機械学習を活用してSEの職務経歴書を読み込ませて判断材料にすることが出来れば、問題点のいくらかは補強されるんじゃないかと思います。<br />
<br />
こんな風に「もしかしたらこんなことが出来るんじゃないかな?」と期待が膨らんでいく辺りが、機械学習の楽しいところですね。<br />
<br />
<h2>
終わりに</h2>
次回からは上記のAPIを実際に使っていきたいと思います。Anonymousnoreply@blogger.com0tag:blogger.com,1999:blog-5306057209591512828.post-15967123173290676422017-11-27T13:14:00.000+09:002018-03-23T17:21:21.541+09:00【人工知能調査】機械学習のWebAPI株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。<br />
<br />
最近流行の機械学習について勉強中です。<br />
<br />
<a href="https://genesis-tdsg.blogspot.jp/2017/11/blog-post_20.html" target="_blank">前回</a>の調査で、自分で機械学習アプリを作ってみたい場合はGoogleの機械学習ライブラリ「TensorFlow(テンソルフロー)」がオススメとなりました。<br />
<br />
<br />
<ul>
<li><a href="https://www.tensorflow.org/" target="_blank">https://www.tensorflow.org/</a></li>
</ul>
<div>
<br />
<br /></div>
<div>
しかしながら、やっぱり<b>結構難しい</b>んですよね。。。<br />
勉強期間を置かなければ厳しいです。<br />
<br />
しかし、そこは天下のGoogle。そんな初心者でも機械学習が使えるようにWebAPIを用意してくれています。<br />
<br />
ここから先は機械学習WebAPIについて調査してきます。<br />
<br />
<h2>
Google Cloud Platform</h2>
</div>
<div>
<br /></div>
<div>
Googleが提供するWebAPI、それは「Google Cloud Platform」の中にあります。</div>
<div>
通常、<b>「Googleクラウド」。</b></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-3Cih26UDWww/Whj1E45x7DI/AAAAAAAACK8/l6UvZOiTlr80Z_6vZ1CqWjyFY9qNOBFqwCLcBGAs/s1600/WS000000.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="791" data-original-width="1600" height="197" src="https://4.bp.blogspot.com/-3Cih26UDWww/Whj1E45x7DI/AAAAAAAACK8/l6UvZOiTlr80Z_6vZ1CqWjyFY9qNOBFqwCLcBGAs/s400/WS000000.JPG" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ul>
<li><a href="https://cloud.google.com/" target="_blank">https://cloud.google.com/</a></li>
</ul>
<div>
<br /></div>
<br />
<div class="separator" style="clear: both; text-align: left;">
AmazonのAWS、MicrosoftのAzureと並ぶクラウド三巨頭の一角です。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
メニューの内容をいくつか見ていきましょう。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<h3 style="clear: both; text-align: left;">
クラウド コンピューティング サービス</h3>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
「Googleクラウド」という言葉は、暗黙的にこのクラウドコンピューティングサービスのイメージで使われている事が多いです。</div>
<div class="separator" style="clear: both; text-align: left;">
アプリを載せるサーバをクラウド環境で提供するという、クラウド界の一般モデルですね。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
以前、私はこの<span id="goog_1438846680"></span><a href="https://www.blogger.com/"></a><span id="goog_1438846681"></span>中の「GoogleAppEngine」を調査しました。</div>
<div class="separator" style="clear: both; text-align: left;">
<b><span style="color: blue;">驚異的な速さと安さ、処理パワー</span></b>を誇る一方、<span style="color: red;"><b>制約がキツい</b></span>。</div>
<div class="separator" style="clear: both; text-align: left;">
通常の業務システムではこんなの使えませんが、特定局面ではブッチギリの最強を誇る。</div>
<div class="separator" style="clear: both; text-align: left;">
キレ味の鋭いデンジャラスなサービスです。</div>
<div class="separator" style="clear: both; text-align: left;">
当時の時期はこちらをご確認下さい。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ul>
<li><a href="https://genesis-tdsg.blogspot.jp/p/googleappengine.html" target="_blank">https://genesis-tdsg.blogspot.jp/p/googleappengine.html</a></li>
</ul>
<br />
<h3 style="clear: both;">
ストレージとデータサービス、その他</h3>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Googleクラウド上で展開しているデータベースです。</div>
<div class="separator" style="clear: both; text-align: left;">
普通のOracleとかMySQLとかと違い、クラウド上で効率的に処理をするためにチューニングが施されたDBが展開しています。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
が、上記のサイトのデザインを見るとクラウドコンピューティングサービスは別の項目として置かれていますから、違うサービスであるかのように見えます。</div>
<div class="separator" style="clear: both; text-align: left;">
課金体系も別れているので確かに違うサービスと言えばそうですが……。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
私は「クラウドコンピューティングサービスの一部」としか思っていません。</div>
<div class="separator" style="clear: both; text-align: left;">
だって、<b><span style="color: red;">「言語は動かせるけどDBはありません」</span></b>って、それじゃシステムが成り立たないじゃないですか。</div>
<div class="separator" style="clear: both; text-align: left;">
この「クラウドDB」とは、要するに<span style="color: blue;">「GoogleAppEngineの接続先のDB」</span>なんですよ。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="color: red;"><b>DBだけ独立して使うものじゃない。</b></span></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
他の項目である「ネットワーキング」「ビッグデータ」「管理ツール」も同じ。</div>
<div class="separator" style="clear: both; text-align: left;">
全部揃って「Googleクラウド」です。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ul>
<li>Googleクラウドのうち、サーバ部分の詳細はコンピューティングを参照。</li>
<li>Googleクラウドのうち、DB部分はストレージの項目を参照。</li>
<li>Googleクラウドのうち、ネットワーク部分はネットワークの項目。</li>
<li>Googleクラウドでも、特にビッグデータ処理用の機能はビッグデータの項目を参照。</li>
<li>GoogleクラウドのAdminコンソールは管理ツール参照。</li>
</ul>
<br />
<div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
と、みんな繋がっているものです。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
つまり、</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ul>
<li>一つのサービスを実現する為に必要な技術領域毎にメニューを分けている。</li>
<li>全部組み合わせて最終的に一つのWebサービスが出来上がる。</li>
</ul>
<br />
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
と考えるのが分かり易いです。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
課金体系もサーバ処理、DB処理、ネットワークで個別に別れています。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ul>
<li>重い処理があるサービスはコンピュータ代が高くなる。</li>
<li>アクセスが殺到するサービスはネットワークが高くなる。</li>
<li>月々の維持費は全部の合計。</li>
</ul>
<br />
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
こういう課金体系です。</div>
<div class="separator" style="clear: both; text-align: left;">
こうして見ると「クラウドクラウドって言うけど、普通のサーバと似たようなもんじゃないか」というのは、その通りです。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
クラウドはクラウドという新しい技術ではなく、昔ながらの技術の延長線上にある、ちょっと便利なテクニックのようなものなのです。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<h3 style="clear: both; text-align: left;">
機械学習</h3>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
さて、そんなGoogleクラウドの中にねじ込まれている項目があります。</div>
<div class="separator" style="clear: both; text-align: left;">
以前は無かったのにいつのまにか増えました。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-nFl-MGGhjJo/WhkQui1EBEI/AAAAAAAACLY/tjv4QVDFhmwVvwbZDb4uV5PgnQEkFCNrgCLcBGAs/s1600/WS000001.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="408" data-original-width="416" height="392" src="https://3.bp.blogspot.com/-nFl-MGGhjJo/WhkQui1EBEI/AAAAAAAACLY/tjv4QVDFhmwVvwbZDb4uV5PgnQEkFCNrgCLcBGAs/s400/WS000001.JPG" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
これが目当ての機械学習です。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
例えば、<span style="color: blue;"><b>Google検索でテキストボックスに文字を少し入力すると、その先が予測されて表示される</b></span>という機能は、この機械学習の機能を使った結果のはず。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
我々が普段使っている機能の裏側がここに眠っているのでしょう。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<h2 style="clear: both; text-align: left;">
終わりに</h2>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
次回からは、この機械学習について、調査と検証に着手していきたいと思います。</div>
</div>
Anonymousnoreply@blogger.com0tag:blogger.com,1999:blog-5306057209591512828.post-19007181012570678802017-11-20T12:04:00.000+09:002018-03-23T17:21:27.433+09:00【人工知能調査】機械学習を始めてみよう株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。<br />
<br />
最近流行の機械学習について勉強中です。<br />
<br />
これまでの調査で「機械学習とはどういうものか?」というものを触り程度には理解出来たと思います。<br />
しかし、「じゃあ早速業務で使いたいんだけど♪」となると、まだまだハードルが高そうです。<br />
<br />
ここからは具体的にどう実現していけば良いか、について模索していきたいと思います。<br />
<br />
<h2>
二大プラン</h2>
<br />
機械学習は、元を辿るともの凄く高度な技術領域で、特別な研究者でなければ手も足も出ないようなものです。<br />
<br />
しかしながら、最近機械学習がブームになっているのは、そういった偉大なる先人達が一般エンジニアでも使えるようにお膳立てを整えてくれたおかげで、以前よりもずっと身近なものになってきているからです。<br />
<br />
機械学習を導入する手段としては、私は以下の2つに絞り込みたいと思います。<br />
<br />
<ul>
<li>ライブラリ導入 </li>
<li>WebAPI </li>
</ul>
<br />
まずはライブラリから調べてみます。<br />
<br />
<h2>
機械学習ライブラリ</h2>
<br />
機械学習を実現するライブラリを導入して実現するプランです。<br />
「ライブラリ」とは、その名のとおり、普通にソースの集合体です。<br />
<b>オープンソース</b>として公開されているので誰でも取得可能。<br />
<br />
自分でプロジェクトを作成し、公式サイトからダウンロードしたパッケージにパスを通し、起動。<br />
後は自分で実装していく中でライブラリのメソッドを呼んだりするわけです。<br />
<br />
つまり、<b><span style="color: blue;">普通のプラグラミング</span></b>です。<br />
<br />
昔ながらのイメージだと、こういうのは世界有数の先端企業の天才プログラマーが本人以外誰にも分からないような異次元開発を行っているような気がしますが、<br />
実際はネットに転がっていて誰でも活用OKという状況です。<br />
<br />
時代の潮流ですね。<br />
<br />
<h3>
注目のライブラリ:TensorFlow</h3>
<br />
では、世の中にはどのようなライブラリがあるか?<br />
<br />
「機械学習 ライブラリ」で検索すると、結構沢山出てきます。<br />
<span style="color: blue;"><b>機械学習のライブラリは既に世界に溢れています。</b></span><br />
とっくに群雄割拠の時代に突入していると言ってしまって良いでしょう。<br />
<br />
その中で私がイチオシするのは、Googleの<b>TensorFlow(テンソルフロー)</b>です。<br />
<br />
<ul>
<li><a href="https://www.tensorflow.org/">https://www.tensorflow.org/</a> </li>
</ul>
<br />
機械学習のライブラリ開発は、古くは(と言うほど昔ではありませんが)「カルフォルニア大学バークレー校」「FaceBook」などが活躍してきました。<br />
<br />
一方、技術領域の最高峰と目されていたGoogleはソースのオープン化を行っておらず、内部プロジェクトとして秘密裏に進行していました。<br />
「Googleは一体どんなことをやっているんだろう???」とみんなが思っていた2015年、満を持して世界に公開された待望のライブラリ、それがこのTensorFlowです。<br />
<br />
最大の特徴は、Googleが実際にこのライブラリを自社で使っているという<b>「実績」</b>でしょう。<br />
<br />
Googleの迷惑メールフィルタリングとか、画像検索とか、表示される広告の選抜とか、Googleが実現している機能はこのライブラリを使っているわけです。<br />
<br />
<ul>
<li>現在、Googleがこういう機能を実現している。 </li>
<li>これを応用して、自分達の業務に活用したい。 </li>
</ul>
<br />
こういう発想で物事を考えていくことが出来るわけですね。<br />
<br />
2017年の現時点において機械学習を始めたい人は、このTensorFlowを勉強するのが最善の道だと思います。<br />
<br />
<h3>
言語はPython</h3>
<br />
TensorFlowの言語はC言語、C++にも対応していますが、主力はPythonです。<br />
<br />
Pythonは日本ではまだまだ普及しているとは言い難いですが、欧米ではかなり採用比率が高く、特に機械学習業界では「言語=Python」と言ってしまって良いくらい支配的な地位を占めています。<br />
<br />
今一番ホットな言語だと思います。<br />
<br />
機械学習界でPythonが人気を集めるのには理由がありますが、私は特に以下の点が重要だと思います。<br />
<br />
<h4>
インタプリタ言語である</h4>
<div>
<br /></div>
インタプリタ言語とは、書いたソースを逐次解釈して実行するタイプの言語のことで、例えばPerl、Ruby、PHPがそれに該当します。<br />
<br />
C言語みたいにコンパイルを経由しないので高い生産性を持つと評価されます。<br />
<br />
ココ、「コンパイルせずに即実行」という特性がポイントです。<br />
<br />
私のような業務系SEの場合、開発風景は基本的に「基本設計⇒詳細設計⇒実装」と進行します。<br />
キチッと設計してから実装するので、実装は理論上は一撃必殺です。(実際はバグで手戻りしますが)<br />
一撃必殺だからコンパイルも一回で終わりです。<br />
<br />
対して、機械学習は「あーでもない」「こーでもない」と試行錯誤しながら開発が進行します。<br />
<b><span style="color: red;">試行錯誤の度に毎回コンパイルなんてやってられない</span></b>のです。<br />
だからインタプリタ言語が重宝されるわけです。<br />
<br />
この発想は他の開発における言語選びでも一つの基準となりますね。<br />
<br />
<ul>
<li>詳細設計までビシッと書いて一発で実装を完了出来るなら、コンパイル言語 </li>
<li>実装しながら考えるようなやり方なら、インタプリタ言語 </li>
</ul>
<br />
大規模ビジネスシステム開発のウォーターフォールモデルではJava等のコンパイル言語の採用が多く、<br />
<div>
スパイラルモデルやアジャイル開発ではインタプリタ言語採用が多いのも、この辺りが背景にあるわけです。<br />
<br />
人工知能業界は後者なのです。<br />
<br />
<h4>
速い</h4>
<div>
<br /></div>
Pythonのもう一つの特徴。<br />
それはインタプリタ言語にしては速いということです。<br />
<br />
一般的にコンパイル言語の方が速く、インタプリタ言語の方が遅いです。</div>
<div>
Pythonの場合も、流石にC言語よりは遅いのですが、インタプリタ言語の中では速い方だと言われています。<br />
自分でベンチマークしたわけではありませんが、ザックリと<br />
<br />
<ul>
<li>C言語:最速</li>
<li>Python:C言語の5~7倍の処理時間が必要 </li>
<li>Ruby:Pythonの 5~7倍の処理時間が必要</li>
</ul>
<br />
これくらいの違いが出ると思って良さそうです。<br />
(C言語の速さはぶっちぎり)<br />
<br />
なお、言語の処理速度とは難しいもので、処理内容によっても得意不得意があります。<br />
例えば、<span style="color: blue;"><b>「文字列の処理ならこっちの言語の方が速いが、計算処理ならそっちの言語の方が速い」</b></span>なんてこともあるので、一口に速い遅いとは言えないのですが……。<br />
<br />
ともかくPythonは大抵の場合は速いと言われており、特に機械学習がよく使う計算などの機能については定評があります。<br />
<br />
普通に開発していると<span style="color: red;">「言語なんてどれ使っても大して変わらんだろ」</span>というのが正直なところですが、突き詰めていくと違いがあるんですね。<br />
<br />
そんなこんなで、機械学習を習得する道筋は以下です。</div>
<div>
<br />
<ul>
<li>Pythonを覚える。</li>
<li>TensorFlowを導入する。</li>
<li>そこからは普通に実装。</li>
</ul>
<br />
普通に開発です。</div>
<div>
それなりに難しさはあるものの、手も足も出ないような特殊領域の世界ではありません。<br />
<br />
<h2>
続く</h2>
<br />
しかしながら、私はPythonが使えず、現在勉強中の段階です。<br />
<br />
行く行くはTensorFlowを採用した自主開発が出来るようになりたいですが、まだ時間が必要です。<br />
しかし、世の中には「HTTPリクエストを送るだけで結果を貰える」という機械学習のWebAPIサービスも普及しています。<br />
<br />
取り急ぎ機能を使いたい人はWebAPIを利用することもオススメです。<br />
<br />
Pythonの勉強は並行で進行しつつ、次回は機械学習WebAPIについて調査していきたいと思います。</div>
Anonymousnoreply@blogger.com0