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

How Microservices are linked at Cookpad

adorechic
March 14, 2016
44k

How Microservices are linked at Cookpad

adorechic

March 14, 2016
Tweet

Transcript

  1. )PX.JDSPTFSWJDFTBSF
    MJOLFEBU$PPLQBE

    ΫοΫύουגࣜձࣾ
    ٕज़෦։ൃج൫(
    ٢઒ਸྙ

    View Slide

  2. ࠓճ࿩͞ͳ͍͜ͱ
    w.JDSPTFSJWDFTͱ͸ʙ
    w.BSUJO'PXMFS͕ʙ
    wಋೖ͢΂͖͔൱͔ʙ
    w.JDSPTFSWJDFTͷηΦϦʔ

    ֶͼ͍ͨํ͸

    View Slide

  3. ࠓճ࿩͢͜ͱ
    w ΫοΫύουͰͷࣄྫ
    ‣ ͦ΋ͦ΋Ͳ͏͍͏ཻ౓Ͱ෼͔Ε͍ͯΔʁ
    ‣ αʔϏεؒ͸ͲͷΑ͏ʹ௨৴͢Δʁ
    ‣ αʔϏεؒͷςετͬͯͲ͏΍ͬͯΔʁ
    ‣ ߏ੒؅ཧʗσϓϩΠ͸ʁԾ૝Խͯ͠Δʁ
    ‣ ϏϧυύΠϓϥΠϯ͸ʁόονδϣϒ͸ʁ
    ‣ νʔϜؒͷ࿈ܞ΍ҙࢥܾఆ͸Ͳ͏ͯ͠Δʁ

    View Slide

  4. ͲΜͳαʔϏε͔Β
    ߏ੒͞Ε͍ͯΔ͔

    View Slide

  5. αʔϏεͷओͳ෼ྨ
    wϢʔβʔαʔϏε
    ‣ Ϣʔβʔ͕௚઀࢖͏ϓϩμΫτ
    wϏϡʔαʔϏε
    ‣ ͋ΔαʔϏεͷผϏϡʔ
    ‣ ͍ΘΏΔ#BDLFOEGPSGSPOUFOET
    wڞ௨ج൫
    ‣ ܾࡁɺ௨஌ɺϩάFUDʜ

    View Slide

  6. ϢʔβʔαʔϏε

    View Slide

  7. ϢʔβʔαʔϏε

    wϓϩμΫτʹϑΥʔΧεͨ͠λΠϓ
    ྉཧڭࣨ
    Ϩγϐ
    Ϣʔβʔ ΧϑΣ
    ܾࡁ
    ௨஌
    ಠཱͨ͠αʔϏε Α͋͘Δػೳ͸
    ڞ௨ج൫Λ׆༻
    ଞͷυϝΠϯͷϞσϧΛར༻Ͱ͖Δ

    View Slide

  8. ϏϡʔαʔϏε

    wυϝΠϯϞσϧ͸ಉ͡ͰผͷϏϡʔ
    OEM൛
    Ϩγϐ
    Ϩγϐ
    Ϣʔβʔ
    ௨஌
    ࠜຊతʹఏڙ͢Δ΋ͷ͸ಉ͡
    UI΍ΞΧ΢ϯτମܥ͕ҧ͏
    ඞཁʹԠͯ͡ଞαʔϏε
    Λ૊Έ߹ΘͤΔ
    ΦϦδφϧͷυϝΠϯ

    View Slide

  9. ϏϡʔαʔϏε
    w#'' #BDLFOEGPSGSPOUFOET
    ʹ͍ۙ
    ‣ Α͋͘ΔσόΠε͝ͱʹઐ༻ϏϡʔΛ࡞Δ
    έʔε͸΄΅ͳ͍
    ‣ 0&.൛ͷΑ͏ͳέʔεͰ࢖ΘΕ͍ͯΔ
    ఏڙ͢ΔυϝΠϯϞσϧ͸ಉ͡
    㾎ҟͳΔ6*Ͱఏڙ͢Δ
    㾎ΞΧ΢ϯτମܥ͕ҧ͏

    View Slide

  10. ڞ௨ج൫αʔϏε
    wڞ௨ͯ͠࢖ΘΕΔج൫ػೳ
    w 0"VUIϓϩόΠμ
    w ܾࡁ
    w 1VTI௨஌ʗϝʔϧ഑৴
    w ΞΫςΟϏςΟ
    w ϩά
    w ηΩϡΞσʔλ

    View Slide

  11. αʔϏεؒ͸ͲͷΑ͏ʹ
    ௨৴͢Δͷ͔

    View Slide

  12. 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"
    },
    }
    }

    View Slide

  13. (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

    View Slide

  14. (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

    View Slide

  15. αʔϏεؒ௨৴ͷ
    ίετܰݮʗ଱ো֐ੑ

    View Slide

  16. &YQFEJUPS
    wHJUIVCDPNDPPLQBEFYQFEJUPS
    w3VCZ൛ͷ/FUqJY)ZTUSJY
    w"TZODISPOPVTFYFDVUJPO
    wෳ਺ͷαʔϏε͔ΒͷϦιʔεΛฒߦͯ͠औಘ
    w'BVMUUPMFSBODF
    w$JSDVJUCSFBLFS

    View Slide

  17. αʔϏεؒ࿈ܞͷςετ

    View Slide

  18. ޓ׵ੑΛͲ͏୲อ͢Δ͔
    w αʔϏε͝ͱͷςετ͸͞Ε͍ͯΔ
    w ࿈ܞઌ͸ελϒ͢Δ
    w ඇޓ׵ͷมߋʹؾ෇͚ͳ͍
    w ܕPSςετ
    w +40/4DIFNB͸؅ཧ͕େมͦ͏
    w ΋ͱ΋ͱςετจԽ͸ࠜ෇͍͍ͯͨͷͰ্ख͘
    ׆༻͍ͨ͠

    View Slide

  19. $POTVNFS%SJWFO$POUSBDUUFTUJOH
    wར༻ଆ $POTVNFS
    ͕"1*Λελϒͯ͠ςετ
    ‣ ظ଴͢ΔৼΔ෣͍Λܖ໿ $POUSBDU
    ͱͯ͠
    "1*ଆʹ౉͢
    w"1*ଆ͸ࣗ਎͕$POUSBDUΛຬ͍ͨͯ͠Δ͔Ͳ͏
    ͔ݕূʢςετʣ͢Δ

    http://martinfowler.com/articles/consumerDrivenContracts.html

    View Slide

  20. 1BDU
    w HJUIVCDPNSFBMFTUBUFDPNBVQBDU
    w ΫϥΠΞϯτଆ
    w $*ͰQBDUϑΝΠϧΛੜ੒
    w "1*ଆ
    w $*ͰQBDUϑΝΠϧΛWFSJGZ

    ग़య: https://github.com/realestate-com-au/pact#how-does-it-work

    View Slide

  21. 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

    View Slide

  22. 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"
    }
    }

    View Slide

  23. 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

    View Slide

  24. 3BDL7$3
    w HJUIVCDPNNJZBHBXBSBDLWDS
    w 7$3͕ϕʔεͰखܰ
    w "1*ϦΫΤετΛΧηοτσʔλԽͯ͠ελϒ
    w "1*ଆ͕ΧηοτσʔλΛΫϥΠΞϯτʹఏڙ͢Δ
    w ඇޓ׵ͷมߋ͕͋Ε͹ΫϥΠΞϯτଆͷ$*Ͱݕ஌
    w "1*ଆͷϏϧυͷํ͕ߴස౓ͷ৔߹ɺΫϥΠΞϯτଆͷ
    ݕ஌લʹϦϦʔε͞Ε͏Δ
    w ݱࡏ͸1BDUʹҠߦͨ͠

    View Slide

  25. αʔϏεΛ·͍ͨͩ
    ΤϥʔΛ௥੻͢Δ

    View Slide

  26. 4FOUSZ
    w HJUIVCDPNHFUTFOUSZTFOUSZ
    w αʔϏε͝ͱͷΤϥʔΛू໿؅ཧ͍ͯ͠Δ
    w ͜Ε͚ͩͩͱαʔϏεؒͷඥ෇͚͕Ͱ͖ͳ͍
    w αʔϏε"ˠ#΁ͷϦΫΤετ࣌ʹΤϥʔ
    w Τϥʔ͸"ͱ#ͦΕͧΕͰه࿥͞ΕΔ
    w ͜ͷো֐ʹΑΔΤϥʔͷൣғ͸ʁ

    View Slide

  27. 5SBDF-PHHJOH
    w ϦΫΤετ*%
    w ϔομʹ͋Ε͹ͦͷ··࢖͍ɺͳ͚Ε͹࠾൪
    w (BSBHF$MJFOU͕ϦΫΤετ࣌ʹηοτ
    w ϦΫΤετઌʹ఻೻
    w 4FOUSZ
    w ϦΫΤετ*%ͰΤϥʔΛݕࡧ

    View Slide

  28. αʔόʔʗ࣮ߦ؀ڥʗߏ੒؅ཧ

    View Slide

  29. %PDLFS
    w ϙʔλϒϧͳ࣮ߦ؀ڥ
    w TUBHJOHQSPEVDUJPOόονಉ͡Πϝʔδ
    w ؀ڥґଘ஋͸؀ڥม਺ͱͯ͠஫ೖ
    w ຊମͷڊେ3BJMTͳͲҰ෦Λআ͖ɺ΄ͱΜͲͷΞϓϦέʔ
    γϣϯ͕%PDLFS
    w ΞϓϦέʔγϣϯͷϦϙδτϦʹ%PDLFSpMF
    w ։ൃऀ͕खݩͰ࿔ΕΔΑ͏ʹ
    w ϖωτϨςετ؀ڥͳͲඞཁʹԠ͙ͯ͢͡࡞ΕΔ

    View Slide

  30. ϏϧυύΠϓϥΠϯ
    w$*ͰΞϓϦέʔγϣϯͷςετ
    w%PDLFSΠϝʔδ࡞੒
    wBTTFUQSFDPNQJMFࡁΈͷΠϝʔδ
    wTUBHJOHʹࣗಈσϓϩΠ
    wQSPEVDUJPO͸DIBUPQTͰσϓϩΠ

    View Slide

  31. )BLP
    w HJUIVCDPNFBHMFUNUIBLP
    w %PDLFSΞϓϦ༻ͷσϓϩΠπʔϧ
    w ΫοΫύουͰ͸όοΫΤϯυʹ&$4Λར༻
    w ΞϓϦέʔγϣϯ͝ͱͷઃఆ͸:".-Ͱ؅ཧ
    w ؀ڥ͝ͱʹ؀ڥม਺ΛઃఆͰ͖Δ
    w ൿಗ஋͸FUDFOWFUDWBVMUͰ؅ཧ

    View Slide

  32. FUDFOWFUDWBVMU
    w HJUIVCDPNTPSBIFUDFOW
    w FUDEͰઃఆ஋Λ؅ཧ
    w HJUIVCDPNTPSBIFUDWBVMU
    w FUDEͷ஋Λ҉߸Խ
    w ΋ͱ΋ͱFUDEʹ"$-͕ແ͔ͬͨͨΊ࡞ΒΕͨ
    w ࢦఆͷ伴Λ͍࣋ͬͯΔΠϯελϯεͰ͔͠෮߸
    Ͱ͖ͳ͍

    View Slide

  33. FUDXFC
    w HJUIVCDPNTPSBIFUDXFC

    View Slide

  34. DIBUPQT
    w )VCPUͰσϒϩΠ
    w σϓϩΠδϣϒ͸3VOEFDLͰ؅ཧ
    w σϓϩΠํ๏͕౷Ұ͞Ε͍ͯΔ
    w νϟοτݟͯΔͱΘ͔Δ

    View Slide

  35. όονδϣϒ

    View Slide

  36. ,VSPLP
    wશαʔϏεͷδϣϒΛҰׅ؅ཧ
    ‣ ϫʔΫϑϩʔ؅ཧ
    ผαʔϏεͷδϣϒΛϑοΫ͢Δ
    ‣ 8FCίϯιʔϧͰΤϥʔ֬ೝɾ࠶࣮ߦ

    View Slide

  37. ,VSPLP
    wαʔϏεͷ࠷৽ͷ%PDLFSΠϝʔδΛ࣮ߦ
    ‣ αʔϏε͝ͱͷϫʔΧʔ؀ڥෆཁ
    ‣ Ҏલ͸֤ΞϓϦͰLVSPLPઐ༻ͷߏ੒؅ཧΛ
    ༻ҙ͍ͯͨ͠
    ‣ ֤αʔϏεͷΞϓϦέʔγϣϯ͕ͦͷ··ಈ
    ͘

    View Slide

  38. νʔϜ͝ͱͷαϙʔτ
    νʔϜΛԣஅͨ͠ҙࢥܾఆ

    View Slide

  39. ٕज़ྖҬ՝୊ڞ༗ձ
    w֤νʔϜͷٕज़Ϧʔμʔͱٕज़ج൫ʴΠϯϑϥ
    Ͱٕज़తͳ՝୊ʹ͍ͭͯ࿩͠߹͏
    w։ൃ͢Δͱ͖ʹࠔ͍ͬͯΔ͜ͱ
    w͋ͬͨΒخ͍͠΋ͷɺ΋͏ཁΒͳ͍΋ͷ
    wΈΜͳ͕ࠔ͍ͬͯΔʗඞཁͱ͍ͯ͠Δͷ͔ɺ
    ͦͷνʔϜ͚ͩͳͷ͔

    View Slide

  40. ٕज़ج൫୲౰
    w ֤νʔϜͷٕज़తͳࠩ
    w ٕज़ج൫ʹ·Θ͢༨ྗ͕͋Δʗͳ͍
    w ج൫ܥͷܦݧ͕͋Δϝϯόʔ͕͍Δʗ͍ͳ͍
    w ֤νʔϜʹઐ೚ͷٕज़ج൫୲౰
    w ௨ৗͷґཔͱ͸ผʹΧδϡΞϧʹ૬ஊͰ͖Δ
    w ͕ͬͭΓೖͬͯվળ͢Δ͜ͱ΋

    View Slide

  41. ·ͱΊ
    w αʔϏεߏ੒
    ‣ ϓϩμΫτϑΥʔΧεʗ#''ʗڞ௨ج൫
    w αʔϏεؒͷ࿈ܞ
    ‣ 3&45GVM)ZQFSNFEJB"1*(BSBHF
    ‣ $%$UFTUJOH1BDU
    w%PDLFSΛத৺ͱͨ͠؀ڥ
    ‣ )BLP &$4
    FUDFOWFUDWBVMU ,VSPLP
    wνʔϜ࿈ܞʗαϙʔτ
    ‣ ٕज़ྖҬ՝୊ڞ༗ձɺٕज़ج൫୲౰

    View Slide