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
43k
How Microservices are linked at Cookpad
adorechic
March 14, 2016
Tweet
Share
More Decks by adorechic
See All by adorechic
採用技術、絞るか広げるか / Make variety of technology widely or narrowly?
adorechic
0
75
Rails + ReactなSPAサイトでのSEO / SEO at Rails + React SPA
adorechic
4
26k
分かれたシステムをていねいにモノリスに集約する/Integrate decentralized systems to a monolith carefully
adorechic
16
18k
クックパッドがどのようにMicroservicesしてきたか/How Cookpad shifts to Microservices
adorechic
58
39k
Microservices Overview
adorechic
0
160
Microservices stacks
adorechic
1
150
Featured
See All Featured
JazzCon 2018 Closing Keynote - Leadership for the Reluctant Leader
reverentgeek
175
9.1k
Building an army of robots
kneath
301
40k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
270
12k
How to train your dragon (web standard)
notwaldorf
66
4.3k
The Pragmatic Product Professional
lauravandoore
21
3.5k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
500
130k
Into the Great Unknown - MozCon
thekraken
2
310
Designing for Performance
lara
600
65k
VelocityConf: Rendering Performance Case Studies
addyosmani
317
22k
A Tale of Four Properties
chriscoyier
149
21k
The Power of CSS Pseudo Elements
geoffreycrofte
52
4.3k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
24
4.7k
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 HJUIVCDPNDPPLQBE
[email protected]
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νʔϜ࿈ܞʗαϙʔτ ‣ ٕज़ྖҬ՝ڞ༗ձɺٕज़ج൫୲