From REST to gRPC:
An API Evolution Story
Joe Runde Michael Keeling
IBM IBM
@joerunde @michaelkeeling
2
What is gRPC?
Open source Remote Procedure Call framework
3
What is gRPC?
Open source Remote Procedure Call framework
“… a modern, bandwidth and CPU efficient, low latency
way to create massively distributed systems that span
data centers”
4
Why should we use gRPC?
5
Why is gRPC awesome?
Performance
6
Performance Benefits
HTTP / REST
7
Performance Benefits
HTTP / REST gRPC
8
How does gRPC improve performance?
• HTTP/2 transport protocol
• Binary encodings via protocol buffers
• No more parsing text!
• Compression
• Streaming
9
Why is gRPC awesome?
Performance
10
Why is gRPC awesome?
Performance
Remote Procedure Calls
11
REST setup is tedious
headers = {}
headers.put(“X-FooBar-User”,
user.getFooBarID())
headers.put(“FooBarTransaction”,
app.getNextTxnIDAtomic())
headers.put(“FooBarAlgoType”,
ApproximateFoo.toHeaderString())
12
REST setup is tedious
Public class Foo {
@JsonProperty(name=”foo_id”)
String id;
@JsonProperty(name=”bar”)
int bar;
...
}
13
REST setup is tedious
Public class Foo {
...
public
Foo(@JsonProperty(“foo_id”,required=true)
String id,
@JsonProperty(“bar”,required=true)
int bar)
{ ... }
}
14
RPC setup is easy
request = FooService.RequestBuilder()
.setId(foo.getId())
.setBar(foo.getBar())...
.build();
response = fooClient.DoFooBar(request);
15
Why is gRPC Awesome?
Performance
Remote Procedure Calls
16
Why is gRPC Awesome?
Performance
Remote Procedure Calls
Strategic Direction of our Platform
17
18
<insert slick demo here>
19
Just one problem…
Our current microservices
all use REST.
20
21
Business Constraints
22
The Transition Plan
• Phase 1: Design gRPC API
• Phase 2: Run REST and gRPC services
• Phase 3: Transition functional tests
• Phase 4: Remove REST functionality
23
DESIGN THE API
Phase I
24
Designing a gRPC API
REST: gRPC:
POST rpc AddFoo(Foo)
/api/foo returns FooID;
GET rpc GetFoo(FooID)
/api/foo/{foo_id} returns Foo;
25
Designing a gRPC API
REST: gRPC:
POST message Foo {
/api/foo FooID id = 1;
repeated Bar bars = 2;
GET }
/api/foo/{foo_id}
message FooID {
string val = 1;
}
26
Designing a gRPC API
REST: gRPC:
POST rpc AddBar(Bar)
/api/foo/{foo_id}/bar returns BarID;
GET rpc GetFoo(BarID)
/api/foo/{foo_id}/bar/ returns Bar;
{bar_id}
27
Designing a gRPC API
REST: gRPC:
POST rpc AddBar(Bar)
/api/foo/{foo_id}/bar returns BarID;
GET rpc GetFoo(BarID)
/api/foo/{foo_id}/bar/ returns Bar;
{bar_id}
28
Designing a gRPC API
REST: gRPC:
message Bar{
POST BarID id = 1;
/api/foo/{foo_id}/bar int baz = 2;
}
GET
/api/foo/{foo_id}/bar/ message BarID {
{bar_id} FooID foo_id = 1;
string bar_id = 2;
}
29
Designing a gRPC API
Bar service:
/api/foo/{foo_id}/bar/{bar_id}
Buzz service:
/api/foo/{foo_id}/buzz/{buzz_id}
30
SERVE REST AND GRPC
Phase II
31
Current: REST Only
REST
Caller
FooBar
Service
32
Future: REST and gRPC
REST gRPC
Caller Caller
FooBar
Service
33
We need to evolve our API without
damaging basic functionality.
34
Current: Layers View
Rest Service
Code Package
Business Logic Models
is allowed to
use Datastore Access
35
Future: Layers View
Rest gRPC
Service Service
Code Package
Business Logic Models
is allowed to
use Datastore Access
36
Layer Pattern Rocks!
A code review comment:
"What's with the service
layer? This just passes
its inputs to our business
logic functions, it's
redundant cruft!"
37
Evolving the code went really well…
38
39
Things that suddenly became a problem
• Health Checks
• API Discovery
• No curl
• Headers?
• SSL?
• Simple community examples
40
TRANSITION FUNCTIONAL TESTS
Phase III
41
Specification by Example
42
Specification by Example- REST
43
Ruby metaprogramming
Choice of programming language really paid off
request = Object::const_get(
”FooBar::#{message_name}").decode_json(json)
response = client.method(method_name.to_sym)
.call(request)
44
Specification by Example- gRPC
45
200+ tests transitioned in 1 week
46
Why did this go so well?
• Expressiveness of spec by example
• Flexibility of Ruby
• gRPC can decode JSON
47
REMOVE REST FUNCTIONALITY
Phase IV
48
rm –rf src/*rest*
49
We need to retain some REST endpoints
REST gRPC
Caller Caller
FooBar
Service
50
51
Current Layered Architecture
Service Rest gRPC
Service Service
Business Logic Models
FooBar
Service
Datastore Access
52
Layers Forked – Two Services
REST Service
FooBar
gRPC Clients Proxy
Service gRPC Service
Business Logic Models
FooBar
Service
Datastore Access
53
Evil wizards strike again!
54
NOW WE’RE READY FOR
RELEASE…?
55
New problems we created
• Health Checks
• API Discovery
• No curl
• Headers?
• SSL?
56
New problems we created
• Health Checks
• API Discovery
• No curl
• Headers?
• SSL?
57
API Discovery
• REST – Ask the service!
• gRPC – Find the (correct) proto file?
58
API Discovery
• REST – Ask the service!
• gRPC – Find the (correct) proto file?
• Standard InfoService serves github url + version
• Snapshot proto files with releases
• Client vendors the proto files they use
59
60
Tools support
• Basically Nonexistent
• Our solutions:
• Hand roll mocks for testing
• Write new functional tests each time we
wanted to use curl
61
Adios,
REST!
62
INTERESTING THINGS WE
LEARNED
63
• The right kinds of abstractions promote
extensibility
• Focus on the domain model
• Create a specification by example
• Take care when choosing frameworks
• Deal with risks of technology adoption
64
Would we do it again?
65
Would we do it again?
Yes.
• Super easy to integrate with a service
• Promotes small polyglot services
• Difficult to do bad things
• Performance is 🔥 🔥 🔥
66
Thank you!
Michael Keeling Joe Runde
@michaelkeeling @joerunde
neverletdown.net
Buy Design It! now at
http://bit.ly/2pJOrly
BACKUP
68
69
70
71
72