iosdc_2018.pdf
by
Kyohei Ito
Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
grpc-swiftΛͬͯ iOSΞϓϦͰշదͳ gRPC௨৴Λߦ͏ɹɹ 2018/08/31 iOSDC
Slide 2
Slide 2 text
About Me ҏ౻ɹګฏ Github : KyoheiG3 Twitter : @KyoheiG3
Slide 3
Slide 3 text
About Me ΩϡϨʔγϣϯ Ameba OWND AbemaTV SUPERCHOICE ࠓ·ͨ৽ن
Slide 4
Slide 4 text
gPRC
Slide 5
Slide 5 text
gRPCͬͯԿʁ • Google͕࡞ͬͨRPCΛ࣮ݱ͢ΔͨΊͷϑϨʔϜϫʔΫ • ͚ࣾͷStubbyΛɺ2015ʹΦʔϓϯԽͨ͠ͷ • HTTP2
Slide 6
Slide 6 text
RPCͬͯԿʁ • ϦϞʔτϓϩγʔδϟίʔϧͷུ • ϓϩάϥϜ͔ΒผͷΞυϨεۭؒʹ͋Δαϒϧʔνϯखଓ ͖Λ࣮ߦ͢Δ͜ͱΛՄೳʹ͢Δٕज़
Slide 7
Slide 7 text
HTTP2 • SPDYΛج൫ʹ࡞Γग़͞Εͨ • SPDYGoogle
Slide 8
Slide 8 text
Մೳͳ௨৴ํࣜ
Slide 9
Slide 9 text
Unaryʢ୯ൃͷ௨৴ʣ • 1ͭͷϦΫΤετʹର͠ɺϨεϙϯεΛ1ͭฦ͢ • HTTP1ܥͱಉ͡Α͏ͳεςʔτϨεͳ௨৴ํࣜ
Slide 10
Slide 10 text
Server StreamingʢαʔόετϦʔϛϯάʣ • 1ͭͷϦΫΤετʹର͠ɺϨεϙϯεΛෳฦ͢ • αʔόpush ϙʔϦϯάʹஔ͖ΘΔ
Slide 11
Slide 11 text
Client StreamingʢΫϥΠΞϯτετϦʔϛϯάʣ • ෳͷϦΫΤετʹର͠ɺϨεϙϯεΛ1ͭฦ͢ • ϑΝΠϧΞοϓϩʔυͳͲ
Slide 12
Slide 12 text
Bi-Directional StreamingʢํετϦʔϛϯάʣ • ෳͷϦΫΤετʹର͠ɺϨεϙϯεΛෳฦ͢ • νϟοτͳͲ
Slide 13
Slide 13 text
Αࣖ͘ʹ͢ΔProtocol Buffersͱͷҧ͍ͬͯʁ • Protocol Buffers௨৴͢Δσʔλͷܗࣜʢjson, xml...ʣ • gRPC௨৴ͷखஈ
Slide 14
Slide 14 text
͢͜͠Protocol Buffersͷ͓͞Β͍
Slide 15
Slide 15 text
protobuf • protobufͱུ͞ΕΔ͜ͱ͕ଟ͍ • όΠφϦϕʔε • .protoϑΝΠϧͰσʔλܗࣜΛఆٛ
Slide 16
Slide 16 text
echo.proto syntax = "proto3"; package echo; message EchoRequest { string text = 1; } message EchoResponse { string text = 1; }
Slide 17
Slide 17 text
protobuf • .protoϑΝΠϧ͔ΒɺswiftgoϑΝΠϧΛ࡞Մೳ
Slide 18
Slide 18 text
protobuf $ protoc echo.proto --plugin=./protoc-gen-swift --swift_out=.
Slide 19
Slide 19 text
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() {} }
Slide 20
Slide 20 text
protobuf • swiftͰApple͕ެࣜʹαϙʔτ1 • όΠφϦͷγϦΞϥΠζɾσγϦΞϥΠζͷϥΠϒϥ Ϧʹґଘ • ܰͯ͘ܕ҆શ 1 https://github.com/apple/swift-protobuf
Slide 21
Slide 21 text
protobuf σϝϦοτ • ௨৴σʔλͷՄಡੑ͕͗͢Δʢͱ͍͏͔ಡΊͳ͍ʣ • ಋೖʹҰखؒඞཁ
Slide 22
Slide 22 text
protobuf ϝϦοτ ׂѪ͠·͢ɻ ϝϦοτͨ͘͞Μ͋ΔͷͰɺσʔλܗࣜͷબࢶͷҰͭʹೖ ΕΔͷ͋Γͩͱࢥ͍·͢ɻ
Slide 23
Slide 23 text
gRPC × protobuf • gRPC͕ར༻͢ΔσϑΥϧτͷσʔλܗ͕ࣜprotobuf • gRPC͋͘·Ͱ௨৴ͷखஈͳͷͰɺσʔλܗࣜҰԠjsonͱ ͔Մೳ • ͚ͲɺprotobufͱgRPCζϒζϒͳͷͰҰॹʹ͏લఏ
Slide 24
Slide 24 text
SwiftGRPC
Slide 25
Slide 25 text
SwiftGRPC • objective-cͰc++Ͱ࣮͞ΕͨgrpcΛར༻2 • swiftͰར༻͢Δʹগʑ໘ 2 https://github.com/grpc/grpc
Slide 26
Slide 26 text
SwiftGRPC • grpcͷΠϯλʔϑΣʔεΛswiftͰϥοϓ
Slide 27
Slide 27 text
Officially Supported Platforms3 C/C++, C#, Dart *, Go, Java, Node.js, PHP *, Python, Ruby * ·ͩbeta SwiftΞϯΦϑΟγϟϧͰ͔͢?! 3 https://grpc.io/about/#osp
Slide 28
Slide 28 text
ಋೖ
Slide 29
Slide 29 text
ಋೖ • ͱʹ͔͘protobufલఏ • SwiftGRPCͷprotocϓϥάΠϯΛ࡞ • .protoϑΝΠϧ͔Β.swiftϑΝΠϧΛ࡞
Slide 30
Slide 30 text
protobufΛΠϯετʔϧ $ brew install protobuf
Slide 31
Slide 31 text
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
Slide 32
Slide 32 text
ඞཁʹԠͯ͡pathΛ௨͢ • ࣮ߦ࣌ʹϓϥάΠϯͷpathΛࢦఆͰ͖ΔͷͰඞਢͰͳ͍ $ mkdir ~/.protoc $ cp ./protoc-gen-swift ./protoc-gen-swiftgrpc ~/.protoc $ echo 'export PATH=$PATH:$HOME/.protoc' >> ~/.bash_profile $ source ~/.bash_profile
Slide 33
Slide 33 text
protoc-gen-swiftgrpc • SwiftGRPCͷprotocϓϥάΠϯ • protobufͱಉ༷ʹ.proto͔Β.swiftΛ࡞
Slide 34
Slide 34 text
echo.protoʢbeforeʣ syntax = "proto3"; package echo; message EchoRequest { string text = 1; } message EchoResponse { string text = 1; }
Slide 35
Slide 35 text
echo.protoʢserviceʣ • serviceͷதʹɺrpcϑΟʔϧυΛఆٛ͢Δ service Echo { rpc }
Slide 36
Slide 36 text
echo.protoʢserviceʣ • rpcϑΟʔϧυʹҙͷϝιουΛఆٛ͢Δ service Echo { rpc Get }
Slide 37
Slide 37 text
echo.protoʢserviceʣ • ϦΫΤετͷΦϒδΣΫτΛఆٛ͢Δ service Echo { rpc Get(EchoRequest) }
Slide 38
Slide 38 text
echo.protoʢserviceʣ • ϨεϙϯεͷΦϒδΣΫτΛఆٛ͢Δ service Echo { rpc Get(EchoRequest) returns(EchoResponse) {} }
Slide 39
Slide 39 text
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) {} }
Slide 40
Slide 40 text
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) {} }
Slide 41
Slide 41 text
protoc-gen-swiftgrpc $ protoc echo.proto --plugin=./protoc-gen-swiftgrpc --swiftgrpc_out=.
Slide 42
Slide 42 text
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 }
Slide 43
Slide 43 text
EchoʢαϯϓϧʣͰίʔυղઆ
Slide 44
Slide 44 text
Echoͷಈ͔͠ํ • SwiftGRPC.xcodeprojΛ࡞͢Δ $ make project
Slide 45
Slide 45 text
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
Slide 46
Slide 46 text
Echoͷಈ͔͠ํ • ./Examples/EchoXcode/Echo.xcodeprojΛ։͘
Slide 47
Slide 47 text
Echoͷಈ͔͠ํ • ./SwiftGRPC.xcodeprojΛϓϩδΣΫτʹՃ͢Δ
Slide 48
Slide 48 text
Echoͷಈ͔͠ํ • Target DependenciesʹSwiftGRPC.frameworkΛՃ͢Δ
Slide 49
Slide 49 text
Echo for Client
Slide 50
Slide 50 text
Echo_EchoServiceClient • ΫϥΠΞϯτ͔ΒαʔόͷଓΛཧ • ෦ͰChannelΦϒδΣΫτΛอ࣋ • Echo_EchoServiceʹ४ڌ • get, expand, collect, updateϝιουΛ࣮ߦͯ͠ɺετ ϦʔϛϯάΛߦ͏ͨΊͷCallΦϒδΣΫτΛ࡞
Slide 51
Slide 51 text
Echo_EchoServiceClient let service = Echo_EchoServiceClient(address: "YOUR_ADDRESS", secure: false)
Slide 52
Slide 52 text
Echo_EchoExpandCallʢServerStreamingʣ • expand()ϝιουͰऔಘ • αʔόετϦʔϛϯά͕Մೳ • receive()ϝιουΛ࣮ߦՄೳ
Slide 53
Slide 53 text
Echo_EchoExpandCallʢServerStreamingʣ var requestMessage = Echo_EchoRequest() requestMessage.text = "message" let expandCall = try service.expand(requestMessage) { _ in } try expandCall.receive { response in // ϨεϙϯεΛड͚औΔ }
Slide 54
Slide 54 text
Echo_EchoCollectCallʢClientStreamingʣ • collect()ϝιουͰऔಘ • ΫϥΠΞϯτετϦʔϛϯά͕Մೳ • send(), closeAndReceive()ϝιουΛ࣮ߦՄೳ
Slide 55
Slide 55 text
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͚ͩσʔλΛड͚औΕΔ }
Slide 56
Slide 56 text
Echo_EchoUpdateCallʢBidirectionalStreamingʣ • update()ϝιουͰऔಘ • ํετϦʔϛϯά͕Մೳ • send(), receive(), closeSend()ϝιουΛ࣮ߦՄೳ
Slide 57
Slide 57 text
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 {}
Slide 58
Slide 58 text
ΫϥΠΞϯτ࣮ͷجຊతͳྲྀΕ • Service͔ΒCallΦϒδΣΫτΛ࡞͢Δ • ࡞ͨ͠CallΦϒδΣΫτʹ༻ҙ͞Ε͍ͯΔstreamingͷϝ ιουΛݺͼग़͢ • CallΦϒδΣΫτstreaming͕ऴྃ͢Δ·Ͱอ͓࣋ͯ͘͠ ※ Unaryྫ֎
Slide 59
Slide 59 text
Echo_EchoGetCallʢUnaryʣ • get()ϝιουͰऔಘ • streaming༻ͷϝιου༻ҙ͞Ε͍ͯͳ͍
Slide 60
Slide 60 text
Echo_EchoGetCallʢUnaryʣ var requestMessage = Echo_EchoRequest() requestMessage.text = "message" let getCall = try service.get(requestMessage) { response, callResult in }
Slide 61
Slide 61 text
ΫϥΠΞϯτ࣮ͷಛ • CallΦϒδΣΫτΛ࡞͔ͬͨ࣌ΒtimeoutΧϯτμϯ • σϑΥϧτ600ඵͰɺϦΫΤετݸผʹઃఆෆՄ • ClientStreamingͷsend()ʹҾͰͤΔtimeoutɺಉظ ௨৴͢Δࡍͷsemaphoreͷػ࣌ؒ
Slide 62
Slide 62 text
ΫϥΠΞϯτ࣮ͷಛ • receive()ɺ1ͰσʔλΛड͚औΔͱͦΕҎ࣮߱ߦ͞ Εͳ͍ͷͰɺ࠶receive()ΛݺͿඞཁ͕͋Δ • ͳʹ͔͠ΒͷΤϥʔ͕ग़ͨΒͦΕҎ߱ૹड৴Ͱ͖ͳ͍ͷͰɺ CallΦϒδΣΫτ͔Β࠶࡞͢Δඞཁ͕͋Δ • throws͕ͨΒଟ͍
Slide 63
Slide 63 text
ΫϥΠΞϯτͷstubʹ͍ͭͯ • ServerΛϩʔΧϧʹ࣮ͯ͠stubԽ
Slide 64
Slide 64 text
Echo for Server
Slide 65
Slide 65 text
ServiceServer • αʔόͷΫϥΠΞϯτ͔ΒͷଓΛཧ • ෦ͰServerΦϒδΣΫτΛอ࣋ • Echo_EchoProviderʹ४ڌͨ͠ΦϒδΣΫτΛड͚औΔ • startϝιουͰɺଓͷड৴Λ։࢝
Slide 66
Slide 66 text
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()
Slide 67
Slide 67 text
Echo_EchoProvider • get, expand, collect, updateϝιουͰɺΫϥΠΞϯ τͷϨεϙϯεΛߦ͏ • ҾͰ͞ΕΔSessionΦϒδΣΫτͰৼΔ͍Λ࣮
Slide 68
Slide 68 text
Echo_EchoProviderʢget == Unaryʣ • Echo_EchoRequestΦϒδΣΫτΛऔಘ • Echo_EchoResponseΛฦͨ͠Βऴྃ
Slide 69
Slide 69 text
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 }
Slide 70
Slide 70 text
Echo_EchoProviderʢexpand == ServerStreamingʣ • Echo_EchoRequestΦϒδΣΫτΛऔಘ • ඞཁʹԠͯ͡sessionͷsend()Λ࣮ߦ • ServerStatusΛฦ͠ɺ͔ͭsend()͕ྃͨ͠Βऴྃ
Slide 71
Slide 71 text
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 }
Slide 72
Slide 72 text
Echo_EchoProviderʢcollect == ClientStreamingʣ • ϦΫΤετsessionͷreceive()Ͱऔಘ • Echo_EchoResponseΛฦͨ͠Βऴྃ
Slide 73
Slide 73 text
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 }
Slide 74
Slide 74 text
Echo_EchoProviderʢupdate == BidiStreamingʣ • ϦΫΤετsessionͷreceive()Ͱऔಘ • ඞཁʹԠͯ͡sessionͷsend()Λ࣮ߦ • ServerStatusΛฦ͠ɺ͔ͭsend()͕ྃͨ͠Βऴྃ
Slide 75
Slide 75 text
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 }
Slide 76
Slide 76 text
αʔό࣮ͷجຊతͳྲྀΕ • Echo_EchoProviderʹ४ڌͨ͠ΦϒδΣΫτΛ࡞͢Δ • ProviderͷϝιουͰಉظతʹॲཧ͠ɺΛฦͯ͠ऴྃ
Slide 77
Slide 77 text
SwiftGRPCClient
Slide 78
Slide 78 text
No content
Slide 79
Slide 79 text
SwiftGRPCClient > https://github.com/cats-oss/grpc-swift-client • ΫϥΠΞϯτઐ༻ͷgRPCϥΠϒϥϦ • SwiftGRPCʹґଘ • timeoutΛϦΫΤετ୯ҐͰܾΊͨΓ • ϦΫΤετͷ్தͰॲཧΛΠϯλʔηϓτͨ͠Γ • receive()ΛࣗಈͰϦτϥΠͯ͘͠ΕͨΓ
Slide 80
Slide 80 text
protoc-gen-swiftgrpc-client $ protoc echo.proto --plugin=./protoc-gen-swiftgrpc-client --swiftgrpc-client_out=.
Slide 81
Slide 81 text
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 } }
Slide 82
Slide 82 text
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͚ͩσʔλΛड͚औΕΔ }
Slide 83
Slide 83 text
SwiftGRPCClientʢClientStreamingʣ let stream = Session.shared.stream(with: EchoClientRequest()) stream .send("message") { response in // ૹ৴݁ՌΛड͚औΔ } stream .closeAndReceive { response in // close࣌ʹ1͚ͩσʔλΛड͚औΕΔ }
Slide 84
Slide 84 text
SwiftGRPCʢServerStreamingʣ var requestMessage = Echo_EchoRequest() requestMessage.text = "message" let expandCall = try service.expand(requestMessage) { _ in } try expandCall.receive { response in // ϨεϙϯεΛड͚औΔ }
Slide 85
Slide 85 text
SwiftGRPCClientʢServerStreamingʣ let stream = Session.shared.stream(with: EchoServerRequest(text: "message")) .receive { response in // ϨεϙϯεΛड͚औΔ }
Slide 86
Slide 86 text
SwiftGPRCClientʢRxʣ extension Reactive where Base: Streaming, Base.Request: UnaryRequest { func data() -> Observable { 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() } } } }
Slide 87
Slide 87 text
SwiftGPRCClientʢRxʣ Session.shared.stream(with: EchoUnaryRequest()).rx.data() .subscribe(onNext: { response in // ϨεϙϯεΛड͚औΔ }, onError: { error in // ΤϥʔΛड͚औΔ }) .disposed(by: disposeBag)
Slide 88
Slide 88 text
SwiftGPRCClient • ΫϥΠΞϯτʹSwiftGPRCClientΛར༻ͯ͠ɺstubͱͯ͠ SwiftGRPCͷαʔό࣮Λར༻͢Δ
Slide 89
Slide 89 text
ॴײͱࠓޙ
Slide 90
Slide 90 text
ॴײ • ࠷ॳcallͷcancel͢Βແ͔ͬͨ • ಋೖ͕ਏ͔ͬͨ • Τϥʔ࣌ͷࡉ͔͍ڍಈ͕௫ΈͮΒ͍
Slide 91
Slide 91 text
Swift Summit
Slide 92
Slide 92 text
ࠓޙ • ࠷ۙυΠπਓͷΤϯδχΞ͕ฃಆͯ͠ϝϯςφϯε • Network.frameworkͷಋೖͷݕ౼ͳͲ͕͞Ε͍ͯΔ • ͱΓ͋͑ͣਖ਼ࣜʹgrpcҰʹೖͬͯཉ͍͠
Slide 93
Slide 93 text
grpc-swiftΛͬͯiOSΞϓϦͰշదͳgRPC௨৴Λߦ͏ɹɹ https://github.com/cats-oss/grpc-swift-client Github : KyoheiG3 Twitter : @KyoheiG3
Slide 94
Slide 94 text
Thanks!