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

grapi: Bulding JSON API server with grpc-gateway for microservices

grapi: Bulding JSON API server with grpc-gateway for microservices

Masayuki Izumi

April 15, 2018
Tweet

More Decks by Masayuki Izumi

Other Decks in Programming

Transcript

  1. ©2018 Wantedly, Inc. grapi: Building JSON API server with grpc-gateway

    for microservices Go Conference 2018 Spring 13.Apr.2018 - @izumin5210
  2. ©2018 Wantedly, Inc. $ whoami a.k.a. usamimi engineer izumin5210 Engineer

    at Wantedly, Inc. Wantedly People ‣ Web Application Engineer - Profile Data Strategy Group ‣ Interests in developer productivity on microservices Gopher, Rubyist, JavaScripter and Androider
  3. ©2018 Wantedly, Inc. grapi: Building JSON API server with grpc-gateway

    for microservices Go Conference 2018 Spring 13.Apr.2018 - @izumin5210
  4. ©2018 Wantedly, Inc. WHY Go ? Microservices and Go in

    Wantedly ͋ΘͤͯΑΈ͍ͨ Why microservices ? Why Rails and Go ? ‣ %PDLFS͕ૣ͔͘Β1SPEVDUJPOͰ࢖ΘΕ͍ͯͨ  .JDSPTFSWJDFTPO,VCFSOFUFTΛೖΕ΍͍͢ ‣ ΍Γ͍ͨ͜ͱʹ࠷దͳٕज़બఆΛ  ઐ໳৬1ZUIPO $   υϝΠϯ͕ݟ͑ͯΔ(Pʕ◔ϖ◔ʔ  ͦΕҎ֎3BJMT Rails Developer Meetup 2018: Microservices on "Rails"
 https://www.wantedly.com/companies/wantedly/post_articles/113554
  5. ©2018 Wantedly, Inc. WHY Go ? Microservices and Go in

    Wantedly ͋ΘͤͯΑΈ͍ͨ Why microservices ? Why Rails and Go ? ‣ %PDLFS͕ૣ͔͘Β1SPEVDUJPOͰ࢖ΘΕ͍ͯͨ  .JDSPTFSWJDFTPO,VCFSOFUFTΛೖΕ΍͍͢ ‣ ΍Γ͍ͨ͜ͱʹ࠷దͳٕज़બఆΛ  ઐ໳৬1ZUIPO $   υϝΠϯ͕ݟ͑ͯΔ(Pʕ◔ϖ◔ʔ  ͦΕҎ֎3BJMT Rails Developer Meetup 2018: Microservices on "Rails"
 https://www.wantedly.com/companies/wantedly/post_articles/113554
  6. ©2018 Wantedly, Inc. WHY Go ? Microservices and Go in

    Wantedly Microservices and Go Wantedly People ❤ Go ‣ ܰྔɾϋΠύϑΥʔϚϯε  ,VCFSOFUFTͱͷ૬ੑ˕ ‣ αʔϏεؒ௨৴ͳͲͰ*0͕૿͕͑ͪ  go͚ͬͯͭΔ͚ͩͰඇಉظʹͳͬͯศར  sync errgroup chanͳͲ΋ศར Rails Developer Meetup 2018: Microservices on "Rails"
 https://www.wantedly.com/companies/wantedly/post_articles/113554
  7. ©2018 Wantedly, Inc. WHY Go ? Microservices and Go in

    Wantedly Microservices and Go Wantedly People ❤ Go ‣ ܰྔɾϋΠύϑΥʔϚϯε  ,VCFSOFUFTͱͷ૬ੑ˕ ‣ αʔϏεؒ௨৴ͳͲͰ*0͕૿͕͑ͪ  go͚ͬͯͭΔ͚ͩͰඇಉظʹͳͬͯศར  sync errgroup chanͳͲ΋ศར Rails Developer Meetup 2018: Microservices on "Rails"
 https://www.wantedly.com/companies/wantedly/post_articles/113554
  8. ©2018 Wantedly, Inc. Web API with Go How do you

    build Web API with Go ? ‣ Stdlib net/http ‣ Lightweight / High-performance package - e.g. gin, echo, ... ‣ (Full-stack) web-app framework - e.g. Revel, beego, ... The Go gopher was designed by Renée French.
  9. ©2018 Wantedly, Inc. Go in Wantedly We uses github.com/gin-gonic/gin ‣

    ॳظ͔ΒHJOΛར༻͖ͯͨ͠  ʢৄࡉ͸஌Βͳ͍ʣ  ൺֱత͸΍͔͘Βcontext.Contextϕʔεͩͬͨʁ  ػೳɾੑೳͷόϥϯεʁ  ͔ΜͨΜͳWBMJEBUJPOͱ͔΋͍ͭͯΔ  ύϑΥʔϚϯε΋ѱ͘ͳ͍  ඇৗʹ੎͍͕͋ͬͨʢվળ΋௒ૣ͍ʣ Rails Developer Meetup 2018: Microservices on "Rails"
 https://www.wantedly.com/companies/wantedly/post_articles/113554 gin gin gin gin gin ? Web API with Go in Wantedly
  10. ©2018 Wantedly, Inc. // Boilerplate code for JSON API server

    in net/http // ちょっとした誇張表現がはいっているかも func CreateBook(w http.ResponseWriter, r *http.Request) { data, err := ioutil.ReadAll(r) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } req := &CreateBookRequest{} if err = json.Unmarshal(data, book); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } // ここが本当に実現したいロジック w.WriteHeader(http.StatusCreated) if err := json.NewEncoder(w).Encode(book); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } } (PͷͭΒ͞ Boilerplate in net/http FH$36%ͷ$ʢ$SFBUFʣͷ࣮૷XJUInet/http  IUUQ3FRVFTU͔ΒCPEZಡΈग़͠  ΤϥʔϋϯυϦϯά  CPEZΛTUSVDUʹVONBSTIBM  ΤϥʔϋϯυϦϯά  ຊ౰ʹ࣮ݱ͍ͨ͠ϩδοΫΛॻ͘  ΤϥʔϋϯυϦϯά  +40/ʹNBSTIBMͯ͠SFTQPOTFʹॻ͘  ΤϥʔϋϯυϦϯά
  11. ©2018 Wantedly, Inc. (PͷͭΒ͞ Boilerplate in gin FH$36%ͷ$ʢ$SFBUFʣͷ࣮૷XJUIgin  SFRVFTUCPEZΛTUSVDUʹVONBSTIBM

     ΤϥʔϋϯυϦϯά  ຊ౰ʹ࣮ݱ͍ͨ͠ϩδοΫΛॻ͘  ΤϥʔϋϯυϦϯά  Ϩεϙϯεͭ͘Δ // Boilerplate code for JSON API server in gin-gonic/gin func CreateBook(c *gin.Context) { req := &CreateBookRequest{} if err := c.BindJSON(req) { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } // ここが本当に実現したいロジック c.JSON(200, book) }
  12. ©2018 Wantedly, Inc. // GET /@:user_id/books?page=2&per=10 func ListBooks(c *gin.Context) {

    userID, err := strconv.Atoi(c.Param("user_id")) // TOOD: Should handle errors page, err := strconv.Atoi(c.Query("page")) // TOOD: Should handle errors per, err := strconv.Atoi(c.Query("per")) // TOOD: Should handle errors // ... c.JSON(200, books) } (PͷͭΒ͞ query/path params "MMRVFSZQBUIQBSBNTBSFTUSJOH ‣ 63-༝དྷͷύϥϝλ͸͢΂ͯstringʹͳΔ  ݩσʔλ͕จࣈྻͳͷͰ
 ౰ͨΓલͬͪΌ౰ͨΓલ͕ͩʜ ‣ ύϥϝλͻͱͭͻͱͭܕม׵ʁ  ৬ਓͷखʹΑΔ͔͋ͨͨΈͷ͋Δ
  13. ©2018 Wantedly, Inc. (PͷͭΒ͞ type BookService interface { ListBooks(context.Context, *ListBooksRequest)

    ([]*Book, error) CreateBook(context.Context, *CreateBookRequest) (*Book, error) // ... } ࣮૷͍ͨ͠ͷ͸͜Ε͚ͩͷ͸ͣ
  14. ©2018 Wantedly, Inc. gRPC WHAT is gRPC? gRPC? (PPHMF࡞ͬͨ31$GSBNFXPSL͕044ʹͳͬͨ΋ͷ ҎԼHSQDJPΑΓҾ༻

     4JNQMFTFSWJDFEFpOJUJPO  8PSLTBDSPTTMBOHVBHFTBOEQMBUGPSNT  4UBSURVJDLMZBOETDBMF  #JEJSFDUJPOBMTUSFBNJOHBOEJOUFHSBUFEBVUI
  15. ©2018 Wantedly, Inc. gRPC WHAT is gRPC? gRPC? (PPHMF࡞ͬͨ31$GSBNFXPSL͕044ʹͳͬͨ΋ͷ ҎԼHSQDJPΑΓҾ༻

     4JNQMFTFSWJDFEFpOJUJPO  8PSLTBDSPTTMBOHVBHFTBOEQMBUGPSNT  4UBSURVJDLMZBOETDBMF  #JEJSFDUJPOBMTUSFBNJOHBOEJOUFHSBUFEBVUI
  16. ©2018 Wantedly, Inc. gRPC "Simple service definition" service BookService {

    rpc CreateBook (CreateBookRequest) returns (Book) {} } message Book { string book_id = 1; } message CreateBookRequest { Book book = 1; } ͜Ε͕
  17. ©2018 Wantedly, Inc. gRPC "Simple service definition" ͜͏ͳΔ type BookServiceServer

    interface { CreateBook(context.Context, *CreateBookRequest) (*Book, error) } type Book struct { BookId string `protobuf:"..." json:"book_id,omitempty"` } type CreateBookRequest struct { Book *Book `protobuf:"..." json:"book,omitempty"` }
  18. ©2018 Wantedly, Inc. gRPC "Simple service definition" ͜Ε͚࣮ͩ૷͢Ε͹0, type BookServiceServer

    interface { CreateBook(context.Context, *CreateBookRequest) (*Book, error) } type Book struct { BookId string `protobuf:"..." json:"book_id,omitempty"` } type CreateBookRequest struct { Book *Book `protobuf:"..." json:"book,omitempty"` }
  19. ©2018 Wantedly, Inc. gRPC "Simple service definition" ϦΫΤετ಺༰΋ͪΌΜͱߏ଄ମʹϚοϐϯάͯ͘͠ΕΔ type BookServiceServer

    interface { CreateBook(context.Context, *CreateBookRequest) (*Book, error) } type Book struct { BookId string `protobuf:"..." json:"book_id,omitempty"` } type CreateBookRequest struct { Book *Book `protobuf:"..." json:"book,omitempty"` }
  20. ©2018 Wantedly, Inc. service BookService { rpc CreateBook (CreateBookRequest) returns

    (Book) {} } message Book { string book_id = 1; } message CreateBookRequest { Book book = 1; } gRPC WHY gRPC? Code generation To use protobuf as IDL (Interface Definition Language) ‣ protoc protoc-gen-go  1SPUPDPM#VGGFSTͷεΩʔϚ͔Β
 αʔόɾΫϥΠΞϯτͷ*'ͱ࣮૷Λੜ੒ ‣ ੜ੒͞ΕΔαʔόͷ*'ͷ࣮૷Λొ࿥  grpc.Server͕ϦΫΤετΛTUSVDUʹόΠϯυ  ొ࿥࣮ͨ͠૷Λݺͼग़ͯ͘͠ΕΔ type BookServiceServer interface { CreateBook(context.Context, *CreateBookRequest) (*Book, error) } type Book struct { BookId string `protobuf:"..." json:"book_id,omitempty"` } type CreateBookRequest struct { Book *Book `protobuf:"..." json:"book,omitempty"` }
  21. ©2018 Wantedly, Inc. service BookService { rpc CreateBook (CreateBookRequest) returns

    (Book) {} } message Book { string book_id = 1; } message CreateBookRequest { Book book = 1; } gRPC WHY gRPC? Code generation with protoc ‣ QSPUPD QSPUPDHFOHP  1SPUPDPM#VGGFSTͷεΩʔϚ͔Β
 αʔόɾΫϥΠΞϯτͷ*'ͱ࣮૷Λੜ੒ ‣ ੜ੒͞ΕΔαʔόͷ*'ͷ࣮૷Λొ࿥  grpc.Server͕ϦΫΤετΛTUSVDUʹόΠϯυ  ొ࿥࣮ͨ͠૷Λݺͼग़ͯ͘͠ΕΔ type BookServiceServer interface { CreateBook(context.Context, *CreateBookRequest) (*Book, error) } type Book struct { BookId string `protobuf:"..." json:"book_id,omitempty"` } type CreateBookRequest struct { Book *Book `protobuf:"..." json:"book,omitempty"` } ࣗ෼͕ͨͪॻ͘ͷ͸αʔόͷ࣮૷ ຊ౰ʹඞཁͳϩδοΫͷΈʹूதͰ͖Δʂ
  22. ©2018 Wantedly, Inc. Why NOT gRPC? gRPC ͷϜζΧγ͞  H31$͸)551ͷίωΫγϣϯΛுΓͬͺͳ͠ʹ͢Δ

     Πϯϑϥ·ΘΓͷϜζΧγ͞(SBDFGVMͳ%FQMPZ -PBE#BMBODJOH FUD  1SPUPCVGόΠφϦΛ΍ΓͱΓ͢Δ  DVSM΋࢖͑ͳ͍ʜ  ΫϥΠΞϯτ΋͍··Ͱͱશ͘ҟͳΔٕज़Λ࢖͏͜ͱʹ ߟ͑Δ͜ͱ͕ଟ͍ʂ ΍Δ͚ͩͰ͸͋Δ͚ͲɼՔಇதͷαʔϏεʹυΧοͱ͍ΕΔͷ͸େม gRPC WHY gRPC?
  23. ©2018 Wantedly, Inc. Why NOT gRPC? gRPC ͷϜζΧγ͞  H31$͸)551ͷίωΫγϣϯΛுΓͬͺͳ͠ʹ͢Δ

     Πϯϑϥ·ΘΓͷϜζΧγ͞(SBDFGVMͳ%FQMPZ -PBE #BMBODJOH FUD  1SPUPCVGόΠφϦΛ΍ΓͱΓ͢Δ  DVSM΋࢖͑ͳ͍ʜ  ΫϥΠΞϯτ΋͍··Ͱͱશ͘ҟͳΔٕज़Λ࢖͏͜ͱʹ ߟ͑Δ͜ͱ͕ଟ͍ʂ ΍Δ͚ͩͰ͸͋Δ͚ͲɼՔಇதͷαʔϏεʹυΧοͱ͍ΕΔͷ͸େม ύϑΥʔϚϯε໘͸Ұ୴ஔ͍͓͍ͯͯɼ*%-ͱDPEFHFOFSBUJPOʹΑΔੜ࢈ੑ޲্Λૂ͍͍ͨ Ώ͘Ώ͘͸H31$Λ࢖͍͖͍ͬͯͨ෍ڭɾݕূͷͨΊɼͱΓ͋͑ͣϛχϚϜʹಋೖ͍ͨ͠ gRPC WHY gRPC?
  24. ©2018 Wantedly, Inc. grpc-gateway WHAT is grpc-gateway? WHAT is grpc-gateway?

    ‣ H31$αʔόͷલஈʹཱͭSFWFSTFQSPYZ ‣ )551 +40/H31$ʹม׵͢Δ ‣ ࠾༻ࣄྫ  FUDEʢ,VCFSOFUFTͷόοΫΤϯυʹ͍Δ෼ࢄ,74ʣ  8BOUFEMZ1FPQMFͰ΋ڈ೥ळ͘Β͍͔Βͬͦ͜Γ࢖͍ͬͯΔ  Ϣʔβ͝ͱͷઃఆ஋Λ൚༻తͳײ͡Ͱ֨ೲ͢Δαʔό  ݁ߏΆ͜Ά͜ୟ͔ΕΔ͚ͲɼݩؾʹϨεϙϯεΛฦ͍ͯ͠Δ
  25. ©2018 Wantedly, Inc. grpc-gateway WHAT is grpc-gateway? "1*Λୟ͘ਓ͔Β͸ )551 +40/Λ஻͍ͬͯΔΑ͏ʹΈ͑Δ

    ैདྷ௨Γͷ؀ڥͰ"1*Λར༻Ͱ͖Δ https://github.com/grpc-ecosystem/grpc-gateway
  26. ©2018 Wantedly, Inc. grpc-gateway WHY grpc-gateway? WHY grpc-gateway? ͳͥHSQDHBUFXBZΛ࢖͍͍͔ͨ ‣

    ؀ڥɾJOUFSGBDF͸ͦͷ··ʹ
 H31$ͷ*%-ͱDPEFHFOSBUJPOΛར༻Ͱ͖Δʂ ‣ ʮͲ͜ʹʯʮԿΛ౤͛Ε͹ʯʮԿ͕ฦͬͯ͘Δ͔ʯ
 *%-ΛಡΊ͹ͻͱ໨Ͱ෼͔Δ  ͍ΘΏΔʮυΩϡϝϯτʯ͕ಘΒΕΔ service BookService { rpc CreateBook (CreateBookRequest) returns (Book) { option (google.api.http) = { post: "/books" body: "book" }; } } H31$)551ͷϚοϐϯά΋୯७໌շ
  27. ©2018 Wantedly, Inc. grpc-gateway WHY grpc-gateway? WHY grpc-gateway? ͳͥHSQDHBUFXBZΛ࢖͍͍͔ͨ 

    ͍ΘΏΔʮυΩϡϝϯτʯ͕ಘΒΕΔ *OUFSGBDF%SJWFO%FWFMPQNFOU͕࣮ݱͰ͖Δ ʢ4XBHHFS΍+40/4DIFNB͕໨ࢦͨ͠ੈքʣ service BookService { rpc CreateBook (CreateBookRequest) returns (Book) { option (google.api.http) = { post: "/books" body: "book" }; } } H31$)551ͷϚοϐϯά΋୯७໌շ
  28. ©2018 Wantedly, Inc. grpc-gateway ͭΒ͍ͱ͜Ζ ͭΒ͍ͱ͜Ζᶃ QSPUPDͷίϚϯυ͕௒Ή͔͍ͣ͠ # gRPC サーバ

    & クライアント生成 protoc \ -I ./vendor/github.com/grpc-ecosystem-grpc-gateway \ -I ./vendor/github.com/grpc-ecosystem-grpc-gateway/thrid_party/googleapis \ --go_out=plugins=grpc:. api/protos/book.proto # grpc-gateway の reverse proxy 生成 protoc \ -I ./vendor/github.com/grpc-ecosystem-grpc-gateway \ -I ./vendor/github.com/grpc-ecosystem-grpc-gateway/thrid_party/googleapis \ --grpc-gateway_out=logtostderr=true:grpc:. api/protos/book.proto
  29. ©2018 Wantedly, Inc. grpc-gateway ͭΒ͍ͱ͜Ζ ͭΒ͍ͱ͜Ζᶄ ʮαʔόΛىಈ͢Δ·Ͱʯ͕௕͍ ‣ αʔόΛͭಈ͔͢ͷͰ౰ͨΓલͰ͸͋Δ͕ʜ 

    ճͷnet.Listen  ͭαʔόͷηοτΞοϓɾىಈ  ͭͷαʔόͷTIVUEPXOॲཧʜ ‣ ࠓճͷείʔϓ͸͋͘·Ͱʮੜ࢈ੑΛ্͛Δʯ͜ͱ  ֤ΤϯυϙΠϯτ࣮૷ͷੜ࢈ੑ͸্͕ͬͯ΋ɼ࠷ॳ͕ͩΔ͍ͱαʔϏε࡞Δ͜ͱࣗମ͕ԯ߷ʹͳΔʜ
  30. ©2018 Wantedly, Inc.  8SJUJOH+40/"1*JO(P  ຊ࣭͡Όͳ͍ίʔυΛͨ͘͞Μॻ͔ͳ͍ͱ͍͚ͳ͍  H31$*%- $PEFHFOFSBUJPO

    )JHIQFSGPSNBODF  ҰํͰɼ͍ΖΜͳલ४උ͕ඞཁʹͳΔ  ੜ࢈ੑΛ্͛Δ͜ͱΛ༏ઌ͍ͨ͠*%-ͱDPEFHFOFSBUJPO͚ͩ࢖͏  HSQDHBUFXBZNBQTH31$UP)551 +40/  H31$Λ͍ͭ΋ͷ؀ڥͰར༻Մೳ  ͔͠͠ɼϓϩδΣΫτͷελʔτμογϡ͕ಷ͘ͳͬͯ͠·͏ʜ grapi ͜͜·Ͱͷ໰୊੔ཧ
  31. ©2018 Wantedly, Inc.  8SJUJOH+40/"1*JO(P  ຊ࣭͡Όͳ͍ίʔυΛͨ͘͞Μॻ͔ͳ͍ͱ͍͚ͳ͍  H31$*%- $PEFHFOFSBUJPO

    )JHIQFSGPSNBODF  ҰํͰɼ͍ΖΜͳલ४උ͕ඞཁʹͳΔ  ੜ࢈ੑΛ্͛Δ͜ͱΛ༏ઌ͍ͨ͠*%-ͱDPEFHFOFSBUJPO͚ͩ࢖͏  HSQDHBUFXBZNBQTH31$UP)551 +40/  H31$Λ͍ͭ΋ͷ؀ڥͰར༻Մೳ  ͔͠͠ɼϓϩδΣΫτͷελʔτμογϡ͕ಷ͘ͳͬͯ͠·͏ʜ grapi ͜͜·Ͱͷ໰୊੔ཧ
  32. ©2018 Wantedly, Inc. grapi WHAT is grapi? grapi ಡΈํ͸ʮ͙ΒͬͽʯΒ͍͠ ‣

    IUUQTHJUIVCDPNJ[VNJOHSBQJ ‣ ʮߟ͑Δ͜ͱΛݮΒ͢ʯ͜ͱͰ
 ੜ࢈ੑΛ͋͛ΔͨΊͷ$-*QBDLBHF  (FOFSBUFTQSPKFDUTLFMFUPO  (FOFSBUFTTFSWJDFTLFMFUPOT  8SBQTQSPUPD
  33. ©2018 Wantedly, Inc. grapi WHAT is grapi? grapi init SBJMTOFXతͳ

    ‣ ϓϩδΣΫτͷεέϧτϯੜ੒ ‣ ׬ྃޙʹʮHSBQJTFSWFSʯΛ࣮ߦ͢Ε͹
 αʔό͕ىಈ͢Δঢ়ଶʹͳΔ [~/src/github.com/izumin5210-sandbox/sampleapp] :) % grapi init . ➜ Initialize project ✔ .gitignore ✔ Gopkg.toml ✔ grapi.toml ✔ api/protos/.keep ✔ app/run.go ✔ app/server/.keep ✔ cmd/server/run.go ▸ Install dependencies Root project is "github.com/izumin5210-sandbox/sampleapp" 2 transitively valid internal packages 4 external packages imported from 3 projects (0) ✓ select (root) (1) ? attempt github.com/golang/protobuf with 1 pkgs; 3 (1) try github.com/golang/[email protected]
  34. ©2018 Wantedly, Inc. grapi WHAT is grapi? grapi g service

    SBJMTHDPOUSPMMFSతͳ ‣ H31$TFSWJDFͷεέϧτϯੜ੒  1SPUPCVGͱ(Pͷαʔό࣮૷ͷ࿮͕Ͱ͖Δ  QSPUPDͷ࣮ߦ΋΍ͬͯ͘ΕΔʢޙड़ʣ ‣ ͋ͱ͸࿮ΛຒΊΔ͚ͩΈ͍ͨͳঢ়ଶ ‣ grapi g scaffold-serviceʹ͢Δͱ
 "1*ઃܭΨΠυͷඪ४ϝιου͕
 શͯἧͬͨঢ়ଶʹͳΔʢޙड़ʣ [~/src/github.com/izumin5210-sandbox/sampleapp] :) % grapi g scaffold-service book ➜ Scaffold service ✔ api/protos/book.proto ✔ app/server/book_server.go ✔ app/server/book_server_register_funcs.go ✔ app/server/book_server_test.go ➜ Execute protoc ▸ Install plugins ✔ protoc-gen-go ✔ protoc-gen-grpc-gateway ✔ protoc-gen-swagger ▸ Execute protoc ✔ api/protos/book.proto
  35. ©2018 Wantedly, Inc. grapi WHAT is grapi? API Design Guide

    ͍͍"1*࡞ΔͨΊͷΨΠυϥΠϯCZ(PPHMF ‣ ͍͍"1*Λ࡞ΔͨΊͷΞϨίϨ͕ॻ͍ͯ͋Δ  H31$ϕʔεH31$ʹ׳Εͯͳ͍ਓ͸ಡΉͱྑ͍ ‣ ඪ४ϝιου  ͍ΘΏΔ$36%࣮ݱʹඞཁͳϝιου܈  /BNJOH 3FRVFTU 3FTQPOTFͷܗࣜͳͲΛఆٛ API ઃܭΨΠυ https://cloud.google.com/apis/design/
  36. ©2018 Wantedly, Inc. grapi WHAT is grapi? grapi protoc ΋͏QSPUPDͷҾ਺͸֮͑ͳͯ͘େৎ෉

    ‣ grapi.tomlΈ͍͍ͯײ͡ʹ  QMVHJOͷϏϧυ  api/protos/**/*.protoAʹରͯ͠protoc࣮ߦ  Ҿ਺΋͍͍ײ͡ʹ૊ΈཱͯΒΕΔ [protoc] protos_dir = "./api/protos" out_dir = "./api" import_dirs = [ "./vendor/github.com/grpc-ecosystem/grpc-gateway", "./vendor/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis", ] [[protoc.plugins]] path = "./vendor/github.com/golang/protobuf/protoc-gen-go" name = "go" args = { plugins = "grpc" } [[protoc.plugins]] path = "./vendor/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gat name = "grpc-gateway" args = { logtostderr = true } [[protoc.plugins]] path = "./vendor/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger" name = "swagger" args = { logtostderr = true }
  37. ©2018 Wantedly, Inc. grapi WHAT is grapi? αʔόͷىಈ αʔό࣮૷ͷొ࿥͸ճͰ͍͍Α ‣

    grapiserver.New()Έ͍͍ͯײ͡ʹઃఆ  ىಈϙʔτͱ͔  *OUFSDFQUPSͱ͔ ‣ ࣮૷ͷొ࿥͸A8JUI4FSWFSTAʹ౉͚ͩ͢  ͦΕ͚ͩͰ͍͍Α͏ʹίʔυ͕ੜ੒͞Ε͍ͯΔ func Run() error { s := grapiserver.New( grapiserver.WithDefaultLogger(), grapiserver.WithServers( server.NewBookServiceServer(), // <= これ ), ) return s.Serve() }
  38. ©2018 Wantedly, Inc. grapi WHAT is grapi? αʔόͷىಈ Ωϛ͚ͩͷ࠷ڧͷΦϓγϣϯΛ࡞Ζ͏ ‣

    ΊͬͪΌ͍Ζ͍Ζ΍ͬͯ͘ΕΔຐ๏ͷΦϓγϣϯ Λఏڙ͢Δύοέʔδ͕ଘࡏʢQSJWBUFʣ  ΞΫηεϩΪϯάͱ͔  ϝτϦΫεͱ͔  ΤϥʔϨϙʔςΟϯάͱ͔ ‣ ͜Ε͸·ͨͷػձʹ͓࿩͠·͢
 ؾʹͳΔਓ͸࿩Λฉ͖ʹདྷ͍ͯͩ͘͞ʣ func Run() error { defer servicex.Close() s := grapiserver.New( servicex.WithDefault(), // <= これ grapiserver.WithServers( server.NewBookServiceServer(), ), ) return s.Serve() }
  39. ©2018 Wantedly, Inc. grapi WHY grapi? Design philosophy of grapi

    HSBQJͷࢥ૝ͱ͔ ‣ ໨ࢦ͢͸rails newͱrails g create-react-app  ֤ΤϯυϙΠϯτͷ࣮૷͚ͩॻ͚͹͍͍ੈք ‣ ʮϑϧελοΫʯʹ͸͠ͳ͍  .JDSPTFSWJDFͰ࢖͏ͨΊʹ࡞ͬͨ  ͳΔ΂͘খ͍͞΋ͷ͕Ͱ͖ΔΑ͏ʹͳ͍ͬͯΕ͹ɼ෗ͬͯ΋ؾܰʹࣺͯΒΕΔ  4NBMMJT#FBVUJGVM
  40. ©2018 Wantedly, Inc. grapi WHY grapi? Design philosophy of grapi

    HSBQJͷࢥ૝ͱ͔ ‣ ҰํͰɼ03.΍)551$MJFOUͷΑ͏ͳࡉ͔͍࿩ʹ͸౿Έࠐ·ͳ͍  .JDSPTFSWJDF޲͚ͳͷͰɼ3%#͡Όͳ͍͓΋͠ΖόοΫΤϯυΛ࣋ͬͯΔέʔε΋͋Δ  03.ʹݶͬͯݴ͑͹ɼσϑΝΫτ͕ͳ͍  3BJMTͷ"DUJWF3FDPSEͷΑ͏ͳҟৗͳੜ࢈ੑ޲্͕ݟࠐΊΔ΋ͷ͕ͳ͍  ʢҰํͰɼQMVHJOػߏ͚ͭͯ֎෇͚ରԠ͸΍ͬͯ΋͍͍͔΋ʣ
  41. ©2018 Wantedly, Inc.  8SJUJOH+40/"1*JO(P  ຊ࣭͡Όͳ͍ίʔυΛͨ͘͞Μॻ͔ͳ͍ͱ͍͚ͳ͍  H31$*%- $PEFHFOFSBUJPO

    )JHIQFSGPSNBODF  ҰํͰɼ͍ΖΜͳલ४උ͕ඞཁʹͳΔ  ੜ࢈ੑΛ্͛Δ͜ͱΛ༏ઌ͍ͨ͠*%-ͱDPEFHFOFSBUJPO͚ͩ࢖͏  HSQDHBUFXBZNBQTH31$UP)551 +40/  H31$Λ͍ͭ΋ͷ؀ڥͰར༻Մೳ  ͔͠͠ɼϓϩδΣΫτͷελʔτμογϡ͕ಷ͘ͳͬͯ͠·͏ʜ Conclusion ղܾ͔ͨͬͨ͠໰୊
  42. ©2018 Wantedly, Inc.  HSBQJ$PEFHFOSBUPSBOEHPQBDLBHFUPSFEVDFCPJMFSQMBUFT  CPJMFQMBUFΛ๾໓QSPUPD·ΘΓͷ൥ࡶ͞ΛӅṭ  ͍͍ײ͡ͷίʔυδΣωϨʔλ 

    ߟ͑Δ͜ͱΛݮΒͤΔͷͰɼຊ࣭తͳ࣮૷ʹूதͰ͖Δ ં֯ͷϚΠΫϩαʔϏεΞʔΩςΫνϟͳͷͰɼ ಛੑΛཧղ͠ద੾ͳٕज़બఆΛ৺͕͚ͯ)BQQZ)BDLJOH͠Α͏ Conclusion ՝୊ղܾ & ·ͱΊ