fast and reliable swift apis with grpc
TRANSCRIPT
![Page 1: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/1.jpg)
Fast and Reliable Swift APIs with gRPCTim BurksGoogle, Inc.
![Page 2: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/2.jpg)
I’m talking about Networked APIs.
Application Programming Interfaces that operate across a network of computers. They communicate using network protocols including HTTP, and are frequently produced by different organizations than the ones that consume them.
Google API Design Guide: Glossary
![Page 3: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/3.jpg)
I love APIs.
![Page 4: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/4.jpg)
I hate SDKs.
Closed-Source SDKs:● Snoop user or developer data.● Do other unauthorized things.● Fail to build or run.
Open-Source SDKs:● Also fail to build or run.● Introduce dependencies that I don’t want.● Are just ugly and gross.
![Page 5: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/5.jpg)
but now I make SDKs…
● google-cloud-python● google-cloud-node● google-cloud-ruby● google-cloud-java● google-cloud-go● google-cloud-php● google-cloud-dotnet
● google-api-python-client● google-api-nodejs-client● google-api-ruby-client● google-api-java-client● google-api-go-client● google-api-php-client● google-api-dotnet-client● google-api-objectivec-client● google-api-objectivec-client-for-rest
![Page 6: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/6.jpg)
Google API Discovery Service
![Page 7: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/7.jpg)
![Page 8: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/8.jpg)
October 4, 2000
![Page 9: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/9.jpg)
Protocol Buffersa language-neutral, platform-neutral, extensible mechanism for serializing structured data.
![Page 10: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/10.jpg)
“Protocol Buffers” means several things
1. A serialization mechanism2. An interface description language3. A methodology
![Page 11: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/11.jpg)
Protocol Buffer Serialization
It’s just a stream of bytes
[field_number<<3 + wire_type] [length if necessary] [data]...
$ hexdump /tmp/request.bin 0000000 0a 05 68 65 6c 6c 6f
0a is “0000 1010”, so
field_number = 1 and wire_type = 2
![Page 12: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/12.jpg)
The Protocol Buffer Language
package echo;
message EchoRequest { string text = 1;}
message EchoResponse { string text = 1;}
service Echo { rpc Get(EchoRequest) returns (EchoResponse) {} rpc Update(stream EchoRequest) returns (stream EchoResponse) {}}
![Page 13: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/13.jpg)
The Protocol Buffer Methodology
$ protoc echo.proto -o echo.out --swift_out=.
$ which protoc-gen-swift../bin/protoc-gen-swift
$ more echo.pb.swift // DO NOT EDIT.//// Generated by the Swift generator plugin...// Source: echo.proto
...
![Page 14: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/14.jpg)
![Page 15: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/15.jpg)
![Page 16: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/16.jpg)
![Page 17: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/17.jpg)
![Page 18: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/18.jpg)
Interface Builder for Data
message Person {
string name = 1;
int32 id = 2;
string email = 3;
message PhoneNumber {
string number = 1;
}
repeated PhoneNumber phone = 4;
}
Interface Builder: Developers specify their interfaces using a special tool, tooling compiles and integrates that into their apps.
Protocol Buffers: Developers specify their data structures using a special language, tooling compiles and integrates that into their apps.
![Page 19: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/19.jpg)
10 billion+ API calls
every second
![Page 20: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/20.jpg)
![Page 21: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/21.jpg)
![Page 22: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/22.jpg)
![Page 23: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/23.jpg)
Interoperability
Java Service
Python Service
GoLang Service
C++ Service
gRPC Service
gRPC Stub
gRPC Stub
gRPC Stub
gRPC Stub
gRPC Service
gRPC Service
gRPC Service
gRPC Stub
![Page 24: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/24.jpg)
Nonstreaming APIsa.k.a. “Unary”
Client sends one request.
Server sends one response.
message HelloRequest { string name = 1;}
message HelloReply { string message = 1;}
service HelloService { rpc SayHello(HelloRequest) returns (HelloReply);}
![Page 25: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/25.jpg)
Streaming APIsClient-Streaming
Client sends multiple messages.
Server sends one response.
Server may choose to send the response before all the client messages are received.
message Latency { string name = 1; double val = 2;}
message Histogram { string name = 1 double p99 = 2; double p999 = 3; double avg = 4;}
service MetricsService { rpc ReportLatency(stream Latency) returns Histogram;}
![Page 26: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/26.jpg)
Streaming APIsServer-Streaming
Client sends one request.
Server sends multiple messages.
message Stock { string stocksymbol = 1;}
message Quote { double price = 1;}
service StockTickerService { rpc GetTicker(Stock) returns (stream Quote);}
![Page 27: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/27.jpg)
Streaming APIsBidirectional Streaming
Client and server can send multiple messages to each other.
Client and server can send messages independently; neither has to wait to receive a message before sending a message.
message Message { string text = 1;}
service ChatService { rpc Chat(stream Message) returns (stream Message);}
![Page 28: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/28.jpg)
gRPC Implementations: Native
C/C++, Java, Go
gRPC Core
HTTP 2.0
SSL
Code Generated API Application Layer
Framework Layer
Transport Layer
![Page 29: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/29.jpg)
gRPC Implementations: Wrapped
C#, Node.js, Ruby, PHP, Python, Obj-C, Swift
Python
Obj-C, C#, C++, ...Ruby PHPPython
C gRPC Core
HTTP 2.0
SSL
Language Bindings
Code Generated
Ruby PHP Obj-C, C#, C++,...
Application Layer
Framework Layer
Transport Layer
![Page 30: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/30.jpg)
gRPC Sample Service
package echo;
message EchoRequest { // The text of a message to be echoed. string text = 1;}
message EchoResponse { // The text of an echo response. string text = 1;}
service Echo { // Immediately returns an echo of a request. rpc Get(EchoRequest) returns (EchoResponse) {} // Splits a request into words and returns each word in a stream of messages. rpc Expand(EchoRequest) returns (stream EchoResponse) {} // Collects a stream of messages and returns them concatenated when the caller closes. rpc Collect(stream EchoRequest) returns (EchoResponse) {} // Streams back messages as they are received in an input stream. rpc Update(stream EchoRequest) returns (stream EchoResponse) {}}
![Page 31: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/31.jpg)
Running the generator(s)
$ lsecho.proto
$ protoc echo.proto --swift_out=. --swiftgrpc_out=.
$ lsecho.client.pb.swift echo.proto swiftgrpc.logecho.pb.swift echo.server.pb.swift
echo.proto Protocol Buffer language source file
echo.pb.swift generated by protoc-gen-swift
echo.client.pb.swift generated by protoc-gen-swiftgrpc
echo.server.pb.swift generated by protoc-gen-swiftgrpc
swiftgrpc.log generated by protoc-gen-swiftgrpc
![Page 32: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/32.jpg)
gRPC Swift server protocol (generated)
// To build a server, implement a class that conforms to this protocol.
public protocol Echo_EchoProvider {
func get(request : Echo_EchoRequest, session : Echo_EchoGetSession) throws -> Echo_EchoResponse
func expand(request : Echo_EchoRequest, session : Echo_EchoExpandSession) throws
func collect(session : Echo_EchoCollectSession) throws
func update(session : Echo_EchoUpdateSession) throws
}
![Page 33: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/33.jpg)
gRPC Swift server sample (handwritten)
// get returns requests as they were received.func get(request : Echo_EchoRequest, session : Echo_EchoGetSession) throws -> Echo_EchoResponse { return Echo_EchoResponse(text:"Swift echo get: " + request.text)}
// update streams back messages as they are received in an input stream.func update(session : Echo_EchoUpdateSession) throws -> Void { while true { do { let request = try session.Receive() try session.Send(Echo_EchoResponse(text:"Swift echo update: \(request.text)")) } catch Echo_EchoServerError.endOfStream { break } } try session.Close()}
![Page 34: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/34.jpg)
gRPC Swift unary client sample (handwritten)
var requestMessage = Echo_EchoRequest(text:message)
let responseMessage = try service.get(requestMessage) // blocking
print("get received: " + responseMessage.text)
![Page 35: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/35.jpg)
gRPC Swift streaming client sample (handwritten)
let sem = DispatchSemaphore(value: 0)let updateCall = try service.update() // blockingDispatchQueue.global().async { while true { do { let responseMessage = try updateCall.Receive() // blocking print("Received: \(responseMessage.text)") } catch Echo_EchoClientError.endOfStream { sem.signal() break } }}let parts = message.components(separatedBy:" ")for part in parts { let requestMessage = Echo_EchoRequest(text:part) try updateCall.Send(requestMessage) sleep(1)}try updateCall.CloseSend()
// Wait for the call to complete.sem.wait()
![Page 36: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/36.jpg)
Try it!https://github.com/grpc/grpc-swift/wiki
![Page 37: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/37.jpg)
To Do:
● Build Systems (currently Swift PM only)
○ Wanted: CocoaPods, Carthage
○ Xcode: `swift package generate-xcodeproj`
● gRPC-Core code is vendored. Can this be organized better?
● Need to build and pass gRPC interoperability tests.
● Increased metadata access.
● Other issues at https://github.com/grpc/grpc-swift/issues.
![Page 38: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/38.jpg)
To Do: Wrap Google Datastore API
● Entity-oriented NoSQL data store, heavily used by Google App Engine apps.
● Usually mapped to native structs:// golangtype Task struct {
Category stringDone boolPriority intDescription string `datastore:",noindex"`PercentComplete float64Created time.TimeTags []string
} Swift Mirrors and Decoders?
![Page 39: Fast and Reliable Swift APIs with gRPC](https://reader034.vdocuments.us/reader034/viewer/2022052117/5a6477a97f8b9afc4d8b4811/html5/thumbnails/39.jpg)
To Do: Auth
● https://github.com/google/auth-library-swift (available)
○ MacOS: Gets OAuth tokens from a browser
○ Linux on GCP: Gets OAuth tokens from the GCP environment
● To Do: Support Service Accounts
○ Requires JWT signing with RS256