Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

Building Better APIs with gRPC - Postmates Andr...

Building Better APIs with gRPC - Postmates Android Tech Talk

This talk was a part of the "&droid" event at Postmates HQ.
gRPC is usually used by backend services to communicate with each other.
In the talk we go over our experiences of building gRPC apis for mobile clients.
Speakers:
- Parth Mehta
- Veeren Mandalia

Avatar for Parth Mehta

Parth Mehta

July 23, 2019
Tweet

Other Decks in Programming

Transcript

  1. About Postmates Postmates is on a mission to help people

    unlock the best of their cities – and their lives – with an insanely reliable on-demand “anything” network.
  2. By the Numbers 4 Major Offices (SFO - BNA -

    SEA - MEX) 1,300 Employees 3,500 Cities 500K Merchants 140K Couriers Per Week 6.5M Deliveries Per Month
  3. Speakers James 
 Lee Android Engineering Lead Veeren Mandalia Android

    Engineering Lead Hai 
 Le Android Engineer Parth 
 Mehta Server Engineering Lead Gaurav 
 Murti Android Engineer Bianca Curutan Mobile Engineer MC
  4. Problem • Improve platform responsiveness and reliability - e.g., Postmates

    only have a limited time when viewing a delivery offer, every second matters • Reduce engineering time - API definition & implementation
  5. • Remote Procedure Call-based • High performance because of multiplexing

    and compression • Open source • Multiplatform
  6. Shared API Definition • Service and models defined in proto

    definition files • Definition shared between server & Android/iOS clients • Serves as the single source of truth of API definition and documentation
  7. Service Definition gRPC (proto definition file) service FleetService { rpc

    Events (EventsRequest) returns (stream EventsResponse) {} }
  8. Model Definition message EventsResponse { string token = 1; repeated

    Event events = 2; } message EventsRequest { string token = 1; bool limit = 2; }
  9. Tight API Contracts message EventsResponse { string token = 1;

    repeated Event events = 2; } message EventsRequest { string token = 1; bool limit = 2; }
  10. Tight API Contracts message EventsError { oneof error_oneof { InvalidToken

    invalid_token = 1; UnsupportedLimit unsupported_limit = 2; Error generic = 3; } }
  11. Generated Code • The protobuf compiler (protoc) then generates language

    specific framework and application code • Output - Client: Java, Swift - Server: Go, Python
  12. API Updates CI CI message EventsRequest { string token =

    1; bool limit = 2; enum event_type = 3; }
  13. Creating a Stub val target = "fleet.postmates.com:428" val channel: ManagedChannel

    = OkHttpChannelBuilder .forTarget(target) .keepAliveTime(15, SECONDS) .keepAliveTimeout(10, SECONDS) .userAgent(“Postmate Android User Agent”) .let { builder -> AndroidChannelBuilder.fromBuilder(builder) .context(context) } .build()
  14. Make a Request util.getObservableFromRpc<EventsRequest, EventsResponse> { streamObserver -> fleetServiceStub.events(request, streamObserver)

    }.observeOn(ioScheduler) .subscribe({ eventsResponse -> // Process events, e.g. Show offer to Postmate }, { throwable -> // Handle error })
  15. RxJava Utilities fun <Req, Resp> getObservableFromRpc(rpc: (StreamObserver<Resp>) -> Unit): Observable<Resp>

    { return Observable.fromEmitter({ emitter: Emitter<Resp> -> val responseObserver = object : CancellableStreamObserver<Req, Resp>() { override fun onError(t: Throwable) { super.onError(t) emitter.onError(t) } override fun onNext(value: Resp) = emitter.onNext(value) override fun onCompleted() = emitter.onCompleted() } emitter.setCancellation { responseObserver.cancel() } rpc(responseObserver) }, Emitter.BackpressureMode.LATEST) }
  16. RxJava Utilities abstract class CancellableStreamObserver<Req, Resp> : ClientResponseObserver<Req, Resp> {

    var requestStream: ClientCallStreamObserver<Req>? = null override fun beforeStart(requestStream: ClientCallStreamObserver<Req>?) { this.requestStream = requestStream } @CallSuper override fun onError(t: Throwable) { // Handle error.. } fun cancel() { requestStream?.cancel("Forceful cancellation of stream", StatusException(Status.CANCELLED)) } }
  17. Performance Multiplexing • Multiple ongoing RPCs over a single connection

    Compact over the wire • Protobuf over the wire • Compression
  18. Bi-Directional Streaming • gRPC supports Bi-Directional streaming • Faster and

    more efficient data transfer over a persistent connection • Ideal for payloads like events
  19. Event Latency on REST vs gRPC 0% 15% 30% 45%

    60% 10ms 50ms 100ms 250ms 500ms 750ms 1000ms 1500ms 2000ms SLOW gRPC REST