41
Fast and Reliable Swift APIs with gRPC Tim Burks Google, Inc.

Fast and Reliable Swift APIs with gRPC

Embed Size (px)

Citation preview

Page 1: Fast and Reliable Swift APIs with gRPC

Fast and Reliable Swift APIs with gRPCTim BurksGoogle, Inc.

Page 2: Fast and Reliable Swift APIs with gRPC

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

I love APIs.

Page 4: Fast and Reliable Swift APIs with gRPC

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

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

Google API Discovery Service

Page 8: Fast and Reliable Swift APIs with gRPC

October 4, 2000

Page 9: Fast and Reliable Swift APIs with gRPC

Protocol Buffersa language-neutral, platform-neutral, extensible mechanism for serializing structured data.

Page 10: Fast and Reliable Swift APIs with gRPC

“Protocol Buffers” means several things

1. A serialization mechanism2. An interface description language3. A methodology

Page 11: Fast and Reliable Swift APIs with gRPC

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

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

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
Page 15: Fast and Reliable Swift APIs with gRPC
Page 16: Fast and Reliable Swift APIs with gRPC
Page 17: Fast and Reliable Swift APIs with gRPC
Page 18: Fast and Reliable Swift APIs with gRPC

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

10 billion+ API calls

every second

Page 20: Fast and Reliable Swift APIs with gRPC
Page 21: Fast and Reliable Swift APIs with gRPC
Page 22: Fast and Reliable Swift APIs with gRPC
Page 23: Fast and Reliable Swift APIs with gRPC

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

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

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

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

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

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

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

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

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

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

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

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

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

Try it!https://github.com/grpc/grpc-swift/wiki

Page 37: Fast and Reliable Swift APIs with gRPC

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

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

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

Page 40: Fast and Reliable Swift APIs with gRPC

Build a gRPC service, get a free REST API!