複数のRecyclerViewで巨大なリスト扱ってめちゃくちゃ死にまくったまとめ

前提 : RecyclerView

いわゆるVirtualScroll実装。
Viewの初期化時の計算や転送コストを下げつつ、画面に表示されるリストを「見えてる分だけ」に制限してリストのガワを最大限再利用することで、レイアウトのレンダリングコストを下げる実装。
似たような機構はiOSやwebでの無限スクロール系ライブラリにもある。
VirtualDOM的なアレとは非なる。

アンチパターンと解決

画像の再利用をしない

  • 問題
    リストの行を表現するxml上で直接drawableフォルダ内のimageリソースを指定したりすると、レイアウトの初期化時にどんどんメモリが確保されていってやがてOOMを迎える。
    また、新しいリストの生成時にも画像の確保コストでUIスレッドがブロックし、なんかカクカクするようになる。

  • 解決
    面倒でもPicassoやGlideなどのライブラリを使いながら、コード側で随時画像キャッシュを使ってリスト内の該当箇所にimageを当てていく。
    と言うかAndroidにおいて直接imageviewにbitmapをアタッチすることは根本的にアンチパターンだと思っておく。確保時にOOMで死ぬ。

Picassoなどは内部にWeakMap?的な実装を持てるため、割り当てたメモリ上限を超えると勝手にアクセス頻度の少ないものは捨ててくれる。

// インスタンス実装
ActivityManager am = (ActivityManager) MainApplication.getApplication().getSystemService(Context.ACTIVITY_SERVICE);
boolean largeHeap = (MainApplication.getApplication().getApplicationInfo().flags & ApplicationInfo.FLAG_LARGE_HEAP) != 0;
int memoryClass = am.getMemoryClass();
if (largeHeap && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    memoryClass = am.getLargeMemoryClass();
}
int cacheSize = 1024 * 1024 * memoryClass / 8;
Picasso picasso = new Picasso.Builder(MainApplication.getApplication()).memoryCache(new LruCache(cacheSize)).build();
Picasso.setSingletonInstance(picasso);

// 画像当てこみ

Picasso.with(view.getContext())
    .load(hashMap.get("url"))
    .resize(size ,size)
    .into((ImageView) imageView);

リストの追加通知にとりあえずnotifyDataSetChanged()を叩く

  • 問題
    VirtualScrollとVirtualDOM的なアレと同じような感じでとりあえず adapter:::notifyDataSetChanged()を雑に叩くと計算コストが半端ない。
    予期せぬリストまでviewが再生成されたりする。
    今までのアプリでは実は表示するものの数が大したことないので割と問題なかったが、複数タブにそれぞれ複数のrecyclerView実装を抱えて、なおかつ巨大なリスト群を扱うとスレッドがブロックする。

  • 解決
    多少実装が複雑になっても myAdapter.notifyItemRangeInserted(lastCount , newCount); など適切に追加/変更を伝える必要がある。
    ただし最近はAdapterに食わせるviewModelにidを与えておくことで、雑に notifyDataSetChanged() を呼んでも問題ないような作りになってきているらしい(試してない)

スクロールリスナー動きすぎ問題

  • 問題
    無限スクロール実装のために、スクロール時に全体のリスト数と表示されているアイテムのindexを監視している。
    数十ms間隔でイベントが来る時とかもあって、そんなに毎回計算が要らない。

  • 解決
    現在時間を使う。 new Date().getTime() あたりを使って、適当に前の時間との差分を取りながらスロットルする。
    リスナー内であまり複雑なことをしないなら必要ないかも。

setHasFixedSize(true)を設定しない

  • 解決
    特に必要がなければデフォルトで設定しておく。

行内のインタラクションのためにnotify~系を叩く

  • 問題
    別の場所で起こったインタラクションなどをリスト内の行viewに反映させる時、前述の notifyDataSetChanged()だともちろん重い。
    アダプターの機構でrangeをとって更新でもいいけど正直管理が複雑なのと融通が利かないのがある。

  • 解決
    リストで表示された各行Viewの onAttachedToWindow() , onDetachedToWindow() ライフサイクルイベントで、適当なObserverパターン実装を購読し、各行viewが自分で差分を計算したほうが個人的には融通がきくと思われる。
    なんか負けた気がするけど。
    画面上に表示されているものだけになるので、observer側でたくさんイベントが走ろうが走査数は実は大したことないはず。

VideoView , 横スクロールページャーなどをリストの一部に実装する

  • 問題
    スライダーやVideoViewがリストの一部になると、画面から出た際に随時detacheされ、状態が初期化してしまう時。

  • 解決

 RecyclerView:::setItemViewCacheSize(i : int);

のサイズを必要な分大きくしておくか、リスト再生成時に、適切に状態を復元する機構を用意しないといけない。
特にVideoViewはPlayer部分とレンダリングされるViewを分離しなくてはいけないので、ちゃちゃっとビデオ表示したい用途だとだいぶ面倒くさそうだけど。
多分にステートフルなコンポーネントだとまあしょうがないという気はする。

無限スクロールでどんどんメモリに行情報溜まっていくよ問題

  • 問題
    別にAndroidに限ったことではないが、無限スクロール実装でだんだん表示すべきdataのリストが貯まっていく。

  • 解決
    リスト内で表示しないものは、行情報の取得時に別スレッド側であらかじめプロパティをどんどん捨てておく。サーバー側で抜けるならサーバー側で。
    description , リリースノートなど巨大な文字列を有するものには割と効く。
    あとは保持しているリストの上の方の過去のデータを適切に消したり、SharedPreference的なところに一時的に書き出しておく、などの実装が考えられる。結構複雑になりそうのでやってないけど。

Read More

[AWS Summit Tokyo 2017 Day3] AWSが支えるEightのリコメンデーションエンジンの裏側

名刺管理で有名な株式会社SanSanさんのアプリ、「Eight」での事例です。
とても濃い内容で、StepFunctionsの待ち受け運用とか非常に参考になりました。

ビジネス

  • 個人向け名刺管理アプリ、Eight
  • 名刺の唾がりをビジネスに変える/つながった相手とコミュニケーション
  • 日本の名刺交換の10%をさばいている!(!)
  • 名刺交換のUpdate.相手が転職しても繋がりを維持する
  • 「つながり」をリコメンデーションエンジンで

問題/旧リコメンデーション

  • RedshiftとEC2上のリコメンド計算エンジンで計算、CloudSearchでリコメンド
  • Redshift、複雑怪奇なクエリ、集計性能に依存
  • CloudSearch,全文検索エンジンとしてではなく関係性スコアのソートのみに使っていた
  • パフォーマンスダウン!
  • オペレーションコスト!

リコメンドアーキテクチャ刷新。

  • データ分析
  • アルゴリズム
  • リアルタイム性 <= もっともここを大事に

リアルタイムリコメンデーションエンジンを作り直そう

  • ログデータは今まで通りRedShift
  • 中間データ更新にKinesis + Lambda
  • 中間データはDynamoDBをストレージに

  • => 2ヶ月でできた!

構成

ストリーム
* Kinesis,DynamoDB Stream
コンシューマ
* Lambda
ストレージ
* RedShift,DynamoDB,ElastuCache

  • 名刺間のレーテイングデータをひたすらDynamoとLambdaで生成する。
  • データが更新されたらSQS発火、EC2上のワーカーが中間データから実際のリコメンドデータを生成

コツ

  • KinesisはPut Recordsでリクエストをまとめる
  • メモリ設定でリソースを増やす
  • DynamoDBはなるべくBatchWriteを使う
  • パフォーマンスが大幅に改善された

  • Function数の増加問題

    • Functionをシンプルにしすぎると数が増えすぎて管理できない問題
    • ある意味Function内でルーティングすることでストリームの種類によって処理を分岐する
  • ストリーム – コンシューマ問題
    • StreamとLambdaがお互いを維持できるバランスにならない
    • ストリームをLambdaが書き直して差戻すFunctionを作る(分身の術)

残った問題と解決

  • レーティングデータの陳腐化
  • アルゴリズムが変わり中間データの価値がなくなる
  • RedShiftにある過去ログから全て中間データを作り直した! => Data Pipelineを利用して数時間で再生成!
  • リコメンドのマイグレーション

    • まずLambdaを停止
    • 再生成してから再起動
    • まるで心臓バイパス手術
    • ダウンタイムなしでやるにはワークフロー大事
  • そこでちょうどリリースされたAWS Step Function

    • Lambdaの処理完了
    • DataPipilineの処理まち
    • タイムアウトはStepFunctionの定間隔リトライが使える!!!!!!!!

サーバーレスの利点

* スケーラブル
* 柔軟性
* 気軽さ

Read More

[AWS Summit Tokyo 2017 Day3] AWS Lambdaで変わるバッチの世界 – CPUトータル100時間を10分で終わらせるには –

ERPの開発をしている 株式会社ワークスアプリケーションさんでの事例です。
どちらかというとエンタープライズ向けっぽい会社さんですね。
ClosureコンパイラをLambda上に載せる、VPC多用の必要がどうしてもある、あたりがならではという感じで面白かったです。

事例

  • 画面の高速描画のための前処理

問題

  • HTML,JS,CSSの最適化
  • HTMLテンプレートの事前コンパイル
  • よくある構成
    • Hadoop,Spark,インスタンス並列化
    • ガチでやると100時間
    • 長い!コスト高い!
    • 終わらないインスタンス最適化作業
    • 10分で支度しな(意訳)

そこでLambda

Lambdaの特徴

  • スケーリング管理コスト0
  • インスタンス管理コスト0
  • 100ms単位の課金
  • 選べるランタイム / 箇所ごとに柔軟に言語を選ぼう
  • 流動的な分散数と処理時間にマッチ
    => やってみようと思った

Lambda

  • Before: 以前の処理
    • javaのwebフレームワークが画面のリストを作成/HTMLを最適化/jsのコンパイル/cddのコンパイル
    • この辺のフローが同期的
    • 画面が大きくなるとスケールしない
    • Closure CompilerをSpringFWで動かしていた
    • Less(CSS)コンパイル => SpringFW上で動作
  • After: 最適化
    • jar作成時にコードにキャッシュしとける情報はする
    • HTMLを最適化するだけのfunctionとして整理
    • GoogleClojureコンパイラ単体で動作するFunctionに
    • LessのコンパイルのFunctionはnodejsとして分離

SpringFrameworkをLambdaで動かすか否か

  • ガチで動かすと占有時間が長い
    • => そこでコンストラクタだけを使う
  • コンテナのコールドスタートも適切に利用
    • => 初期化処理にシングルトンを利用して余計な処理を省く

起動とプロセス管理

  • S3にファイルをputすることで処理を与える。
  • 実行ファイル名のサフィックスで処理の分岐を行う
  • ピタゴラ処理のエビデンスにPending,RunnningなどステータスをS3に随時吐く(!)
  • 進捗はs3上に置いたプロセス進捗ファイルだけをlistすることで確認する

Trouble Shooting

  • 速度は思ったより早くない

    • 128MB => 1546MB
    • CPUパワーはメモリ容量に比例 1.5GBだと2コア/3コア利用可能
  • 同時実行数上限3000で運用
    だが、実行数が上がらない,なぜ。。。 => VPCのせい

  • Lessのコンパイルがエラー

    • Lambdaの起動よりS3のPut時間が後の場合があった <= !?
    • s3のイベントを使う場合は結果整合性であることを忘れないように
  • s3のイベントが登録されていない

    • Ansibleで1つのbucketに100Function設定しているはず
    • 1この登録を1回回すんじゃなく1度で100イベント登録したらうまくいった
  • 想定金額より多い

    • Cloudwatch Logsのログのせい

デプロイ

  • nodeはzip,javaはjar
  • お客さんごとに別VPC/1bucket。イベント当てるのはAnsibleでやる

まとめ

  • 10分半になった!

課題

  • 今度はDBがスケールしなくて高負荷に耐えられない問題

Read More

[AWS Summit Tokyo Day3] AWS Lambdaを使ったモバイルバックエンドのサーバーレス開発事例

「株式会社ワイヤアンドワイヤレス」さんでのモバイルアプリのバックエンドのサーバーレス化の事例をお聞きしてきました。
ロギングやデプロイフローなど、みんなどうしてるんだろー?って思ってところが概観できたと思います。

ビジネス

  • 公衆WIFI事業者
  • TRABEL_JAPAN WIFI
  • 外国人旅行者向け。国内にはユーザー動向や広告配信を提供

システム構成

  • v1
    • ELB,EC2等を利用した一般的な構成
    • ロジックがクライアントに集中してしまっていいた
  • v2
    • ELBをもうひとつ前に
  • v3
    • API GatewayとLambdaを全面に出した

サーバーレス?

  • 用意するものはコードと構成パラメータ
  • API Gateway通った上でEC2で
  • 基本はAPI Gatewayを前に置くベース
  • Dynamo,S3への書き込み

API Gareway / Lambdaの実装方針

  • Lambdaファンクション自体は同じものを使って、ビルドスクリプト側で環境を分ける

苦労した点

  • Lambdaの起動時間 (Java)
    • VPC内の運用、ENIをアタッチする時間が膨大
    • CloudwatchのイベントでVPCないのLambdaを定期的に起動してあっためる
    • 起動時間が短縮される
  • Gatewayのレイテンシ
    • 常に同期処理になるのでAPI Gatewayとの相性は良い
    • なのでLambdaを非同期でつなぐことで処理が一定になる
  • E2Eテスト問題
  • ログ/エラー箇所の問題

APIのリソースとLambdaのデプロイ

  • API GatewayはSwaggerで管理できる
  • APIリソースとlambdaを1対1にした
  • 負荷が高い時は例外的に別の関数
  • SAMを使っている

Lambda関数の言語間検証

  • JVM系はまあ遅い
  • CPUがっつり使う処理があればJavaとかのが早いかも

Lambdaのテスト

  • ユニットテスト
    • AWSサービスのモックを内製
    • pythonのMagic Mock
    • あるいはAWS上に環境を準備
  • クラウド使ってるんだから
    • モック使わずに
    • SAMでサービスをデプロイ
    • テスト終わってから殺す

パッケージング/デプロイ

  • プレフィックスをつけて試験/本番をデプロイ
  • SAM => GitLab => Jenkins

ロギング

  • aws-cli/jqでパースする
  • アプリケーションログにはrequestIdを出力
  • X-Rayでトランザクション数/Durationが確認可能
  • agentが入れられない代わりにx-rayがある

まとめ

  • 導入に関しては開発のシステム構成の概念が違うためそれなりの学習は必要になる

Read More

[AWS Summit Tokyo 2017 Day3]バイタルデータの意味付けと言う荒波を乗り終える!適切な処理分担のためのサーバレスアーキテクチャ

最終日です。暑すぎじゃないですか。本日はサーバーレスに特化したセッションを中心に回っていく予定です。

本稿では、株式会社JINSさんのウェアラブルデバイスと、そのデータ処理におけるサーバレス環境の利用についてのセッションをレポートします。

商品「JINS MEME」

  • JINSのウェアラブルメガネデバイス
  • 集中/瞑想/覚醒などの情報を読み取る(!)
  • それを客観的に見ることで自分のバイタルを管理していこうぜ、というプロジェクト。
  • 頭部加速度/回転角/瞬き/視線移動/周波数 などの情報をSDKで得られる。
  • メガネ => スマホ => クラウドに送信

バイタル(生体データ)

  • バイタルデータの中で心拍センサーは枯れているのでよく使われている
  • バイタルデータは本来めんどくさい。
    • 心拍/脈拍 => 枯れている/周期性がある。ノイズデータが消せる
    • モーション => パターン認識。機械学習。めんどくさい。
    • 眼電位/脳波 => ノイズがある。統計/機械学習が必要。めんどくさい。
  • 眼電位の生データはノイズが多くデータ量が多い!
  • バイタルデータならではのレイヤーの深さと通信制約 => そのままではなく概観したデータを圧縮しないといけない。
  • ウェアラブル端末ならではの機能制約にかなり苦しみがある

サーバー側アーキテクチャへの落とし込み

  • スケーラビリティを保つため、キューとバッチではなくストリームの逐次処理化したい
  • リアルタイム/ステートレス化して差分アルゴリズムを整える
  • 「売れるか売れないか」わからない状態で構成を組むことに難があった => Lambdaの使用
  • Rはサーバレスアーキテクチャと相性が悪い大量データのバッチ式処理
  • Shiny を利用して分析しながらの開発

ウェアラブルに足を突っ込んできての雑感

  • 分業が進み過ぎていてインテグレーションは大変
  • 最新のツールを利用して理解できる範囲を広げる
  • AWSを利用することで集中したいものに工数をさく

感想

ステートレスなFunction構造がはまるところと逆に相性が悪いところ、その辺の事例が確認できました。
利用の際はその辺を意識していきたいと思います。

Read More

[AWS Summit Tokyo 2017 Day3] ECSでコンテナ化と Terraform でインフラコード化した話

「株式会社インテリジェンス」 さんでのオンプレからAWSの導入事例のセッションの中で、
コンテナ化や infrastructure as code の話が出てきて面白かったので記します。
弊社もこの辺の整備は挑戦していきたい。

課題

  • 2016年4月以前

    • レガシーインフラ!
    • グループ共通のオンプレ基盤
    • 子会社に随時スケール依頼/調査依頼投げる
    • スケールしない
    • 秘伝のタレ
    • ブラックボックス
    • 積み上がることで新しいサービスを始められるスピードが逆に下がっていく
  • 移行作業

    • DevOpsチーム4名
    • ぽんぽん依頼投げられて集中できない
    • エンジニアだけでなく会社としての協力
    • 移行デーを週に2日設けてそれに集中する
    • 2016年11月に移行開始 => 2017年4月完了

アーキテクチャ

  • ALB , ECSによるnginxコンテナ , マカレル、等々。

Terraformによるプロビジョニングを導入

  • 古参メンバーの秘伝のタレをterafform化。
  • infrastructure as code.
  • terraformを導入して困ったところは一部あった
    • dry run と実際のプロビジョニングとの結果が違うことがあった
    • 当時はアップデートが頻繁だった

ALB & コンテナ

  • ALBとECSとの親和性が良い
  • nginxコンテナ
  • なせコンテナにしたか?
    • 依存関係が明確に分離。
    • 開発と本番の環境が一致する。
    • スケールするのが簡単
  • blue green developmentがすごい
    • 3つのコマンドで完了
    • ALBにつながっているバージョン1のコンテナが徐々に減らされていって、バージョン2のコンテナが徐々にぶら下がっていく
    • 戻すときも同じ作業なので簡単

Aurora

  • はじめは MySQL on RDS にしようとしていたが、性能と監査ログの機能からAuroraに決めた
  • 移行にかんしてはAWSのサポートにどんどん聞く

監視

  • プロセス監視 => mackerel
  • ログ監視 => fluentd
  • アラートをSlackに飛ばす

NFS

S3 + goofys に移行した
* とてもいいことがあったわけでもないのでEFS早くきてほしい

小さく素早く始める

  • とにかく素早くstagng構築
  • 2段階で移行
    • 旧環境と新環境で並列稼働させる

移行して良かったか?

YES

  • ブラックボックスが全てプロビジョニングコードに落とし込まれた
  • ハンドリングが可能
  • 全てが透明
  • 市場変化に楽しく対応できるようになる

Read More

[AWS Summit Tokyo 2017 Day3] EPSONにおけるサーバーレスアーキテクチャ導入事例

Day3です。コンピューターのバッテリーがやばいです。
ブロックチェーンやKinesisに関してのセッションを今日は拝聴していました。
本稿では、EPSON社のサーバーレスの導入事例のセッションの様子を記そうと思います。

サービス

プリンターからのレシートを解析、DB上にストアするアプリケーション
その情報をネイティブアプリから見れるサービス

課題

AWS上でサービスを展開する上で、オンプレの思考のまま設計
Web API => EC2インスタンスにwebアプリを置いてビジネスロジックを持ち込む => RDSにレシートデータ蓄積

  • 密結合
  • 毎回インフラ側にスケール依頼をしていて立ち行かなくなってきた
  • 同期処理でのブロック処理

プリンシプル

  • スケーラブルにする
  • サービス間を疎結合にする
  • マネージドサービスの活用

アーキテクチャ

AWSのマネージドサービスをフル活用することで活用する
(ほぼ)世界の各ロケーションでフルスケーラブル/高可用の環境が構築できた。

  • 情報の格納

    • プリンター => EC2 => Kinesis => lambdaでレシートをS3に格納
    • s3のレシートのputからSQSを発火、AWS Beanstalk上のworkerで解析。
    • 解析結果をさらにKinesis Streamに入れ込み、Auroraへ格納
  • ユーザーアプリからサービスにアクセスする

    • 実際にユーザーのクライアントアプリからレシートの検索結果を見る。APIGateWay/LambdaでAPIを書いている。
    • このLambdaはS3やAuroraにアクセスしてユーザーに情報を返す。
  • システムのOverViewを作っておくと、自分が今何をしているのかとか、

  • 本格実装して半年で軌道に乗った

「新しい作り方」に会社として向き合うには

  • 啓発/習得/権限
    • 背中を押す経験 -> ワークショップの開催
    • ベンダーロックインの議論にははじめの実績で答えを出す
    • 権限と責任範囲を明確にした
    • 細かく作って細かく壊す
    • ビジネスロジックを最適に分割/コスト資産

まとめ

  • ビジネスは容赦なく変化し、アーキテクチャは破綻する
  • 踏み出す勇気と受けいれる心
  • 現実的なフルスタックエンジニアリング
  • サーバーレスによって「担当範囲のスコープ」だけでなく「価値提供に集中できるチーム/メンバーが自己成長できるチーム」が出来上がった

Read More

[AWS Summit Tokyo Day2] 中堅企業での事例に学ぶAWS活用サクセスストーリー

AWS Summit Tokyoが始まりました!
これから3日間、気になった講演ごとにメモしたことをレポしようかな!と思います!

早速始めます。

表題の通り、最初の記事は 中堅企業での事例に学ぶAWS活用サクセスストーリーです。


Rekognition活用事例 – 千株式会社

AWSへの移行

  • イベントフォトのネット販売サービス
  • 2013-2016にオンプレから移行
  • 大容量の画像をNFSに保持していたのを、 s3に移行した

Rekognitionの活用

  • 深層学習による顔認識サービス

  • 運動会などの膨大な画像の中で、「自分の子供だけこの写真の中から集めたい」という要求への対応

  • 顔に対してcreate_indexする()

  • 現在Tokyo Regeonでサポートされていない => Rekognitionは同リージョンのs3しか使えない
    => そこで、オレゴンで顔index作成後、オレゴンのs3からは画像のレプリカを消すことにした

  • 顔検索APIはcroudfront => API Gateway => Lambda => Rekognition の流れで使う


AWS Direct Connectの活用 コールダイレクト株式会社

  • コールセンターシステム をオンプレからAWS Direct Connectに移行
  • Amazon Connectというクラウド型のコンタクトセンターを使う

東横インIT集客ソリューション

東横インの予約システムの開発をしている会社さん。

セキュリティの担保

  • PCI DSSというセキュリティ要件に準拠した決済システムを構築する必要がある。

  • PCI DSSに準拠してクレジットカード情報等を安全に保持するには? => AWS KMSの利用!

  • オンプレで暗号化すると開発・運用コストが辛い

  • IAMで取り出し、Cloudtrailに取り出し記録が残るのでPCI DSSに準拠できた!


株式会社千代田グラビヤ

社内システムのAWSヘの移行

各SaaSの接続

  • 勤怠システムや社内スケジュールを様々な外部サービスをまたいで使っている。
  • そのHUbとしてMasterのDBをRDS Oracleで保持
  • EBSボリュームの使用

株式会社アトラ工

求人メディアGreenのオンプレからAWSヘの移行

AWS DMSの使用

  • 他社クラウドRDBをマイグレーションするサービスを使って、随時データベースをAWSのAuroraに移行した。
  • ダウンタイムがほとんどなく移行が完了

まとめ

xxxがしたい!という要求があれば、AWSバートナーにどんどん聞いてください!とのことでした。

Read More

Apple DeveloperとiTunes Connectに追加するユーザーとその権限

Apple DeveloperとiTunes Connectに追加するユーザーにはそれぞれ様々な権限を付与することができる。

付与する権限によっては、自分が開発しているアプリ以外の情報やレポート情報などを参照したり、それらを修正したりいろんなことが出来てしまう。

自社アプリしか作ってない場合や少人数で開発している場合は、とりあえずadmin権限もらってよしなにやれば良いんだけど、これが受託開発とかしていると、まぁ、そんなザルな権限を付与してもらうわけにはいかないので、適切な権限をもらうことになる。

ただ、この権限まわりがややこしい上に日本語のドキュメントが古くて使い物にならなかったり、わかりやすい情報が容易に参照できない場所にあったり、あと取引先があまりiTunes ConnectとかApple Developerについて詳しくない場合にはこっちが適切な権限を選んでください、と言うしかなかったりするので、その辺の理解するためにまとめた。

Apple DeveloperとiTunes Connectのそれぞれのユーザー権限の概要

Apple Developerのユーザー権限

Apple Developerはユーザー権限が3種類しかないうえに、3つのうちAgentの権限はApple Developer Programに最初に登録したメールアドレスのユーザーのみなので、基本的に付与できる権限は、AdminとMemberだけで理解は早い。

しかし、シンプル故に細かいユーザー設定が出来ないのが難しい所。

各権限でのできることは以下の通り。

https://developer.apple.com/support/roles/ より抜粋

この表のうち、Memberの白丸は閲覧権限しかないという感じ。

また、Create and Remove Development Certificatesの部分は黒丸で表記してあり、普通に証明書の発行ができるかと思いきや、あくまでDevelopmentの証明書が作れるだけでDistributionの証明書は作れるわけではない。
なのでその場合は、別途Adminユーザーにお願いするしかない。

これを見て分かる通り、Member権限は本当にただ開発するだけで、それ以外は何も出来ない。
各種証明書の発行、Provisioning Profileの発行、テスト端末の登録/管理、ユーザーの登録/管理などができず、基本的に情報の閲覧しかできないので、Member権限はほとんど何も出来ないと言って良いだろう。

また、Apple Developerの権限は、iTunes Connectの権限と違ってアプリ毎に付与ができないので、メンバー権限のあるユーザーでも他アプリの情報/テスト端末情報が見れてしまうのも場合によっては問題かもしれない。

まぁ、他アプリの情報っていってもApp IDや証明書が発行されているかどうかだけだし、テスト端末情報といってもランダムな文字列のUDIDが書いてあるだけなので、実質問題はないのだが。

一応書いておくと、Apple Developerのユーザー追加はしなくても開発することはできる。
ただその場合は、テスト端末の登録、各種証明書の発行、Provisioning Profileの発行を全部してもらって、開発者は証明書とProvisioning Profileを開発機にインストール、XCodeで「Automatically manage signing」のチェックを外して、インストールしたProvisioning Profileを選択しなければならない。

このユーザー登録なしでの開発は、証明書の期限が切れたり、新しいテスト端末を追加しようとしたら、その度に権限を持っているユーザーに対して証明書やProvisioning Profileの発行をお願いしなければいけないので、結構手間がかかる。
なので最低限Admin権限があると取り回しがしやすい。

iTunes Connect

こっちのユーザー権限は全部で7つ。
そのうちLegal権限は最初に登録したメールアドレスのユーザーのみなので実質6つなのだが、複数の権限を付与することが出来る分、話は結構複雑。
とりあえずiTunes Connectのヘルプに書いてあった各権限のできることは以下の通り。

iTunes Connectのユーザー登録ページの?ボタンを押すと出て来る表。
なんでドキュメントにこの一覧が書いていないのか。

このうち、Admin権限は全権限をもっているので他に並列して付与することができず、FinanceとSales、App ManagerとDeveloper/Marketerの権限の組み合わせもできない。
また、AdminとFinance以外はアプリ毎にアクセス権限を付与することが出来る。

以下にざっくりと出来ることと最低限付与しないといけない権限の関係をまとめた。

出来ること 権限
TestFlightの外部テスターの作成/編集 App Manager
アプリ情報の作成と審査の提出 App Manager
アプリ情報の編集 Marketer
アプリ内課金の作成/編集 Marketer
プロモーションコードの作成/編集 Marketer
リリースビルドのアップロード Developer
TestFlightの内部テスターの作成/編集 Developer/Marketer
売上情報/アナリティクスの閲覧 Sales

こんな感じ。

また、ざっくり出来ることの多さで言えば、

Admin > App Manager > Developer = Marketer
Admin > Finance > Sales

という感じだろうか。
左側が上位互換の権限だと考えて良い。

iTunes Connectに関しても、Apple Developerと同じでユーザー登録しなければ開発できないか、というと別にそういうわけではない。

iTunes Connectにアップロードするのが他の誰かであれば、XCodeのOrganizerからアーカイブしたアプリを選択してExportして、アップロードするユーザーに渡せばよい。

アップロードするユーザーは、XCodeに付属の自分のApplication Loaderでアーカイブファイルを取り込んでアップロードすればよい。

ただ、アップロードはMacからじゃないとできないし、Application Loaderとかはバージョンによって最新のアプリを取り込んでアップロードとかできなかったりするので、開発者は最低限Developerの権限ぐらいは持っておくと、アップロードするユーザーとのバージョン調整に手間取らなくて良いかもしれない。

Read More

AWSの各種アラートをSlackで受け取る

多分みんなやっているとは思うけど、自分のためにメモ。

AWSの各種アラートをSNSで設定して、とりあえずSNSに自分のメールを追加して、深夜にひとりメールでアラートを受け取ってるみなさん、それSlackでやりましょう。
CloudwatchからSNSに投げているのであれば、Lambda functionをBlue Printからサクッと作るだけでお手軽にSlackに投稿できますよ!(多分)
~~もうメールとかつらいし駆逐していこう~~

実装の全体の流れ

  1. Slackのアラートを流したいチャンネルにIncoming Webhooksを追加
  2. Lambdaに与えるパラメータの暗号化用にKMSで暗号化キーを作る
  3. Lambdaの実行用にRoleを作る
  4. Slack投稿用のLambda functionを作る
  5. おもむろにアラートを上げる。
  6. みんな幸せ(?)

1. Incoming Webhooksを追加

Slackのアラートを流したいチャンネルに、App DirectoryからIncoming WebHooksを追加。
追加した際に出てきたWebhook URLをメモる。

2. KMSで暗号化キーを作る

IAMのKMSのページに行って、後述するLambdaのパラメータの暗号化用にKMSでキーを作ります。
IAMのページはリージョンがグローバルになるので、KMSのページで作るキーはリージョン毎に作りますので、keyを作るリージョンを間違えないように。
キー管理者とキーユーザーはなくても大丈夫です。
作ったキーのARNをメモる。

3. Lambdaの実行用にIAMのRoleを作る

LambdaでKMSのkeyを使って復号化出来るように、IAMで新しいRoleを作ります。
作るRoleにアタッチするポリシーは以下の通り。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1443036478000",
            "Effect": "Allow",
            "Action": [
                "kms:Decrypt"
            ],
            "Resource": [
                "2でメモったARN"
            ]
        }
    ]
}

4. Lambda functionを作る

Lambdaを作ります。
Blue Printの選択で、’cloudwatch-alarm-to-slack’を選択しましょう。
幸せになります。

環境変数の設定項目で、
slackChannelにSlackのチャンネル名を、
kmsEncryptedHookUrlには暗号化したURLを入れます。

暗号化したURLは次の手順で作ります。
1. Enable Encryption Helpersのチェックボックスをチェック
2. 暗号化キーの選択で、2で作った暗号化キーを選択
3. kmsEncryptedHookUrlのvalueに、1で作ったSlackのWebhookのURLを入れる
4. おもむろに暗号化ボタンを押します。
5. 暗号化されます。

Lambdaのロールはもちろん3で作ったRoleを設定。

5. アラートを上げる

CloudWatchのしきい値を変更してアラートを上げてください。

6. みんな幸せ

市民、あなたは幸せですか?

Read More