Upgrade to Pro — share decks privately, control downloads, hide ads and more …

How Microservices are linked at Cookpad

adorechic
March 14, 2016
45k

How Microservices are linked at Cookpad

adorechic

March 14, 2016
Tweet

Transcript

  1. ࠓճ࿩͢͜ͱ w ΫοΫύουͰͷࣄྫ ‣ ͦ΋ͦ΋Ͳ͏͍͏ཻ౓Ͱ෼͔Ε͍ͯΔʁ ‣ αʔϏεؒ͸ͲͷΑ͏ʹ௨৴͢Δʁ ‣ αʔϏεؒͷςετͬͯͲ͏΍ͬͯΔʁ ‣

    ߏ੒؅ཧʗσϓϩΠ͸ʁԾ૝Խͯ͠Δʁ ‣ ϏϧυύΠϓϥΠϯ͸ʁόονδϣϒ͸ʁ ‣ νʔϜؒͷ࿈ܞ΍ҙࢥܾఆ͸Ͳ͏ͯ͠Δʁ 
  2. 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" }, } }
  3. (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
  4. (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
  5. ޓ׵ੑΛͲ͏୲อ͢Δ͔ w αʔϏε͝ͱͷςετ͸͞Ε͍ͯΔ w ࿈ܞઌ͸ελϒ͢Δ w ඇޓ׵ͷมߋʹؾ෇͚ͳ͍ w ܕPSςετ w

    +40/4DIFNB͸؅ཧ͕େมͦ͏ w ΋ͱ΋ͱςετจԽ͸ࠜ෇͍͍ͯͨͷͰ্ख͘ ׆༻͍ͨ͠ 
  6. 1BDU w HJUIVCDPNSFBMFTUBUFDPNBVQBDU w ΫϥΠΞϯτଆ w $*ͰQBDUϑΝΠϧΛੜ੒ w "1*ଆ w

    $*ͰQBDUϑΝΠϧΛWFSJGZ  ग़య: https://github.com/realestate-com-au/pact#how-does-it-work
  7. 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
  8. 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" } }
  9. 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
  10. 3BDL7$3 w HJUIVCDPNNJZBHBXBSBDLWDS w 7$3͕ϕʔεͰखܰ w "1*ϦΫΤετΛΧηοτσʔλԽͯ͠ελϒ w "1*ଆ͕ΧηοτσʔλΛΫϥΠΞϯτʹఏڙ͢Δ w

    ඇޓ׵ͷมߋ͕͋Ε͹ΫϥΠΞϯτଆͷ$*Ͱݕ஌ w "1*ଆͷϏϧυͷํ͕ߴස౓ͷ৔߹ɺΫϥΠΞϯτଆͷ ݕ஌લʹϦϦʔε͞Ε͏Δ w ݱࡏ͸1BDUʹҠߦͨ͠ 
  11. %PDLFS w ϙʔλϒϧͳ࣮ߦ؀ڥ w TUBHJOHQSPEVDUJPOόονಉ͡Πϝʔδ w ؀ڥґଘ஋͸؀ڥม਺ͱͯ͠஫ೖ w ຊମͷڊେ3BJMTͳͲҰ෦Λআ͖ɺ΄ͱΜͲͷΞϓϦέʔ γϣϯ͕%PDLFS

    w ΞϓϦέʔγϣϯͷϦϙδτϦʹ%PDLFSpMF w ։ൃऀ͕खݩͰ࿔ΕΔΑ͏ʹ w ϖωτϨςετ؀ڥͳͲඞཁʹԠ͙ͯ͢͡࡞ΕΔ 
  12. FUDFOWFUDWBVMU w HJUIVCDPNTPSBIFUDFOW w FUDEͰઃఆ஋Λ؅ཧ w HJUIVCDPNTPSBIFUDWBVMU w FUDEͷ஋Λ҉߸Խ w

    ΋ͱ΋ͱFUDEʹ"$-͕ແ͔ͬͨͨΊ࡞ΒΕͨ w ࢦఆͷ伴Λ͍࣋ͬͯΔΠϯελϯεͰ͔͠෮߸ Ͱ͖ͳ͍ 
  13. ·ͱΊ w αʔϏεߏ੒ ‣ ϓϩμΫτϑΥʔΧεʗ#''ʗڞ௨ج൫ w αʔϏεؒͷ࿈ܞ ‣ 3&45GVM)ZQFSNFEJB"1*(BSBHF ‣

    $%$UFTUJOH1BDU w%PDLFSΛத৺ͱͨ͠؀ڥ ‣ )BLP &$4 FUDFOWFUDWBVMU ,VSPLP wνʔϜ࿈ܞʗαϙʔτ ‣ ٕज़ྖҬ՝୊ڞ༗ձɺٕज़ج൫୲౰