SlideShare una empresa de Scribd logo
1 de 15
Developmet
Application with Elixir
        @k1complete
abstract
• Elixirにおいて、本格的なアプリケーション
 を開発するために必要そうな内容を実例に
 そって紹介

• Erlang/OTPの知識を前提とせず頑張ってみ
 ます

• 最終的にはElixir、Erlang/OTPのドキュメン
 トを読む気になれば
Elixirとは
•   José Valimが開発しているErlang VM上に構築された、以下の
    特徴を持つプログラミング言語

    •   現代的な文法

    •   Erlang/OTPとのバイナリ相互互換性(並行指向、耐障害性
        といったErlang/OTPの特徴を全て持つ)。JavaVMでScala
        がしたことをErlang VMで行っているようなもの

    •   メタプログラミング支援機能

        •   プロトコル、レコードによるポリモーフィズム

        •   本物のマクロ
Erlang/OTPとは
•   Open Telecom Platformの略で、EricssonのOTPチームにより母体が開
    発され、Erlangコミュニティにより継続されている、通信アプリケー
    ションに必要とされる機能/非機能要件をサポートするライブラリ

    •   アプリケーション管理(applicationビヘイビア)

    •   汎用サーバ(gen_serverビヘイビア)

    •   状態遷移マシン(gen_fsmビヘイビア)

    •   スーパバイザ(supervisorビヘイビア)

    •   動的アップグレード(releaseハンドラ)

    •   ando more....!
お題: KVSサーバ
1. Key-Valueストア機能の要件(FR)

 1.1.ユーザごとに個別のKV空間を割り当てる。

 1.2.キーはアトムのみで登録と読み出し、削除、変更がで
    きる。

2. それ以外の要件(NFR)

 2.1.マルチユーザにサービスする事

 2.2.クライアントが接続しているサーバがクラッシュして
    も復活する事
全体の構造
      app                   起動と停止

                   クライアントの要求によりsupervisor for
   supervisor            serverの起動を行う

                   1サーバに一つ起動し、サーバクラッシュ
   supervisor
    supervisor       時の再起動と、KVSテーブル保持
    for server
     for server
                   1クライアントに一つ起動し、KVSの操作
  gen_server
  gen_server                 を実施
                   gen_serverのコールバックとして実装する
      ekvs         ETSを利用したKVSモジュール(not OTP)


なるだけOTPモジュールを組み合わせるのがOTP way
ekvs
• ekvsはETS(erlang term strage)を利用し
  て簡単にすます
 defmodule Ekvs do
  def new(id) do
                                       defp keys(_id, :"$end_of_table", a) do
   new(id, [])
                                        a
  end
                                       end
  def new(id, opts) do
                                       defp keys(id, r, a) do
   :ets.new(id, opts)
                                        keys(id, :ets.next(id, r), [r | a])
  end
                                       end
  def put(id, k, v) do
                                       def keys(id) do
   true = :ets.insert(id, {k, v})
                                        keys(id, :ets.first(id), [])
   id
                                       end
  end
                                       def delete(id, k) do
  def get(id, k) do
                                        :ets.delete(id, k)
   case :ets.lookup(id, k) do
                                        id
     [] -> nil
                                       end
     [{^k, v}] -> v
                                      end
   end
  end
gen_serverとは

• 並行指向のElixir(Erlang/OTP)では、単にマルチユー
  ザを束ねるプロセスをサーバとは考えない。

• サーバはそのリソースを管理するものと考える。

• サーバとして共通に必要な部分をビヘイビア(振る舞
  い)としてまとめたのがgen_server

• 固有部分は指定された名前のコールバック関数を実装
  することで、適切にgen_server側から呼び出される。
ekvsサーバの実装
           • elixirではGenServer.Behaviorモジュールがある
                 ため、これをuseしてコールバックを実装する。
defmodule Kvs.Server do
 use GenServer.Behavior                                    def handle_call({:delete, key}, _from, state) do
 def start_link(id, tbl_id) do                              {:reply, :ok, Ekvs.delete(state, key)}
  :gen_server.start_link({:local, id}, __MODULE__, [id,    end
tbl_id], [])                                               def handle_call({:keys}, _from, state) do
 end                                                        {:reply, Ekvs.keys(state), state}
 def init([_id, tbl_id]) do                                end
  :io.format("kvs.server[~p]~n", [tbl_id])                 def terminate(reason, state) do
  {:ok, tbl_id}                                             :error_logger.error_report('#{inspect __MODULE__}
 end                                                      crashed:n#{inspect reason}')
 def handle_call({:get, key}, _from, state) do              :error_logger.error_report('#{inspect __MODULE__}
  {:reply, Ekvs.get(state, key), state}                   snapshot:n#{inspect state}')
 end                                                        :ok
 def handle_call({:put, key, value}, _from, state) do      end
  {:reply, value, Ekvs.put(state, key, value)}            end
 end
supervisorとは
•   子プロセスの(再)起動に責任を持つビヘイビア。プログラマは再起動ポリシーと子プロセス
    のスペックを指定するだけで、異常事態(プロセスのクラッシュ)への対処を行ってくれる

    •   再起動ポリシー

        •   one_for_one 一つが落ちたら、その一つを再起動

        •   one_for_all 一つが落ちたら、全ての子プロセスを再起動

        •   rest_for_all 一つが落ちたら、そのプロセス以降に起動された物を全て再起動

        •   再起動トライ数、最大リトライ秒数...

    •   子プロセスのスペック

        •   restart :permanent(常に再起動), :transient(再起動されない), :temporary(異常終了の
            ときのみ再起動)

        •   type worker/supervisorのいずれか

        •   module_list 子プロセスを実装するモジュール。リリースハンドラはこれを元にアッ
            プグレード時に再起動するプロセスを決定します。
supervisor for
               GenServer
•   init()は以下のとおり
                                    defmodule Kvs.Srv.Sup do
    •   :ets.newでテーブルを作成し、           use Supervisor.Behavior, []
                                     def init(args) do
        それをKvs.Serverへ渡すように           key = args
        childspecを記述。                 tbl_id = :ets.new(key, [:public])
                                      childspec = {key,
                                        {Kvs.Server, :start_link, [key, tbl_id]},
    •   :one_for_oneタイプと
                                         :permanent,
        し、:permanent に存在さ                100000,
                                         :worker,
        せ、:workerタイプの子プロセス               [Kvs.Server]}
                                       {:ok, {{:one_for_one,
    •   サーバの起動は、                         10, # AllowedRestart(count)
                                         100}, # MaxSeconds(sec)
        Kvs.Server.start_linkを呼び出
                                         [childspec]}}
        す。                           end
                                    end
•   以上でsupervisor完了
Supervisor for
               Supervisor
                                       defmodule Kvs.Sup do
•   クライアントからの要求に応じ                      use Supervisor.Behavior, []
                                        def init(_args) do
    て、子プロセスを起動するような                      {:ok, {{:one_for_one,
    supervisorは、                               10, # AllowedRestart(count)
                                               100}, # MaxSeconds(sec)
    supervisor.start_childと                    []}}
                                        end
    supervisor.terminate_childを使う。      def connect(super_ref, key) do
                                         childspec = {key,
    •   connect関数: Kvs.SrvSupの生成          {Kvs.Srv.Sup, :start_link, [key]},
                                          :temporary,
        supervisor.start_child 関数によ
                                           10000, #shutown wait time(milisec)
        り動的に開始                             :supervisor,
                                           [Kvs.Srv.Sup]}
    •   quit関数: Kvs.SrvSupの終了            :supervisor.start_child(super_ref, childspec)
                                        end
        supervisor.terminate_child関数    def quit(super_ref, key) do
                                         :supervisor.terminate_child(super_ref, key)
        呼び出し
                                        end
                                       end
application
                        defmodule KvsApp do
• OTPアプリケーションと           @behaviour :application
                         def start() do
 して start, stop関数を用意      :ok = :application.start(:kvs)
                         end
                         def start(_type, args) do
 する必要がある。                 Kvs.Sup.start_link(:kvs_sup, args)
                         end
                         def stop() do
• 中身はトップレベルの              :application.stop(:kvs)
                         end
 supervisorモジュールであ       def stop(state) do
                          Kvs.Sup.stop(:application_stop, state)
                         end
 るKvs.Sup.start_linkや   end


 Kvs.Sup.stopを呼び出す
 だけ。
mix.exs
                            defmodule MyApp.MixFile do
• ビルド用のmix.exs               use Mix.Project
                             def project do
• ビルド定義もelixirスクリプトで記         [app: :kvs,
                               version: "0.0.1"]
  述。                         end
                             def application do
                              [mod: {KvsApp,[]},
• バージョンやアプリケーションの              applications: [:sasl ],
                               registered: [:kvs],
  メインモジュール、デスクリプ               description: 'Hello Server App']

  ションを指定するだけで、kvs.app        end
                            end
  は自動でmixがビルドしてくれる。

• mix new <app>で<app>用のセッ
  トアップをしてくれる。
github

今回のコードは以下に曝していますので
ご自由にどうぞ。



https://github.com/k1complete/kvs.git

Más contenido relacionado

La actualidad más candente

Itamae-Serverspec入門
Itamae-Serverspec入門Itamae-Serverspec入門
Itamae-Serverspec入門辰徳 斎藤
 
CMSとPerlで遊ぼう
CMSとPerlで遊ぼうCMSとPerlで遊ぼう
CMSとPerlで遊ぼうDaiki Ichinose
 
Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」
Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」
Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」fukuoka.ex
 
Perlで伝統芸能
Perlで伝統芸能Perlで伝統芸能
Perlで伝統芸能hitode909
 
Elixir入門「第6回:Elixirはtry…catchを書かない~障害対応のパラダイムシフト~」
Elixir入門「第6回:Elixirはtry…catchを書かない~障害対応のパラダイムシフト~」Elixir入門「第6回:Elixirはtry…catchを書かない~障害対応のパラダイムシフト~」
Elixir入門「第6回:Elixirはtry…catchを書かない~障害対応のパラダイムシフト~」fukuoka.ex
 
Serverspecの活用tips紹介
Serverspecの活用tips紹介Serverspecの活用tips紹介
Serverspecの活用tips紹介Daisuke Ikeda
 
15分でCakePHPを始める方法(Nseg 2013-11-09 )
15分でCakePHPを始める方法(Nseg 2013-11-09 )15分でCakePHPを始める方法(Nseg 2013-11-09 )
15分でCakePHPを始める方法(Nseg 2013-11-09 )hiro345
 
初級者向けレッスン 51回 ─── 例外
初級者向けレッスン 51回 ─── 例外初級者向けレッスン 51回 ─── 例外
初級者向けレッスン 51回 ─── 例外higaki
 
2017年夏のPerl
2017年夏のPerl2017年夏のPerl
2017年夏のPerlcharsbar
 
T sql の parse と generator
T sql の parse と generatorT sql の parse と generator
T sql の parse と generatorOda Shinsuke
 
やや関数型を意識した風Elixir/Phoenixご紹介
やや関数型を意識した風Elixir/Phoenixご紹介やや関数型を意識した風Elixir/Phoenixご紹介
やや関数型を意識した風Elixir/Phoenixご紹介fukuoka.ex
 
WordPress関数の処理コストを考えよう
WordPress関数の処理コストを考えようWordPress関数の処理コストを考えよう
WordPress関数の処理コストを考えようNaoki Matsuda
 
Elixir入門「第2回:PC間で通信するアプリをサクっと書いてみる」
Elixir入門「第2回:PC間で通信するアプリをサクっと書いてみる」Elixir入門「第2回:PC間で通信するアプリをサクっと書いてみる」
Elixir入門「第2回:PC間で通信するアプリをサクっと書いてみる」fukuoka.ex
 
Flow.js
Flow.jsFlow.js
Flow.jsuupaa
 
Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」【旧版】※新版あります
Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」【旧版】※新版ありますElixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」【旧版】※新版あります
Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」【旧版】※新版ありますfukuoka.ex
 
Perl 非同期プログラミング
Perl 非同期プログラミングPerl 非同期プログラミング
Perl 非同期プログラミングlestrrat
 
omoon.org の裏側 〜FuelPHP の task 活用例〜
omoon.org の裏側 〜FuelPHP の task 活用例〜omoon.org の裏側 〜FuelPHP の task 活用例〜
omoon.org の裏側 〜FuelPHP の task 活用例〜Sotaro Omura
 

La actualidad más candente (20)

Itamae-Serverspec入門
Itamae-Serverspec入門Itamae-Serverspec入門
Itamae-Serverspec入門
 
CMSとPerlで遊ぼう
CMSとPerlで遊ぼうCMSとPerlで遊ぼう
CMSとPerlで遊ぼう
 
Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」
Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」
Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」
 
Perlで伝統芸能
Perlで伝統芸能Perlで伝統芸能
Perlで伝統芸能
 
Tottoruby 20110903
Tottoruby 20110903Tottoruby 20110903
Tottoruby 20110903
 
Elixir入門「第6回:Elixirはtry…catchを書かない~障害対応のパラダイムシフト~」
Elixir入門「第6回:Elixirはtry…catchを書かない~障害対応のパラダイムシフト~」Elixir入門「第6回:Elixirはtry…catchを書かない~障害対応のパラダイムシフト~」
Elixir入門「第6回:Elixirはtry…catchを書かない~障害対応のパラダイムシフト~」
 
Serverspecの活用tips紹介
Serverspecの活用tips紹介Serverspecの活用tips紹介
Serverspecの活用tips紹介
 
15分でCakePHPを始める方法(Nseg 2013-11-09 )
15分でCakePHPを始める方法(Nseg 2013-11-09 )15分でCakePHPを始める方法(Nseg 2013-11-09 )
15分でCakePHPを始める方法(Nseg 2013-11-09 )
 
初級者向けレッスン 51回 ─── 例外
初級者向けレッスン 51回 ─── 例外初級者向けレッスン 51回 ─── 例外
初級者向けレッスン 51回 ─── 例外
 
2017年夏のPerl
2017年夏のPerl2017年夏のPerl
2017年夏のPerl
 
T sql の parse と generator
T sql の parse と generatorT sql の parse と generator
T sql の parse と generator
 
Hbstudy41 auto scaling
Hbstudy41 auto scalingHbstudy41 auto scaling
Hbstudy41 auto scaling
 
やや関数型を意識した風Elixir/Phoenixご紹介
やや関数型を意識した風Elixir/Phoenixご紹介やや関数型を意識した風Elixir/Phoenixご紹介
やや関数型を意識した風Elixir/Phoenixご紹介
 
あらためてPHP5.3
あらためてPHP5.3あらためてPHP5.3
あらためてPHP5.3
 
WordPress関数の処理コストを考えよう
WordPress関数の処理コストを考えようWordPress関数の処理コストを考えよう
WordPress関数の処理コストを考えよう
 
Elixir入門「第2回:PC間で通信するアプリをサクっと書いてみる」
Elixir入門「第2回:PC間で通信するアプリをサクっと書いてみる」Elixir入門「第2回:PC間で通信するアプリをサクっと書いてみる」
Elixir入門「第2回:PC間で通信するアプリをサクっと書いてみる」
 
Flow.js
Flow.jsFlow.js
Flow.js
 
Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」【旧版】※新版あります
Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」【旧版】※新版ありますElixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」【旧版】※新版あります
Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」【旧版】※新版あります
 
Perl 非同期プログラミング
Perl 非同期プログラミングPerl 非同期プログラミング
Perl 非同期プログラミング
 
omoon.org の裏側 〜FuelPHP の task 活用例〜
omoon.org の裏側 〜FuelPHP の task 活用例〜omoon.org の裏側 〜FuelPHP の task 活用例〜
omoon.org の裏側 〜FuelPHP の task 活用例〜
 

Similar a Development app-with-elixir

Elixir Meetup #1 Loggerの構造と拡張
Elixir Meetup #1 Loggerの構造と拡張Elixir Meetup #1 Loggerの構造と拡張
Elixir Meetup #1 Loggerの構造と拡張Sugawara Genki
 
x86とコンテキストスイッチ
x86とコンテキストスイッチx86とコンテキストスイッチ
x86とコンテキストスイッチMasami Ichikawa
 
ebisu.rb #19 超実践 super
ebisu.rb #19 超実践 superebisu.rb #19 超実践 super
ebisu.rb #19 超実践 superKaito Minatoya
 
Everyday Life with clojure.spec
Everyday Life with clojure.specEveryday Life with clojure.spec
Everyday Life with clojure.specKent Ohashi
 
軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題
軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題
軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題Makoto Setoh
 
今日から使い始めるChef
今日から使い始めるChef今日から使い始めるChef
今日から使い始めるChefMasahiro NAKAYAMA
 
Continuation with Boost.Context
Continuation with Boost.ContextContinuation with Boost.Context
Continuation with Boost.ContextAkira Takahashi
 
Clojure programming-chapter-2
Clojure programming-chapter-2Clojure programming-chapter-2
Clojure programming-chapter-2Masao Kato
 
ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~
ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~
ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~Akabane Hiroyuki
 
eZ Publish勉強会9月〜テンプレート言語〜
eZ Publish勉強会9月〜テンプレート言語〜eZ Publish勉強会9月〜テンプレート言語〜
eZ Publish勉強会9月〜テンプレート言語〜ericsagnes
 
Cookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう
Cookpad 17 day Tech internship 2017 言語処理系入門 RubyをコンパイルしようCookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう
Cookpad 17 day Tech internship 2017 言語処理系入門 RubyをコンパイルしようKoichi Sasada
 
EC-CUBE + PHPUnit で 実践テスト駆動開発
EC-CUBE + PHPUnit で 実践テスト駆動開発EC-CUBE + PHPUnit で 実践テスト駆動開発
EC-CUBE + PHPUnit で 実践テスト駆動開発Kentaro Ohkouchi
 
for JSDeferred Code Reading
for JSDeferred Code Readingfor JSDeferred Code Reading
for JSDeferred Code ReadingKenichirou Oyama
 
EWD 3トレーニングコース#31 ewd-xpressでWebおよびRESTサービスを作る
EWD 3トレーニングコース#31 ewd-xpressでWebおよびRESTサービスを作るEWD 3トレーニングコース#31 ewd-xpressでWebおよびRESTサービスを作る
EWD 3トレーニングコース#31 ewd-xpressでWebおよびRESTサービスを作るKiyoshi Sawada
 
EWD 3トレーニングコース#31 ewd-xpressでWebおよびRESTサービスを作る
EWD 3トレーニングコース#31 ewd-xpressでWebおよびRESTサービスを作るEWD 3トレーニングコース#31 ewd-xpressでWebおよびRESTサービスを作る
EWD 3トレーニングコース#31 ewd-xpressでWebおよびRESTサービスを作るKiyoshi Sawada
 
JavaScript 講習会 #1
JavaScript 講習会 #1JavaScript 講習会 #1
JavaScript 講習会 #1Susisu
 
Awsで構築したのだよ 05 プロセス監視、メモリ使用率、ディスク使用率をCloudWatchのカスタムメトリクスに追加したい
Awsで構築したのだよ 05 プロセス監視、メモリ使用率、ディスク使用率をCloudWatchのカスタムメトリクスに追加したいAwsで構築したのだよ 05 プロセス監視、メモリ使用率、ディスク使用率をCloudWatchのカスタムメトリクスに追加したい
Awsで構築したのだよ 05 プロセス監視、メモリ使用率、ディスク使用率をCloudWatchのカスタムメトリクスに追加したい聡 大久保
 
Cinnamon - simple deploy tool
Cinnamon - simple deploy toolCinnamon - simple deploy tool
Cinnamon - simple deploy toolYuki Shibazaki
 

Similar a Development app-with-elixir (20)

Elixir Meetup #1 Loggerの構造と拡張
Elixir Meetup #1 Loggerの構造と拡張Elixir Meetup #1 Loggerの構造と拡張
Elixir Meetup #1 Loggerの構造と拡張
 
x86とコンテキストスイッチ
x86とコンテキストスイッチx86とコンテキストスイッチ
x86とコンテキストスイッチ
 
ebisu.rb #19 超実践 super
ebisu.rb #19 超実践 superebisu.rb #19 超実践 super
ebisu.rb #19 超実践 super
 
Everyday Life with clojure.spec
Everyday Life with clojure.specEveryday Life with clojure.spec
Everyday Life with clojure.spec
 
軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題
軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題
軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題
 
今日から使い始めるChef
今日から使い始めるChef今日から使い始めるChef
今日から使い始めるChef
 
Continuation with Boost.Context
Continuation with Boost.ContextContinuation with Boost.Context
Continuation with Boost.Context
 
VerilatorとSystemC
VerilatorとSystemCVerilatorとSystemC
VerilatorとSystemC
 
Clojure programming-chapter-2
Clojure programming-chapter-2Clojure programming-chapter-2
Clojure programming-chapter-2
 
ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~
ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~
ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~
 
eZ Publish勉強会9月〜テンプレート言語〜
eZ Publish勉強会9月〜テンプレート言語〜eZ Publish勉強会9月〜テンプレート言語〜
eZ Publish勉強会9月〜テンプレート言語〜
 
Cookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう
Cookpad 17 day Tech internship 2017 言語処理系入門 RubyをコンパイルしようCookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう
Cookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう
 
EC-CUBE + PHPUnit で 実践テスト駆動開発
EC-CUBE + PHPUnit で 実践テスト駆動開発EC-CUBE + PHPUnit で 実践テスト駆動開発
EC-CUBE + PHPUnit で 実践テスト駆動開発
 
for JSDeferred Code Reading
for JSDeferred Code Readingfor JSDeferred Code Reading
for JSDeferred Code Reading
 
EWD 3トレーニングコース#31 ewd-xpressでWebおよびRESTサービスを作る
EWD 3トレーニングコース#31 ewd-xpressでWebおよびRESTサービスを作るEWD 3トレーニングコース#31 ewd-xpressでWebおよびRESTサービスを作る
EWD 3トレーニングコース#31 ewd-xpressでWebおよびRESTサービスを作る
 
EWD 3トレーニングコース#31 ewd-xpressでWebおよびRESTサービスを作る
EWD 3トレーニングコース#31 ewd-xpressでWebおよびRESTサービスを作るEWD 3トレーニングコース#31 ewd-xpressでWebおよびRESTサービスを作る
EWD 3トレーニングコース#31 ewd-xpressでWebおよびRESTサービスを作る
 
JavaScript 講習会 #1
JavaScript 講習会 #1JavaScript 講習会 #1
JavaScript 講習会 #1
 
Awsで構築したのだよ 05 プロセス監視、メモリ使用率、ディスク使用率をCloudWatchのカスタムメトリクスに追加したい
Awsで構築したのだよ 05 プロセス監視、メモリ使用率、ディスク使用率をCloudWatchのカスタムメトリクスに追加したいAwsで構築したのだよ 05 プロセス監視、メモリ使用率、ディスク使用率をCloudWatchのカスタムメトリクスに追加したい
Awsで構築したのだよ 05 プロセス監視、メモリ使用率、ディスク使用率をCloudWatchのカスタムメトリクスに追加したい
 
About Jobs
About JobsAbout Jobs
About Jobs
 
Cinnamon - simple deploy tool
Cinnamon - simple deploy toolCinnamon - simple deploy tool
Cinnamon - simple deploy tool
 

Development app-with-elixir

  • 2. abstract • Elixirにおいて、本格的なアプリケーション を開発するために必要そうな内容を実例に そって紹介 • Erlang/OTPの知識を前提とせず頑張ってみ ます • 最終的にはElixir、Erlang/OTPのドキュメン トを読む気になれば
  • 3. Elixirとは • José Valimが開発しているErlang VM上に構築された、以下の 特徴を持つプログラミング言語 • 現代的な文法 • Erlang/OTPとのバイナリ相互互換性(並行指向、耐障害性 といったErlang/OTPの特徴を全て持つ)。JavaVMでScala がしたことをErlang VMで行っているようなもの • メタプログラミング支援機能 • プロトコル、レコードによるポリモーフィズム • 本物のマクロ
  • 4. Erlang/OTPとは • Open Telecom Platformの略で、EricssonのOTPチームにより母体が開 発され、Erlangコミュニティにより継続されている、通信アプリケー ションに必要とされる機能/非機能要件をサポートするライブラリ • アプリケーション管理(applicationビヘイビア) • 汎用サーバ(gen_serverビヘイビア) • 状態遷移マシン(gen_fsmビヘイビア) • スーパバイザ(supervisorビヘイビア) • 動的アップグレード(releaseハンドラ) • ando more....!
  • 5. お題: KVSサーバ 1. Key-Valueストア機能の要件(FR) 1.1.ユーザごとに個別のKV空間を割り当てる。 1.2.キーはアトムのみで登録と読み出し、削除、変更がで きる。 2. それ以外の要件(NFR) 2.1.マルチユーザにサービスする事 2.2.クライアントが接続しているサーバがクラッシュして も復活する事
  • 6. 全体の構造 app 起動と停止 クライアントの要求によりsupervisor for supervisor serverの起動を行う 1サーバに一つ起動し、サーバクラッシュ supervisor supervisor 時の再起動と、KVSテーブル保持 for server for server 1クライアントに一つ起動し、KVSの操作 gen_server gen_server を実施 gen_serverのコールバックとして実装する ekvs ETSを利用したKVSモジュール(not OTP) なるだけOTPモジュールを組み合わせるのがOTP way
  • 7. ekvs • ekvsはETS(erlang term strage)を利用し て簡単にすます defmodule Ekvs do def new(id) do defp keys(_id, :"$end_of_table", a) do new(id, []) a end end def new(id, opts) do defp keys(id, r, a) do :ets.new(id, opts) keys(id, :ets.next(id, r), [r | a]) end end def put(id, k, v) do def keys(id) do true = :ets.insert(id, {k, v}) keys(id, :ets.first(id), []) id end end def delete(id, k) do def get(id, k) do :ets.delete(id, k) case :ets.lookup(id, k) do id [] -> nil end [{^k, v}] -> v end end end
  • 8. gen_serverとは • 並行指向のElixir(Erlang/OTP)では、単にマルチユー ザを束ねるプロセスをサーバとは考えない。 • サーバはそのリソースを管理するものと考える。 • サーバとして共通に必要な部分をビヘイビア(振る舞 い)としてまとめたのがgen_server • 固有部分は指定された名前のコールバック関数を実装 することで、適切にgen_server側から呼び出される。
  • 9. ekvsサーバの実装 • elixirではGenServer.Behaviorモジュールがある ため、これをuseしてコールバックを実装する。 defmodule Kvs.Server do use GenServer.Behavior def handle_call({:delete, key}, _from, state) do def start_link(id, tbl_id) do {:reply, :ok, Ekvs.delete(state, key)} :gen_server.start_link({:local, id}, __MODULE__, [id, end tbl_id], []) def handle_call({:keys}, _from, state) do end {:reply, Ekvs.keys(state), state} def init([_id, tbl_id]) do end :io.format("kvs.server[~p]~n", [tbl_id]) def terminate(reason, state) do {:ok, tbl_id} :error_logger.error_report('#{inspect __MODULE__} end crashed:n#{inspect reason}') def handle_call({:get, key}, _from, state) do :error_logger.error_report('#{inspect __MODULE__} {:reply, Ekvs.get(state, key), state} snapshot:n#{inspect state}') end :ok def handle_call({:put, key, value}, _from, state) do end {:reply, value, Ekvs.put(state, key, value)} end end
  • 10. supervisorとは • 子プロセスの(再)起動に責任を持つビヘイビア。プログラマは再起動ポリシーと子プロセス のスペックを指定するだけで、異常事態(プロセスのクラッシュ)への対処を行ってくれる • 再起動ポリシー • one_for_one 一つが落ちたら、その一つを再起動 • one_for_all 一つが落ちたら、全ての子プロセスを再起動 • rest_for_all 一つが落ちたら、そのプロセス以降に起動された物を全て再起動 • 再起動トライ数、最大リトライ秒数... • 子プロセスのスペック • restart :permanent(常に再起動), :transient(再起動されない), :temporary(異常終了の ときのみ再起動) • type worker/supervisorのいずれか • module_list 子プロセスを実装するモジュール。リリースハンドラはこれを元にアッ プグレード時に再起動するプロセスを決定します。
  • 11. supervisor for GenServer • init()は以下のとおり defmodule Kvs.Srv.Sup do • :ets.newでテーブルを作成し、 use Supervisor.Behavior, [] def init(args) do それをKvs.Serverへ渡すように key = args childspecを記述。 tbl_id = :ets.new(key, [:public]) childspec = {key, {Kvs.Server, :start_link, [key, tbl_id]}, • :one_for_oneタイプと :permanent, し、:permanent に存在さ 100000, :worker, せ、:workerタイプの子プロセス [Kvs.Server]} {:ok, {{:one_for_one, • サーバの起動は、 10, # AllowedRestart(count) 100}, # MaxSeconds(sec) Kvs.Server.start_linkを呼び出 [childspec]}} す。 end end • 以上でsupervisor完了
  • 12. Supervisor for Supervisor defmodule Kvs.Sup do • クライアントからの要求に応じ use Supervisor.Behavior, [] def init(_args) do て、子プロセスを起動するような {:ok, {{:one_for_one, supervisorは、 10, # AllowedRestart(count) 100}, # MaxSeconds(sec) supervisor.start_childと []}} end supervisor.terminate_childを使う。 def connect(super_ref, key) do childspec = {key, • connect関数: Kvs.SrvSupの生成 {Kvs.Srv.Sup, :start_link, [key]}, :temporary, supervisor.start_child 関数によ 10000, #shutown wait time(milisec) り動的に開始 :supervisor, [Kvs.Srv.Sup]} • quit関数: Kvs.SrvSupの終了 :supervisor.start_child(super_ref, childspec) end supervisor.terminate_child関数 def quit(super_ref, key) do :supervisor.terminate_child(super_ref, key) 呼び出し end end
  • 13. application defmodule KvsApp do • OTPアプリケーションと @behaviour :application def start() do して start, stop関数を用意 :ok = :application.start(:kvs) end def start(_type, args) do する必要がある。 Kvs.Sup.start_link(:kvs_sup, args) end def stop() do • 中身はトップレベルの :application.stop(:kvs) end supervisorモジュールであ def stop(state) do Kvs.Sup.stop(:application_stop, state) end るKvs.Sup.start_linkや end Kvs.Sup.stopを呼び出す だけ。
  • 14. mix.exs defmodule MyApp.MixFile do • ビルド用のmix.exs use Mix.Project def project do • ビルド定義もelixirスクリプトで記 [app: :kvs, version: "0.0.1"] 述。 end def application do [mod: {KvsApp,[]}, • バージョンやアプリケーションの applications: [:sasl ], registered: [:kvs], メインモジュール、デスクリプ description: 'Hello Server App'] ションを指定するだけで、kvs.app end end は自動でmixがビルドしてくれる。 • mix new <app>で<app>用のセッ トアップをしてくれる。

Notas del editor

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n