SlideShare une entreprise Scribd logo
1  sur  40
スマートフォン向けサービスにおける
          サーバサイド設計入門




            2012/09/28 hatak
            at YAPC::Asia Tokyo 2012
自己紹介
• hatak (HATAKEYAMA Hisashi)

        @hisashi

         hatak



• ネット広告会社 → ソーシャルゲーム会社

    • インフラや運用寄りの仕事をしてることが多いです

    • わりとなんでも



• インフラ / MySQL / Perl な場所に時々います
このトークの内容
• 今年春より新規サービスの立ち上げを行うことに

  • 元々インフラや運用がメインだったので、いろいろ試行錯誤することに

• このサービスを実例として紹介しながら説明

  • をしようと思ったのですが、まだリリースされていないため

• 代替の例としてシンプルな SNS を作る流れで整理・説明します



• 概説的というか、Perl に限らない話も出てきます

  • 今まで試行錯誤してみた話を整理します

  • むしろ「開発初心者が設計に入門してみました」という話かも。。

• TMTOETDI
アジェンダ
• 設計

 • サービスを作るための最初をどうやって考えていくか

• 開発

 • サーバサイドをどのように作っていったか

• 連携

 • アプリとサーバを連携させるのにどうしたか
設計   Design
今回考えるサービスの概要
• 『スマートフォン用専用アプリで利用する SNS』 を例として整理します

    • 現在開発中のサービスとは異なります。。



•   LiteSNS

    • iOS (iPhone) アプリで利用

      • 利用にはユーザ登録が必要

    • 機能

      • メッセージや写真の投稿ができる

      • 投稿にコメントやいいねがつけられる

      • 友達のフィードが見れる
そもそもアプリでなければならない?
• アプリにしなければならないか、を最初に整理してみる

 • ブラウザで閲覧するタイプのサービスではダメなのか?

  • 例) カメラやGPSなどの利用の有無

• 機能ごとに処理を行うのがサーバかクライアントかで考えてみる

 • データを保存する場所は?

 • 投稿データの編集は?

  • 例) 画像加工(リサイズ, 減色, フィルタなど)

 • SNS へのログイン・データ取得は?

  • 例) facebook にログインしてトークンを取得
ネイティブとブラウザベース
• それぞれのメリット・デメリットを踏まえておく

 • ネイティブアプリが優位な点

  • カメラやセンサーなどの利用が容易

  • アプリマーケットからの導線が期待できる

  • リッチなユーザ体験を実現しやすい

 • ブラウザベースのアプリが優位な点

  • アプリアップデート時の作業・影響が少ない

  • システム構成をシンプルに保ちやすい

• その上で特性を十分に活かせるようにした方がよい
見える側から裏側へと考えていく

• 作業に着手するのもこの順になる
 • 作りながら、互いに連携して軌道修正していく必要もある
画面 / UI を考える
• 先人に学ぶのがいいと思う

 • 自分で触ってみるのが一番

• OS のガイドラインもあるので参考にしてみる

 • iOS Human Interface Guidelines

 • Android Design ( http://developer.android.com/design/ )

• 様々な書籍も出版されている
WebAPI を考える
• method + param/body → response を考える

  • REST の考え方を取り入れつつ、使いやすい URL を考える

  • ブラウザと異なり PUT / DELETE などのメソッドも使える

• 他のサービスがどのように作っているかを調べてみる

  • 既存のサービスの API (facebook, Twitter, Google+ など)

  • フレームワークの思想 (Catalyst, Ruby on Rails)
サーバサイドを考える

• アプリケーションサーバは並列に追加できるように
• 用途に応じて複数のデータストアを用意
 • データベースサーバ (MySQL)
   • 永続的に保存するデータ
 • KVS (Redis)
   • 永続的に保存するデータ
   • DB よりもアクセス/更新などの頻度が高いもの
 • キャッシュ (memcached)
   • ローカルなキャッシュ(消えてもいい)
   • app サーバ毎に保持
LoadBalancer




   App           App                   App          App

  Nginx         Nginx                  Nginx       Nginx

 Starman       Starman             Starman        Starman

memcached    memcached           memcached      memcached




             LoadBalancer                      LoadBalancer
 DB Master                        KVS Master

  MySQL      DB Slave                  Redis   KVS Slave
               DB Slave                          KVS Slave
             MySQL                               Redis
               MySQL                               Redis
ユーザ管理

• セッションは Cookie で管理
 • OAuth なども考えたが、まずは非公開 API なのでシンプルに
 • スマートフォンアプリ側のライブラリも Cookie を処理してくれる
• アクティブなセッションが把握できる仕組みが必要
 • アプリ削除でそのまま接続できなくなったセッションの処理
 • PUSH 通知を行っても良いアクティブなセッションの把握
 • 古いセッションの Expire が必要な場合もある
 • アクティブなセッションを確認する機能
開発   Development
Perl での開発

• Perl を選んだ理由
  • 比較的勝手が分かる言語
     • 今 を取り入れてそれなりの規模の開発をできるかどうか
  • CPAN のモジュール群の魅力
• システムに依存しない環境
$ curl	
  -­‐kL	
  https://raw.github.com/gist/2775862	
  |	
  bash

  • perlbrew
     • システムの Perl を直接使いたくない
  • Carton
     • ローカルの開発環境など複数のプロジェクトが同居するときに重宝
フレームワーク

• Amon2
  • 拡張が自由にできる   自分でやらなきゃいけない

  • 仕組みを考えていく上では柔軟性が高いと思い選択


• 使ってみて
  • コード量も依存も少ないので困ったら読めばいい
  • 自分がやりやすい形に作り替えていける感じはとても良い
    • もともとの設計思想から外れてしまっているかも知れないが。。。
アプリケーションの全体構成

• Amon2::Setup::Flavor::Large を利用してスケルトンを生成
$ amon2-setup.pl --flavor=Large,Teng LiteSNS

  • これをベースとして構成を手直ししていく
• LiteSNS の中で Amon2::Web を継承したコントローラ群を複数用意
     LiteSNS::APIv1 --- API としてレスポンスを返す (JSON)

     LiteSNS::Admin --- ブラウザで閲覧する認証付き管理画面 (HTML)

• 全体で共用するモジュールはコントローラと並列の階層
     LiteSNS::Model --- ロジックをまとめたモジュール

     LiteSNS::DB --- データベースモジュール

     LiteSNS::Exceptions --- 例外モジュール
LiteSNS
├── APIv1                    API Module <Amon2::Web>
│   ├── Controller             Controller
│   │   ├── Article
│   │   ├── User
│   │   └── ...
│   ├── Dispatcher             Dispatcher
│   └── Response               Response Model
│          ├── Article
│          ├── User
│          └── ...
├── Admin                    Admin-Web Module <Amon2::Web>
│   ├── Controller
│   └── Dispatcher
├── Constants                Constant (Common)
├── DB
│   └── Main                 Main Database <Teng>
│          ├── Row
│          │  ├── Articles
│          │  ├── Users
│          │  └── ...
│          └── Schema
├── Exceptions               Exception <Class::Exception>
├── Model                    Logic Model
│   ├── Article
│   ├── User
│   └── ...
└── Util                     UtilityMethods (Common)
LiteSNS::DB

• ORM として Teng を利用
 • あとでモデルでちゃんと SQL 整理すればいい
   • でも、インデックスなどをしっかり考えると整理はあった方がいい
 • 管理画面のようなケースはORMのままでもいいと思う
• データセット毎に別のクラスとして用意
 • 複数系統持つことになると思うので
 • データセットや master / slave をつなぎ替えられるように
• 日付や定義値などのカラムは inflate / deflate 設定しておく
データの論理削除

• 全テーブルにフラグ (row_status) を持たせておく
    1 : enable

    0 : disable

   -1 : deleted

• DB クラスで Class::Method::Modifiers を使う
  • delete メソッドを置き換えてしまう
package LiteSNS::DB::Main;
use parent qw(Teng);
use Class::Method::Modifiers;
use DateTime;

use constant STATUS => {
    ENABLE => 1,      # 有効
    DISABLE => 0,     # 無効
    DELETED => -1,    # 削除
};

around delete => sub {
    my ($orig, $self, $table_name, $delete_condition) = @_;
    my $update_row_data = {
        updated_at => DateTime->now(time_zone => 'Asia/Tokyo'),
        row_status => STATUS()->{DELETED},
    };
    $self->update($table_name, $update_row_data, $delete_condition);
};

before single => sub {
    my ($self, $table_name, $search_condition, $search_attr) = @_;
    unless (defined $search_condition->{row_status}) {
        $search_condition->{row_status} = STATUS()->{ENABLE};
    }
};

...
LiteSNS::Model

• 共通の処理として呼べるようにコントローラから分離
 • API だけでなく、Admin や CLI からも同じ処理をする可能性があるため
 • Mouse ベースでリクエストに依存しない処理をまとめたクラスを作成
• 常に決まった処理をするようなロジックをまとめる
 • フローに沿ったステータスの遷移
   • 例) 友達の状態をチェックして申請中 → 承認にステータスを変える
 • 合計数のインクリメント/デクリメント
   • 例) コメントを投稿したら、その記事のコメント数をインクリメント
LiteSNS::APIv1::Response

• レスポンスを詰め込むオブジェクトを用意
 • 入れ子構造
 • 不要カラムの削除や属性名の変更など
• Teng::Row を詰め込んで JSON で出力したいハッシュに変換・整形
 • 最初は Teng::Row に変換メソッドを組み込んでみた
 • テーブルとモデルが必ずしも一対一対応しなかったので分離
users                {
                                        id => 928,
               id                       user => {
                                           id => 1001,
               name                        name => ‘taro’,
                                        },
               password
articles                                title => ‘今日のランチ’,
               article_count            body => ‘パンがおいしかった!’,
 id                                     createdAt => ‘2012-09-28 13:24:01’,
               row_status               comments => [
 user_id                                   {
               created_at                     user => {
 title
               updated_at                        id => 1034,
 body                                            name => ‘jiro’,
                                              },
 comment_count                                body => ‘おいしそうだね!’,
 like_count                                   createdAt => ‘2012-09-28 13:31:34’,
                                           },
 row_status         comments               {
                                              user => {
 created_at           id                         id => 1001,
 updated_at           user_id                    name => ‘taro’,
                                              },
                      article_id              body => ‘焼きたてをだしてくれるん
                                              だー’,
                      body                    createdAt => ‘2012-09-28 13:35:18’,
                      row_status           },
                                        ],
                      created_at   },
                      updated_at
JSON レスポンスの生成

• 標準プラグイン Amon2::Plugin::Web::JSON を利用
  • 今回はレスポンスコードを変えたかったので一部変更
    • Controller からの戻り値でレスポンスコードを渡せるように


• JSON / JSON::XS
  • PERL -> JSON では数字の取り扱いに注意
    • 類推してくれるが、明示的に数値になっていないと数値にならない
エラーと例外の処理

• Class::Exception を利用
  • アプリケーション共通で利用する例外クラスを作成
  • 例外が発生した場合にこのインスタンスを投げる
• Dispatcher / Worker のレベルで Exception をキャッチする
  • 該当する例外の内容に合わせてエラーメッセージを生成
  • HTTP ステータスコードに割り当ててレスポンスとして作成
テスト

• Model や共通関数などはテストを作っておく
 • 実際に処理させてチェックだと面倒
 • テストに合わせて daemon を起動するようにしてあげると良い
   • http://perl-users.jp/articles/advent-calendar/2011/test/18
• テストを書きすぎるとキリが無くなってしまうのでバランス大事
 • Jenkins などの CI ツールをうまく活用
• API はレスポンスのテストしやすい
 • JSON なので期待値との比較などが容易
 • Test::WWW::Mechanize::PSGI などを活用
環境ごとの切り分け

• Amon2 の機能で config を切り替えられる
  • 接続先ホストやユーザ名などを変えておく
  • 開発時だけ環境変数でフラグを入れたりすると便利
• 本番と開発環境でドメイン + 階層が異なってもうまく吸収できる
  • 同一ドメインで全てをサーブしたい場合はまとめた psgi を作ってたてる
# app.psgi
...
builder {
    mount '/api/' => Plack::Util::load_psgi('api.psgi');
    mount '/admin/' => Plack::Util::load_psgi('admin.psgi');
};


  • 異なるドメインの場合は個別にプロセスをたてる
      • Proxy などでわけてアクセスできるようにする
本番環境

• Starman + Server::Starter
$ carton	
  exec	
  -­‐-­‐	
  start_server	
  -­‐-­‐port=5000	
  -­‐-­‐signal-­‐on-­‐hup=USR1	
  -­‐-­‐	
  
plackup	
  -­‐s	
  Starlet	
  -­‐-­‐spawn-­‐interval=5


   • プロセスを supervisord で立ち上げる
       • 標準出力のログは supervisord がファイルに書き出してくれる
• ローカルに Nginx をたててローカルの Starman に送る
   • Nginx 側でアクセスログを取得
   • 管理画面のアクセス制御や多段 Proxy 時のヘッダコントロールなど
連携   Cooperation
クライアントアプリとの連携

• iPhone を例にいくつか紹介
  • Objective-C 的な話も出てきますが軽く触れるだけにします


• AFNetworking (https://github.com/AFNetworking/AFNetworking)

  • AFJSONRequestOperation で JSON -> NSDirectory と変換

  • NSDirectory で init できるようにデータオブジェクトを定義しておく

    • オブジェクトが入れ子になっているようにしておく

  • このクラスがあるから、API の出力も同じようにできるオブジェクトを考
    えてるわけで
API のコールと JSON 値の変換
• 1回のリクエストで階層化したデータを返せるようにする

 • 通信回数を抑えることが大事

  • 画面遷移の度に通信を発生させたくない

 • 海外を見据えてるなら通信環境が優れている場所ばかりとは限らないため



• 値を変更したらその変更を通知して画面も更新する必要がある

• インターフェイスとのバランスも考える必要がある

 • 送信 ボタンがあるとは限らず、トリガスイッチだけだったりもする



• アプリ開発者と連携しながら相互に調整する必要がある
リクエストヘッダ

• 独自のユーザエージェントを設定
• 独自の HTTP ヘッダをアプリからの通信時に埋め込む
 • クライアントアプリのバージョン
   • X-LiteSNS-Version
 • ユーザの閲覧環境
   • X-LiteSNS-Locale
   • X-LiteSNS-Language
   • X-LiteSNS-Timezone
• このあたりはアプリサイドのコードで埋め込むことができる
 • ルールを決めておくことが大事
APNS を用いた PUSH 通知

• Apple Push Notification Service (APNS)
  • 詳細は iOS Developer Library を参照
• 通知の流れ
  1.アプリでデバイストークンを取得してサーバに送信

     • NSData を16進数などに変換してサーバに POST
  2.サーバサイドでアクティブなセッションと紐づけて保持しておく

  3.モジュールを利用して通知パケットを APNS サーバに送る

     • Net::APNS, AnyEvent::APNS
• AnyEvent::APNS の例は typester さんの解説が分かりやすいです
  • http://perl-users.jp/articles/advent-calendar/2010/hacker/7
-­‐(void)applicationDidFinishLaunching:(UIApplication	
  *)application	
  
{	
  	
  	
  	
  
	
  	
  	
  	
  //	
  初回起動時に	
  「“LiteSNS”はあなたにプッシュ通知を..」	
  という確認ダイアログを表示
	
  	
  	
  	
  [[UIApplication	
  sharedApplication]	
  registerForRemoteNotificationTypes:
                                            (UIRemoteNotificationTypeAlert
                                            	
  |	
  UIRemoteNotificationTypeBadge
                                                | UIRemoteNotificationTypeSound)];
}

-­‐	
  (void)application:(UIApplication	
  *)app	
  didRegisterForRemoteNotificationsWithDeviceToken:
(NSData	
  *)deviceToken	
  
{	
  
	
  	
  	
  	
  //	
  ここで	
  NSData	
  形式の	
  deviceToken	
  を16進数変換して送ります
}


use Net::APNS;

my $APNS = Net::APNS->new;

my $notification = $APNS->notify({
        cert   => ‘path/to/app.cer’,
        key    => ‘path/to/app.key’,
    });
$notification->devicetoken(‘device_token’); # ここで16進数のトークンをセットする
$notification->message("new message from LiteSNS"); # 通知メッセージ本文
$notification->badge(1); # アプリアイコンにつけるバッジの数

$notification->write;
まとめ   Summary
まとめ
• 設計

 • 見えるところから見えないところへと考えを掘り下げていく

 • 最初に全てを決めきれないので、作りながら微調整は必要

• 開発

 • 仕組みを考えながら組み合わせて作っていく

 • スケールする仕組みをあとからでも入れられるようにする

• 連携

 • ライブラリをうまく使ってデータを組み立てていく

 • スマートフォンならでは、アプリならではの視点も必要
まとめ
• やってみて分かったこと

 • 様々な観点が必要とされている

   • プログラム、ミドルウェア、に加えてフロント側も

   • 特性とかユーザの利用シーンもちゃんと考えないとうまく作れない

 • でも、難しいことではない

   • (本来は)全部を一人でできなくてもいい

   • タスクを振るとき、全体を設計するときにあると良い

 • 何ができるか、を知っていることが大事

   • Titanium など敷居の低い開発手法もあるので試してみるのが良い
ご清聴ありがとうございました!

Contenu connexe

Tendances

超実践 Cloud Spanner 設計講座
超実践 Cloud Spanner 設計講座超実践 Cloud Spanner 設計講座
超実践 Cloud Spanner 設計講座Samir Hammoudi
 
やはりお前らのMVCは間違っている
やはりお前らのMVCは間違っているやはりお前らのMVCは間違っている
やはりお前らのMVCは間違っているKoichi Tanaka
 
オブジェクト指向できていますか?
オブジェクト指向できていますか?オブジェクト指向できていますか?
オブジェクト指向できていますか?Moriharu Ohzu
 
RESTful Web アプリの設計レビューの話
RESTful Web アプリの設計レビューの話RESTful Web アプリの設計レビューの話
RESTful Web アプリの設計レビューの話Takuto Wada
 
マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!mosa siru
 
ゲームアーキテクチャパターン (Aurora Serverless / DynamoDB)
ゲームアーキテクチャパターン (Aurora Serverless / DynamoDB)ゲームアーキテクチャパターン (Aurora Serverless / DynamoDB)
ゲームアーキテクチャパターン (Aurora Serverless / DynamoDB)Amazon Web Services Japan
 
トランザクションスクリプトのすすめ
トランザクションスクリプトのすすめトランザクションスクリプトのすすめ
トランザクションスクリプトのすすめpospome
 
ドメイン駆動設計 モデリング_実装入門勉強会_2020.3.8
ドメイン駆動設計 モデリング_実装入門勉強会_2020.3.8ドメイン駆動設計 モデリング_実装入門勉強会_2020.3.8
ドメイン駆動設計 モデリング_実装入門勉強会_2020.3.8Koichiro Matsuoka
 
ソーシャルゲームのためのデータベース設計
ソーシャルゲームのためのデータベース設計ソーシャルゲームのためのデータベース設計
ソーシャルゲームのためのデータベース設計Yoshinori Matsunobu
 
SolrとElasticsearchを比べてみよう
SolrとElasticsearchを比べてみようSolrとElasticsearchを比べてみよう
SolrとElasticsearchを比べてみようShinsuke Sugaya
 
こわくない Git
こわくない Gitこわくない Git
こわくない GitKota Saito
 
Azure API Management 俺的マニュアル
Azure API Management 俺的マニュアルAzure API Management 俺的マニュアル
Azure API Management 俺的マニュアル貴志 上坂
 
Djangoのエントリポイントとアプリケーションの仕組み
Djangoのエントリポイントとアプリケーションの仕組みDjangoのエントリポイントとアプリケーションの仕組み
Djangoのエントリポイントとアプリケーションの仕組みShinya Okano
 
Mercari JPのモノリスサービスをKubernetesに移行した話 PHP Conference 2022 9/24
Mercari JPのモノリスサービスをKubernetesに移行した話 PHP Conference 2022 9/24Mercari JPのモノリスサービスをKubernetesに移行した話 PHP Conference 2022 9/24
Mercari JPのモノリスサービスをKubernetesに移行した話 PHP Conference 2022 9/24Shin Ohno
 
Fluentdのお勧めシステム構成パターン
Fluentdのお勧めシステム構成パターンFluentdのお勧めシステム構成パターン
Fluentdのお勧めシステム構成パターンKentaro Yoshida
 
マイクロサービス時代の認証と認可 - AWS Dev Day Tokyo 2018 #AWSDevDay
マイクロサービス時代の認証と認可 - AWS Dev Day Tokyo 2018 #AWSDevDayマイクロサービス時代の認証と認可 - AWS Dev Day Tokyo 2018 #AWSDevDay
マイクロサービス時代の認証と認可 - AWS Dev Day Tokyo 2018 #AWSDevDay都元ダイスケ Miyamoto
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」Takuto Wada
 
Swaggerでのapi開発よもやま話
Swaggerでのapi開発よもやま話Swaggerでのapi開発よもやま話
Swaggerでのapi開発よもやま話KEISUKE KONISHI
 
ドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Spring
ドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Springドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Spring
ドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Spring増田 亨
 

Tendances (20)

超実践 Cloud Spanner 設計講座
超実践 Cloud Spanner 設計講座超実践 Cloud Spanner 設計講座
超実践 Cloud Spanner 設計講座
 
やはりお前らのMVCは間違っている
やはりお前らのMVCは間違っているやはりお前らのMVCは間違っている
やはりお前らのMVCは間違っている
 
オブジェクト指向できていますか?
オブジェクト指向できていますか?オブジェクト指向できていますか?
オブジェクト指向できていますか?
 
Keycloak入門
Keycloak入門Keycloak入門
Keycloak入門
 
RESTful Web アプリの設計レビューの話
RESTful Web アプリの設計レビューの話RESTful Web アプリの設計レビューの話
RESTful Web アプリの設計レビューの話
 
マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!
 
ゲームアーキテクチャパターン (Aurora Serverless / DynamoDB)
ゲームアーキテクチャパターン (Aurora Serverless / DynamoDB)ゲームアーキテクチャパターン (Aurora Serverless / DynamoDB)
ゲームアーキテクチャパターン (Aurora Serverless / DynamoDB)
 
トランザクションスクリプトのすすめ
トランザクションスクリプトのすすめトランザクションスクリプトのすすめ
トランザクションスクリプトのすすめ
 
ドメイン駆動設計 モデリング_実装入門勉強会_2020.3.8
ドメイン駆動設計 モデリング_実装入門勉強会_2020.3.8ドメイン駆動設計 モデリング_実装入門勉強会_2020.3.8
ドメイン駆動設計 モデリング_実装入門勉強会_2020.3.8
 
ソーシャルゲームのためのデータベース設計
ソーシャルゲームのためのデータベース設計ソーシャルゲームのためのデータベース設計
ソーシャルゲームのためのデータベース設計
 
SolrとElasticsearchを比べてみよう
SolrとElasticsearchを比べてみようSolrとElasticsearchを比べてみよう
SolrとElasticsearchを比べてみよう
 
こわくない Git
こわくない Gitこわくない Git
こわくない Git
 
Azure API Management 俺的マニュアル
Azure API Management 俺的マニュアルAzure API Management 俺的マニュアル
Azure API Management 俺的マニュアル
 
Djangoのエントリポイントとアプリケーションの仕組み
Djangoのエントリポイントとアプリケーションの仕組みDjangoのエントリポイントとアプリケーションの仕組み
Djangoのエントリポイントとアプリケーションの仕組み
 
Mercari JPのモノリスサービスをKubernetesに移行した話 PHP Conference 2022 9/24
Mercari JPのモノリスサービスをKubernetesに移行した話 PHP Conference 2022 9/24Mercari JPのモノリスサービスをKubernetesに移行した話 PHP Conference 2022 9/24
Mercari JPのモノリスサービスをKubernetesに移行した話 PHP Conference 2022 9/24
 
Fluentdのお勧めシステム構成パターン
Fluentdのお勧めシステム構成パターンFluentdのお勧めシステム構成パターン
Fluentdのお勧めシステム構成パターン
 
マイクロサービス時代の認証と認可 - AWS Dev Day Tokyo 2018 #AWSDevDay
マイクロサービス時代の認証と認可 - AWS Dev Day Tokyo 2018 #AWSDevDayマイクロサービス時代の認証と認可 - AWS Dev Day Tokyo 2018 #AWSDevDay
マイクロサービス時代の認証と認可 - AWS Dev Day Tokyo 2018 #AWSDevDay
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
 
Swaggerでのapi開発よもやま話
Swaggerでのapi開発よもやま話Swaggerでのapi開発よもやま話
Swaggerでのapi開発よもやま話
 
ドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Spring
ドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Springドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Spring
ドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Spring
 

En vedette

通信対戦ゲームを作った話
通信対戦ゲームを作った話通信対戦ゲームを作った話
通信対戦ゲームを作った話mipsparc
 
日曜プログラマーが
1週間くらいで通信対戦ゲームを作ってみた
日曜プログラマーが
1週間くらいで通信対戦ゲームを作ってみた日曜プログラマーが
1週間くらいで通信対戦ゲームを作ってみた
日曜プログラマーが
1週間くらいで通信対戦ゲームを作ってみたYuusuke Takeuchi
 
Djangoフレームワークの紹介
Djangoフレームワークの紹介Djangoフレームワークの紹介
Djangoフレームワークの紹介Shinya Okano
 
新入社員のための大規模ゲーム開発入門 サーバサイド編
新入社員のための大規模ゲーム開発入門 サーバサイド編新入社員のための大規模ゲーム開発入門 サーバサイド編
新入社員のための大規模ゲーム開発入門 サーバサイド編infinite_loop
 
Djangoによるスマホアプリバックエンドの実装
Djangoによるスマホアプリバックエンドの実装Djangoによるスマホアプリバックエンドの実装
Djangoによるスマホアプリバックエンドの実装Nakazawa Yuichi
 
自宅で出来る!ゲームサーバの作り方
自宅で出来る!ゲームサーバの作り方自宅で出来る!ゲームサーバの作り方
自宅で出来る!ゲームサーバの作り方光晶 上原
 
ゲームサーバ開発現場の考え方
ゲームサーバ開発現場の考え方ゲームサーバ開発現場の考え方
ゲームサーバ開発現場の考え方Daisaku Mochizuki
 
年の瀬!リアルタイム通信ゲームサーバ勉強会
年の瀬!リアルタイム通信ゲームサーバ勉強会年の瀬!リアルタイム通信ゲームサーバ勉強会
年の瀬!リアルタイム通信ゲームサーバ勉強会monobit
 

En vedette (8)

通信対戦ゲームを作った話
通信対戦ゲームを作った話通信対戦ゲームを作った話
通信対戦ゲームを作った話
 
日曜プログラマーが
1週間くらいで通信対戦ゲームを作ってみた
日曜プログラマーが
1週間くらいで通信対戦ゲームを作ってみた日曜プログラマーが
1週間くらいで通信対戦ゲームを作ってみた
日曜プログラマーが
1週間くらいで通信対戦ゲームを作ってみた
 
Djangoフレームワークの紹介
Djangoフレームワークの紹介Djangoフレームワークの紹介
Djangoフレームワークの紹介
 
新入社員のための大規模ゲーム開発入門 サーバサイド編
新入社員のための大規模ゲーム開発入門 サーバサイド編新入社員のための大規模ゲーム開発入門 サーバサイド編
新入社員のための大規模ゲーム開発入門 サーバサイド編
 
Djangoによるスマホアプリバックエンドの実装
Djangoによるスマホアプリバックエンドの実装Djangoによるスマホアプリバックエンドの実装
Djangoによるスマホアプリバックエンドの実装
 
自宅で出来る!ゲームサーバの作り方
自宅で出来る!ゲームサーバの作り方自宅で出来る!ゲームサーバの作り方
自宅で出来る!ゲームサーバの作り方
 
ゲームサーバ開発現場の考え方
ゲームサーバ開発現場の考え方ゲームサーバ開発現場の考え方
ゲームサーバ開発現場の考え方
 
年の瀬!リアルタイム通信ゲームサーバ勉強会
年の瀬!リアルタイム通信ゲームサーバ勉強会年の瀬!リアルタイム通信ゲームサーバ勉強会
年の瀬!リアルタイム通信ゲームサーバ勉強会
 

Similaire à スマートフォン向けサービスにおけるサーバサイド設計入門

CodeIgniter入門
CodeIgniter入門CodeIgniter入門
CodeIgniter入門Sho A
 
ASP.NET Core WebAPIでODataを使おう
ASP.NET Core WebAPIでODataを使おうASP.NET Core WebAPIでODataを使おう
ASP.NET Core WebAPIでODataを使おうDevTakas
 
Awsで構築したのだよ 05 プロセス監視、メモリ使用率、ディスク使用率をCloudWatchのカスタムメトリクスに追加したい
Awsで構築したのだよ 05 プロセス監視、メモリ使用率、ディスク使用率をCloudWatchのカスタムメトリクスに追加したいAwsで構築したのだよ 05 プロセス監視、メモリ使用率、ディスク使用率をCloudWatchのカスタムメトリクスに追加したい
Awsで構築したのだよ 05 プロセス監視、メモリ使用率、ディスク使用率をCloudWatchのカスタムメトリクスに追加したい聡 大久保
 
脱コピペ!デザイナーにもわかるPHPとWP_Query
脱コピペ!デザイナーにもわかるPHPとWP_Query脱コピペ!デザイナーにもわかるPHPとWP_Query
脱コピペ!デザイナーにもわかるPHPとWP_QueryHidekazu Ishikawa
 
Webサーバのチューニング
WebサーバのチューニングWebサーバのチューニング
WebサーバのチューニングYu Komiya
 
データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回Naoyuki Yamada
 
PHPフレームワーク入門
PHPフレームワーク入門PHPフレームワーク入門
PHPフレームワーク入門Sho A
 
Inside mobage platform
Inside mobage platformInside mobage platform
Inside mobage platformToru Yamaguchi
 
Cloudstack user group meeting in osaka
Cloudstack user group meeting in osakaCloudstack user group meeting in osaka
Cloudstack user group meeting in osakaNaotaka Jay HOTTA
 
Azure でサーバーレス、 Infrastructure as Code どうしてますか?
Azure でサーバーレス、 Infrastructure as Code どうしてますか?Azure でサーバーレス、 Infrastructure as Code どうしてますか?
Azure でサーバーレス、 Infrastructure as Code どうしてますか?Kazumi IWANAGA
 
おすすめ gem
おすすめ gemおすすめ gem
おすすめ gemchocoby
 
activerecord-oracle_enhanced-adapterのご紹介
activerecord-oracle_enhanced-adapterのご紹介activerecord-oracle_enhanced-adapterのご紹介
activerecord-oracle_enhanced-adapterのご紹介Kevin Toyoda
 
Rails Controller Fundamentals
Rails Controller FundamentalsRails Controller Fundamentals
Rails Controller FundamentalsTakashi SAKAGUCHI
 
Windows PowerShell 2.0 の基礎知識
Windows PowerShell 2.0 の基礎知識Windows PowerShell 2.0 の基礎知識
Windows PowerShell 2.0 の基礎知識shigeya
 
⑯jQueryをおぼえよう!その2
⑯jQueryをおぼえよう!その2⑯jQueryをおぼえよう!その2
⑯jQueryをおぼえよう!その2Nishida Kansuke
 
SmartPhone development guide with CoffeeScript + Node + HTML5 Technology, for...
SmartPhone development guide with CoffeeScript + Node + HTML5 Technology, for...SmartPhone development guide with CoffeeScript + Node + HTML5 Technology, for...
SmartPhone development guide with CoffeeScript + Node + HTML5 Technology, for...Naoya Ito
 
WTM53 phpフレームワーク いまさらcodeigniter
WTM53 phpフレームワーク いまさらcodeigniterWTM53 phpフレームワーク いまさらcodeigniter
WTM53 phpフレームワーク いまさらcodeigniterMasanori Oobayashi
 
PHP開発者のためのNoSQL入門
PHP開発者のためのNoSQL入門PHP開発者のためのNoSQL入門
PHP開発者のためのNoSQL入門じゅん なかざ
 
20091030cakephphandson 01
20091030cakephphandson 0120091030cakephphandson 01
20091030cakephphandson 01Yusuke Ando
 

Similaire à スマートフォン向けサービスにおけるサーバサイド設計入門 (20)

CodeIgniter入門
CodeIgniter入門CodeIgniter入門
CodeIgniter入門
 
ASP.NET Core WebAPIでODataを使おう
ASP.NET Core WebAPIでODataを使おうASP.NET Core WebAPIでODataを使おう
ASP.NET Core WebAPIでODataを使おう
 
Awsで構築したのだよ 05 プロセス監視、メモリ使用率、ディスク使用率をCloudWatchのカスタムメトリクスに追加したい
Awsで構築したのだよ 05 プロセス監視、メモリ使用率、ディスク使用率をCloudWatchのカスタムメトリクスに追加したいAwsで構築したのだよ 05 プロセス監視、メモリ使用率、ディスク使用率をCloudWatchのカスタムメトリクスに追加したい
Awsで構築したのだよ 05 プロセス監視、メモリ使用率、ディスク使用率をCloudWatchのカスタムメトリクスに追加したい
 
脱コピペ!デザイナーにもわかるPHPとWP_Query
脱コピペ!デザイナーにもわかるPHPとWP_Query脱コピペ!デザイナーにもわかるPHPとWP_Query
脱コピペ!デザイナーにもわかるPHPとWP_Query
 
Webサーバのチューニング
WebサーバのチューニングWebサーバのチューニング
Webサーバのチューニング
 
データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回
 
PHPフレームワーク入門
PHPフレームワーク入門PHPフレームワーク入門
PHPフレームワーク入門
 
Inside mobage platform
Inside mobage platformInside mobage platform
Inside mobage platform
 
Cloudstack user group meeting in osaka
Cloudstack user group meeting in osakaCloudstack user group meeting in osaka
Cloudstack user group meeting in osaka
 
Azure でサーバーレス、 Infrastructure as Code どうしてますか?
Azure でサーバーレス、 Infrastructure as Code どうしてますか?Azure でサーバーレス、 Infrastructure as Code どうしてますか?
Azure でサーバーレス、 Infrastructure as Code どうしてますか?
 
おすすめ gem
おすすめ gemおすすめ gem
おすすめ gem
 
activerecord-oracle_enhanced-adapterのご紹介
activerecord-oracle_enhanced-adapterのご紹介activerecord-oracle_enhanced-adapterのご紹介
activerecord-oracle_enhanced-adapterのご紹介
 
Rails Controller Fundamentals
Rails Controller FundamentalsRails Controller Fundamentals
Rails Controller Fundamentals
 
Windows PowerShell 2.0 の基礎知識
Windows PowerShell 2.0 の基礎知識Windows PowerShell 2.0 の基礎知識
Windows PowerShell 2.0 の基礎知識
 
⑯jQueryをおぼえよう!その2
⑯jQueryをおぼえよう!その2⑯jQueryをおぼえよう!その2
⑯jQueryをおぼえよう!その2
 
SmartPhone development guide with CoffeeScript + Node + HTML5 Technology, for...
SmartPhone development guide with CoffeeScript + Node + HTML5 Technology, for...SmartPhone development guide with CoffeeScript + Node + HTML5 Technology, for...
SmartPhone development guide with CoffeeScript + Node + HTML5 Technology, for...
 
WTM53 phpフレームワーク いまさらcodeigniter
WTM53 phpフレームワーク いまさらcodeigniterWTM53 phpフレームワーク いまさらcodeigniter
WTM53 phpフレームワーク いまさらcodeigniter
 
Redmine Ansible
Redmine AnsibleRedmine Ansible
Redmine Ansible
 
PHP開発者のためのNoSQL入門
PHP開発者のためのNoSQL入門PHP開発者のためのNoSQL入門
PHP開発者のためのNoSQL入門
 
20091030cakephphandson 01
20091030cakephphandson 0120091030cakephphandson 01
20091030cakephphandson 01
 

Dernier

クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfFumieNakayama
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)Hiroshi Tomioka
 
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineerYuki Kikuchi
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?akihisamiyanaga1
 
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...博三 太田
 
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)UEHARA, Tetsutaro
 
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案sugiuralab
 
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfFumieNakayama
 

Dernier (8)

クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
 
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
 
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
 
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
 
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
 
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
 

スマートフォン向けサービスにおけるサーバサイド設計入門

  • 1. スマートフォン向けサービスにおける サーバサイド設計入門 2012/09/28 hatak at YAPC::Asia Tokyo 2012
  • 2. 自己紹介 • hatak (HATAKEYAMA Hisashi) @hisashi hatak • ネット広告会社 → ソーシャルゲーム会社 • インフラや運用寄りの仕事をしてることが多いです • わりとなんでも • インフラ / MySQL / Perl な場所に時々います
  • 3. このトークの内容 • 今年春より新規サービスの立ち上げを行うことに • 元々インフラや運用がメインだったので、いろいろ試行錯誤することに • このサービスを実例として紹介しながら説明 • をしようと思ったのですが、まだリリースされていないため • 代替の例としてシンプルな SNS を作る流れで整理・説明します • 概説的というか、Perl に限らない話も出てきます • 今まで試行錯誤してみた話を整理します • むしろ「開発初心者が設計に入門してみました」という話かも。。 • TMTOETDI
  • 4. アジェンダ • 設計 • サービスを作るための最初をどうやって考えていくか • 開発 • サーバサイドをどのように作っていったか • 連携 • アプリとサーバを連携させるのにどうしたか
  • 5. 設計 Design
  • 6. 今回考えるサービスの概要 • 『スマートフォン用専用アプリで利用する SNS』 を例として整理します • 現在開発中のサービスとは異なります。。 • LiteSNS • iOS (iPhone) アプリで利用 • 利用にはユーザ登録が必要 • 機能 • メッセージや写真の投稿ができる • 投稿にコメントやいいねがつけられる • 友達のフィードが見れる
  • 7. そもそもアプリでなければならない? • アプリにしなければならないか、を最初に整理してみる • ブラウザで閲覧するタイプのサービスではダメなのか? • 例) カメラやGPSなどの利用の有無 • 機能ごとに処理を行うのがサーバかクライアントかで考えてみる • データを保存する場所は? • 投稿データの編集は? • 例) 画像加工(リサイズ, 減色, フィルタなど) • SNS へのログイン・データ取得は? • 例) facebook にログインしてトークンを取得
  • 8. ネイティブとブラウザベース • それぞれのメリット・デメリットを踏まえておく • ネイティブアプリが優位な点 • カメラやセンサーなどの利用が容易 • アプリマーケットからの導線が期待できる • リッチなユーザ体験を実現しやすい • ブラウザベースのアプリが優位な点 • アプリアップデート時の作業・影響が少ない • システム構成をシンプルに保ちやすい • その上で特性を十分に活かせるようにした方がよい
  • 9. 見える側から裏側へと考えていく • 作業に着手するのもこの順になる • 作りながら、互いに連携して軌道修正していく必要もある
  • 10. 画面 / UI を考える • 先人に学ぶのがいいと思う • 自分で触ってみるのが一番 • OS のガイドラインもあるので参考にしてみる • iOS Human Interface Guidelines • Android Design ( http://developer.android.com/design/ ) • 様々な書籍も出版されている
  • 11. WebAPI を考える • method + param/body → response を考える • REST の考え方を取り入れつつ、使いやすい URL を考える • ブラウザと異なり PUT / DELETE などのメソッドも使える • 他のサービスがどのように作っているかを調べてみる • 既存のサービスの API (facebook, Twitter, Google+ など) • フレームワークの思想 (Catalyst, Ruby on Rails)
  • 12. サーバサイドを考える • アプリケーションサーバは並列に追加できるように • 用途に応じて複数のデータストアを用意 • データベースサーバ (MySQL) • 永続的に保存するデータ • KVS (Redis) • 永続的に保存するデータ • DB よりもアクセス/更新などの頻度が高いもの • キャッシュ (memcached) • ローカルなキャッシュ(消えてもいい) • app サーバ毎に保持
  • 13. LoadBalancer App App App App Nginx Nginx Nginx Nginx Starman Starman Starman Starman memcached memcached memcached memcached LoadBalancer LoadBalancer DB Master KVS Master MySQL DB Slave Redis KVS Slave DB Slave KVS Slave MySQL Redis MySQL Redis
  • 14. ユーザ管理 • セッションは Cookie で管理 • OAuth なども考えたが、まずは非公開 API なのでシンプルに • スマートフォンアプリ側のライブラリも Cookie を処理してくれる • アクティブなセッションが把握できる仕組みが必要 • アプリ削除でそのまま接続できなくなったセッションの処理 • PUSH 通知を行っても良いアクティブなセッションの把握 • 古いセッションの Expire が必要な場合もある • アクティブなセッションを確認する機能
  • 15. 開発 Development
  • 16. Perl での開発 • Perl を選んだ理由 • 比較的勝手が分かる言語 • 今 を取り入れてそれなりの規模の開発をできるかどうか • CPAN のモジュール群の魅力 • システムに依存しない環境 $ curl  -­‐kL  https://raw.github.com/gist/2775862  |  bash • perlbrew • システムの Perl を直接使いたくない • Carton • ローカルの開発環境など複数のプロジェクトが同居するときに重宝
  • 17. フレームワーク • Amon2 • 拡張が自由にできる 自分でやらなきゃいけない • 仕組みを考えていく上では柔軟性が高いと思い選択 • 使ってみて • コード量も依存も少ないので困ったら読めばいい • 自分がやりやすい形に作り替えていける感じはとても良い • もともとの設計思想から外れてしまっているかも知れないが。。。
  • 18. アプリケーションの全体構成 • Amon2::Setup::Flavor::Large を利用してスケルトンを生成 $ amon2-setup.pl --flavor=Large,Teng LiteSNS • これをベースとして構成を手直ししていく • LiteSNS の中で Amon2::Web を継承したコントローラ群を複数用意 LiteSNS::APIv1 --- API としてレスポンスを返す (JSON) LiteSNS::Admin --- ブラウザで閲覧する認証付き管理画面 (HTML) • 全体で共用するモジュールはコントローラと並列の階層 LiteSNS::Model --- ロジックをまとめたモジュール LiteSNS::DB --- データベースモジュール LiteSNS::Exceptions --- 例外モジュール
  • 19. LiteSNS ├── APIv1 API Module <Amon2::Web> │   ├── Controller Controller │   │   ├── Article │   │   ├── User │   │   └── ... │   ├── Dispatcher Dispatcher │   └── Response Response Model │      ├── Article │      ├── User │      └── ... ├── Admin Admin-Web Module <Amon2::Web> │   ├── Controller │   └── Dispatcher ├── Constants Constant (Common) ├── DB │   └── Main Main Database <Teng> │      ├── Row │      │  ├── Articles │      │  ├── Users │   │  └── ... │      └── Schema ├── Exceptions Exception <Class::Exception> ├── Model Logic Model │   ├── Article │   ├── User │   └── ... └── Util UtilityMethods (Common)
  • 20. LiteSNS::DB • ORM として Teng を利用 • あとでモデルでちゃんと SQL 整理すればいい • でも、インデックスなどをしっかり考えると整理はあった方がいい • 管理画面のようなケースはORMのままでもいいと思う • データセット毎に別のクラスとして用意 • 複数系統持つことになると思うので • データセットや master / slave をつなぎ替えられるように • 日付や定義値などのカラムは inflate / deflate 設定しておく
  • 21. データの論理削除 • 全テーブルにフラグ (row_status) を持たせておく 1 : enable 0 : disable -1 : deleted • DB クラスで Class::Method::Modifiers を使う • delete メソッドを置き換えてしまう
  • 22. package LiteSNS::DB::Main; use parent qw(Teng); use Class::Method::Modifiers; use DateTime; use constant STATUS => { ENABLE => 1, # 有効 DISABLE => 0, # 無効 DELETED => -1, # 削除 }; around delete => sub { my ($orig, $self, $table_name, $delete_condition) = @_; my $update_row_data = { updated_at => DateTime->now(time_zone => 'Asia/Tokyo'), row_status => STATUS()->{DELETED}, }; $self->update($table_name, $update_row_data, $delete_condition); }; before single => sub { my ($self, $table_name, $search_condition, $search_attr) = @_; unless (defined $search_condition->{row_status}) { $search_condition->{row_status} = STATUS()->{ENABLE}; } }; ...
  • 23. LiteSNS::Model • 共通の処理として呼べるようにコントローラから分離 • API だけでなく、Admin や CLI からも同じ処理をする可能性があるため • Mouse ベースでリクエストに依存しない処理をまとめたクラスを作成 • 常に決まった処理をするようなロジックをまとめる • フローに沿ったステータスの遷移 • 例) 友達の状態をチェックして申請中 → 承認にステータスを変える • 合計数のインクリメント/デクリメント • 例) コメントを投稿したら、その記事のコメント数をインクリメント
  • 24. LiteSNS::APIv1::Response • レスポンスを詰め込むオブジェクトを用意 • 入れ子構造 • 不要カラムの削除や属性名の変更など • Teng::Row を詰め込んで JSON で出力したいハッシュに変換・整形 • 最初は Teng::Row に変換メソッドを組み込んでみた • テーブルとモデルが必ずしも一対一対応しなかったので分離
  • 25. users { id => 928, id user => { id => 1001, name name => ‘taro’, }, password articles title => ‘今日のランチ’, article_count body => ‘パンがおいしかった!’, id createdAt => ‘2012-09-28 13:24:01’, row_status comments => [ user_id { created_at user => { title updated_at id => 1034, body name => ‘jiro’, }, comment_count body => ‘おいしそうだね!’, like_count createdAt => ‘2012-09-28 13:31:34’, }, row_status comments { user => { created_at id id => 1001, updated_at user_id name => ‘taro’, }, article_id body => ‘焼きたてをだしてくれるん だー’, body createdAt => ‘2012-09-28 13:35:18’, row_status }, ], created_at }, updated_at
  • 26. JSON レスポンスの生成 • 標準プラグイン Amon2::Plugin::Web::JSON を利用 • 今回はレスポンスコードを変えたかったので一部変更 • Controller からの戻り値でレスポンスコードを渡せるように • JSON / JSON::XS • PERL -> JSON では数字の取り扱いに注意 • 類推してくれるが、明示的に数値になっていないと数値にならない
  • 27. エラーと例外の処理 • Class::Exception を利用 • アプリケーション共通で利用する例外クラスを作成 • 例外が発生した場合にこのインスタンスを投げる • Dispatcher / Worker のレベルで Exception をキャッチする • 該当する例外の内容に合わせてエラーメッセージを生成 • HTTP ステータスコードに割り当ててレスポンスとして作成
  • 28. テスト • Model や共通関数などはテストを作っておく • 実際に処理させてチェックだと面倒 • テストに合わせて daemon を起動するようにしてあげると良い • http://perl-users.jp/articles/advent-calendar/2011/test/18 • テストを書きすぎるとキリが無くなってしまうのでバランス大事 • Jenkins などの CI ツールをうまく活用 • API はレスポンスのテストしやすい • JSON なので期待値との比較などが容易 • Test::WWW::Mechanize::PSGI などを活用
  • 29. 環境ごとの切り分け • Amon2 の機能で config を切り替えられる • 接続先ホストやユーザ名などを変えておく • 開発時だけ環境変数でフラグを入れたりすると便利 • 本番と開発環境でドメイン + 階層が異なってもうまく吸収できる • 同一ドメインで全てをサーブしたい場合はまとめた psgi を作ってたてる # app.psgi ... builder { mount '/api/' => Plack::Util::load_psgi('api.psgi'); mount '/admin/' => Plack::Util::load_psgi('admin.psgi'); }; • 異なるドメインの場合は個別にプロセスをたてる • Proxy などでわけてアクセスできるようにする
  • 30. 本番環境 • Starman + Server::Starter $ carton  exec  -­‐-­‐  start_server  -­‐-­‐port=5000  -­‐-­‐signal-­‐on-­‐hup=USR1  -­‐-­‐   plackup  -­‐s  Starlet  -­‐-­‐spawn-­‐interval=5 • プロセスを supervisord で立ち上げる • 標準出力のログは supervisord がファイルに書き出してくれる • ローカルに Nginx をたててローカルの Starman に送る • Nginx 側でアクセスログを取得 • 管理画面のアクセス制御や多段 Proxy 時のヘッダコントロールなど
  • 31. 連携 Cooperation
  • 32. クライアントアプリとの連携 • iPhone を例にいくつか紹介 • Objective-C 的な話も出てきますが軽く触れるだけにします • AFNetworking (https://github.com/AFNetworking/AFNetworking) • AFJSONRequestOperation で JSON -> NSDirectory と変換 • NSDirectory で init できるようにデータオブジェクトを定義しておく • オブジェクトが入れ子になっているようにしておく • このクラスがあるから、API の出力も同じようにできるオブジェクトを考 えてるわけで
  • 33. API のコールと JSON 値の変換 • 1回のリクエストで階層化したデータを返せるようにする • 通信回数を抑えることが大事 • 画面遷移の度に通信を発生させたくない • 海外を見据えてるなら通信環境が優れている場所ばかりとは限らないため • 値を変更したらその変更を通知して画面も更新する必要がある • インターフェイスとのバランスも考える必要がある • 送信 ボタンがあるとは限らず、トリガスイッチだけだったりもする • アプリ開発者と連携しながら相互に調整する必要がある
  • 34. リクエストヘッダ • 独自のユーザエージェントを設定 • 独自の HTTP ヘッダをアプリからの通信時に埋め込む • クライアントアプリのバージョン • X-LiteSNS-Version • ユーザの閲覧環境 • X-LiteSNS-Locale • X-LiteSNS-Language • X-LiteSNS-Timezone • このあたりはアプリサイドのコードで埋め込むことができる • ルールを決めておくことが大事
  • 35. APNS を用いた PUSH 通知 • Apple Push Notification Service (APNS) • 詳細は iOS Developer Library を参照 • 通知の流れ 1.アプリでデバイストークンを取得してサーバに送信 • NSData を16進数などに変換してサーバに POST 2.サーバサイドでアクティブなセッションと紐づけて保持しておく 3.モジュールを利用して通知パケットを APNS サーバに送る • Net::APNS, AnyEvent::APNS • AnyEvent::APNS の例は typester さんの解説が分かりやすいです • http://perl-users.jp/articles/advent-calendar/2010/hacker/7
  • 36. -­‐(void)applicationDidFinishLaunching:(UIApplication  *)application   {                //  初回起動時に  「“LiteSNS”はあなたにプッシュ通知を..」  という確認ダイアログを表示        [[UIApplication  sharedApplication]  registerForRemoteNotificationTypes: (UIRemoteNotificationTypeAlert  |  UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)]; } -­‐  (void)application:(UIApplication  *)app  didRegisterForRemoteNotificationsWithDeviceToken: (NSData  *)deviceToken   {          //  ここで  NSData  形式の  deviceToken  を16進数変換して送ります } use Net::APNS; my $APNS = Net::APNS->new; my $notification = $APNS->notify({ cert => ‘path/to/app.cer’, key => ‘path/to/app.key’, }); $notification->devicetoken(‘device_token’); # ここで16進数のトークンをセットする $notification->message("new message from LiteSNS"); # 通知メッセージ本文 $notification->badge(1); # アプリアイコンにつけるバッジの数 $notification->write;
  • 37. まとめ Summary
  • 38. まとめ • 設計 • 見えるところから見えないところへと考えを掘り下げていく • 最初に全てを決めきれないので、作りながら微調整は必要 • 開発 • 仕組みを考えながら組み合わせて作っていく • スケールする仕組みをあとからでも入れられるようにする • 連携 • ライブラリをうまく使ってデータを組み立てていく • スマートフォンならでは、アプリならではの視点も必要
  • 39. まとめ • やってみて分かったこと • 様々な観点が必要とされている • プログラム、ミドルウェア、に加えてフロント側も • 特性とかユーザの利用シーンもちゃんと考えないとうまく作れない • でも、難しいことではない • (本来は)全部を一人でできなくてもいい • タスクを振るとき、全体を設計するときにあると良い • 何ができるか、を知っていることが大事 • Titanium など敷居の低い開発手法もあるので試してみるのが良い