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

How Microservices are linked at Cookpad

Avatar for adorechic adorechic
March 14, 2016
45k

How Microservices are linked at Cookpad

Avatar for adorechic

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νʔϜ࿈ܞʗαϙʔτ ‣ ٕज़ྖҬ՝୊ڞ༗ձɺٕज़ج൫୲౰