Slide 1

Slide 1 text

©2018 Wantedly, Inc. grapi: Building JSON API server with grpc-gateway for microservices Go Conference 2018 Spring 13.Apr.2018 - @izumin5210

Slide 2

Slide 2 text

©2018 Wantedly, Inc. "HFOEB .JDSPTFSWJDFTͱ(P 8FC"1*XJUI(Pߟ͑ͳ͍ͱ͍͚ͳ͍໰୊ H31$8):8)"5 HSQDHBUFXBZ8):8)"5 HSBQJNJDSPTFSWJDFTΛޮ཰Α͘࡞͍ͬͯͨ͘Ίʹ

Slide 3

Slide 3 text

©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

Slide 4

Slide 4 text

©2018 Wantedly, Inc. grapi: Building JSON API server with grpc-gateway for microservices Go Conference 2018 Spring 13.Apr.2018 - @izumin5210

Slide 5

Slide 5 text

©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

Slide 6

Slide 6 text

©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

Slide 7

Slide 7 text

©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

Slide 8

Slide 8 text

©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

Slide 9

Slide 9 text

©2018 Wantedly, Inc. Web API with Go How do you build Web API with Go?

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

©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

Slide 12

Slide 12 text

©2018 Wantedly, Inc. ೰·͍͠໰୊ ຊ౰ʹͭΒ͍

Slide 13

Slide 13 text

©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ʹॻ͘ ΤϥʔϋϯυϦϯά

Slide 14

Slide 14 text

©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) }

Slide 15

Slide 15 text

©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ʹͳΔ ݩσʔλ͕จࣈྻͳͷͰ
 ౰ͨΓલͬͪΌ౰ͨΓલ͕ͩʜ ‣ ύϥϝλͻͱͭͻͱͭܕม׵ʁ ৬ਓͷखʹΑΔ͔͋ͨͨΈͷ͋Δ

Slide 16

Slide 16 text

©2018 Wantedly, Inc. (PͷͭΒ͞ type BookService interface { ListBooks(context.Context, *ListBooksRequest) ([]*Book, error) CreateBook(context.Context, *CreateBookRequest) (*Book, error) // ... } ࣮૷͍ͨ͠ͷ͸͜Ε͚ͩͷ͸ͣ

Slide 17

Slide 17 text

©2018 Wantedly, Inc. ͦ͏ͩɺH31$Λ࢖͓͏

Slide 18

Slide 18 text

©2018 Wantedly, Inc. gRPC: WHY & WHAT H31$ͬͯͲ͕͜خ͍͠ͷʁ

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

©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; } ͜Ε͕

Slide 22

Slide 22 text

©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"` }

Slide 23

Slide 23 text

©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"` }

Slide 24

Slide 24 text

©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"` }

Slide 25

Slide 25 text

©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) ‣ protocprotoc-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"` }

Slide 26

Slide 26 text

©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 ‣ QSPUPDQSPUPDHFOHP 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"` } ࣗ෼͕ͨͪॻ͘ͷ͸αʔόͷ࣮૷ ຊ౰ʹඞཁͳϩδοΫͷΈʹूதͰ͖Δʂ

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

©2018 Wantedly, Inc. grpc-gateway: WHY & WHAT HSQDHBUFXBZͷૉ੖Β͠͞ʹ͍ͭͯޠΔ࣌ؒ

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

©2018 Wantedly, Inc. grpc-gateway WHAT is grpc-gateway? https://github.com/grpc-ecosystem/grpc-gateway

Slide 32

Slide 32 text

©2018 Wantedly, Inc. grpc-gateway WHAT is grpc-gateway? H31$αʔόͷલஈʹཱͭ 3FWFSTF1SPYZHSQDHBUFXBZ https://github.com/grpc-ecosystem/grpc-gateway

Slide 33

Slide 33 text

©2018 Wantedly, Inc. grpc-gateway WHAT is grpc-gateway? "1*Λୟ͘ਓ͔Β͸ )551+40/Λ஻͍ͬͯΔΑ͏ʹΈ͑Δ ैདྷ௨Γͷ؀ڥͰ"1*Λར༻Ͱ͖Δ https://github.com/grpc-ecosystem/grpc-gateway

Slide 34

Slide 34 text

©2018 Wantedly, Inc. grpc-gateway WHAT is grpc-gateway? 1SPYZͷ࣮૷ protocprotoc-gen-grpc-gatewayͰੜ੒ https://github.com/grpc-ecosystem/grpc-gateway

Slide 35

Slide 35 text

©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ͷϚοϐϯά΋୯७໌շ

Slide 36

Slide 36 text

©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ͷϚοϐϯά΋୯७໌շ

Slide 37

Slide 37 text

©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

Slide 38

Slide 38 text

©2018 Wantedly, Inc. grpc-gateway ͭΒ͍ͱ͜Ζ ͭΒ͍ͱ͜Ζᶄ ʮαʔόΛىಈ͢Δ·Ͱʯ͕௕͍ ‣ αʔόΛͭಈ͔͢ͷͰ౰ͨΓલͰ͸͋Δ͕ʜ ճͷnet.Listen ͭαʔόͷηοτΞοϓɾىಈ ͭͷαʔόͷTIVUEPXOॲཧʜ ‣ ࠓճͷείʔϓ͸͋͘·Ͱʮੜ࢈ੑΛ্͛Δʯ͜ͱ ֤ΤϯυϙΠϯτ࣮૷ͷੜ࢈ੑ͸্͕ͬͯ΋ɼ࠷ॳ͕ͩΔ͍ͱαʔϏε࡞Δ͜ͱࣗମ͕ԯ߷ʹͳΔʜ

Slide 39

Slide 39 text

©2018 Wantedly, Inc. grapi: Building JSON API with gRPC ϚΠΫϩαʔϏεΛޮ཰Α࣮͘૷͢ΔͨΊͷઓུ

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

©2018 Wantedly, Inc. HSQDHBUFXBZελʔτμογϡ͕஗͘ͳΔ H31$ੜ࢈ੑΛ্͍͛ͨ ͜ͷΪϟοϓΛຒΊΔԿ͔͕ඞཁ

Slide 43

Slide 43 text

©2018 Wantedly, Inc. ཁ͢Δʹʮ࠷ॳʹॻ͘ίʔυྔ͕ଟ͍ෳࡶʯͳͷ͕໰୊ HSQDHBUFXBZελʔτμογϡ͕஗͘ͳΔ

Slide 44

Slide 44 text

©2018 Wantedly, Inc. ཁ͢Δʹʮ࠷ॳʹॻ͘ίʔυྔ͕ଟ͍ෳࡶʯͳͷ͕໰୊ HSQDHBUFXBZελʔτμογϡ͕஗͘ͳΔ ͦ΋ͦ΋ਓྨ͕ॻ͘ඞཁ͸ͳ͍ͷͰ͸ʁʂ

Slide 45

Slide 45 text

©2018 Wantedly, Inc. grapi WHAT is grapi? grapi ಡΈํ͸ʮ͙ΒͬͽʯΒ͍͠ ‣ IUUQTHJUIVCDPNJ[VNJOHSBQJ ‣ ʮߟ͑Δ͜ͱΛݮΒ͢ʯ͜ͱͰ
 ੜ࢈ੑΛ͋͛ΔͨΊͷ$-*QBDLBHF (FOFSBUFTQSPKFDUTLFMFUPO (FOFSBUFTTFSWJDFTLFMFUPOT 8SBQTQSPUPD

Slide 46

Slide 46 text

©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/protobuf@v1.0.0

Slide 47

Slide 47 text

©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

Slide 48

Slide 48 text

©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/

Slide 49

Slide 49 text

©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 }

Slide 50

Slide 50 text

©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() }

Slide 51

Slide 51 text

©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() }

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

©2018 Wantedly, Inc. grapi WHY grapi? Design philosophy of grapi HSBQJͷࢥ૝ͱ͔ ‣ ҰํͰɼ03.΍)551$MJFOUͷΑ͏ͳࡉ͔͍࿩ʹ͸౿Έࠐ·ͳ͍ .JDSPTFSWJDF޲͚ͳͷͰɼ3%#͡Όͳ͍͓΋͠ΖόοΫΤϯυΛ࣋ͬͯΔέʔε΋͋Δ 03.ʹݶͬͯݴ͑͹ɼσϑΝΫτ͕ͳ͍ 3BJMTͷ"DUJWF3FDPSEͷΑ͏ͳҟৗͳੜ࢈ੑ޲্͕ݟࠐΊΔ΋ͷ͕ͳ͍ ʢҰํͰɼQMVHJOػߏ͚ͭͯ֎෇͚ରԠ͸΍ͬͯ΋͍͍͔΋ʣ

Slide 54

Slide 54 text

©2018 Wantedly, Inc. Next actions & Conclusion ͭ͗΍Δ͜ͱ·ͱΊ

Slide 55

Slide 55 text

©2018 Wantedly, Inc. αʔϏεؒ௨৴Λগͣͭ͠H31$ʹ w ͍·͸HSQDHBUFXBZט·͍ͤͯΔ͚Ͳɼͳ͍ʹӽͨ͜͠ͱ͸ͳ͍ w *TUJP͕ೖΔͷͰΠϯϑϥपΓ͸໰୊ͳ͍ʁ Next actions ΍͍ͬͯͧ͘

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

©2018 Wantedly, Inc. HSBQJ$PEFHFOSBUPSBOEHPQBDLBHFUPSFEVDFCPJMFSQMBUFT CPJMFQMBUFΛ๾໓QSPUPD·ΘΓͷ൥ࡶ͞ΛӅṭ ͍͍ײ͡ͷίʔυδΣωϨʔλ ߟ͑Δ͜ͱΛݮΒͤΔͷͰɼຊ࣭తͳ࣮૷ʹूதͰ͖Δ ં֯ͷϚΠΫϩαʔϏεΞʔΩςΫνϟͳͷͰɼ ಛੑΛཧղ͠ద੾ͳٕज़બఆΛ৺͕͚ͯ)BQQZ)BDLJOH͠Α͏ Conclusion ՝୊ղܾ & ·ͱΊ