投稿者「inamuu」のアーカイブ

Amazon ConnectとLambdaとSendGridで作る電話確認システム

inamuu|2019年06月19日
AWS

こんにちは、SREチームの稲村です。
最近Oculus Questを購入して、日々の運動不足解消に役立てています。
VRの世界は本当に凄いですね。

電話確認システムとは

さて、ランサーズでは、クライアント様とランサー様それぞれの存在証明の一つとして電話確認の実施を推奨しています。
具体的には、プロフィール画面で番号登録した電話から、弊社指定の番号へ電話をかけていただくことで電話確認が行われるシステムです。
今回はそのシステムをAmazon ConnectとLambdaとSendGridへ移行した話をご紹介します。

移行前の構成

移行前は下記のような構成になっておりました。

外部の業者で050番号を契約し、提供された認証情報を使って、AWS EC2のAsteriskを使ったIP-PBX環境が構築されていました。
ユーザーから電話がかかってくると、Asteriskサーバーまで接続されます。
その後、別のEC2のBatchサーバーにあるCakePHPで作成されたShellを使って電話番号のチェックを行い、問題なければDBのステータス更新を行います。
最後にユーザー様へのアナウンス用の音声ファイルの再生を行い、メールサーバー経由で確認結果のメールを送信して終了する仕組みでした。

なぜ移行することになったか

移行することになった経緯として、既存の電話確認のシステムには下記課題がありました。

  1. 電話確認を行うサーバーが1台のSPOFだった
  2. インフラと一部アプリケーションソースが構成管理されていなかった
  3. 検証環境が無かった
  4. 構築時のドキュメントが古くなり、新規での構築が容易では無かった

元々、弊社サービスを通じてランサー様に構築いただいた仕組みだったようですが、構築からすでに5年が経過しており、EC2インスタンスが弊社で唯一のt1系で動いていたこともあり、まずは構成管理を主目的におき、Ansibleでセットアップするところからスタートしました。
しかしながら、構築時のドキュメントが古くなってしまったため残っていたドキュメントの内容ではうまく動かず、新規で検証サーバーを構築するのが困難でした。
その後、しばらく手がつけられずにいたところ、別件でAWSの営業担当からAmazon Connectに関する情報を教えていただき、Lambda連携をすることでAmazon Connectで代替ができそうということを教えていただいたので、思い切ってシステム刷新に取り組むことにしました。

Amazon Connectとは

https://aws.amazon.com/jp/connect/

Amazon Connectはマネージドのコールセンターサービスです。
Webベースで電話の受電、架電がおこなえる上に、東京リージョンに対応しており、日本語のテキスト読み上げも対応しています。
この日本語のテキスト読み上げが自動音声としては大変優秀で、日本語で書いた漢字を含むテキストをそのまま読み上げてくれます。
電話番号は050と0120から選択でき、申請から数分で電話番号が発行されます。
また、元々コールセンター向けのサービスということもあり、受電時の問い合わせフローを作成できる専用のエディターがあり、その画面がとても良くできています。
※下記が問い合わせフローの専用エディターのイメージです。

みずほ銀行のようなメガバンクのコールセンターでも採用されているようです。

https://www.serverworks.co.jp/case/mizuhobank.html

移行後の構成

移行後は下記構成で構築いたしました。

電話の受電、およびユーザーの入力のロジック部分を全てAmazon Connectで設定しました。
と言っても、管理画面でマウスを使ってドラッグアンドドロップでロジックが構成できるので、Amazon Connetを触り始めて数時間で作成することができました。
また、AsteriskのagiというCGIに似たPythonで書かれたファイルと、CakePHPの電話確認用のShellを、LambdaでPythonに統一して作り直しました。
Lambdaでは極力シンプルになるようにして、DBへの処理とメール配信処理(SendGridのAPIを実行する処理)を行い、ユーザーに渡すメッセージのテキストを戻り値として返すようにしました。

Lambdaの起動

LambdaからRDSへ接続するにあたり、VPCに配置する必要があります。
VPCに配置されたLambdaは定期的に呼び出されている場合は終了せずに再利用されますが、しばらくすると終了してしまうことになります。
Amazon ConnectからLambdaへの接続の最大待機時間は8秒で、8秒以内にLambdaが起動しないと電話が突然終了してしまうため、下記を追加してCloudWatch Ruleで引数を何も渡さずに定期実行するようにしました。
※10分おきの設定で問題なく稼働することを確認しています。また、一ヶ月呼び出しても4300回あまりなので、費用もほとんど発生しません。

def lambda_handler(event, context):
    if 'Details' not in event:
        print('keys does not exist')
        return

Lambdaが定期的に呼び出されますが、DetailsがKeyで渡らない限りは何も処理をせずに終了します。
Lambdaの最後の戻り値はjsonでメッセージ用のテキストを渡すようにしており、そのままAmazon Connectに渡されます。
Amazon Connectの次のステップでLambdaから渡されたテキストを動的に読み上げすることで、意図したメッセージをユーザーにアナウンスすることができます。

メールの配信

Lambdaでメールの仕組みを一から作成するにはボリュームがでかいので、すでに社内で利用実績のあるSendGridを使ってメールを送信することにしました。

https://github.com/sendgrid/sendgrid-python

import os
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail

message = Mail(
    from_email='from_email@example.com',
    to_emails='to@example.com',
    subject='Sending with Twilio SendGrid is Fun',
    html_content='<strong>and easy to do anywhere, even with Python</strong>')
try:
    sg = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY'))
    response = sg.send(message)
    print(response.status_code)
    print(response.body)
    print(response.headers)
except Exception as e:
    print(str(e))

上記はREADMEのサンプルですが、見てわかるように大変シンプルなコードでメール配信が行えるようになりました。

その他

AmazonConnectからLambdaを呼び出すには、下記設定をAWS CLIから行う必要があります。

aws lambda add-permission --function-name function:XXXXX --statement-id 1 --principal connect.amazonaws.com --action lambda:InvokeFunction --source-account XXXXX --source-arn arn:aws:connect:ap-northeast-1:XXXXX:instance/XXXXX --profile XXXXX

https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html

まとめ

Amazon ConnectとLambdaとSendGridを使って、電話確認システムの移行が行えました。
検証からリリースまで数週間で出来たことを考えると、とてもスムーズに移行できたと思います。
普段スマートフォンに触れてはいるものの、電話の世界は奥深いのでまだまだ知らない部分が多々あります。
そういった点においても、電話部分をまるっと任せることができたのは大きく、今後機能拡張をすることになっても、Lambdaに手を入れることで簡単に実装することができるようになりました。
今後も新しいサービスには目を光らせて、マネージドにお任せできるところはお任せしていきたいです。

開発ランチ(Lunchers #6) ~kakakakakkuさんによるzenhub & モブプログラミングによるプロジェクトリード~

inamuu|2018年07月11日
開発ランチ(lunchers)

はじめまして、SREチームの稲村と申します。
最近、会社と自宅それぞれで自作キーボード使うようになり、日々快適なキーボード生活を送っています。
自分の好きなキースイッチとキーマッピングが選択できるのは最高ですね。

さて、今回のLunchersでは、巧みな文章力と確かな技術力で書かれたブログで有名なkakakakakku(カカカカック)さんに、プロジェクトリード理論編ということで「ZenHubとモブプログラミング」についてお話していただきました。

イベントページ

https://lancers-engineer.connpass.com/event/92801/

発表時の資料

ご挨拶

弊社神庭からLunchersというイベントの趣旨について説明を行いました。
なお、今回初めて弊社コワーキングスペースを利用して、社内/社外/フリーランスの方を交えての開催となりました。

フリーランス専用のコワーキングスペースを無償提供開始

kakakakakkuさんについて

  • 株式会社マクアケでSREをやっている
  • ブログを大事にしており、アウトプット芸人と呼ばれている
  • 副業でRuby on Railsの講師もやっている

kakakakakkuさんの「楽しく!アウトプットを習慣化しよう」の記事はこちら

ZenHubを使ったタスクの管理

前半はZenHubを使ったタスクの管理方法についてお話いただきました。

  • BacklogsとDoingとReviewingとClosedを作る
  • Backlogsはメンバーを割り当てない
  • DoingはWIP制限する
  • プランニングポーカーはやってない
  • 優先度は言わない
  • 優先順位を使う、上が最も優先順位が高いようにする
  • デイリースクラム(朝会)
  • みんなの前でcloseすることで右に進んでるcloseおめでとう を朝会で共有する
  • 流れの速さをデイリースクラムで感じ取る
  • 完了の定義を決める

質問

  • Q: GithubのProjectsやTrelloと比べてZenHubを使用している理由はあるか。
  • A: ZenHubだとEpic(issueをまとめる)機能が良い。
  • Q: ビジネス上の理由で差し込みが入るタスクはどうするか。
  • A: 障害対応などの緊急を要する場合を除き、あとまわしにしてBacklogsに入れて対応する。
  • Q: ラベルの付け方どうしているか。
  • A: 職務(デザイン、フロント、サーバーサイド、インフラなど)横断でやりたいので職務でラベル付けしている。スキルマップを作成して、自分が高めていきたい職務に挑戦しているのを可視化している。

ZenHubを中心に話していただきましたが、Github ProjectsやTrelloでも採用できる内容で大変参考になりました。
特に、タスクの粒度はバラバラになりがちで作業記録を残していったらissueが膨大な量になってしまうということはよくあると思います。
kakakakakkuさんのチームでは1つのタスクを1-3日で終わるような粒度に落とし込んで、タスクの完了までのサイクルを高めているようでした。
また、優先度を使わないという点でも、高中低のような優先度を設定してしまうと同じ優先度のものがBacklogsに存在してしまうので、優先順位にして上が最も順位が高いというルールに定めているのは、ZenHubの画面をパッと見てタスクの状況を把握しやすいルールだなと感じました。

モブプログラミングについて

後半はモブプログラミングについてお話いただきました。

  • スウォーミング
  • 「タスクをメンバー」にではなく、「メンバーをタスク」に割り当てる
  • One day in Kanban land
  • みんなで詰まっているタスクを終わらせる
  • 実装、設計、エディタとかのテクニックを共有する
  • モブリリースでみんなでデカイ画面でリリースする
  • ポモドーロ
  • メンバー全員のコミットが並んで達成感がある

質問

  • Q: Aさんのタスクが遅くなった場合、BさんとCさんがフォローすると、BさんCさんのタスクが遅くなってしまうのを防ぐにはどうすればよいか。
  • A: もともとBacklogでメンバーをアサインしていなければ他のタスクが遅れるということは基本的には無い。
  • Q: モブプログラミングの開催頻度はどれくらいか。
  • A: kakakakakkuさんのチームでは週一か二週に1回。イベント的にやったり教育的にやったりもするし、毎日やっているチームもあるがコストは高くなる。

チームでプロジェクトを完遂していくにあたり、メンバーをタスクに割り当てるというのはなるほどなぁと思いました。
インフラだからインフラだけ進めるというのではなく、優先順位の高いものをみんなで進めていくというのはまさにチームで為せる技です。
また、モブプログラミングを実施することで、みんなでワイワイと時間を決めて作業を進めることで個々が得た知識を共有でき、スキルの底上げだったり、作業に対する共通認識が生まれやすいだろうと感じました。

kakakakakkuさんの「モブプログラミングの基礎を学べる洋書「Getting Started with Mob Programming」を読んだ」の記事はこちら

全体を通して

kakakakakkuさんの発表は実務でどう活用しているかの話以外にも、分かりやすい例えを使って発表をしていただき、大変素晴らしい発表でした。
社内だけではなく、社外から来られた方も沢山質問をされていて、みなさん有意義な時間を過ごすことが出来たのではないでしょうか。
我々SREチームでもGithub Projectsを使ってタスク管理を行っており、大きめのリリース時にはメンバー全員でリリースを見届けることもあるので、今回発表いただいた内容はすぐにでも取り込めるものばかりで大変参考になりました。

kakakakakkuさん、来社いただいた皆様、お忙しいところ誠にありがとうございました!!

※さっそく今回のイベントをブログにしていただいている「プロジェクトの成功を支える ZenHub と モブプログラミング」の記事はこちら