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
How Microservices are linked at Cookpad
Search
adorechic
March 14, 2016
46k
12
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
How Microservices are linked at Cookpad
adorechic
March 14, 2016
More Decks by adorechic
See All by adorechic
採用技術、絞るか広げるか / Make variety of technology widely or narrowly?
adorechic
0
150
Rails + ReactなSPAサイトでのSEO / SEO at Rails + React SPA
adorechic
4
27k
分かれたシステムをていねいにモノリスに集約する/Integrate decentralized systems to a monolith carefully
adorechic
16
19k
クックパッドがどのようにMicroservicesしてきたか/How Cookpad shifts to Microservices
adorechic
58
40k
Microservices Overview
adorechic
0
220
Microservices stacks
adorechic
1
210
Featured
See All Featured
YesSQL, Process and Tooling at Scale
rocio
174
15k
Heart Work Chapter 1 - Part 1
lfama
PRO
8
36k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
340
How Software Deployment tools have changed in the past 20 years
geshan
1
34k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
249
1.3M
Abbi's Birthday
coloredviolet
3
9.3k
Testing 201, or: Great Expectations
jmmastey
46
8.2k
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
0
360
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
How to train your dragon (web standard)
notwaldorf
97
6.7k
Claude Code のすすめ
schroneko
67
230k
Transcript
)PX.JDSPTFSWJDFTBSF MJOLFEBU$PPLQBE ΫοΫύουגࣜձࣾ ٕज़෦։ൃج൫( ٢ਸྙ
ࠓճ͞ͳ͍͜ͱ w.JDSPTFSJWDFTͱʙ w.BSUJO'PXMFS͕ʙ wಋೖ͖͔͢൱͔ʙ w.JDSPTFSWJDFTͷηΦϦʔ ֶͼ͍ͨํ
ࠓճ͢͜ͱ w ΫοΫύουͰͷࣄྫ ‣ ͦͦͲ͏͍͏ཻͰ͔Ε͍ͯΔʁ ‣ αʔϏεؒͲͷΑ͏ʹ௨৴͢Δʁ ‣ αʔϏεؒͷςετͬͯͲ͏ͬͯΔʁ ‣
ߏཧʗσϓϩΠʁԾԽͯ͠Δʁ ‣ ϏϧυύΠϓϥΠϯʁόονδϣϒʁ ‣ νʔϜؒͷ࿈ܞҙࢥܾఆͲ͏ͯ͠Δʁ
ͲΜͳαʔϏε͔Β ߏ͞Ε͍ͯΔ͔
αʔϏεͷओͳྨ wϢʔβʔαʔϏε ‣ Ϣʔβʔ͕͏ϓϩμΫτ wϏϡʔαʔϏε ‣ ͋ΔαʔϏεͷผϏϡʔ ‣ ͍ΘΏΔ#BDLFOEGPSGSPOUFOET wڞ௨ج൫
‣ ܾࡁɺ௨ɺϩάFUDʜ
ϢʔβʔαʔϏε
ϢʔβʔαʔϏε wϓϩμΫτʹϑΥʔΧεͨ͠λΠϓ ྉཧڭࣨ Ϩγϐ Ϣʔβʔ ΧϑΣ ܾࡁ ௨ ಠཱͨ͠αʔϏε
Α͋͘Δػೳ ڞ௨ج൫Λ׆༻ ଞͷυϝΠϯͷϞσϧΛར༻Ͱ͖Δ
ϏϡʔαʔϏε wυϝΠϯϞσϧಉ͡ͰผͷϏϡʔ OEM൛ Ϩγϐ Ϩγϐ Ϣʔβʔ ௨ ࠜຊతʹఏڙ͢Δͷಉ͡ UIΞΧϯτମܥ͕ҧ͏
ඞཁʹԠͯ͡ଞαʔϏε ΛΈ߹ΘͤΔ ΦϦδφϧͷυϝΠϯ
ϏϡʔαʔϏε w#'' #BDLFOEGPSGSPOUFOET ʹ͍ۙ ‣ Α͋͘ΔσόΠε͝ͱʹઐ༻ϏϡʔΛ࡞Δ έʔε΄΅ͳ͍ ‣ 0&.൛ͷΑ͏ͳέʔεͰΘΕ͍ͯΔ
ఏڙ͢ΔυϝΠϯϞσϧಉ͡ 㾎ҟͳΔ6*Ͱఏڙ͢Δ 㾎ΞΧϯτମܥ͕ҧ͏
ڞ௨ج൫αʔϏε wڞ௨ͯ͠ΘΕΔج൫ػೳ w 0"VUIϓϩόΠμ w ܾࡁ w 1VTI௨ʗϝʔϧ৴ w ΞΫςΟϏςΟ
w ϩά w ηΩϡΞσʔλ
αʔϏεؒͲͷΑ͏ʹ ௨৴͢Δͷ͔
3&45GVM)ZQFSNFEJB"1* wύϑΥʔϚϯεΑΓॊೈੑʗૄ݁߹Λॏࢹ ‣ Ϟσϧ͕ඇৗʹଟؔ͘࿈͕ෳࡶ ‣ ಛఆͷߴෛՙϞσϧ͕͋ΔΘ͚Ͱͳ͍ { "id": 123,
"name": "ύυඒ", "kitchen": { "id": 15, "created": "2016-03-10T10:59:24+09:00", } }, "_links": { "self": { "href": "/v1/users/123" }, "recipes": { "href": "/v1/users/123/recipes" }, } }
(BSBHF w HJUIVCDPNDPPLQBEHBSBHF w 3&45GVMIZQFSNFEJB"1*GPS3BJMT class Employee < ActiveRecord::Base
include Garage::Representer belongs_to :division has_many :projects property :id property :title property :division, selectable: true collection :projects, selectable: true link(:division) { division_path(division) } link(:projects) { employee_projects_path(self) } def self.build_permissions(perms, other, target) perms.permits! :read end end
(BSBHF$MJFOU w HJUIVCDPNDPPLQBEHBSBHF@DMJFOU w YYYDMJFOU͕ແݶ૿৩͠ͳ͍ w ͲͷαʔϏεΛར༻͢Δͱ͖ಉ͡ΠϯλʔϑΣΠε w αʔϏε͝ͱʹҟͳΔͱֶशίετ͕ߴ͍
# GET https://garage.example.com/v1/me user = client.get("/me") user.id user.name # GET https://garage.example.com/v1/recipes recipes = client.get("/recipes") recipes.total_count recipes[0].id recipes[0].name
αʔϏεؒ௨৴ͷ ίετܰݮʗোੑ
&YQFEJUPS wHJUIVCDPNDPPLQBEFYQFEJUPS w3VCZ൛ͷ/FUqJY)ZTUSJY w"TZODISPOPVTFYFDVUJPO wෳͷαʔϏε͔ΒͷϦιʔεΛฒߦͯ͠औಘ w'BVMUUPMFSBODF w$JSDVJUCSFBLFS
αʔϏεؒ࿈ܞͷςετ
ޓੑΛͲ͏୲อ͢Δ͔ w αʔϏε͝ͱͷςετ͞Ε͍ͯΔ w ࿈ܞઌελϒ͢Δ w ඇޓͷมߋʹؾ͚ͳ͍ w ܕPSςετ w
+40/4DIFNBཧ͕େมͦ͏ w ͱͱςετจԽ͍͍ࠜͯͨͷͰ্ख͘ ׆༻͍ͨ͠
$POTVNFS%SJWFO$POUSBDUUFTUJOH wར༻ଆ $POTVNFS ͕"1*Λελϒͯ͠ςετ ‣ ظ͢ΔৼΔ͍Λܖ $POUSBDU ͱͯ͠ "1*ଆʹ͢ w"1*ଆ͕ࣗ$POUSBDUΛຬ͍ͨͯ͠Δ͔Ͳ͏
͔ݕূʢςετʣ͢Δ http://martinfowler.com/articles/consumerDrivenContracts.html
1BDU w HJUIVCDPNSFBMFTUBUFDPNBVQBDU w ΫϥΠΞϯτଆ w $*ͰQBDUϑΝΠϧΛੜ w "1*ଆ w
$*ͰQBDUϑΝΠϧΛWFSJGZ ग़య: https://github.com/realestate-com-au/pact#how-does-it-work
1BDU w ΫϥΠΞϯτଆ describe 'get_all' do let(:recipe_a) { {
id: Pact.like(1), name: Pact.like('Curry') } } let(:recipe_b) { { id: Pact.like(2), name: Pact.like('Salada') } } before do provider_app.given('there are 2 recipes'). upon_receiving('a request for recipes'). with(method: :get, path: '/v1/recipes'). will_respond_with( status: 200, headers: { 'Content-Type' => Pact.term( generate: 'application/json', matcher: %r{application/json} ), }, body: [recipe_a, recipe_b] ) end it 'returns recipes' do recipes = described_class.get_all expect(recipes.size).to eq(2) expect(recipes.first.name).to eq('Curry') end end
1BDU w QBDUpMFʢҰ෦ʣ { "consumer": { "name": "ConsumerApp" },
"provider": { "name": "ProviderApp" }, "interactions": [ { "description": "a request for recipes", "provider_state": "there are 2 recipes", "request": { "method": "get", "path": "/v1/recipes" }, "response": { "status": 200, "headers": { "Content-Type": { "json_class": "Pact::Term", "data": { "generate": "application/json", "matcher": { "json_class": "Regexp", "o": 0, "s": "application/json" } }
1BDU w "1*ଆ w ඞཁͳલॲཧ͚ͩ༻ҙ͢Δ Pact.provider_states_for 'ConsumerApp' do provider_state
"there are 2 recipes" do set_up do %w[Curry Salada].each {|name| Recipe.create!(name: name) } end end end
3BDL7$3 w HJUIVCDPNNJZBHBXBSBDLWDS w 7$3͕ϕʔεͰखܰ w "1*ϦΫΤετΛΧηοτσʔλԽͯ͠ελϒ w "1*ଆ͕ΧηοτσʔλΛΫϥΠΞϯτʹఏڙ͢Δ w
ඇޓͷมߋ͕͋ΕΫϥΠΞϯτଆͷ$*Ͱݕ w "1*ଆͷϏϧυͷํ͕ߴසͷ߹ɺΫϥΠΞϯτଆͷ ݕલʹϦϦʔε͞Ε͏Δ w ݱࡏ1BDUʹҠߦͨ͠
αʔϏεΛ·͍ͨͩ ΤϥʔΛ͢Δ
4FOUSZ w HJUIVCDPNHFUTFOUSZTFOUSZ w αʔϏε͝ͱͷΤϥʔΛूཧ͍ͯ͠Δ w ͜Ε͚ͩͩͱαʔϏεؒͷඥ͚͕Ͱ͖ͳ͍ w αʔϏε"ˠ#ͷϦΫΤετ࣌ʹΤϥʔ w
Τϥʔ"ͱ#ͦΕͧΕͰه͞ΕΔ w ͜ͷোʹΑΔΤϥʔͷൣғʁ
5SBDF-PHHJOH w ϦΫΤετ*% w ϔομʹ͋Εͦͷ··͍ɺͳ͚Ε࠾൪ w (BSBHF$MJFOU͕ϦΫΤετ࣌ʹηοτ w ϦΫΤετઌʹ w
4FOUSZ w ϦΫΤετ*%ͰΤϥʔΛݕࡧ
αʔόʔʗ࣮ߦڥʗߏཧ
%PDLFS w ϙʔλϒϧͳ࣮ߦڥ w TUBHJOHQSPEVDUJPOόονಉ͡Πϝʔδ w ڥґଘڥมͱͯ͠ೖ w ຊମͷڊେ3BJMTͳͲҰ෦Λআ͖ɺ΄ͱΜͲͷΞϓϦέʔ γϣϯ͕%PDLFS
w ΞϓϦέʔγϣϯͷϦϙδτϦʹ%PDLFSpMF w ։ൃऀ͕खݩͰ࿔ΕΔΑ͏ʹ w ϖωτϨςετڥͳͲඞཁʹԠ͙ͯ͢͡࡞ΕΔ
ϏϧυύΠϓϥΠϯ w$*ͰΞϓϦέʔγϣϯͷςετ w%PDLFSΠϝʔδ࡞ wBTTFUQSFDPNQJMFࡁΈͷΠϝʔδ wTUBHJOHʹࣗಈσϓϩΠ wQSPEVDUJPODIBUPQTͰσϓϩΠ
)BLP w HJUIVCDPNFBHMFUNUIBLP w %PDLFSΞϓϦ༻ͷσϓϩΠπʔϧ w ΫοΫύουͰόοΫΤϯυʹ&$4Λར༻ w ΞϓϦέʔγϣϯ͝ͱͷઃఆ:".-Ͱཧ w
ڥ͝ͱʹڥมΛઃఆͰ͖Δ w ൿಗFUDFOWFUDWBVMUͰཧ
FUDFOWFUDWBVMU w HJUIVCDPNTPSBIFUDFOW w FUDEͰઃఆΛཧ w HJUIVCDPNTPSBIFUDWBVMU w FUDEͷΛ҉߸Խ w
ͱͱFUDEʹ"$-͕ແ͔ͬͨͨΊ࡞ΒΕͨ w ࢦఆͷ伴Λ͍࣋ͬͯΔΠϯελϯεͰ͔͠෮߸ Ͱ͖ͳ͍
FUDXFC w HJUIVCDPNTPSBIFUDXFC
DIBUPQT w )VCPUͰσϒϩΠ w σϓϩΠδϣϒ3VOEFDLͰཧ w σϓϩΠํ๏͕౷Ұ͞Ε͍ͯΔ w νϟοτݟͯΔͱΘ͔Δ
όονδϣϒ
,VSPLP wશαʔϏεͷδϣϒΛҰׅཧ ‣ ϫʔΫϑϩʔཧ ผαʔϏεͷδϣϒΛϑοΫ͢Δ ‣ 8FCίϯιʔϧͰΤϥʔ֬ೝɾ࠶࣮ߦ
,VSPLP wαʔϏεͷ࠷৽ͷ%PDLFSΠϝʔδΛ࣮ߦ ‣ αʔϏε͝ͱͷϫʔΧʔڥෆཁ ‣ Ҏલ֤ΞϓϦͰLVSPLPઐ༻ͷߏཧΛ ༻ҙ͍ͯͨ͠ ‣ ֤αʔϏεͷΞϓϦέʔγϣϯ͕ͦͷ··ಈ ͘
νʔϜ͝ͱͷαϙʔτ νʔϜΛԣஅͨ͠ҙࢥܾఆ
ٕज़ྖҬ՝ڞ༗ձ w֤νʔϜͷٕज़Ϧʔμʔͱٕज़ج൫ʴΠϯϑϥ Ͱٕज़తͳ՝ʹ͍ͭͯ͠߹͏ w։ൃ͢Δͱ͖ʹࠔ͍ͬͯΔ͜ͱ w͋ͬͨΒخ͍͠ͷɺ͏ཁΒͳ͍ͷ wΈΜͳ͕ࠔ͍ͬͯΔʗඞཁͱ͍ͯ͠Δͷ͔ɺ ͦͷνʔϜ͚ͩͳͷ͔
ٕज़ج൫୲ w ֤νʔϜͷٕज़తͳࠩ w ٕज़ج൫ʹ·Θ͢༨ྗ͕͋Δʗͳ͍ w ج൫ܥͷܦݧ͕͋Δϝϯόʔ͕͍Δʗ͍ͳ͍ w ֤νʔϜʹઐͷٕज़ج൫୲ w
௨ৗͷґཔͱผʹΧδϡΞϧʹ૬ஊͰ͖Δ w ͕ͬͭΓೖͬͯվળ͢Δ͜ͱ
·ͱΊ w αʔϏεߏ ‣ ϓϩμΫτϑΥʔΧεʗ#''ʗڞ௨ج൫ w αʔϏεؒͷ࿈ܞ ‣ 3&45GVM)ZQFSNFEJB"1*(BSBHF ‣
$%$UFTUJOH1BDU w%PDLFSΛத৺ͱͨ͠ڥ ‣ )BLP &$4 FUDFOWFUDWBVMU ,VSPLP wνʔϜ࿈ܞʗαϙʔτ ‣ ٕज़ྖҬ՝ڞ༗ձɺٕज़ج൫୲