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

マルチテナント・ウェブアプリケーションの実践

FUJI Goro
December 09, 2017

 マルチテナント・ウェブアプリケーションの実践

Kibelaのマルチテンシーを解説します。 #railsdm 2017 の資料です。

FUJI Goro

December 09, 2017
Tweet

More Decks by FUJI Goro

Other Decks in Technology

Transcript

  1. ࣗݾ঺հ • ౻ ޗ࿠ (@__gfx__) • Bit JourneyͰKibelaͱ͍͏৘ใڞ༗πʔϧΛ։ൃத • TypeScript,

    GraphQL, React Native͋ͨΓʹڵຯ͋ Γ • ࠓճ࿩͢ͷ͸Kibelaͷཪଆʹ͍ͭͯ
  2. ͜͜ͰҰݴ: GraphQL͸͍͍ͧ • RESTful API ͷ୅ସͱͯ͠࡞ΒΕͨRPC࢓༷ • RESTfulϥΠΫͳϦιʔεࢦ޲ͱRPCͷܕ҆શੑͷ͍͍ͱ͜ͲΓ • υΩϡϝϯτγεςϜ΋಺แ͍ͯͯ͠API

    console͕࠷ߴͷ࢓্͕Γ • KibelaͷWeb API͸GraphQLΛ࠾༻ • ಺෦API͸ঃʑʹஔ͖׵͑த • ެ։API΋GraphQLʹ͢Δ༧ఆ
  3. Ϛϧνςφϯγʔͷڞ༗Ϩϕϧ • Ҿ༻: Web ΞϓϦέʔγϣϯΛϚϧνςφϯτܕ SaaS ιϦϡʔγϣϯʹม׵͢Δ - IBM https://www.ibm.com/developerworks/jp/cloud/library/cl-multitenantsaas/

    1. ϋʔυ΢ΣΞͱϏδωεϩδοΫͷΈͷڞ༗ 2. (1)ʹՃ͑ͯΞϓϦέʔγϣϯϓϩηεͷڞ༗ 3. (2)ʹՃ͑ͯσʔλϕʔεͷڞ༗
  4. Kibela͸ (3) DBͷڞ༗ • ڞ༗Ͱ͖ΔϦιʔε͸͢΂ͯڞ༗ • ʮ࠷΋ޮ཰తͳਅͷϚϧνςφϯγʔʯ • by IBM

    • ͨͩ͠Kibelaͷ৔߹ɺPostgreSQLͷschemaʹ ΑͬͯRDBMSͷ໊લۭؒ͸෼཭͍ͯ͠Δʢޙड़ʣ
  5. URLͷ໊લۭؒ: domain vs path • URLͷ໊લۭؒ: subdomainϨϕϧͰ෼཭ • $team.kibe.la ͱ͍͏υϝΠϯʹνʔϜ໊ΛؚΉܗ

    • ηογϣϯCookie͸νʔϜ͝ͱʹಠཱ͠ɺڞ༗͠ͳ͍ • ϩʔΧϧͰͷ։ൃ͸ϧʔϓόοΫυϝΠϯΛར༻ • $team.lvh.me:3000 ͳͲ
  6. RDBMSͷ໊લۭؒ෼཭ • PostgreSQL͸ database - schema - table ͱ͍͏ ֊૚ߏ଄

    • ҟͳΔschema͸ಉ໊͡લͷtableΛ࣋ͯΔ • schemaͷ୳ࡧ͸؀ڥม਺PATHͷΑ͏ʹߦΘΕΔ • ࢀߟ: https://www.postgresql.org/docs/current/static/ddl-schemas.html
  7. PostgreSQLͷschemaͷઃఆ • apartment gemΛར༻ • Rackϛυϧ΢ΣΞͱͯ͠ಈ͖ɺαϒυϝΠϯΛPg schemaͱΈͳ ͯ͠ `SET search_path

    TO $subdomain,public` ͢Δ • subdomain = schema nameͱ͢Δ͜ͱͰɺDB઀ଓͳ͠ʹ search_pathͷઃఆ͕Ͱ͖Δ • ͦͷ͔ΘΓsubdomain (≒team name) ͷϦωʔϜ࣌ʹschema name΋ม͑Δඞཁ͕͋Δ
  8. Memcached for Rails Cache • namespace͸ϦΫΤετ͝ͱʹҟͳΔͷͰɺProcͱ ໊ͯ͠લۭؒߏஙϧʔνϯΛ౉͢ඞཁ͕͋Δ • Rails.cacheͷૢ࡞ͷͨͼʹຖճnamespace callback

    ͕ݺ͹Εͯจࣈྻߏங͕૸Δ # config/environments/production.rb config.cache_store = :dalli_store, elasticache, { namespace: -> { “k-#{Team.current_subdomain}” }, }
  9. Redis by redis-namespace • Redis.current = Redis::Namespace.new(…) ͕switchͩͬͨ • ͔͠͠redis.rbΛΈΔͱRedis.current͕Ϋϥεม਺ͩʂʂʂ

    • JobQueue͕sidekiqͳͷͰεϨουηʔϑͰͳ͍ͱ͍͚ ͳ͍ • ϞϯΩʔύονΛ͋ͯͯRedis.currentΛ࠶ఆٛ͢Δ͜ͱʹ ͨ͠
  10. monekey_patches/redis.rb class Redis INSTANCE = Redis.new # @return [Redis] def

    self.current RequestStore.fetch(”Redis.current/#{Team.current_subdomain}”) do if Team.current.present? Namespace.new(Team.current_subdomain, redis: INSTANCE) else INSTANCE end end def self.current=(_redis) raise "Don't use Redis.current=" end end
  11. Testing • rspecͷbefore/afterͰςφϯτͷsetup/teardownΛ͍ͯͨ͠ Βܹ྽ʹॏ͔ͬͨʢ͋ͨΓ·͑ʣ • before(:suite) / after(:suite) Ͱςφϯτͷ४උΛ͢ΔΑ͏ʹ •

    namepsacingͷςετ͸ͳ͔ͳ͔೉͍͠ • ଞͷςφϯτΛ࡞ͬͯΞΫηεՄೳੑΛςετͨ͠Γ͸͢Δ • Ϛϧνςφϯγʔ x ϚϧνεϨου͸ఘΊ…