AliEaters#8参加レポート

2018年11月14日に行われたAliEaters#8に参加しました。

alibabacloud.connpass.com

今回は11月11日(独身の日)の直後だったので独身の日にまつわるトピックが多かったです。

ではセッションを1つずつ紹介していきます。

(1) Double 11 独身の日を支えるAlibaba Cloudのテクノロジー

f:id:asmsuechan:20181116082553j:plain

Alibaba Cloud Japanの泉さんによる発表です。

泉さんが強調していたのはアリババクラウドは世界最速・最大規模のクラウドプラットフォームで最高の安定性を持っているということでした。これは、独身の日には1兆5000億件の注文があるそうで、このリクエストをサービスを落とすことなく捌ききっていることが根拠になっています。

世界規模で見ると技術的にはアメリカが一番優れているけど実世界への適用という意味では中国が一番優れている、という意見をどこかで目にしたことがあるのですが、こういう面を踏まえると「ああそうだな」って納得させられますね。

もう一つ泉さんが取り上げていたのが「5GBのファイルを10,000サーバに同時に配信する」ためのシステムであるDragonFlyというものです。

DragonFlyというのはP2Pベースのファイル配信システムのことで、これを使うことでアリババ内部ではどんな大きなファイルでも平均12秒でダウンロードできるようになっているらしいです。

ちなみにDragonFlyはGitHubOSSとして公開されています: dragonflyoss/DragonFly

一言感想

さすが中の人!といった感じでアリババのことがめちゃくちゃ分かりやすくまとまっていました。言いたいことが正確で非常に分かりやすかったので私もこんな発表ができるようになりたいです。

(2) 飞天2.0(Apsara 2.0)

f:id:asmsuechan:20181116111049j:plain

前回のミートアップでは開始5分前にノックダウンして帰宅し発表できなかったキングオブMVPことSBクラウドの森さん(@mosuke5)のリベンジです。

独身の日でもキャッシュサーバーとして使われていたApsaraDB for Redisに関しての発表でした。

ApsaraDB for Redisとは名前の通りAlibaba Cloudで使われているRedisのことです。これの裏側はApsaraCacheというアリババに魔改造されてなぜかmemcacheのプロトコルを喋るようになってしまったRedisくんで動いていて、チューニングが効いててパフォーマンスが30%向上しているらしいです。

Redisはキャッシュサーバーとして利用されるためにReadの方がWriteより多くなるから中国リージョンではReadとWriteのインスタンスを分割しているとのこと。

mosuke5さんは「最近英語での情報発信が増えているので、アリババが国際転換を本気で考えている。嬉しい!」と喜んでいました。私も嬉しいです。

一言感想

技術的な話を根拠を込めてしっかり話されていました。さすが技術の人です。

(3) Maker Fair 深圳レポート -無人コンビニの比較-

f:id:asmsuechan:20181116110922j:plain

最近SBクラウドにジョインされた寺尾さんの深セン無人コンビニ比較です。

寺尾さんは深センで行われたMakers Fairに行くため渡中したそうです。なおMaker Fairには「コナンくんが犯人を見つけた時のメガネ」をかけて参加した模様です。

f:id:asmsuechan:20181116111534j:plain

新鮮にあるwell go、f5未来商店、百鮮GO无人超市という3つの無人コンビニに行ったそうです(詳しくは下のスライドにまとまっています・・・!)。

無人コンビニも決済はQRコードベースで行われているらしいです。また、商品の認識はRFIDで行なっているみたいで誤認識を防ぐ目的で陳列感覚が少し広かったとのこと。

無人コンビニは結構カジュアルにサービス停めるみたいで、少し目を離した隙にメンテナンスのためシャッターが閉まってしまっていたって話に中国っぽさを感じましたw

スライド

www.slideshare.net

一言感想

Makers Fair、中国語初心者なのに中国語で説明頑張ったらしくてめちゃくちゃすごいです。。。

日本でも、無人じゃなくていいからセルフレジをもっとたくさん導入してほしいと願っています。

(4) AlibabaCloudとAWSをゴリゴリいじった結果、便利だと思った機能

f:id:asmsuechan:20181116113212j:plain

スカイアーチ大連から出張で来られた金さんの発表です。めちゃくちゃ日本語うまかった。

この発表では名言が飛び出ました。「アリババクラウドの方が"人間的"なサービスだと思います」。うん、人間的!

これはどの層へ向けたサービスなのかが関わっています。AWSは完全にデベロッパー向けですので複雑で結構難しい(けど使いこなせたら最強)、アリババクラウドはシンプルに設定を行うことができるサービスです。

ただ、シンプルなのはそもそも機能がまだ多くないことが大きな理由です。

あと、シンプルだと明示的に裏側の設定が決められてしまいデフォルトではちょっと高めの課金が行われるってところもちょっと狙われてそうですw

発表で上げられた機能で気になったのは下の2つです。

  • SLBのWeight設定。デフォルトの優先度は100で、この値によってリクエストを振り分ける優先度を決めてくれる。
  • ISP回線の設定。ここを変えるだけでサービスの国際化が楽にできる。

SLBのWeightを変えることで、サーバーのスペックによって振り分けの対象を変えることができるようになります。コストの最適化に有効ですね。

サービスの国際化は金盾がある中国ならではですね。

一言感想

最後にスカイアーチさんへのお問い合わせ窓口のスライドがあってよかったですw

(5) アリババクラウドでサーバレス頑張ってモバイルアプリを作った

f:id:asmsuechan:20181116115125j:plain

私の発表です。詳しい話はAlibaba Cloud Advent Calendar 2018の12/3で書くつもりです!

今回も発表前にビール1リットルくらい飲んでコンディションを整えて臨みました。

簡単に言うとアリババクラウドでFunction Computeを使ってサーバレスやった中での学びやつらみの話でした。

正直この辺の話は実装中戸惑った時に知りたい話なので、その時ググって私のブログ記事を読めば解決します。みなさんアリババクラウドでサーバレスやっていきましょう!

(6) アリババクラウドMVP表彰

アリババクラウドコミュニティへの貢献者に与えられたアリババクラウドMVP(Most Valuable Professional)の表彰式が行われました。

f:id:asmsuechan:20181116120809j:plain

私もいただきました、ありがとうございます!

アフターパーティー(って言うとちょっとカッコよくなるけど普通の懇親会)もめちゃくちゃ盛り上がって楽しかったです。

次回は12月12日です。残り枠少なめなので興味のある方はお早めに!

alibabacloud.connpass.com

Babel7でES6のテストをmochaで走らせようとすると Cannot find module 'babel-core/register'

Babel7でES6のテストをするためにmochani --compilers js:babel-core/register" をつけて実行したところ以下のエラーが起きました。

$ yarn run test
yarn run v1.5.1
(node:86730) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
$ mocha --compilers  js:babel-core/register
internal/modules/cjs/loader.js:583
    throw err;
    ^

Error: Cannot find module 'babel-core/register'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:581:15)
    at Function.Module._load (internal/modules/cjs/loader.js:507:25)
    at Module.require (internal/modules/cjs/loader.js:637:17)
    at require (internal/modules/cjs/helpers.js:20:18)
    at program.compilers.forEach.c (/Users/asmsuechan/src/bot/node_modules/mocha/bin/_mocha:503:3)
    at Array.forEach (<anonymous>)
    at Object.<anonymous> (/Users/asmsuechan/src/bot/node_modules/mocha/bin/_mocha:495:19)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)
    at startup (internal/bootstrap/node.js:236:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:560:3)
error An unexpected error occurred: "Command failed.
Exit code: 1
Command: sh
Arguments: -c mocha --compilers  js:babel-core/register
Directory: /Users/asmsuechan/src/bot
Output:
".
info If you think this is a bug, please open a bug report with the information provided in "/Users/asmsuechan/src/bot/yarn-error.log".
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

以下のような設定です。

// package.json
  "scripts": {
    "test": "mocha --compilers js:babel-core/register",
    "deploy": "serverless deploy",
    "build": "babel scripts/* -d dist"
  },

  "devDependencies": {
    "@babel/cli": "^7.1.5",
    "@babel/core": "^7.1.5",
    "@babel/preset-env": "^7.1.5",
    "aws-sdk": "^2.9.0",
    "chai": "^3.5.0",
    "chai-as-promised": "^6.0.0",
    "mitt": "^1.1.3",
    "mocha": "^5.2.0",
    "sinon": "^7.1.1"
  }

// .babelrc
{
  "presets": [
    [
      "@babel/preset-env"
    ]
  ]
}

解決

Babel公式の Upgrade to Babel 7 に書いてありました。

The deprecated usage of babel-core/register has been removed in Babel 7; instead use the standalone package @babel/register.

yarn add --dev @babel/register してscriptsを"test": "mocha --compilers js:@babel/register" としたら通るようになりました。

なお、mochaの --compilers オプションはいずれ使えなくなるらしいので --require @babel/register にしましょう。

アリババクラウドで作ったサービスを公開して1ヶ月でかかった料金

みなさん気になるお金の話です。

私は今サーバレス+RDSでサービスを公開しています。このサービスが1ヶ月で消費した値段を公開します。

結論

サービスを公開して1ヶ月で4000円分程利用しました。

作ったサービスの構成

ざっくりと、こんな感じです。

f:id:asmsuechan:20181029115611p:plain

作ったサービスの規模

SNSなのですが人がいません。

(そもそも集客していません。まだプロモーションうまく考えていないためスマホアプリリリースした後誰にも知らせないまま放置しちゃってます)

集計の期間

集計の期間は9月1日から9月30日までです。

開発開始: 9月1日
リリース: 9月21日

サーバレスな環境にしたので開発でもほとんどお金はかからないと思い最初からクラウドで動かしていました。

内訳など

まず、料金・支払い管理の利用状況です。

公開したサービスで使用しているリソースとドキュメントに書いてある値段を以下の表に示します。

サービス名 ドキュメントの値段(円) 実際の値段 備考
Function Compute 0 0.024 100万リクエスト/月まで無料
API Gateway 0 0.196 100万リクエスト/月まで無料
ApsaraDB for RDS 3600 3604.930 rds.mysql.t1.smallを利用
Alibaba Cloud DNS 0 0
OSS 0 0.074 5GBまで無料
Log Service 0 296.796 ログファイル500万
合計 3700 3902.02

Log Serviceが想像以上に使ってましたね。まあ許容範囲内です。

ちなみにFunction Computeの微妙な課金は開発環境と本番環境のInternetOutで生じたものです。

まとめ

日本のアリババクラウドは今ミートアップなども含めて無料で使えるクーポンを配布してくれています。このクーポンのおかげで今のところほとんどお金を払わずに済んでいます。

クーポンが気になる方はアリババクラウドのミートアップに顔を出してみましょう!(本記事はクーポンをいただけることを保証するものではありません)

alibabacloud.connpass.com

.apkファイルに署名できない問題

.apkファイルの中の署名鍵を消しましょう。

$ jarsigner -verbose -keystore app/myapp.keystore app/build/outputs/apk/app-release.apk myapp
Enter Passphrase for keystore:
jarsigner: unable to sign jar: java.util.zip.ZipException: invalid entry compressed size (expected 20224 but got 20510 bytes)
$ zip -d app/build/outputs/apk/app-release.apk META-INF/\*
deleting: META-INF/CERT.RSA
deleting: META-INF/CERT.SF
deleting: META-INF/MANIFEST.MF

参考

stackoverflow.com

Alibaba CloudのFunction Computeに環境変数を設定する方法

Function Computeに環境変数を設定するためにはtemplate.ymlにEnvironmentVariablesセクションを追加します。

例えば、NODE_ENV=productionを追加したいときはtemplate.ymlに以下を追加します。

EnvironmentVariables:
  NODE_ENV: production

以下はtemplate.ymlの全文です。

# template.yml
ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Resources:
  MyServicei: # service name
    Type: 'Aliyun::Serverless::Service'
    Properties:
      Description: 'fc for auto testing'
    graphql: # function name
      Type: 'Aliyun::Serverless::Function'
      Properties:
        Handler: index.handler
        Runtime: nodejs8
        CodeUri: './'
        Timeout: 60
        EnvironmentVariables:
          NODE_ENV: production

  MyFunctionGroup: # group name
    Type: 'Aliyun::Serverless::Api'
    Properties:
      StageName: RELEASE
      DefinitionBody:
        '/':
          post:
            x-aliyun-apigateway-api-name: myapi
            x-aliyun-apigateway-request-config:
              requestProtocol: 'https'
            x-aliyun-apigateway-fc:
              arn: acs:fc:::services/${MyService.Arn}/functions/${graphql.Arn}/

公式のサンプル(github.com/aliyun/fun)が参考になります。

HTTPSに対応したAlibaba CloudのAPI GatewayがAndroidでNetwork request failedする問題

API GatewayHTTPS化したらreact-nativeのAndroidアプリからfetchできなくなってしまいました。

HTTPへのリクエストは成功するのですがHTTPSへのリクエストを送ると以下のエラーが出てしまいます。

TypeError: Network request failed
    at XMLHttpRequest.xhr.onerror (blob:http://localhost:8081/2cf03b53-c0b2-404c-8dda-906f61a7d7ee:27276:18)
    at XMLHttpRequest.dispatchEvent (blob:http://localhost:8081/2cf03b53-c0b2-404c-8dda-906f61a7d7ee:29368:27)
    at XMLHttpRequest.setReadyState (blob:http://localhost:8081/2cf03b53-c0b2-404c-8dda-906f61a7d7ee:29121:20)
    at XMLHttpRequest.__didCompleteResponse (blob:http://localhost:8081/2cf03b53-c0b2-404c-8dda-906f61a7d7ee:28948:16)
    at blob:http://localhost:8081/2cf03b53-c0b2-404c-8dda-906f61a7d7ee:29058:47
    at RCTDeviceEventEmitter.emit (blob:http://localhost:8081/2cf03b53-c0b2-404c-8dda-906f61a7d7ee:3707:37)
    at MessageQueue.__callFunction (blob:http://localhost:8081/2cf03b53-c0b2-404c-8dda-906f61a7d7ee:2593:44)
    at blob:http://localhost:8081/2cf03b53-c0b2-404c-8dda-906f61a7d7ee:2370:17
    at MessageQueue.__guard (blob:http://localhost:8081/2cf03b53-c0b2-404c-8dda-906f61a7d7ee:2546:13)
    at MessageQueue.callFunctionReturnFlushedQueue (blob:http://localhost:8081/2cf03b53-c0b2-404c-8dda-906f61a7d7ee:2369:14)

ドキュメントやissueやらを読み漁って悩んでいると、以下のコメントを見つけました。どうやら証明書が間違っている時にもこのエラーが出るそうです。

github.com

解決法

中間CA証明書とクロスルート証明書を追加したら解決しました。

さくらのRapidSSLだとこの2つの証明書はここにあって、それぞれコピペします。

そしてAPI GatewaySSL証明書を追加するテキストエリアに以下のように証明書を3つまとめて入力します。

-----BEGIN CERTIFICATE-----
SSL証明書
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
中間CA証明証
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
クロスルート証明書
-----END CERTIFICATE-----

これで私は通信できるようになりました。

参考

qiita.com

Alibaba CloudのAPI GatewayをHTTPS化する

独自ドメインを設定したAPI GatewayのエンドポイントをHTTPS対応させます。なお、Function Computeをバックグラウンドで動かしています。

基本は以下の公式ドキュメントを参考にしました。

jp.alibabacloud.com

SSL証明書の取得

私はさくらのRapidSSLで取得しました。SSL証明書買ったの久々です。

CSR作成なんかは完全に忘れていましたので以下を参考にしました。

qiita.com

サーバー認証

API Gatewayでちょっと苦労するのがサーバー認証キーのアップロードです。

普通のサーバーのようにファイルをアップロードすることはできないので、API Gatewayのエンドポイントを/.well-known/pki-validation/fileauth.txtと設定してGETで認証キーを返すようにします。

webコンソール画面からだとAPI Gatewayのエンドポイントに/.well-known/pki-validation/fileauth.txtを設定することができなかった(多分ドットがバリデーションエラーになる)ので、template.ymlを使ってデプロイします。

ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Resources:
  MyService: # service name
    Type: 'Aliyun::Serverless::Service'
    Properties:
      Description: 'my fc'
    myfunction: # function name
      Type: 'Aliyun::Serverless::Function'
      Properties:
        Handler: index.handler
        Runtime: nodejs8
        CodeUri: './'
        Timeout: 60

  MyFunctionGroup: # group name
    Type: 'Aliyun::Serverless::Api'
    Properties:
      StageName: RELEASE
      DefinitionBody:
        '/.well-known/pki-validation/fileauth.txt':
          get:
            x-aliyun-apigateway-api-name: myfunction
            x-aliyun-apigateway-fc:
              arn: acs:fc:::services/${MyService.Arn}/functions/${myfunction.Arn}/

index.jsはこちらです。

module.exports.handler = (event, context, callback) => {
  callback(null, { statusCode: 200, body: 'YOUR KEY IN fileauth.txt' });
};

API GatewayのFunction GroupにSSL証明書を追加する

画面をポチポチしてSSL証明書を追加します。

Function GroupからSSL証明書を追加します。 f:id:asmsuechan:20180912160130p:plain

秘密鍵はパスワードを削除する必要があります。 f:id:asmsuechan:20180912161000p:plain

HTTPSで通信できるようにする

次にAPI GatewayHTTPSを受け取るように変更します。template.ymlで設定を定義している人は画面からでは変更できません。template.ymlを変更しましょう。

template.ymlに以下を追加します。

            x-aliyun-apigateway-request-config:
              requestProtocol: 'https'

以下はtemplate.ymlの全体です。

ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Resources:
  MyService: # service name
    Type: 'Aliyun::Serverless::Service'
    Properties:
      Description: 'my fc'
    myfunction: # function name
      Type: 'Aliyun::Serverless::Function'
      Properties:
        Handler: index.handler
        Runtime: nodejs8
        CodeUri: './'
        Timeout: 60

  MyFunctionGroup: # group name
    Type: 'Aliyun::Serverless::Api'
    Properties:
      StageName: RELEASE
      DefinitionBody:
        '/':
          get:
            x-aliyun-apigateway-api-name: myfunction
            x-aliyun-apigateway-request-config:
              requestProtocol: 'https'
            x-aliyun-apigateway-fc:
              arn: acs:fc:::services/${MyService.Arn}/functions/${myfunction.Arn}/

これをfun deployしたらHTTPS対応が完了します。

Tips

curlを送った時のレスポンスのserverがTengineならFunction Computeまでリクエストが渡っていて、nginxならAPI Gatewayがレスポンスを返しています。