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

iosdc_2018.pdf

4d40d82cc3c676e8a67ffc2a473bf423?s=47 Kyohei Ito
August 31, 2018
1.7k

 iosdc_2018.pdf

4d40d82cc3c676e8a67ffc2a473bf423?s=128

Kyohei Ito

August 31, 2018
Tweet

Transcript

  1. grpc-swiftΛ࢖ͬͯ iOSΞϓϦͰ΋շదͳ gRPC௨৴Λߦ͏ɹɹ 2018/08/31 iOSDC

  2. About Me ҏ౻ɹګฏ Github : KyoheiG3 Twitter : @KyoheiG3

  3. About Me ΩϡϨʔγϣϯ Ameba OWND AbemaTV SUPERCHOICE ࠓ·ͨ৽ن

  4. gPRC

  5. gRPCͬͯԿʁ • Google͕࡞ͬͨRPCΛ࣮ݱ͢ΔͨΊͷϑϨʔϜϫʔΫ • ࣾ಺޲͚ͷStubbyΛɺ2015೥ʹΦʔϓϯԽͨ͠΋ͷ • HTTP2

  6. RPCͬͯԿʁ • ϦϞʔτϓϩγʔδϟίʔϧͷུ • ϓϩάϥϜ͔ΒผͷΞυϨεۭؒʹ͋Δαϒϧʔνϯ΍खଓ ͖Λ࣮ߦ͢Δ͜ͱΛՄೳʹ͢Δٕज़

  7. HTTP2 • SPDYΛج൫ʹ࡞Γग़͞Εͨ • SPDY΋Google੡

  8. Մೳͳ௨৴ํࣜ

  9. Unaryʢ୯ൃͷ௨৴ʣ • 1ͭͷϦΫΤετʹର͠ɺϨεϙϯεΛ1ͭฦ͢ • HTTP1ܥͱಉ͡Α͏ͳεςʔτϨεͳ௨৴ํࣜ

  10. Server StreamingʢαʔόετϦʔϛϯάʣ • 1ͭͷϦΫΤετʹର͠ɺϨεϙϯεΛෳ਺ฦ͢ • αʔόpush ϙʔϦϯάʹஔ͖׵ΘΔ

  11. Client StreamingʢΫϥΠΞϯτετϦʔϛϯάʣ • ෳ਺ͷϦΫΤετʹର͠ɺϨεϙϯεΛ1ͭฦ͢ • ϑΝΠϧΞοϓϩʔυͳͲ

  12. Bi-Directional Streamingʢ૒ํ޲ετϦʔϛϯάʣ • ෳ਺ͷϦΫΤετʹର͠ɺϨεϙϯεΛෳ਺ฦ͢ • νϟοτͳͲ

  13. Αࣖ͘ʹ͢ΔProtocol Buffersͱͷҧ͍ͬͯʁ • Protocol Buffers͸௨৴͢Δσʔλͷܗࣜʢjson, xml...ʣ • gRPC͸௨৴ͷखஈ

  14. ͢͜͠Protocol Buffersͷ͓͞Β͍

  15. protobuf • protobufͱུ͞ΕΔ͜ͱ͕ଟ͍ • όΠφϦϕʔε • .protoϑΝΠϧͰσʔλܗࣜΛఆٛ

  16. echo.proto syntax = "proto3"; package echo; message EchoRequest { string

    text = 1; } message EchoResponse { string text = 1; }
  17. protobuf • .protoϑΝΠϧ͔Βɺswift΍goϑΝΠϧΛ࡞੒Մೳ

  18. protobuf $ protoc echo.proto --plugin=./protoc-gen-swift --swift_out=.

  19. echo.pb.swift struct Echo_EchoRequest { var text: String = String() var

    unknownFields = SwiftProtobuf.UnknownStorage() init() {} } struct Echo_EchoResponse { var text: String = String() var unknownFields = SwiftProtobuf.UnknownStorage() init() {} }
  20. protobuf • swiftͰ΋Apple͕ެࣜʹαϙʔτ1 • όΠφϦͷγϦΞϥΠζɾσγϦΞϥΠζͷ଎౓͸ϥΠϒϥ Ϧʹґଘ • ܰͯ͘ܕ҆શ 1 https://github.com/apple/swift-protobuf

  21. protobuf σϝϦοτ • ௨৴σʔλͷՄಡੑ͕௿͗͢Δʢͱ͍͏͔ಡΊͳ͍ʣ • ಋೖʹҰखؒඞཁ

  22. protobuf ϝϦοτ ׂѪ͠·͢ɻ ϝϦοτ͸ͨ͘͞Μ͋ΔͷͰɺσʔλܗࣜͷબ୒ࢶͷҰͭʹೖ ΕΔͷ͸͋Γͩͱࢥ͍·͢ɻ

  23. gRPC × protobuf • gRPC͕ར༻͢ΔσϑΥϧτͷσʔλܗ͕ࣜprotobuf • gRPC͸͋͘·Ͱ௨৴ͷखஈͳͷͰɺσʔλܗࣜ͸ҰԠjsonͱ ͔΋Մೳ • ͚ͲɺprotobufͱgRPC͸ζϒζϒͳͷͰҰॹʹ࢖͏લఏ

  24. SwiftGRPC

  25. SwiftGRPC • objective-cͰ͸c++Ͱ࣮૷͞ΕͨgrpcΛར༻2 • swiftͰར༻͢Δʹ͸গʑ໘౗ 2 https://github.com/grpc/grpc

  26. SwiftGRPC • grpcͷΠϯλʔϑΣʔεΛswiftͰϥοϓ

  27. Officially Supported Platforms3 C/C++, C#, Dart *, Go, Java, Node.js,

    PHP *, Python, Ruby * ͸·ͩbeta Swift͸ΞϯΦϑΟγϟϧͰ͔͢?! 3 https://grpc.io/about/#osp
  28. ಋೖ

  29. ಋೖ • ͱʹ͔͘protobufલఏ • SwiftGRPCͷprotocϓϥάΠϯΛ࡞੒ • .protoϑΝΠϧ͔Β.swiftϑΝΠϧΛ࡞੒

  30. protobufΛΠϯετʔϧ $ brew install protobuf

  31. SwiftGRPCͷprotocϓϥάΠϯΛ࡞੒ • grpc-swiftΛcloneͯ͠build $ git clone https://github.com/grpc/grpc-swift.git $ cd grpc-swift

    $ make all > .protoc-gen-swift .protoc-gen-swiftgrpc
  32. ඞཁʹԠͯ͡pathΛ௨͢ • ࣮ߦ࣌ʹϓϥάΠϯͷpathΛࢦఆͰ͖ΔͷͰඞਢͰ͸ͳ͍ $ mkdir ~/.protoc $ cp ./protoc-gen-swift ./protoc-gen-swiftgrpc

    ~/.protoc $ echo 'export PATH=$PATH:$HOME/.protoc' >> ~/.bash_profile $ source ~/.bash_profile
  33. protoc-gen-swiftgrpc • SwiftGRPCͷprotocϓϥάΠϯ • protobufͱಉ༷ʹ.proto͔Β.swiftΛ࡞੒

  34. echo.protoʢbeforeʣ syntax = "proto3"; package echo; message EchoRequest { string

    text = 1; } message EchoResponse { string text = 1; }
  35. echo.protoʢserviceʣ • serviceͷதʹɺrpcϑΟʔϧυΛఆٛ͢Δ service Echo { rpc }

  36. echo.protoʢserviceʣ • rpcϑΟʔϧυʹ೚ҙͷϝιουΛఆٛ͢Δ service Echo { rpc Get }

  37. echo.protoʢserviceʣ • ϦΫΤετͷΦϒδΣΫτΛఆٛ͢Δ service Echo { rpc Get(EchoRequest) }

  38. echo.protoʢserviceʣ • ϨεϙϯεͷΦϒδΣΫτΛఆٛ͢Δ service Echo { rpc Get(EchoRequest) returns(EchoResponse) {}

    }
  39. echo.protoʢserviceʣ • stream͸ෳ਺ճͷॲཧΛՄೳʹ͢Δఆٛ service Echo { rpc Get(EchoRequest) returns (EchoResponse)

    {} rpc Expand(EchoRequest) returns (stream EchoResponse) {} rpc Collect(stream EchoRequest) returns (EchoResponse) {} rpc Update(stream EchoRequest) returns (stream EchoResponse) {} }
  40. echo.protoʢafterʣ syntax = "proto3"; package echo; message EchoRequest { string

    text = 1; } message EchoResponse { string text = 1; } service Echo { rpc Get(EchoRequest) returns (EchoResponse) {} rpc Expand(EchoRequest) returns (stream EchoResponse) {} rpc Collect(stream EchoRequest) returns (EchoResponse) {} rpc Update(stream EchoRequest) returns (stream EchoResponse) {} }
  41. protoc-gen-swiftgrpc $ protoc echo.proto --plugin=./protoc-gen-swiftgrpc --swiftgrpc_out=.

  42. echo.grpc.swift protocol Echo_EchoProvider: ServiceProvider { func get(request: Echo_EchoRequest, session: Echo_EchoGetSession)

    throws -> Echo_EchoResponse func expand(request: Echo_EchoRequest, session: Echo_EchoExpandSession) throws -> ServerStatus? func collect(session: Echo_EchoCollectSession) throws -> Echo_EchoResponse? func update(session: Echo_EchoUpdateSession) throws -> ServerStatus? } protocol Echo_EchoService: ServiceClient { func get(_ request: Echo_EchoRequest) throws -> Echo_EchoResponse func get(_ request: Echo_EchoRequest, completion: @escaping (Echo_EchoResponse?, CallResult) -> Void) throws -> Echo_EchoGetCall func expand(_ request: Echo_EchoRequest, completion: ((CallResult) -> Void)?) throws -> Echo_EchoExpandCall func collect(completion: ((CallResult) -> Void)?) throws -> Echo_EchoCollectCall func update(completion: ((CallResult) -> Void)?) throws -> Echo_EchoUpdateCall }
  43. EchoʢαϯϓϧʣͰίʔυղઆ

  44. Echoͷಈ͔͠ํ • SwiftGRPC.xcodeprojΛ࡞੒͢Δ $ make project

  45. Echoͷಈ͔͠ํ • ./third_party/swift-protobuf͕ඞཁ • ࠷ۙऔಘεΫϦϓτ͕࡟আ͞Εͨ4 $ mkdir third_party $ cd

    third_party $ git clone https://github.com/apple/swift-protobuf.git 4 https://github.com/grpc/grpc-swift/pull/296
  46. Echoͷಈ͔͠ํ • ./Examples/EchoXcode/Echo.xcodeprojΛ։͘

  47. Echoͷಈ͔͠ํ • ./SwiftGRPC.xcodeprojΛϓϩδΣΫτʹ௥Ճ͢Δ

  48. Echoͷಈ͔͠ํ • Target DependenciesʹSwiftGRPC.frameworkΛ௥Ճ͢Δ

  49. Echo for Client

  50. Echo_EchoServiceClient • ΫϥΠΞϯτ͔Βαʔό΁ͷ઀ଓΛ؅ཧ • ಺෦ͰChannelΦϒδΣΫτΛอ࣋ • Echo_EchoServiceʹ४ڌ • get, expand,

    collect, updateϝιουΛ࣮ߦͯ͠ɺετ ϦʔϛϯάΛߦ͏ͨΊͷCallΦϒδΣΫτΛ࡞੒
  51. Echo_EchoServiceClient let service = Echo_EchoServiceClient(address: "YOUR_ADDRESS", secure: false)

  52. Echo_EchoExpandCallʢServerStreamingʣ • expand()ϝιουͰऔಘ • αʔόετϦʔϛϯά͕Մೳ • receive()ϝιουΛ࣮ߦՄೳ

  53. Echo_EchoExpandCallʢServerStreamingʣ var requestMessage = Echo_EchoRequest() requestMessage.text = "message" let expandCall

    = try service.expand(requestMessage) { _ in } try expandCall.receive { response in // ϨεϙϯεΛड͚औΔ }
  54. Echo_EchoCollectCallʢClientStreamingʣ • collect()ϝιουͰऔಘ • ΫϥΠΞϯτετϦʔϛϯά͕Մೳ • send(), closeAndReceive()ϝιουΛ࣮ߦՄೳ

  55. Echo_EchoCollectCallʢClientStreamingʣ let collectCall = try service.collect { _ in }

    var requestMessage = Echo_EchoRequest() requestMessage.text = "message" try collectCall.send(requestMessage) { error in // ΤϥʔΛड͚औΔ } try collectCall.closeAndReceive { response in // close࣌ʹ1౓͚ͩσʔλΛड͚औΕΔ }
  56. Echo_EchoUpdateCallʢBidirectionalStreamingʣ • update()ϝιουͰऔಘ • ૒ํ޲ετϦʔϛϯά͕Մೳ • send(), receive(), closeSend()ϝιουΛ࣮ߦՄೳ

  57. Echo_EchoUpdateCallʢBidirectionalStreamingʣ let updateCall = try service.update { _ in }

    try updateCall.receive { response in // ϨεϙϯεΛड͚औΔ } var requestMessage = Echo_EchoRequest() requestMessage.text = "message" try updateCall.send(requestMessage) { error in // ΤϥʔΛड͚औΔ } try updateCall.closeSend {}
  58. ΫϥΠΞϯτ࣮૷ͷجຊతͳྲྀΕ • Service͔ΒCallΦϒδΣΫτΛ࡞੒͢Δ • ࡞੒ͨ͠CallΦϒδΣΫτʹ༻ҙ͞Ε͍ͯΔstreamingͷϝ ιουΛݺͼग़͢ • CallΦϒδΣΫτ͸streaming͕ऴྃ͢Δ·Ͱอ͓࣋ͯ͘͠ ※ Unary͸ྫ֎

  59. Echo_EchoGetCallʢUnaryʣ • get()ϝιουͰऔಘ • streaming༻ͷϝιου͸༻ҙ͞Ε͍ͯͳ͍

  60. Echo_EchoGetCallʢUnaryʣ var requestMessage = Echo_EchoRequest() requestMessage.text = "message" let getCall

    = try service.get(requestMessage) { response, callResult in }
  61. ΫϥΠΞϯτ࣮૷ͷಛ௃ • CallΦϒδΣΫτΛ࡞ͬͨ࣌఺͔ΒtimeoutΧ΢ϯτμ΢ϯ • σϑΥϧτ͸600ඵͰɺϦΫΤετݸผʹ͸ઃఆෆՄ • ClientStreamingͷsend()ʹҾ਺Ͱ౉ͤΔtimeout͸ɺಉظ ௨৴͢Δࡍͷsemaphoreͷ଴ػ࣌ؒ

  62. ΫϥΠΞϯτ࣮૷ͷಛ௃ • receive()͸ɺ1౓Ͱ΋σʔλΛड͚औΔͱͦΕҎ࣮߱ߦ͞ Εͳ͍ͷͰɺ࠶౓receive()ΛݺͿඞཁ͕͋Δ • ͳʹ͔͠ΒͷΤϥʔ͕ग़ͨΒͦΕҎ߱ૹड৴Ͱ͖ͳ͍ͷͰɺ CallΦϒδΣΫτ͔Β࠶౓࡞੒͢Δඞཁ͕͋Δ • throws͕΍ͨΒଟ͍

  63. ΫϥΠΞϯτͷstubʹ͍ͭͯ • ServerΛϩʔΧϧʹ࣮૷ͯ͠stubԽ

  64. Echo for Server

  65. ServiceServer • αʔό΁ͷΫϥΠΞϯτ͔Βͷ઀ଓΛ؅ཧ • ಺෦ͰServerΦϒδΣΫτΛอ࣋ • Echo_EchoProviderʹ४ڌͨ͠ΦϒδΣΫτΛड͚औΔ • startϝιουͰɺ઀ଓͷड৴Λ։࢝

  66. ServiceServer class EchoProvider: Echo_EchoProvider { func get() {} func expand()

    {} func collect() {} func update() {} } let provider = EchoProvider() let server = ServiceServer(address: "YOUR_ADDRESS", serviceProviders: [provider]) server.start()
  67. Echo_EchoProvider • get, expand, collect, updateϝιου಺ͰɺΫϥΠΞϯ τ΁ͷϨεϙϯεΛߦ͏ • Ҿ਺Ͱ౉͞ΕΔSessionΦϒδΣΫτͰৼΔ෣͍Λ࣮૷

  68. Echo_EchoProviderʢget == Unaryʣ • Echo_EchoRequestΦϒδΣΫτΛऔಘ • Echo_EchoResponseΛฦͨ͠Βऴྃ

  69. Echo_EchoProviderʢget == Unaryʣ func get(request: Echo_EchoRequest, session _: Echo_EchoGetSession) throws

    -> Echo_EchoResponse { var response = Echo_EchoResponse() response.text = request.text + " response" return response }
  70. Echo_EchoProviderʢexpand == ServerStreamingʣ • Echo_EchoRequestΦϒδΣΫτΛऔಘ • ඞཁʹԠͯ͡sessionͷsend()Λ࣮ߦ • ServerStatusΛฦ͠ɺ͔ͭsend()͕׬ྃͨ͠Βऴྃ

  71. Echo_EchoProviderʢexpand == ServerStreamingʣ func expand(request: Echo_EchoRequest, session: Echo_EchoExpandSession) throws ->

    ServerStatus? { var response = Echo_EchoResponse() response.text = request.text + " response" try! session.send(response) { // ΤϥʔΛड͚औΔ } return .ok }
  72. Echo_EchoProviderʢcollect == ClientStreamingʣ • ϦΫΤετ͸sessionͷreceive()Ͱऔಘ • Echo_EchoResponseΛฦͨ͠Βऴྃ

  73. Echo_EchoProviderʢcollect == ClientStreamingʣ func collect(session: Echo_EchoCollectSession) throws -> Echo_EchoResponse? {

    var response = Echo_EchoResponse() let request = try! session.receive() response.text = request.text + " response" return response }
  74. Echo_EchoProviderʢupdate == BidiStreamingʣ • ϦΫΤετ͸sessionͷreceive()Ͱऔಘ • ඞཁʹԠͯ͡sessionͷsend()Λ࣮ߦ • ServerStatusΛฦ͠ɺ͔ͭsend()͕׬ྃͨ͠Βऴྃ

  75. Echo_EchoProviderʢupdate == BidiStreamingʣ func update(session: Echo_EchoUpdateSession) throws -> ServerStatus? {

    let request = try! session.receive() var response = Echo_EchoResponse() response.text = request.text + " response" try! session.send(response) { // ΤϥʔΛड͚औΔ } return .ok }
  76. αʔό࣮૷ͷجຊతͳྲྀΕ • Echo_EchoProviderʹ४ڌͨ͠ΦϒδΣΫτΛ࡞੒͢Δ • ProviderͷϝιουͰಉظతʹॲཧ͠ɺ஋Λฦͯ͠ऴྃ

  77. SwiftGRPCClient

  78. None
  79. SwiftGRPCClient > https://github.com/cats-oss/grpc-swift-client • ΫϥΠΞϯτઐ༻ͷgRPCϥΠϒϥϦ • SwiftGRPCʹґଘ • timeoutΛϦΫΤετ୯ҐͰܾΊͨΓ •

    ϦΫΤετͷ్தͰॲཧΛΠϯλʔηϓτͨ͠Γ • receive()ΛࣗಈͰϦτϥΠͯ͘͠ΕͨΓ
  80. protoc-gen-swiftgrpc-client $ protoc echo.proto --plugin=./protoc-gen-swiftgrpc-client --swiftgrpc-client_out=.

  81. protoc-gen-swiftgrpc-client enum Echo_EchoMethod: String, CallMethod { case get = "Get"

    static let service = "echo.Echo" } protocol _Echo_EchoGetRequest { typealias InputType = Echo_EchoRequest typealias OutputType = Echo_EchoResponse } protocol Echo_EchoGetRequest: _Echo_EchoGetRequest, UnaryStreamingRequest {} extension Echo_EchoGetRequest { var method: CallMethod { return Echo_EchoMethod.get } }
  82. SwiftGRPCʢClientStreamingʣ let collectCall = try service.collect { _ in }

    var requestMessage = Echo_EchoRequest() requestMessage.text = "message" try collectCall.send(requestMessage) { error in // ΤϥʔΛड͚औΔ } try collectCall.closeAndReceive { response in // close࣌ʹ1౓͚ͩσʔλΛड͚औΕΔ }
  83. SwiftGRPCClientʢClientStreamingʣ let stream = Session.shared.stream(with: EchoClientRequest()) stream .send("message") { response

    in // ૹ৴݁ՌΛड͚औΔ } stream .closeAndReceive { response in // close࣌ʹ1౓͚ͩσʔλΛड͚औΕΔ }
  84. SwiftGRPCʢServerStreamingʣ var requestMessage = Echo_EchoRequest() requestMessage.text = "message" let expandCall

    = try service.expand(requestMessage) { _ in } try expandCall.receive { response in // ϨεϙϯεΛड͚औΔ }
  85. SwiftGRPCClientʢServerStreamingʣ let stream = Session.shared.stream(with: EchoServerRequest(text: "message")) .receive { response

    in // ϨεϙϯεΛड͚औΔ }
  86. SwiftGPRCClientʢRxʣ extension Reactive where Base: Streaming, Base.Request: UnaryRequest { func

    data() -> Observable<Base.Request.OutputType> { return .create { observer in self.base.data { result in switch result { case .success(let data): observer.onNext(data) observer.onCompleted() case .failure(let error): observer.onError(error) } } return Disposables.create { self.base.cancel() } } } }
  87. SwiftGPRCClientʢRxʣ Session.shared.stream(with: EchoUnaryRequest()).rx.data() .subscribe(onNext: { response in // ϨεϙϯεΛड͚औΔ },

    onError: { error in // ΤϥʔΛड͚औΔ }) .disposed(by: disposeBag)
  88. SwiftGPRCClient • ΫϥΠΞϯτʹSwiftGPRCClientΛར༻ͯ͠ɺstubͱͯ͠ SwiftGRPCͷαʔό࣮૷Λར༻͢Δ

  89. ॴײͱࠓޙ

  90. ॴײ • ࠷ॳ͸callͷcancel͢Βແ͔ͬͨ • ಋೖ͕ਏ͔ͬͨ • Τϥʔ࣌ͷࡉ͔͍ڍಈ͕௫ΈͮΒ͍

  91. Swift Summit

  92. ࠓޙ • ࠷ۙ͸υΠπਓͷΤϯδχΞ͕ฃಆͯ͠ϝϯςφϯε • Network.frameworkͷಋೖͷݕ౼ͳͲ͕͞Ε͍ͯΔ • ͱΓ͋͑ͣਖ਼ࣜʹgrpcҰ଒ʹೖͬͯཉ͍͠

  93. grpc-swiftΛ࢖ͬͯiOSΞϓϦͰ΋շదͳgRPC௨৴Λߦ͏ɹɹ https://github.com/cats-oss/grpc-swift-client Github : KyoheiG3 Twitter : @KyoheiG3

  94. Thanks!