iosdc_2018.pdf
by
Kyohei Ito
×
Copy
Open
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
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!