From REST to gRPC: An API Evolution Story Joe Runde Michael Keeling IBM IBM @joerunde @michaelkeeling
2
What is gRPC? Open source R emote P rocedure C all framework 3
What is gRPC? Open source R emote P rocedure C all 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 { FooID foo_id = 1; {bar_id} 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 Rest gRPC Service Service Service FooBar Business Logic Models Service Datastore Access 52
Layers Forked – Two Services REST Service FooBar Proxy gRPC Clients Service gRPC Service FooBar Business Logic Models 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! Joe Runde Michael Keeling @joerunde @michaelkeeling neverletdown.net Buy Design It! now at http://bit.ly/2pJOrly
BACKUP 68
69
70
71
72
Recommend
More recommend