Introductions

Derek Eskens

@snekse

Dev 20+ years, Consulting 8+ years

Java, JS, Groovy

'Foodie for Life' is tattooed across my tummy

Star Wars > Star Trek

gRPC

gRPC Remote Procedure Calls 🙄

What is gRPC

TL;DR

"A high performance, open source universal RPC framework"

Binary Transport over HTTP/2

Really? 🤨 RPC?

CORBA?

RMI?

SOAP?

Didn't we abandon RPC?

Why is gRPC different?

  • 11+ languages
  • Incredibly fast
  • Small footprint
    (storage, memory, transport)
  • Simple IDL
  • Flexible Evolution
  • BiDi Streaming
  • Integrated Auth
  • Generated Client Libraries

What's wrong with REST?

If you want to get technical...

JSON + HTTP Verbs ≠ REST

If you don't HATEOAS, you hate us

What we really mean

So what's wrong with
RESTful-ish

Maybe nothing!

  • Human Readable
  • Discoverable
  • Low Coupling
  • Low Complexity
  • curl / Postman
  • Caching
  • Easy Versioning?

}

-ish

Where RESTful fails

  • Chattiness
  • Schema/Types
  • Complex Models
  • Beyond the State Engine
  • Performance Costs
  • Common Client Code
  • Streaming

Choices

Who is your API for?

Public?

Volume?

Message Size?

Streaming?

Polyglot?

CRUD?

Bandwidth?

Devices?

When to consider gRPC

  • Performance
  • Cohesion
  • Bandwidth
  • Tolerant Versioning
  • Internal Only Usage
  • Single Client
  • ??? 🎤

The Obvious

  • High throughput internal µServices
  • Streaming content
  • Real-time Applications
  • Interacting with Kafka
  • Programming in Go

The Less Obvious

Mobile Apps

  • Tolerant Versioning
    • App store approvals
    • Old App Versions
  • Client Stubs
    • Fast development
  • Performance
    • Weaker CPUs
    • Data Caps/Speed
    • Save Battery Life

IoT Devices

  • Constraints
  • Limitations
  • Hinderances

Tens of MHz, KBs of Memory

Splitting an Existing Monolith

Why not...?

gRPC vs ...

The Nitty Gritty

HTTP/2

  • Binary Frames
  • HPACK Compression
  • Single Connection
  • Multiplexing
  • Server Push
  • TLS Default
  • Flow Control

Protobuf

  • Default IDL
  • Language Agnostic
  • Platform Agnostic
  • Simple
  • Robust
  • Fast
Technically gRPC is format agnostic

ns/ops

750

1500

2250

syntax = "proto3";

import "google/protobuf/timestamp.proto";

message StockQuoteRequest {
  string symbol = 1;
}

message Price {
  int32 amount = 1; //Thanks NASDAQ 🙄
}

message BidAsk {
  Price bid = 1;
  Price ask = 2;
}

message StockQuoteResponse {
  string symbol = 1;
  Price last 	= 2;
  BidAsk bidAsk = 3;
  google.protobuf.Timestamp date = 4;
}

A Brief Protobuf Syntax Intro

syntax = "proto3";

import "opi/brokerage/financial-instruments/pricing.proto";

service QuoteService {

    // Get the current price
    rpc GetQuote (StockQuoteRequest) 
    	returns (StockQuoteResponse);

    // Get level II streaming quotes
    rpc GetQuoteStream (StockQuoteRequest) 
    	returns (stream StockQuoteResponse);
}

   protoc

Now admire all of your beautiful stubs

public class QuoteServiceImpl extends QuoteServiceImplBase  {

  @Override
  public void getQuote(StockQuoteRequest req, StreamObserver<StockQuoteResponse> rspObserver) {
    try {
      // Get the quote from a 3rd party provider
      RealTimeQuote rtq = rtQuoteProvider.getRealTimeQuote(req.getSymbol());
      
      // Build our response
      StockQuoteResponse stockQuoteResponse = toResponse(req.getSymbol(), rtq);
      
      // send the response
      rspObserver.onNext(stockQuoteResponse); 
      
    } catch (Exception e) {
      rspObserver.onError(Status.UNKNOWN
        .withDescription("Failed to get quote for " + req.getSymbol())
        .augmentDescription(e.getMessage())
        .asRuntimeException()
      );
    } finally {
      rspObserver.onCompleted(); // mark RPC call as complete
    }
  }

  // ...
}

Implementing the Service

  private StockQuoteResponse toResponse(String ticker, RealTimeQuote rtq) {
    return StockQuoteResponse.newBuilder()
      .setSymbol(ticker)
      .setLast(asPrice(rtq.last))
      .setBidAsk(asBidAsk(rtq.bid, rtq.ask))
      .setDate(getTimestamp())
      .build();
  }
  
  private Price asPrice(int value) {
    return Price.newBuilder().setAmount(value).build();
  }

  private BidAsk asBidAsk(int bid, int ask) {
    return BidAsk.newBuilder()
        .setBid(asPrice(bid))
        .setAsk(asPrice(ask))
        .build();
  }
  
  private Timestamp getTimestamp() {
    // ...
  }

Using the Generated Builders

All the Builder Goodness

Cool Stuff

  • Interceptors
  • Timeouts
  • Bi-Directional Streaming
  • REST/graphQL on top of gRPC
  • gRPC-WEB Proxy

Not Cool

  • Spring Support
  • Browser Support
  • Load Balancing
  • Error Handling
  • Private Constructors

Follow the Leaders

Google

Netflix

Uber

Square

Spotify

Twilio

Final Thoughts

Goal Accomplished?

A bullet that is more bronze than silver

gRPC

By Derek Eskens