Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up
for free
How Microservices are linked at Cookpad
adorechic
March 14, 2016
12
41k
How Microservices are linked at Cookpad
adorechic
March 14, 2016
Tweet
Share
More Decks by adorechic
See All by adorechic
adorechic
0
46
adorechic
4
22k
adorechic
16
15k
adorechic
58
39k
adorechic
0
150
adorechic
1
140
Featured
See All Featured
marcelosomers
220
15k
bkeepers
321
53k
akmur
252
19k
zakiwarfel
88
3.3k
eileencodes
113
25k
ddemaree
274
31k
jponch
103
5k
cherdarchuk
71
260k
sachag
267
17k
colly
66
3k
holman
448
130k
shlominoach
176
7.4k
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νʔϜ࿈ܞʗαϙʔτ ‣ ٕज़ྖҬ՝ڞ༗ձɺٕज़ج൫୲