Upgrade to Pro — share decks privately, control downloads, hide ads and more …

マルチテナントアーキテクチャ x Elixir / Phoenix

yujikawa
February 23, 2018

マルチテナントアーキテクチャ x Elixir / Phoenix

マルチテナントアーキテクチャ x Elixir / Phoenix

yujikawa

February 23, 2018
Tweet

More Decks by yujikawa

Other Decks in Programming

Transcript

  1. ϚϧνςφϯτΞʔΩςΫνϟ

    &MJYJS1IPFOJY
    4BB4ͷ࠷લઢ
    GVLVPLBFY
    Ώ͔͡Θ!ZVKJLBXB@QZ

    View Slide

  2. w ໊લ
    w ઒্༞࢘ Ώ͔͡Θ

    w ॴଐ
    w ΧϥϏφςΫϊϩδʔ
    w ৬छ
    w όοΫΤϯυΤϯδχΞ
    w 5XJUUFS
    w !ZVKJLBXB@QZ
    w ීஈͷ͓࢓ࣄ
    w &MJYJS1IPFOJYΛ࢖ͬͨ8FC։ൃ
    w ޷͖ͳݴޠ
    w &MJYJS
    w 1ZUIPO
    w ࠷ۙͷ׆ಈ
    w 1Z$PO,ZVTZVͷϝϯόʔͱͯ͠׆ಈத
    ࣗݾ঺հ

    View Slide

  3. ໨࣍
    w &MJYJSͱ1IPFOJYʹ͍ͭͯ
    w ࠷ۙͷฐࣾͷ&MJYJSࣄ৘
    w ࠷ۙͷੈͷதͷ&MJYJSࣄ৘
    w Ϛϧνςφϯτͱ͸ʁ
    w &MJYJS1IPFOJYͰϚϧνςφϯτΛ͢Δʹ͸ʁ
    w ։ൃ؀ڥʹ͍ͭͯ
    w ࣮૷ฤBQBSUNFOUFY
    w ·ͱΊ

    View Slide

  4. w ؔ਺ܕݴޠ
    w &SMBOH7. #&".
    ্Ͱಈ͘
    w όʔδϣϯ͸
    w 8FCϑϨʔϜϫʔΫʢ3BJMT΍%KBOHPΈ͍ͨͳײ͡ʣ
    w 3BJMTͷTDB⒎PME͕Ͱ͖Δ
    &MJYJSͱ1IPFOJYʹ͍ͭͯ

    View Slide

  5. ࠷ۙͷฐࣾͷ&MJYJSࣄ৘
    w ͜Ε·Ͱʢ݄͝Ζ·Ͱʣ
    w 1ZUIPOΛ࢖ͬͨγεςϜ։ൃ
    w ͜Ε͔Βʢ݄͔Βʣ
    w &MJYJS1IPFOJYΛ࢖ͬͨγεςϜ։ൃ
    w ؔ਺ܕݴޠͷอकੑɾฒྻॲཧͳͲͷߴ଎ੑʹັྗΛײ͡બఆɺγεςϜͷί
    Ξ෦෼͸&MJYJSΛ࢖͏ɻ͍͟ͱͳΕ͹&SMQPSUΛ࢖͍ɺ1ZUIPO౳ଞͷݴޠͱͷ
    ૊Έ߹Θͤ΋Մೳ
    w ࢀߟɿʮ&MJYJSʴ,FSBTʹखܰʹߴ଎ͳʮσʔλαΠΤϯεϓϥοτϑΥʔ
    Ϝʯʙ'MPXͰͷϚϧνίΞ׆༻ࣄྫʙʯIUUQTRJJUBDPNQJBDFSF
    JUFNTDBGCDFECD⒎

    View Slide

  6. ࠷ۙͷฐࣾͷ&MJYJSࣄ৘
    w ͜Ε·Ͱ࢖ͬͯΈͯͷײ૝
    w ϙδςΟϒ 㱼ʆ

    w 1IPFOJYͰ3BJMTฒΈͷര଎։ൃ͕Ͱ͖Δ
    w 5%%ʢςετۦಈ։ൃʣ͕͠΍͍͢
    w ίʔυ͕ಡΈ΍͍͢ʢอक͠΍͍͢ʣ
    w ॲཧ଎౓͕଎͍ʢ1ZUIPOͩͱؾʹͳΔ͕࣌͋Δʣ
    w ڧྗͳύλʔϯϚονͰίʔυྔ͕গͳ͘ࡁΜͩ
    w ωΨςΟϒ ʀ㱼ʀ

    w ৭ʑͳαʔϏεͷެࣜͷϥΠϒϥϦ͸·ͩগͳ͍
    w υΩϡϝϯτ΋গͳ͍ʢ೔ຊޠ͸ಛʹʣ
    ॻ͖΍͍͢ɾಡΈ΍͍͢ɾύΠϓॲཧָ͕͍͠

    View Slide

  7. ࠷ۙͷੈͷதͷ&MJYJSࣄ৘

    View Slide

  8. ࠷ۙͷੈͷதͷ&MJYJSࣄ৘
    w ($1ʢ(PPMHF$MPVE1MBUGPSNʣͰ&MJYJS͕࢖͑ΔΑ
    ͏ʹͳΓ·ͨ͠ʂԼهͷ63-Ͱ͸1IPFOJYΛ࢖͏·Ͱͷ
    νϡʔτϦΞϧ͕ܝࡌ͞Ε͍ͯ·͢ɻڵຯͷ͋Δํ͸ͥͻ
    ৮ͬͯݟ͍ͯͩ͘͞ɻ
    w νϡʔτϦΞϧɿIUUQTDMPVEHPPHMFDPNDPNNVOJUZ
    UVUPSJBMTFMJYJSQIPFOJYPOHPPHMFBQQFOHJOF

    View Slide

  9. ࠷ۙͷੈͷதͷ&MJYJSࣄ৘
    w ༸ॻ͕࣍ʑͱൢച༧ఆ
    ൃച ൃച
    ˞࣌఺ͷ৘ใ
    ൃച
    &MJYJS'PSVNݟͯΔͱ҆͘ങ͑ΔՄೳੑ͋Γʂ

    IUUQTFMJYJSGPSVNDPNUGVODUJPOBMXFCEFWFMPQNFOUXJUI
    FMJYJSPUQBOEQIPFOJYQSBHQSPH

    View Slide

  10. ࠷ۙͷੈͷதͷ&MJYJSࣄ৘
    w ༸ॻ͕࣍ʑͱൢച༧ఆ
    ൃച
    ˞࣌఺ͷ৘ใ
    ൃച
    ଓʑͱຊ͕ग़൛͞ΕɺੈքతϒʔϜ౸དྷʂʁ

    View Slide

  11. Ϛϧνςφϯτͱ͸ʁ
    w Ϛϧνςφϯτͱ͸ʜ
    w ̍ͭͷγεςϜʹෳ਺ͷςφϯτΛಉډ͍ͤͯ͞Δํࣜ
    ͷ͜ͱ
    w اۀ΍νʔϜͰ࢖͏4BB4͕Πϝʔδ͠΍͍͢ͱ͜Ζ
    ʢ#BDLMPHɺ+*3"ɺ2JJUBνʔϜͳͲʣ
    w ϚϧνςφϯτԽʹ͸͍͔ͭ͘ͷ෼཭ͷछྨ͕͋Δ

    View Slide

  12. Ϛϧνςφϯτͱ͸
    w ᶃར༻ऀ͝ͱʹݸผΞϓϦͱݸผͷσʔλϕʔε
    "ࣾ #ࣾ $ࣾ
    "ࣾͷࣾһ #ࣾͷࣾһ $ࣾͷࣾһ
    ӡ༻ίετ͕ߴ͘εέʔϧ͠ʹ͍͘

    View Slide

  13. Ϛϧνςφϯτͱ͸
    "ࣾ #ࣾ $ࣾ
    w ᶄશར༻ऀ͕ಉҰΞϓϦͱݸผͷσʔλϕʔε
    "ࣾͷࣾһ #ࣾͷࣾһ $ࣾͷࣾһ
    ֤%#ͷ؅ཧ͸݈ࡏ͠ӡ༻ίετ͕ߴ͍

    View Slide

  14. Ϛϧνςφϯτͱ͸
    w ᶅશར༻ऀ͕ಉҰΞϓϦͱಉҰσʔλϕʔε
    %#
    ӡ༻ίετ΋௿͘εέʔϧ͠΍͍͢
    ͜ͷΞʔΩςΫνϟ͕Ұ൪Ϛϧνςφϯγʔͱ͞Ε͍ͯΔ
    "ࣾͷࣾһ #ࣾͷࣾһ $ࣾͷࣾһ

    View Slide

  15. Ϛϧνςφϯτͱ͸
    w ϚϧνςφϯτԽʹඞཁͳཁૉ
    w ΞϓϦέʔγϣϯ͕ϚϧνςφϯγʔΛαϙʔτ͢Δ͜ͱ
    w ΞϓϦέʔγϣϯ͕͋Δఔ౓ͷࣗಈαΠϯΞοϓػೳΛඋ͍͑ͯΔ͜ͱ
    w ొ࿥՝ۚϝΧχζϜ͕༻ҙ͞Ε͍ͯΔ͜ͱ
    w ΞϓϦέʔγϣϯΛޮ཰తʹεέʔϦϯάͰ͖Δ͜ͱ
    w ΞϓϦέʔγϣϯͱςφϯτΛ؂ࢹɺߏ੒ɺ؅ཧ͢ΔͨΊͷػೳ͕༻ҙ͞Ε͍ͯΔ͜ͱ
    w ҰҙͷϢʔβʔ*%͓ΑͼೝূΛαϙʔτ͢ΔϝΧχζϜ͕༻ҙ͞Ε͍ͯΔ͜ͱ
    w ςφϯτ͝ͱͷΧελϚΠζΛ͋Δఔ౓Մೳʹ͢ΔͨΊͷϝΧχζϜ͕༻ҙ͞Ε͍ͯΔ
    ͜ͱ
    Ҿ༻ɿʮ8FCΞϓϦέʔγϣϯΛϚϧνςφϯτܕ4BB4ιϦϡʔγϣϯʹม׵͢Δʯ
    IUUQTXXXJCNDPNEFWFMPQFSXPSLTKQDMPVEMJCSBSZDMNVMUJUFOBOUTBBT
    ஫໨
    &MJYJSͰ
    Ͳ͏΍Δʁ

    View Slide

  16. &MJYJS1IPFOJYͰ
    Ϛϧνςφϯτʹ͢Δʹ͸ʁ
    w 044ͷϥΠϒϥϦ͕ଘࡏ͠·͢
    w BQBSUNFOUFY EPXOMPBET

    w IUUQTIFYQNQBDLBHFTBQBSUNFOUFY
    w 5SJQMFY EPXOMPBET

    w IUUQTIFYQNQBDLBHFTUSJQMFY
    ˞࣌఺ͷσʔλ
    ஫໨
    ࠓճ͸
    ͜Ε࢖͏Αʂ
    5SJQMFYͷ࢖͍ํ͸2JJUBʹॻ͖·ͨ͠
    IUUQTRJJUBDPNZVKJLBXBJUFNTCCDFBFEDD

    View Slide

  17. ։ൃ؀ڥʹ͍ͭͯ
    w &MJYJS &SMBOH051

    w 1IPFOJY
    w 1PTUHSF42-

    View Slide

  18. ࣮૷ฤ
    BQBSUNFOUFYͷ࣮૷ํ๏

    View Slide

  19. ࣮૷ฤBQBSUNFOUFY
    w 1IPFOJYͷϓϩδΣΫτΛ࡞੒
    $ mix phx.new tenant_app
    ………লུ
    $ cd tenant_app/
    $ mix ecto.create
    $ mix phx.server
    $ [info] Running TenantAppWeb.Endpoint with Cowboy using
    http://0.0.0.0:4000
    IUUQʹΞΫηεͯ͠Έ·͠ΐ͏

    View Slide

  20. ࣮૷ฤBQBSUNFOUFY
    ͜ͷը໘͕දࣔ͞ΕΕ͹ͻͱ·ͣ0,

    View Slide

  21. ࣮૷ฤBQBSUNFOUFY
    w BQBSUNFOUFYΛNJYFYTʹ௥Ճ
    defp deps do
    [
    {:phoenix, "~> 1.3.0"},
    {:phoenix_pubsub, "~> 1.0"},
    {:phoenix_ecto, "~> 3.2"},
    {:postgrex, ">= 0.0.0"},
    {:phoenix_html, "~> 2.10"},
    {:phoenix_live_reload, "~> 1.0", only: :dev},
    {:gettext, "~> 0.11"},
    {:apartmentex, github: "Dania02525/apartmentex"},
    {:cowboy, "~> 1.0"}
    ]
    end
    ࣌఺͸)FYʹ্͕͍ͬͯΔϓϩάϥϜʹ
    ෆ۩߹͕͋ΓHJUIVC͔ΒΠϯετʔϧ͢ΔΑ͏ʹมߋͨ͠

    View Slide

  22. ࣮૷ฤBQBSUNFOUFY
    w ϥΠϒϥϦΛΠϯετʔϧ
    $ mix deps.get && mix deps.compile

    View Slide

  23. ࣮૷ฤBQBSUNFOUFY
    w ςφϯτςʔϒϧͷ࡞੒
    w αϒυϝΠϯଐੑΛ࣋ͨͤͨDPNQBOJFTςʔϒϧΛ࡞੒ʢί
    ϚϯυͰҰൃʣ
    $ mix phx.gen.context Accounts Company companies sub_domain:string
    ͜ͷίϚϯυ͸ςʔϒϧ࡞੒༻ͷϚΠάϨʔγϣϯϑΝΠϧ΍
    .7$Ͱ͍͏.෦෼·ͰࣗಈͰ࡞੒ͯ͘͠Ε·͢ɻ

    View Slide

  24. ࣮૷ฤBQBSUNFOUFY
    w Ϣʔβ৘ใϓϩάϥϜͷ࡞੒
    w ؆୯ͷͨΊϢʔβͷ໊લ͚ͩΛొ࿥͢ΔΞϓϦΛ࡞੒
    $ mix phx.gen.html Accounts User users name:string
    ͜ͷίϚϯυ͸ςʔϒϧ࡞੒༻ͷϚΠάϨʔγϣϯϑΝΠϧ΍
    .7$Ͱ͍͏.7$શͯࣗಈͰ࡞੒ͯ͘͠Ε·͢ɻ

    View Slide

  25. ࣮૷ฤBQBSUNFOUFY
    w ςφϯτΞϓϦ༻ʹςʔϒϧϚΠάϨʔγϣϯϑΥϧμΛ࡞੒
    w BQBSUNFOUFY͕࢖͑ΔΑ͏ʹϑΥϧμͷ࡞੒͠ɺઌ΄Ͳ࡞ͬ
    ͨϢʔβ৘ใͷϚΠάϨʔγϣϯϑΝΠϧ͚ͩΛҠಈͤ͞·͢ɻ
    $ mkdir priv/repo/tenant_migrations
    $ mv priv/repo/migrations/20180213211936_create_users.exs priv/
    repo/tenant_migrations

    View Slide

  26. ࣮૷ฤBQBSUNFOUFY
    w ϧʔςΟϯάΛ௥Ճ MJCUFOBOU@BQQ@XFCSPVUFSFY

    w Ϣʔβ৘ใͷϧʔςΟϯάΛઃఆ͠·͢
    scope "/", TenantAppWeb do
    pipe_through :browser # Use the default browser stack
    get "/", PageController, :index
    resources "/users", UserController
    end

    View Slide

  27. ࣮૷ฤBQBSUNFOUFY
    w $PNQBOZϚΠάϨʔγϣϯϑΝΠϧʹVOJRVFJOEFYΛઃ

    defmodule TenantApp.Repo.Migrations.CreateCompanies do
    use Ecto.Migration
    def change do
    create table(:companies) do
    add :sub_domain, :string
    timestamps()
    end
    create unique_index(:companies, [:sub_domain])
    end
    end

    View Slide

  28. ࣮૷ฤBQBSUNFOUFY
    w ϚΠάϨʔγϣϯΛ͠·͢
    $ mix ecto.migrate
    [info] == Running
    TenantApp.Repo.Migrations.CreateCompanies.change/0 forward
    [info] create table companies
    [info] create index companies_sub_domain_index
    [info] == Migrated in 0.0s

    View Slide

  29. ࣮૷ฤBQBSUNFOUFY
    w %#ૢ࡞ͷؔ਺Λมߋ͠·͢ MJCUFOBOU@BQQBDDPVOUTBDDPPVOUTFY

    def create_company(attrs \\ %{}) do
    with changeset <- Company.changeset(%Company{}, attrs),
    {:ok, company} <- Repo.insert(changeset),
    do: Apartmentex.new_tenant(Repo, company.sub_domain)
    end
    def create_user(attrs \\ %{}, sub_domain) do
    with changeset <- User.changeset(%User{}, attrs),
    do: Apartmentex.insert(Repo, changeset, sub_domain)
    end
    def list_users(sub_domain) do
    Apartmentex.all(Repo, User, sub_domain)
    end
    ొ࿥ͱऔಘͷؔ਺ʹαϒυϝΠϯରԠΛ͢Δ

    View Slide

  30. ࣮૷ฤBQBSUNFOUFY
    w ςετσʔλͷ࡞੒
    w ಈ࡞֬ೝͷͨΊʹखಈͰ࡞੒͠·͢
    $ iex -S mix
    iex(1)> alias TenantApp.Accounts
    iex(2)> Accounts.create_company(%{sub_domain: "company-aaa"})
    iex(3)> Accounts.create_company(%{sub_domain: "company-zzz"})
    iex(4)> Accounts.create_user(%{name: "Yuji Kawakami"}, "company-aaa")
    iex(5)> Accounts.create_user(%{name: "Taro Tanaka"}, "company-zzz")
    iex(6)> Accounts.create_user(%{name: "Hanako Takahashi"}, "company-zzz")

    View Slide

  31. ࣮૷ฤBQBSUNFOUFY
    w 6TFSίϯτϩʔϥͷมߋ MJCUFOBOU@BQQ@XFCDPOUSPMMFSTVTFS@DPOUSPMMFSFY

    w Ϣʔβ৘ใͷίϯτϩʔϥΛมߋ͠·͢
    def action(conn, _) do
    [sub_domain|_] = String.split(conn.host, ".")
    apply(__MODULE__, action_name(conn), [conn, conn.params, sub_domain])
    end
    def index(conn, _params, sub_domain) do
    users = Accounts.list_users(sub_domain)
    render(conn, "index.html", users: users)
    end
    BDUJPOؔ਺ͰίϯτϩʔϥͰఆٛͨؔ͠਺ʹ
    TVC@EPNBJOΛҾ਺Ͱ౉͢Α͏ʹ͍ͯ͠Δ

    View Slide

  32. ࣮૷ฤBQBSUNFOUFY
    w ςετ༻ʹIPTUTʹυϝΠϯΛઃఆ͠ɺαʔόىಈ
    $ vim /etc/hosts
    127.0.0.1 company-aaa.dev.local dev
    127.0.0.1 company-zzz.dev.local dev
    $ mix phx.server
    Compiling 1 file (.ex)
    [info] Running TenantAppWeb.Endpoint with Cowboy using http://
    0.0.0.0:4000

    View Slide

  33. ࣮ફฤ%&.0

    View Slide

  34. ࣮ફฤ%&.0

    View Slide

  35. ࣮ફฤ%#ͷ༷ࢠ
    1VCMJDʹͳ͍ͬͯΔςʔϒϧ͸DPNQBOJFTͷΈ

    View Slide

  36. ࣮ફฤ%#ͷ༷ࢠ
    1PTUHSFTͷεΩʔϚػೳΛ্ख͘࢖͏͜ͱͰ
    αϒυϝΠϯ͝ͱʹσʔλΛ࣋ͯΔ࢓૊ΈΛ࣮ݱ͍ͯ͠Δ

    View Slide

  37. ·ͱΊ
    w &MJYJS1IPFOJYͰ΋؆୯ʹϚϧνςφϯτͳΞϓϦ͕࡞
    ੒Ͱ͖Δʂ
    w ࠓճͷϚϧνςφϯτରԠ͸1PTUHSFTͰ͕ͨ͠ɺڵຯ͕
    ͋Δਓ͸.Z42-Ͱ΋ࢼͯ͠Έ͍ͯͩ͘͞ɻ
    w ΋͏ҰͭͷϥΠϒϥϦʔ5SJQMFY΋ࢼͯ͠ɺ͍ͭͷ೔͔·
    ͨ࿩͕࣌͢དྷΕ͹͍͍ͳ͊ɾɾ

    View Slide

  38. ͝੩ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠

    View Slide