From REST to gRPC: An API Evolution Story Joe Runde Michael - - PowerPoint PPT Presentation

from rest to grpc
SMART_READER_LITE
LIVE PREVIEW

From REST to gRPC: An API Evolution Story Joe Runde Michael - - PowerPoint PPT Presentation

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


slide-1
SLIDE 1

From REST to gRPC:

Joe Runde IBM @joerunde Michael Keeling IBM @michaelkeeling

An API Evolution Story

slide-2
SLIDE 2

2

slide-3
SLIDE 3

What is gRPC?

Open source Remote Procedure Call framework

3

slide-4
SLIDE 4

What is gRPC?

Open source Remote Procedure Call framework

4

“… a modern, bandwidth and CPU efficient, low latency way to create massively distributed systems that span data centers”

slide-5
SLIDE 5

5

Why should we use gRPC?

slide-6
SLIDE 6

Why is gRPC awesome?

6

Performance

slide-7
SLIDE 7

Performance Benefits

7

HTTP / REST

slide-8
SLIDE 8

Performance Benefits

8

HTTP / REST gRPC

slide-9
SLIDE 9

How does gRPC improve performance?

  • HTTP/2 transport protocol
  • Binary encodings via protocol buffers
  • No more parsing text!
  • Compression
  • Streaming

9

slide-10
SLIDE 10

Why is gRPC awesome?

10

Performance

slide-11
SLIDE 11

Why is gRPC awesome?

11

Performance Remote Procedure Calls

slide-12
SLIDE 12

REST setup is tedious

12

headers = {} headers.put(“X-FooBar-User”, user.getFooBarID()) headers.put(“FooBarTransaction”, app.getNextTxnIDAtomic()) headers.put(“FooBarAlgoType”, ApproximateFoo.toHeaderString())

slide-13
SLIDE 13

REST setup is tedious

13

Public class Foo { @JsonProperty(name=”foo_id”) String id; @JsonProperty(name=”bar”) int bar; ... }

slide-14
SLIDE 14

REST setup is tedious

14

Public class Foo { ... public Foo(@JsonProperty(“foo_id”,required=true) String id, @JsonProperty(“bar”,required=true) int bar) { ... } }

slide-15
SLIDE 15

RPC setup is easy

15

request = FooService.RequestBuilder() .setId(foo.getId()) .setBar(foo.getBar())... .build(); response = fooClient.DoFooBar(request);

slide-16
SLIDE 16

Why is gRPC Awesome?

16

Performance Remote Procedure Calls

slide-17
SLIDE 17

Why is gRPC Awesome?

17

Performance Remote Procedure Calls Strategic Direction of our Platform

slide-18
SLIDE 18

18

slide-19
SLIDE 19

<insert slick demo here>

19

slide-20
SLIDE 20

Just one problem…

Our current microservices all use REST.

20

slide-21
SLIDE 21

21

slide-22
SLIDE 22

Business Constraints

22

slide-23
SLIDE 23

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

slide-24
SLIDE 24

DESIGN THE API

Phase I

24

slide-25
SLIDE 25

Designing a gRPC API

gRPC: rpc AddFoo(Foo) returns FooID; rpc GetFoo(FooID) returns Foo;

25

REST: POST /api/foo GET /api/foo/{foo_id}

slide-26
SLIDE 26

Designing a gRPC API

gRPC: message Foo { FooID id = 1; repeated Bar bars = 2; } message FooID { string val = 1; }

26

REST: POST /api/foo GET /api/foo/{foo_id}

slide-27
SLIDE 27

Designing a gRPC API

gRPC: rpc AddBar(Bar) returns BarID; rpc GetFoo(BarID) returns Bar;

27

REST: POST /api/foo/{foo_id}/bar GET /api/foo/{foo_id}/bar/ {bar_id}

slide-28
SLIDE 28

Designing a gRPC API

gRPC: rpc AddBar(Bar) returns BarID; rpc GetFoo(BarID) returns Bar;

28

REST: POST /api/foo/{foo_id}/bar GET /api/foo/{foo_id}/bar/ {bar_id}

slide-29
SLIDE 29

Designing a gRPC API

gRPC: message Bar{ BarID id = 1; int baz = 2; } message BarID { FooID foo_id = 1; string bar_id = 2; }

29

REST: POST /api/foo/{foo_id}/bar GET /api/foo/{foo_id}/bar/ {bar_id}

slide-30
SLIDE 30

Designing a gRPC API

30

Bar service: /api/foo/{foo_id}/bar/{bar_id} Buzz service: /api/foo/{foo_id}/buzz/{buzz_id}

slide-31
SLIDE 31

SERVE REST AND GRPC

Phase II

31

slide-32
SLIDE 32

Current: REST Only

32

FooBar Service REST Caller

slide-33
SLIDE 33

Future: REST and gRPC

33

FooBar Service REST Caller gRPC Caller

slide-34
SLIDE 34

We need to evolve our API without damaging basic functionality.

34

slide-35
SLIDE 35

Code Package is allowed to use

Current: Layers View

35

Rest Service Business Logic Datastore Access

Models

slide-36
SLIDE 36

Models

36

Code Package is allowed to use Rest Service

Business Logic Datastore Access

gRPC Service

Future: Layers View

slide-37
SLIDE 37

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

slide-38
SLIDE 38

Evolving the code went really well…

38

slide-39
SLIDE 39

39

slide-40
SLIDE 40

Things that suddenly became a problem

  • Health Checks
  • API Discovery
  • No curl
  • Headers?
  • SSL?
  • Simple community examples

40

slide-41
SLIDE 41

TRANSITION FUNCTIONAL TESTS

Phase III

41

slide-42
SLIDE 42

Specification by Example

42

slide-43
SLIDE 43

43

Specification by Example- REST

slide-44
SLIDE 44

Ruby metaprogramming

44

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)

slide-45
SLIDE 45

45

Specification by Example- gRPC

slide-46
SLIDE 46

200+ tests transitioned in 1 week

46

slide-47
SLIDE 47

Why did this go so well?

47

  • Expressiveness of spec by example
  • Flexibility of Ruby
  • gRPC can decode JSON
slide-48
SLIDE 48

REMOVE REST FUNCTIONALITY

Phase IV

48

slide-49
SLIDE 49

49

rm –rf src/*rest*

slide-50
SLIDE 50

We need to retain some REST endpoints

50

REST Caller gRPC Caller FooBar Service

slide-51
SLIDE 51

51

slide-52
SLIDE 52

Current Layered Architecture

52

Models

Rest Service

Business Logic Datastore Access

gRPC Service

FooBar Service Service

slide-53
SLIDE 53

Layers Forked – Two Services

53

Models

Business Logic Datastore Access

gRPC Service

FooBar Service gRPC Clients

REST Service

FooBar Proxy Service

slide-54
SLIDE 54

Evil wizards strike again!

54

slide-55
SLIDE 55

NOW WE’RE READY FOR RELEASE…?

55

slide-56
SLIDE 56

New problems we created

  • Health Checks
  • API Discovery
  • No curl
  • Headers?
  • SSL?

56

slide-57
SLIDE 57

New problems we created

  • Health Checks
  • API Discovery
  • No curl
  • Headers?
  • SSL?

57

slide-58
SLIDE 58

API Discovery

  • REST – Ask the service!
  • gRPC – Find the (correct) proto file?

58

slide-59
SLIDE 59

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

slide-60
SLIDE 60

60

slide-61
SLIDE 61

Tools support

  • Basically Nonexistent
  • Our solutions:
  • Hand roll mocks for testing
  • Write new functional tests each time we

wanted to use curl

61

slide-62
SLIDE 62

62

Adios, REST!

slide-63
SLIDE 63

INTERESTING THINGS WE LEARNED

63

slide-64
SLIDE 64
  • 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

slide-65
SLIDE 65

Would we do it again?

65

slide-66
SLIDE 66

Would we do it again?

  • Super easy to integrate with a service
  • Promotes small polyglot services
  • Difficult to do bad things
  • Performance is 🔦 🔦 🔦

66

Yes.

slide-67
SLIDE 67

Thank you!

Michael Keeling @michaelkeeling neverletdown.net Joe Runde @joerunde

Buy Design It! now at http://bit.ly/2pJOrly

slide-68
SLIDE 68

68

BACKUP

slide-69
SLIDE 69

69

slide-70
SLIDE 70

70

slide-71
SLIDE 71

71

slide-72
SLIDE 72

72