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

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

disc99
October 18, 2019

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

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

disc99

October 18, 2019
Tweet

More Decks by disc99

Other Decks in Technology

Transcript

  1. ͪͳΈʹ w ςΩετɺΤΫηϧΈ͍ͨͳ੩తͳυΩϡϝϯτ w 0QFO"1* 4XBHHFS  w +40/4DIFNB w

    1SPUPDPM#V⒎FST w (SBQI2-˞ࠓ೔ͷςʔϚͱҰ෦ྨࣅ͢Δ෦෼͋Γ  
  2. w 'VODUJPO"͔Β'VODUJPO#Λݺͼग़͢ 4ZTUFN 3VOUJNF ैདྷͷॲཧ 'VODUJPOͷੈք   $PEF 'VODUJPO"

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

    ʜ ^ "1*$MJFOU "1*&YFDVUF \ ʜ ʜ ʜ
 ʜ ʜ ^ "1*ͷੈք w 'VODUJPO"͔Β'VODUJPO#Λݺͼग़͢   /FUXPSL 4ZTUFN 3VOUJNF "1*4FSWFS &OEQPJOU \ ʜ ʜ )BOEMF 
 ʜ ʜ ^ $PEF 'VODUJPO# \ ʜ ʜ ʜ
 ʜ ʜ ^
  4. 'VODUJPOͷੈքWT"1*ͷੈք   'VODBUJPO "1* ఆٛ ݴޠ࢓༷ ༷ʑͳఆٛ ϑΥʔϚοτ ݴޠ࢓༷

    ༷ʑͳϑΥʔϚοτ ϓϩτίϧ ݴޠ࢓༷ ༷ʑͳϓϩτίϧ ίʔυ ͙͢ʹδϟϯϓͰ͖Δ ༷ʑͳϙΠϯτΛܦ༝͢Δඞཁ͕͋Δ ݺͼग़͠ ݴޠ΍*%&౳Ͱߴਫ਼౓อূ
 جຊࣦഊ͠ͳ͍ ఆ͕࣮ٛ૷͞Ε͍ͯΔอূ͕͠ʹ͍͘
 ωοτϫʔΫ౳Ͱ΋ࣦഊ΋͋Δ
  5. 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; }
  6. ଞͷ"1*؅ཧWT1SPUPDPM#V⒎FST   ଞͷ"1*؅ཧ 1SPUPDPM#V⒎FST બ୒ࢶ ఆٛ΍ݺͼग़͠ͷબ୒ࢶ͕૿͑Δ ඪ४తͳํ͕ࣜఆ·͍ͬͯΔ ৴པੑ ఆٛΛ࣮֬ʹ࣮૷Ͱ͖Δอূ͕ͳ͍

    ίʔυੜ੒ʹΑΓ৴པੑ͕޲্͢Δ ֶशίετ ෯޿͍χʔζΛΧόʔ͠Α͏ͱ͍ͯ͠ΔͨΊ ֶशίετ͕ߴ͘ͳΓ΍͍͢ ओཁͳχʔζΛλʔήοτͱ͍ͯ͠ΔͨΊ ֶशίετ͕௿͍ Մಡੑ ൚༻తͳϑΥʔϚοτ :BNMɺ+40/౳ Λ ࢖༻ͯ͠Δ΋ͷ͸࢝Ί΍͍͕͢Մಡੑ͕Լ͕ Γ΍͍͢ ઐ༻ͷ%4-ͷͨΊ'VODBUJPOʹΑΔ؅ཧͷ ײ֮ʹ͍ۙ
  7. 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": {…} } } }
  8. 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 }
  9. ΋ͪΖΜ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; }
  10. ͪͳΈʹ   w ֤ݴޠ޲͚ίʔυੜ੒Λͯ͠Δπʔϧ w QSPUPDHFOHP w QSPUPDHFOKBWB w

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

    ʜ H31$ 1ZUIPO (P IUNM ֤πʔϧͷΤίγεςϜͱͷ࿈ܞ
  12. QSPUPDϓϥάΠϯ w ϓϥάΠϯ
 QSPUPDHFOTXBHHFS
 QSPUPDHFOEPD
 QSPUPDHFOHSQD
 QSPUPDHFOHP w ࣮ߦίϚϯυ QSPUPD1SPUPDPM#V⒎FSTίϯύΠϥ

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

    
 QSPUPDTXBHHFS@PVUFYBNQMFQSPUP
 QSPUPDEPD@PVUFYBNQMFQSPUP
 QSPUPDHSQD@PVUFYBNQMFQSPUP
 QSPUPDHP@PVUFYBNQMFQSPUP  
  14. QSPUPDϓϥάΠϯͷ࢓૊Έ   QSPUPDQMVHJO
 FYQSPUPDHFOYYY QSPUPD NFTTBHF#PPL\ ʜ ʜ ʜ

    ^ FYBNQMFQSPUP (FOFSBUFE $PEF QSPUPD͸ϓϥάΠϯͷग़ྗʹै͍ϑΝΠϧΛੜ੒ ɹ$ protoc —-xxx_out=. example.proto
  15. 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 {…} }
  16. ϓϥάΠϯʹΑΔ֦ு   TXBHHFS
 0QFO"1* +BWB NBSLEPXO QSPUP ʜ ʜ

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

    ʜ H31$ 1ZUIPO (P IUNM ඞཁͳ ίʔυ ߋʹ࿈ܞͷڧԽ
  18. Ԡ༻ྫ   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*ͷΤίγεςϜͷ࿈ܞΛ࣮ݱ