Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
マルチテナント・ウェブアプリケーションの実践
Search
FUJI Goro
December 09, 2017
Technology
14
9.4k
マルチテナント・ウェブアプリケーションの実践
Kibelaのマルチテンシーを解説します。 #railsdm 2017 の資料です。
FUJI Goro
December 09, 2017
Tweet
Share
More Decks by FUJI Goro
See All by FUJI Goro
How to Boost Your Code with WebAssembly
gfx
2
2.7k
AssemblyScriptでライブラリコードの高速化をしてみる
gfx
5
2.9k
実践TypeScriptトークバトル
gfx
1
1.1k
歴史的経緯の説明 as code
gfx
7
2.7k
Elasticsearchによる 全文検索の実装 in Rails
gfx
5
9.3k
すばらしきGraphQLのSEKAIへようこそ
gfx
20
9.2k
How to choose the ORM on Android
gfx
1
4.1k
How Do We Get Along With Static Types
gfx
5
3.3k
"OSSにコントリビュート" なんてしてる場合じゃない!
gfx
21
15k
Other Decks in Technology
See All in Technology
ガチ勢によるPipeCD運用大全〜滑らかなCI/CDを添えて〜 / ai-pipecd-encyclopedia
cyberagentdevelopers
PRO
3
190
オニオンアーキテクチャで実現した 本質課題を解決する インフラ移行の実例
hryushm
14
3k
【若手エンジニア応援LT会】AWS Security Hubの活用に苦労した話
kazushi_ohata
0
150
失敗しないOpenJDKの非互換調査
tabatad
0
260
オーティファイ会社紹介資料 / Autify Company Deck
autifyhq
9
120k
CAMERA-Suite: 広告文生成のための評価スイート / ai-camera-suite
cyberagentdevelopers
PRO
3
260
バクラクにおける可観測性向上の取り組み
yuu26
3
400
新R25、乃木坂46 Mobileなどのファンビジネスを支えるマルチテナンシーなプラットフォームの全体像 / cam-multi-cloud
cyberagentdevelopers
PRO
1
130
AWS CDKでデータリストアの運用、どのように設計する?~Aurora・EFSの実践事例を紹介~/aws-cdk-data-restore-aurora-efs
mhrtech
4
610
ガバメントクラウド単独利用方式におけるIaC活用
techniczna
3
260
独自ツール開発でスタジオ撮影をDX!「VLS(Virtual LED Studio)」 / dx-studio-vls
cyberagentdevelopers
PRO
1
170
コンテンツを支える 若手ゲームクリエイターの アートディレクションの事例紹介 / cagamefi-game
cyberagentdevelopers
PRO
1
110
Featured
See All Featured
How To Stay Up To Date on Web Technology
chriscoyier
788
250k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
228
52k
Building Applications with DynamoDB
mza
90
6.1k
Become a Pro
speakerdeck
PRO
24
5k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
7
150
Scaling GitHub
holman
458
140k
Bootstrapping a Software Product
garrettdimon
PRO
305
110k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
26
2k
Documentation Writing (for coders)
carmenintech
65
4.4k
Java REST API Framework Comparison - PWX 2021
mraible
PRO
28
7.9k
Intergalactic Javascript Robots from Outer Space
tanoku
268
27k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
364
22k
Transcript
ϚϧνςφϯτɾΣϒΞϓ Ϧέʔγϣϯͷ࣮ફ #railsdm 2017/12/08 by @__gfx__ (FUJI Goro)
ࣗݾհ • ౻ ޗ (@__gfx__) • Bit JourneyͰKibelaͱ͍͏ใڞ༗πʔϧΛ։ൃத • TypeScript,
GraphQL, React Native͋ͨΓʹڵຯ͋ Γ • ࠓճ͢ͷKibelaͷཪଆʹ͍ͭͯ
͜͜ͰҰݴ: GraphQL͍͍ͧ • RESTful API ͷସͱͯ͠࡞ΒΕͨRPC༷ • RESTfulϥΠΫͳϦιʔεࢦͱRPCͷܕ҆શੑͷ͍͍ͱ͜ͲΓ • υΩϡϝϯτγεςϜแ͍ͯͯ͠API
console͕࠷ߴͷ্͕Γ • KibelaͷWeb APIGraphQLΛ࠾༻ • ෦APIঃʑʹஔ͖͑த • ެ։APIGraphQLʹ͢Δ༧ఆ
Kibela
Kibelaʹ͍ͭͯ
αʔϏεͱͯ͠ͷKibela • BtoBͷSaaS: Software as a Service • BlogʢʹݸਓͷΞΠσΞʣͱWikiʢʹ৫ͷͨΊͷใʣͱ͍ ͏̎ͭͷੑ࣭ͷυΩϡϝϯτΛॻ͚Δͷ͕ಛͷใ
ڞ༗πʔϧ • GitHubޓͷMarkdown (≒CommonMark)Ͱॻ͚Δ • ڝ߹: Confluence, Google Docs
ϚϧνςφϯτɾΣϒΞϓϦ • ࠓճͷςʔϚʮϚϧνςφϯτɾΣϒΞϓϦ (MTWA)ʯɺSaaSʹ͓͍ͯ1ͭͷγεςϜͰ෮ͷ৫ ʢ㲈اۀɾஂମʣͷνʔϜΛಉډͤ͞ΔΣϒΞϓϦέʔ γϣϯ • ͜ͷτʔΫʹ͓͍ͯʮMTWAͰ͋Δ͜ͱʯΛ୯ʹʮϚ ϧνςφϯγʔʯͱ͍͏ •
KibelaςφϯτΛʮνʔϜʯͱݺͼ৫୯Ґͱ͍ͯ͠Δ
BtoBͷΣϒαʔϏε㲈MTWA • ͜ͷτʔΫͰMTWAͱ͍͏ͱ͖ “BtoBͷΣϒ αʔϏε” ͱ΄΅Ձ • اۀͳͲͷஂମͷ୯ҐͰ͋Δςφϯτʹ෮ͷ ϢʔβʔΞΧϯτ͕ॴଐ͢Δܥͯ͢MTWA •
গͷαʔόʔΠϯελϯεͰଟͷސ٬ʹαʔ ϏεΛఏڙͰ͖ΔͨΊίεύ͕Α͍
Ϛϧνςφϯγʔͷڞ༗Ϩϕϧ • Ҿ༻: Web ΞϓϦέʔγϣϯΛϚϧνςφϯτܕ SaaS ιϦϡʔγϣϯʹม͢Δ - IBM https://www.ibm.com/developerworks/jp/cloud/library/cl-multitenantsaas/
1. ϋʔυΣΞͱϏδωεϩδοΫͷΈͷڞ༗ 2. (1)ʹՃ͑ͯΞϓϦέʔγϣϯϓϩηεͷڞ༗ 3. (2)ʹՃ͑ͯσʔλϕʔεͷڞ༗
MTWAͷઃܭͱ࣮
Ϛϧνςφϯγʔͷઃܭ • ΞΧϯτͷڞ༗Ϩϕϧͷઃܭ • URLͷ໊લۭؒͷઃܭ • ετϨʔδͷ໊લۭؒͷઃܭ • ໊લۭؒΛอূ͢ΔͨΊͷΈͷઃܭ
Kibela (3) DBͷڞ༗ • ڞ༗Ͱ͖ΔϦιʔεͯ͢ڞ༗ • ʮ࠷ޮతͳਅͷϚϧνςφϯγʔʯ • by IBM
• ͨͩ͠Kibelaͷ߹ɺPostgreSQLͷschemaʹ ΑͬͯRDBMSͷ໊લۭ͍ؒͯ͠Δʢޙड़ʣ
MTWAͷΞΧϯτϞσϧ • Ϛϧνςφϯγʔʹ͓͍ͯΞΧϯτϞσϧ2छྨ͋Δ • αʔϏεશମͰΞΧϯτΛڞ༗͢Δ • ྫ: GitHub, npmjs.org •
ςφϯτ͝ͱʹΞΧϯτΛ࡞͢Δ • ྫ: Slack, G Suite, Kibela
GitHubܕ - ΞΧϯτάϩʔόϧ • GitHubܕʮਓʯʹϑΥʔΧεͨ͠ΞΧϯτϞσϧ • ݸਓΞΧϯτͱࣄΞΧϯτͷ۠ผ͕ᐆດʹͳΓ͕ͪ • GitHubͷ߹ɺࣄͷ࣮Λݸਓͷ࣮ʹඥ͚͍͢ϝ Ϧοτ͋Δ
• ϋϯυϧωʔϜ͔͠ެ։ͯ͠ͳ͍ΞΧϯτ͕୭͔ͩΘ͔Βͳ ͘ͳΓ͕ͪ • ཧா…
Slackܕ - ςφϯτ͝ͱʹΞΧϯτΛ࡞ • Ϛϧνςφϯγʔͱͯͪ͜͠Β͕ඪ४త • ΞΧϯτཧ͕ϢʔβʔʹҕͶΒΕͯࡶʹͳΓ͕ͪ • ྫ: ͍·ௐͨΒ1passwordͷதʹslack
account͕20 ݸҎ্͋ͬͨ • G Suite SSOͳͲͰҰݩཧ͢Εݸਓ͕ΞΧϯτ ཧ͢Δඞཁͳ͘ͳΔ
Kibelaͷܾఆ: Slackܕ • GitHubܕͷʮ୭͔ͩΘ͔Βͳ͍ʯ͕հ͗͢Δ • ͲͷςφϯτͰಉ໊͡લʢ㲈ຊ໊ʣ͕ڧཁ͞ΕΔ ͷ·͘͠ͳ͍ͱߟ͑ͨ • झຯ༻ͱࣄ༻Ͱ໊લΛม͍͑ͨ͜ͱ͋Δ •
SlackܕϢʔβʔʹ෮ͷΞΧϯτཧΛڧ͍Δ ͜ͱʹͳΔ͕ɺͦ͜SSOͰ͋ΔఔղܾͰ͖Δ
URLͷ໊લۭؒ: domain vs path • URLͷ໊લۭؒ: subdomainϨϕϧͰ • $team.kibe.la ͱ͍͏υϝΠϯʹνʔϜ໊ΛؚΉܗ
• ηογϣϯCookieνʔϜ͝ͱʹಠཱ͠ɺڞ༗͠ͳ͍ • ϩʔΧϧͰͷ։ൃϧʔϓόοΫυϝΠϯΛར༻ • $team.lvh.me:3000 ͳͲ
ετϨʔδͷ໊લۭؒ • RDBMSKVSͰςφϯτ͝ͱͷσʔλʹ໊ લۭؒΛ͚ͭͯଞͷςφϯτͷσʔλͱࠞ͡ Βͳ͍Α͏ʹ͢Δ • PostgreSQL, memcached, Redis, Elasticseach,
S3, CloudFront, temporary files ͳͲετϨʔδʹؔΘΔͯ͢ͷ໘Ͱ໊લ ۭؒʹΑΔ͕ඞཁ
RDBMSͷ໊લۭؒ • PostgreSQL database - schema - table ͱ͍͏ ֊ߏ
• ҟͳΔschemaಉ໊͡લͷtableΛ࣋ͯΔ • schemaͷ୳ࡧڥมPATHͷΑ͏ʹߦΘΕΔ • ࢀߟ: https://www.postgresql.org/docs/current/static/ddl-schemas.html
PostgreSQLͷschemaͷઃఆ • apartment gemΛར༻ • RackϛυϧΣΞͱͯ͠ಈ͖ɺαϒυϝΠϯΛPg schemaͱΈͳ ͯ͠ `SET search_path
TO $subdomain,public` ͢Δ • subdomain = schema nameͱ͢Δ͜ͱͰɺDBଓͳ͠ʹ search_pathͷઃఆ͕Ͱ͖Δ • ͦͷ͔ΘΓsubdomain (≒team name) ͷϦωʔϜ࣌ʹschema nameม͑Δඞཁ͕͋Δ
Schema͕૿͖͑ͯͯ • team͕૿͑Δͱmigrationʹ͕͔͔࣌ؒΔΑ͏ʹ ͳ͖ͬͯͨ • σʔλྔతʹશવେͨ͜͠ͱͳ͍͕ͣͩ… • ·ͩಛʹରॲ͢Δ΄ͲͰͳ͍ͷͰ์ஔ • ͍ͣΕDBΠϯελϯεͷׂ͕ඞཁ͔
͜͜·Ͱ͍͍Μͩ ͜͜·Ͱ…
KVS, S3, શจݕࡧΤϯδϯ, etc. • DBͷ໊લۭؒঢ়ଶͱಉظ͠ͳ͍ • search_pathPgͷίωΫγϣϯ͝ͱͷઃఆ ͷͨΊ •
ϛυϧΣΞʹΑͬͯඞ໊ͣ͠લۭؒΛ αϙʔτ͍ͯ͠ͳ͍
ૉͳൃ # models/team.rb def self.switch!(name) Apartment::Tenant.switch!(name) MemcachedNamespace.switch!(name) RedisNamespace.switch!(name) AwsS3Namespace.switch!(name) ElasticsearchNamespace.switch!(name)
end
ݱࡏͷKibela • apartment gem͕ A::T.switch! ͚͔ͩ͠ݟͳ ͍͜ͱ͕͋ͬͯϛεΛ༠ൃ͕ͪͩͬͨ͠ • ϚϧνεϨουԽͰόάΛ༠ൃ͕ͪ͠ #
models/team.rb def self.switch!(name) Apartment::Tenant.switch!(name) end
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}” }, }
Redis by redis-namespace • Redis.current = Redis::Namespace.new(…) ͕switchͩͬͨ • ͔͠͠redis.rbΛΈΔͱRedis.current͕Ϋϥεมͩʂʂʂ
• JobQueue͕sidekiqͳͷͰεϨουηʔϑͰͳ͍ͱ͍͚ ͳ͍ • ϞϯΩʔύονΛ͋ͯͯRedis.currentΛ࠶ఆٛ͢Δ͜ͱʹ ͨ͠
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
Elasticsearch • શจݕࡧΤϯδϯ • KibelaͰϚωʔδυαʔϏεΛར༻ • e.g. Amazon Elasticserach Service
• ༻ޠ: index = DBͷtable, document = row
Elasticsearch namespacing v1 • ॳindexΛteam͝ͱʹ࡞͍ͬͯͨ • e.g “kibela-#{Rails.env}-#{team_id}-blog” • team͕૿͑ΔʹͭΕindexͷ࠶ߏங
ʢ㲈migrationʣʹ࣌ؒʢۙͩͱ9࣌ؒʣ͔͔ΔΑ ͏ʹ…
Elasticsearch namespacing v2 • Railsͷ̼odel͝ͱʹͨͩ1ͭͷindexΛ࡞ • documentͷteam_idͰϑΟϧλϦϯά͢Δ filtered aliasΛ࡞ͬͯࢀর͢ΔΑ͏ʹͨ͠ •
index࠶ߏஙരʢ2࣌ؒʣͰऴΘΔΑ͏ʹ • ͔͠͠ϦΫΤετܹʹॏ͘ͳͬͨͷͰௐࠪத
ͦͷଞS3ͳͲ • ॳ subdomain (team name) Ͱ໊લۭؒΛ ࡞͍ͬͯͨ • renameʹରԠ͢ΔͨΊ్தͰ
team id Ͱ໊લ ۭؒΛ࡞ΔΑ͏ʹมߋ
Analytics • schema͕େྔʹ͋ΔDBʹੳΫΤϦଧͯͳ ͍ • team_id Λ༩ͨ͠ੳDBΛόονͰ࡞͢ Δ͜ͱʹͨ͠
Testing • rspecͷbefore/afterͰςφϯτͷsetup/teardownΛ͍ͯͨ͠ Βܹʹॏ͔ͬͨʢ͋ͨΓ·͑ʣ • before(:suite) / after(:suite) Ͱςφϯτͷ४උΛ͢ΔΑ͏ʹ •
namepsacingͷςετͳ͔ͳ͔͍͠ • ଞͷςφϯτΛ࡞ͬͯΞΫηεՄೳੑΛςετͨ͠Γ͢Δ • Ϛϧνςφϯγʔ x ϚϧνεϨουఘΊ…
ࠓޙͷల։ • ςφϯτΛ·͙ͨΞΧϯτใඞཁͬΆ͍ • ͝ͱʹॴଐνʔϜͯ͢ʹϩάΠϯ͢Δ ͷ͕ඇৗʹ໘ͳͨΊ • ϚϧνεϨου x Ϛϧνςφϯτͷςετ
• ·ͨϚϧνεϨουΛશʹఘΊΔҰख
·ͱΊ • Ϛϧνςφϯγʔ༷ΛܾΊΔͷ͕େม • URLɾΞΧϯτɾετϨʔδͳͲߟ͑Δ͜ͱ͕ଟ͍ • ಛʹετϨʔδͷ໊લۭ͕ؒͰָ͍͠ʢͭΒ͍ʣ • Ϛϧνςφϯγʔʹڵຯ͋Ε @__gfx__
ʹDM͍ͩ͘͞ • We are hiring!