全てのAPIをProtocol Buffersで管理する / Manage all APIs with Protocol Buffers

660946c5788429ad71546d35e74a709b?s=47 disc99
October 18, 2019

全てのAPIをProtocol Buffersで管理する / Manage all APIs with Protocol Buffers

全てのAPIをProtocol Buffersで管理する方法と価値を #shinjukult で発表した資料

660946c5788429ad71546d35e74a709b?s=128

disc99

October 18, 2019
Tweet

Transcript

  1. શͯͷ"1*Λ
 1SPUPDPM#VGGFSTͰ؅ཧ͢Δ 4IJOKVLV-5 !EJTD

  2. "CPVU.F w /BNFEJTD
 5XJUUFS!EJTD@ w $PNQBOZΞιϏϡʔגࣜձࣾ
 5FDI-FBE43&

  3. 2VFTUJPO  

  4. "1*ΛͲ͏؅ཧͯ͠·͔͢ w ςΩετɺΤΫηϧΈ͍ͨͳ੩తͳυΩϡϝϯτ w 0QFO"1* 4XBHHFS  w +40/4DIFNB w

    1SPUPDPM#V⒎FST w (SBQI2-  
  5. ࠓ೔ͷ࿩ w ςΩετɺΤΫηϧΈ͍ͨͳ੩తͳυΩϡϝϯτ w 0QFO"1* 4XBHHFS  w +40/4DIFNB w

    1SPUPDPM#V⒎FST w (SBQI2-  
  6. ͪͳΈʹ w ςΩετɺΤΫηϧΈ͍ͨͳ੩తͳυΩϡϝϯτ w 0QFO"1* 4XBHHFS  w +40/4DIFNB w

    1SPUPDPM#V⒎FST w (SBQI2-˞ࠓ೔ͷςʔϚͱҰ෦ྨࣅ͢Δ෦෼͋Γ  
  7. ఻͍͑ͨ͜ͱ  ଞͷ"1*؅ཧํ๏ͱͷҧ͍  1SPUPDPM#V⒎FST͸H31$͚ͩͰͳ͘ɺ3&45"1*΍੩తυΩϡϝ ϯτ΋Ұݩ؅ཧͰ͖Δ  ଍Γͳ͍ػೳ͸ϓϥάΠϯͰࣗ༝ʹ֦ுͰ͖Δ  

  8. ఻͑ͳ͍͜ͱ w 1SPUPDPM#V⒎FSTʹؔͯ͠ͷجૅతͳ಺༰
 ˞༏Εͨ৘ใ͕ͨ͘͞Μެ։͞Ε͍ͯΔͨΊࠓճର৅֎ w 1SPUPDPM#V⒎FSTΛத৺ͱͨ͠ςʔϚʹ͢ΔͨΊɺH31$ݻ༗ͷػೳ͸ۃྗ ৮Ε·ͤΜ  

  9. ఻͍͑ͨ͜ͱ  ଞͷ"1*؅ཧํ๏ͱͷҧ͍  1SPUPDPM#V⒎FST͸H31$͚ͩͰͳ͘ɺ3&45"1*΍੩తυΩϡϝ ϯτ΋Ұݩ؅ཧͰ͖Δ  ଍Γͳ͍ػೳ͸ϓϥάΠϯͰࣗ༝ʹ֦ுͰ͖Δ  

  10. Α͋͘Δύλʔϯ
 "1*؅ཧʹ࣌ؒΛͱΒΕ ։ൃʹूதͰ͖ͳ͍  

  11. ͳ͕͔͔ͥ࣌ؒΔͷ͔  

  12. w 'VODUJPO"͔Β'VODUJPO#Λݺͼग़͢ 4ZTUFN 3VOUJNF ैདྷͷॲཧ 'VODUJPOͷੈք   $PEF 'VODUJPO"

    \ ʜ ʜ 'VODUJPO# 
 ʜ ʜ ^ $PEF 'VODUJPO# \ ʜ ʜ ʜ
 ʜ ʜ ^
  13. 4ZTUFN 3VOUJNF $PEF 'VODUJPO" \ ʜ ʜ "1*&YFDVUF 
 ʜ

    ʜ ^ "1*$MJFOU "1*&YFDVUF \ ʜ ʜ ʜ
 ʜ ʜ ^ "1*ͷੈք w 'VODUJPO"͔Β'VODUJPO#Λݺͼग़͢   /FUXPSL 4ZTUFN 3VOUJNF "1*4FSWFS &OEQPJOU \ ʜ ʜ )BOEMF 
 ʜ ʜ ^ $PEF 'VODUJPO# \ ʜ ʜ ʜ
 ʜ ʜ ^
  14. "1*ఆٛ ݺͼग़͠  

  15. ఆٛ w ఆٛ w ςΩετɺ0QFO"1*4QFDJpDBUJPOɺ(SBQI2-ɺ1SPUPDPM#V⒎FST w ϑΥʔϚοτ w +40/ɺ9.-ɺόΠφϦ w

    ϓϩτίϧ w )551ɺ)551ɺ8FC4PDLFUɺ5$1  
  16. ݺͼग़͠ w ֤ݴޠ͝ͱͷඪ४"1*ΫϥΠΞϯτ w ֤ݴޠ͝ͱͷαʔυύʔςΟ"1*ΫϥΠΞϯτ w "1*ఆ͔ٛΒͷίʔυੜ੒  

  17. 'VODUJPOͷੈքWT"1*ͷੈք   'VODBUJPO "1* ఆٛ ݴޠ࢓༷ ༷ʑͳఆٛ ϑΥʔϚοτ ݴޠ࢓༷

    ༷ʑͳϑΥʔϚοτ ϓϩτίϧ ݴޠ࢓༷ ༷ʑͳϓϩτίϧ ίʔυ ͙͢ʹδϟϯϓͰ͖Δ ༷ʑͳϙΠϯτΛܦ༝͢Δඞཁ͕͋Δ ݺͼग़͠ ݴޠ΍*%&౳Ͱߴਫ਼౓อূ
 جຊࣦഊ͠ͳ͍ ఆ͕࣮ٛ૷͞Ε͍ͯΔอূ͕͠ʹ͍͘
 ωοτϫʔΫ౳Ͱ΋ࣦഊ΋͋Δ
  18. "1*ʹ͢Δ͜ͱͰ બ୒ࢶ↑৴པੑ↓ֶशίετ↑Մಡੑ↓
 
 ߟ͑Δ͜ͱ૿͑Δ ͕͔͔࣌ؒΔ  

  19. 1SPUPDPM#VGGFST  

  20. 1SPUPDPM#V⒎FST w ಛఆͷϓϩάϥϛϯάݴޠɾϓϥοτϑΥʔϜඇґଘͳεΩʔϚݴޠ w ΠϯλʔϑΣΠεΛఆٛ͢ΔͨΊͷ*%- *OUFSGBDF%FpOJUJPO -BOHVBHF  w ओཁͳχʔζΛຬͨͨ͢ΊͷίϯύΫτͳ࢓༷

    w ߴ౓ͳػೳ͕ͳ͍ͨΊ୭Ͱ΋ಡΈॻ͖͠΍͍͢ w γϦΞϥΠζϑΥʔϚοτ +40/ͳͲͷผϑΥʔϚοτ΁ͷมߋ΋Մೳ  w σϑΝΫτͷ௨৴ϑϨʔϜϫʔΫ H31$   syntax = "proto3"; package example; import "google/api/annotations.proto"; // Service for handling books. service BookService { // Get book rpc GetBook (GetBookRequest) returns (Book) {} // Create book rpc CreateBook (CreateBookRequest) returns (Book) {} } // Request for get book message GetBookRequest { string id = 1; } // Request for get book message CreateBookRequest { string name = 1; } // Book data message Book { string id = 1; string name = 2; }
  21. εΩʔϚݴޠͷՁ஋ w ΞϓϦέʔγϣϯ։ൃલʹࣄલఆٛɺؔ܎ऀͰ߹ҙͰ͖Δ w ΠϯλʔϑΣΠεΛఆٛ͢Δ͜ͱʹಛԽ %4- ͍ͯ͠ΔͨΊՄಡੑ͕ߴ͍ w ιʔείʔυ؅ཧ͕͠΍͍͢ɾमਖ਼ͳͲ΋13ͳͲͰ؆୯ʹ؅ཧͰ͖Δ w

    ಛఆͷݴޠ΍ϓϥοτϑΥʔϜʹඇґଘͳͨΊɺಉҰͷఆ͔ٛΒཁ݅ʹ߹Θ࣮ͤ ૷Λબ୒Ͱ͖Δ w ೚ҙͷίʔυΛੜ੒͢Δ͜ͱ͕Ͱ͖Δ  
  22. ଞͷ"1*؅ཧWT1SPUPDPM#V⒎FST   ଞͷ"1*؅ཧ 1SPUPDPM#V⒎FST બ୒ࢶ ఆٛ΍ݺͼग़͠ͷબ୒ࢶ͕૿͑Δ ඪ४తͳํ͕ࣜఆ·͍ͬͯΔ ৴པੑ ఆٛΛ࣮֬ʹ࣮૷Ͱ͖Δอূ͕ͳ͍

    ίʔυੜ੒ʹΑΓ৴པੑ͕޲্͢Δ ֶशίετ ෯޿͍χʔζΛΧόʔ͠Α͏ͱ͍ͯ͠ΔͨΊ ֶशίετ͕ߴ͘ͳΓ΍͍͢ ओཁͳχʔζΛλʔήοτͱ͍ͯ͠ΔͨΊ ֶशίετ͕௿͍ Մಡੑ ൚༻తͳϑΥʔϚοτ :BNMɺ+40/౳ Λ ࢖༻ͯ͠Δ΋ͷ͸࢝Ί΍͍͕͢Մಡੑ͕Լ͕ Γ΍͍͢ ઐ༻ͷ%4-ͷͨΊ'VODBUJPOʹΑΔ؅ཧͷ ײ֮ʹ͍ۙ
  23. બ୒ࢶ↓৴པੑ↑ֶशίετ↓Մಡੑ↑
 
 "1*؅ཧʹ࣌ؒΛͱΒΕͳ͍ ։ൃʹूத͠΍͘͢ͳΔ  

  24. ఻͍͑ͨ͜ͱ  ଞͷ"1*؅ཧํ๏ͱͷҧ͍  1SPUPDPM#V⒎FST͸H31$͚ͩͰͳ͘ɺ3&45"1*΍੩తυΩϡϝ ϯτ΋Ұݩ؅ཧͰ͖Δ  ଍Γͳ͍ػೳ͸ϓϥάΠϯͰࣗ༝ʹ֦ுͰ͖Δ  

  25. 1SPUPDPM#V⒎FSTʹΑΔ3&45"1*؅ཧ w QSPUPDHFOTXBHHFS w εΩʔϚఆٛʹै͍ɺTXBHHFS 0QFO"1* ͷ+40/Λग़ྗ͢Δπʔϧ w ಉҰͷఆ͔ٛΒ3&45"1*؅ཧɺ4XBHHFS$PEFHFOʹΑΔίʔυੜ੒ͱ΋࿈ܞ 

     // Service for handling books. service BookService { // Get book rpc GetBook (GetBookRequest) returns (Book) { option (google.api.http) = { get: "/books/{id}" }; }; } // Request for get book message GetBookRequest { string id = 1; } // Book data message Book { string id = 1; string name = 2; } { "swagger": "2.0", "info": {…}, "schemes": […], "consumes": […], "produces": […], "paths": { "/books/{id}": { "get": { "summary": "Get book", "operationId": "GetBook", "responses": { "200": { "description": "A successful response.", "schema": { "$ref": “#/definitions/exampleBook" } } }, "parameters": [ { "name": "id", "in": "path", "required": true, "type": "string" } ], "tags": […] } } }, "definitions": { "exampleCreateBookRequest": { "type": "object", "properties": { "name": { "type": "string" } }, "title": "Request for get book" }, “exampleBook": {…} } } }
  26. 1SPUPDPM#V⒎FSTʹΑΔ੩తυΩϡϝϯτ؅ཧ   w QSPUPDHFOEPD w εΩʔϚఆٛʹै͍ɺ)5.-ɺ+40/ɺ%PD#PPLɺ.BSLEPXOϑΝΠϧΛੜ੒͢Δπʔϧ // Service for

    handling books. service BookService { // Get book rpc GetBook (GetBookRequest) returns (Book) {} // Create book rpc CreateBook (CreateBookRequest) returns (Book) {} } // Request for get book message GetBookRequest { string id = 1; // Book ID } // Request for get book message CreateBookRequest { string name = 1; // Book name } // Book data message Book { string id = 1; // Book ID string name = 2; // Book name }
  27. ΋ͪΖΜH31$΋   w QSPUPDHFOHSQD w εΩʔϚఆٛʹै͍ɺH31$αʔόʔͱελϒΛੜ੒ public class BookService

    extends BookServiceGrpc.BookServiceImplBase { @Override public void getBook(GetBookRequest request, StreamObserver<Book> responseObserver) { Book response = Book.newBuilder().setId(request.getId()).setName("My book").build(); responseObserver.onNext(response); responseObserver.onCompleted(); } @Override public void createBook(CreateBookRequest request, StreamObserver<Book> responseObserver) { String id = UUID.randomUUID().toString(); Book response = Book.newBuilder().setId(id).setName(request.getName()).build(); responseObserver.onNext(response); responseObserver.onCompleted(); } } BookServiceGrpc.BookServiceBlockingStub stub; void getBook(String id) { GetBookRequest request = GetBookRequest.newBuilder().setId(id).build(); try { Book response = stub.getBook(request); log.info("Book name: " + response.getName()); } catch (Exception e) { log.error("RPC failed", e); } } // Service for handling books. service BookService { // Get book rpc GetBook (GetBookRequest) returns (Book) {} // Create book rpc CreateBook (CreateBookRequest) returns (Book) {} } // Request for get book message GetBookRequest { string id = 1; } // Request for get book message CreateBookRequest { string name = 1; } // Book data message Book { string id = 1; string name = 2; }
  28. ඇಉظΠϕϯτͷ؅ཧ   w QSPUPDHFO\MBOHVBHF^ w NFTTBHFʹΑΔΠϕϯτఆٛͱίʔυੜ੒ɺγϦΞϥΠζ ΠϕϯτۦಈϚΠΫϩαʔϏεΞʔΩςΫνϟ
 IUUQTTQFBLFSEFDLDPNEJTDFWFOUESJWFONJDSPTFSWJDFTBSDIJUFDUVSF TMJEF

    ར༻ྫ ".-νʔϜ͕ͲͷΑ͏ʹϝϧϖΠͷσʔλΛ4QMVOLʹूΊ׆༻͍ͯ͠Δ͔
 IUUQTUFDINFSDBSJDPNFOUSZ
  29. ͪͳΈʹ   w ֤ݴޠ޲͚ίʔυੜ੒Λͯ͠Δπʔϧ w QSPUPDHFOHP w QSPUPDHFOKBWB w

    QSPUPDHFOQZUIPO w QSPUPDHFOEBSU w QSPUPDHFOʜ w ໾ཱͭπʔϧ w QSPUPDHFOWBMJEBUFఆٛʹόϦσʔγϣϯΛ௥Ճ w QSPUPDHFOMJOUఆٛͷ-JOUΛ࣮ߦ w QSPUPDHFOKTPOTDIFNBఆ͔ٛΒ+40/4DIFNBΛੜ੒ w QSPUPDHFOVNMఆ͔ٛΒ6.-Λੜ੒
  30. εΩʔϚఆٛʹΑΔΤίγεςϜ   TXBHHFS
 0QFO"1* +BWB NBSLEPXO QSPUP ʜ ʜ

    ʜ H31$ 1ZUIPO (P IUNM ίʔυੜ੒
  31. εΩʔϚఆٛʹΑΔΤίγεςϜ   TXBHHFS
 0QFO"1* +BWB NBSLEPXO QSPUP ʜ ʜ

    ʜ H31$ 1ZUIPO (P IUNM ֤πʔϧͷΤίγεςϜͱͷ࿈ܞ
  32. εΩʔϚఆٛΛத৺ͱͨ͠ ΤίγεςϜ͕ग़དྷ্͕Δ  

  33. ఻͍͑ͨ͜ͱ  ଞͷ"1*؅ཧํ๏ͱͷҧ͍  1SPUPDPM#V⒎FST͸H31$͚ͩͰͳ͘ɺ3&45"1*΍੩తυΩϡϝ ϯτ΋Ұݩ؅ཧͰ͖Δ  ଍Γͳ͍ػೳ͸ϓϥάΠϯͰࣗ༝ʹ֦ுͰ͖Δ  

  34. QSPUPDϓϥάΠϯ w ϓϥάΠϯ
 QSPUPDHFOTXBHHFS
 QSPUPDHFOEPD
 QSPUPDHFOHSQD
 QSPUPDHFOHP w ࣮ߦίϚϯυ QSPUPD1SPUPDPM#V⒎FSTίϯύΠϥ

    
 QSPUPDTXBHHFS@PVUFYBNQMFQSPUP
 QSPUPDEPD@PVUFYBNQMFQSPUP
 QSPUPDHSQD@PVUFYBNQMFQSPUP
 QSPUPDHP@PVUFYBNQMFQSPUP  
  35. QSPUPDϓϥάΠϯ w ϓϥάΠϯ
 QSPUPDHFOTXBHHFS
 QSPUPDHFOEPD
 QSPUPDHFOHSQD
 QSPUPDHFOHP w ࣮ߦίϚϯυ QSPUPD1SPUPDPM#V⒎FSTίϯύΠϥ

    
 QSPUPDTXBHHFS@PVUFYBNQMFQSPUP
 QSPUPDEPD@PVUFYBNQMFQSPUP
 QSPUPDHSQD@PVUFYBNQMFQSPUP
 QSPUPDHP@PVUFYBNQMFQSPUP  
  36. QSPUPDϓϥάΠϯ w ϓϥάΠϯQSPUPDHFOTXBHHFS ࣮ମ͸όΠφϦ΍εΫϦϓτϑΝΠϧ  w ࣮ߦίϚϯυQSPUPDTXBHHFS@PVUFYBNQMFQSPUP w ϓϥάΠϯͷϧʔϧ1"5)্ʹଘࡏ͢ΔQSPUPDHFOYYY͕ϓϥά Πϯͱͯ͠ར༻Ͱ͖Δ

    ໌ࣔతʹࢦఆ΋Մೳ  w ಉ͡ϧʔϧʹै͍ϓϥάΠϯͷ࡞੒͕Մೳ  
  37. QSPUPDϓϥάΠϯͷ࢓૊Έ   NFTTBHF#PPL\ ʜ ʜ ʜ ^ FYBNQMFQSPUP εΩʔϚఆٛΛߦ͏

  38. QSPUPDϓϥάΠϯͷ࢓૊Έ   ɹ$ protoc —-xxx_out=. example.proto ίϚϯυ࣮ߦ NFTTBHF#PPL\ ʜ

    ʜ ʜ ^ FYBNQMFQSPUP
  39. QSPUPDϓϥάΠϯͷ࢓૊Έ   QSPUPD͸ղੳ݁ՌΛϓϥάΠϯʹඪ४ग़ྗ ɹ$ protoc —-xxx_out=. example.proto QSPUPDQMVHJO
 FYQSPUPDHFOYYY

    QSPUPD NFTTBHF#PPL\ ʜ ʜ ʜ ^ FYBNQMFQSPUP
  40. QSPUPDϓϥάΠϯͷ࢓૊Έ   ϓϥάΠϯ͸ग़ྗ͍ͨ͠಺༰Λඪ४ग़ྗ ɹ$ protoc —-xxx_out=. example.proto QSPUPDQMVHJO
 FYQSPUPDHFOYYY

    QSPUPD NFTTBHF#PPL\ ʜ ʜ ʜ ^ FYBNQMFQSPUP
  41. QSPUPDϓϥάΠϯͷ࢓૊Έ   QSPUPDQMVHJO
 FYQSPUPDHFOYYY QSPUPD NFTTBHF#PPL\ ʜ ʜ ʜ

    ^ FYBNQMFQSPUP (FOFSBUFE $PEF QSPUPD͸ϓϥάΠϯͷग़ྗʹै͍ϑΝΠϧΛੜ੒ ɹ$ protoc —-xxx_out=. example.proto
  42. QSPUPDϓϥάΠϯͷ࡞੒ w FYQSPUPDHFOEVNQ w ೖྗ͞Εͨίʔυੜ੒ϦΫΤετΛͦͷ··μ ϯϓσʔλͱͯ͠ग़ྗ w ͜Ε͚ͩͷίʔυͰϓϥάΠϯ͕؆୯ʹ࡞੒Մೳ w ೖྗ΍ग़ྗͷܗࣜ΋1SPUPDPM#V⒎FSTͰఆٛࡁΈ

      func main() { log.SetFlags(0) log.SetPrefix("protoc-gen-proto: ") data, err := ioutil.ReadAll(os.Stdin) if err != nil {…} request := &plugin.CodeGeneratorRequest{} if err := proto.Unmarshal(data, request); err != nil {…} if len(request.FileToGenerate) == 0 {…} params := util.ParseParams(request) name := "out.gob" if v, ok := params["out"]; ok { name = v } response := &plugin.CodeGeneratorResponse{} data, err = proto.Marshal(request) if err != nil { response.Error = proto.String(err.Error()) } else { response.File = []*plugin.CodeGeneratorResponse_File{ &plugin.CodeGeneratorResponse_File{ Name: proto.String(name), Content: proto.String(string(data)), }, } } data, err = proto.Marshal(response) if err != nil {…} _, err = io.Copy(os.Stdout, bytes.NewReader(data)) if err != nil {…} }
  43. ϓϥάΠϯʹΑΔ֦ு   TXBHHFS
 0QFO"1* +BWB NBSLEPXO QSPUP ʜ ʜ

    ʜ H31$ 1ZUIPO (P IUNM ඞཁͳ ίʔυ ϓϥάΠϯͰ௥Ճੜ੒
  44. ϓϥάΠϯʹΑΔ֦ு   TXBHHFS
 0QFO"1* +BWB NBSLEPXO QSPUP ʜ ʜ

    ʜ H31$ 1ZUIPO (P IUNM ඞཁͳ ίʔυ ߋʹ࿈ܞͷڧԽ
  45. "1*؅ཧʹඞཁͳػೳΛ εΩʔϚఆٛΛϕʔεʹ֦ுͰ͖Δ  

  46. Ԡ༻ྫ   w QSPUPDHFOTQSJOHXFCqVY
 IUUQTHJUIVCDPNEJTDQSPUPDHFOTQSJOHXFCqVY w H31$αʔόʔΛ+40/PWFS)551ରԠͤ͞ΔϓϥάΠϯ w H31$αʔόʔʹରͯ͠௚઀ม׵PSϦόϓϩੜ੒

    MJLF HSQDHBUFXBZ ͷػೳͷ֦ுΛఏڙ w 4QSJOH8FC'MVYͷ)BOEMFSΛੜ੒ w HPPHMFBQJIUUQʹରԠͨ͠3&45"1*ੜ੒΋Մೳ w *%-ΑΔ؅ཧɺίʔυੜ੒ʹΑΔ৴པੑɺ+40/΍ 0QFO"1*ͷΤίγεςϜͷ࿈ܞΛ࣮ݱ
  47. ·ͱΊ w 1SPUPDPM#V⒎FST͸εΩʔϚఆٛΛϕʔεͱͨ͠ΤίγεςϜΛߏங w H31$͚ͩͰͳ͘ɺ3&45"1*΍੩తυΩϡϝϯτ΋Ұݩ؅ཧ w ଍Γͳ͍ػೳ͸ϓϥάΠϯͰࣗ༝ʹ֦ு  

  48. 1SPUPDPM#VGGFSTͰ
 "1*؅ཧΛ׬݁ɾ؆ܿʹ  

  49. ࢀߟ w ࠓ͞Β1SPUPDPM#V⒎FSTͱɺखʹೃછΉಓ۩ͷ࿩ w IUUQTRJJUBDPNZVHVJJUFNTEEC w QSPUPDϓϥάΠϯͷॻ͖ํ w IUUQTRJJUBDPNZVHVJJUFNTEEEFFF