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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
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
How GitHub (no longer) Works
holman
316
150k
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
118
120k
How to make the Groovebox
asonas
2
2.2k
Un-Boring Meetings
codingconduct
0
320
Google's AI Overviews - The New Search
badams
0
1k
The Art of Programming - Codeland 2020
erikaheidi
57
14k
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
2k
Six Lessons from altMBA
skipperchong
29
4.3k
How People are Using Generative and Agentic AI to Supercharge Their Products, Projects, Services and Value Streams Today
helenjbeal
1
220
WENDY [Excerpt]
tessaabrams
11
38k
The Pragmatic Product Professional
lauravandoore
37
7.3k
Why Our Code Smells
bkeepers
PRO
340
58k
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νʔϜ࿈ܞʗαϙʔτ ‣ ٕज़ྖҬ՝ڞ༗ձɺٕज़ج൫୲