Top Banner
Async servers and clients in Rest.li 1
43

Async servers and clients in Rest.li

Jul 17, 2015

Download

Software

Karan Parikh
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Async servers and clients in Rest.li

Async servers and clients in

Rest.li

1

Page 2: Async servers and clients in Rest.li

(Please read the speaker notes)

2

Page 3: Async servers and clients in Rest.li

What is this Rest.li thing

you speak about?

“Rest.li is an open source REST framework for building robust,

scalable RESTful architectures using type-safe bindings and

asynchronous, non-blocking I/O.”

3

Page 4: Async servers and clients in Rest.li

The Stack

Rest.li Data and REST API

D2 Dynamic Discovery and load balancing

R2 Network communication

4

Page 5: Async servers and clients in Rest.li

What do you by mean

by async?

5

Page 6: Async servers and clients in Rest.li

What do you mean by

async (I/O)?

6

Request 1

Request 2

Blocked on I/O

Tim

e

Sync Async

Free CPU

Page 7: Async servers and clients in Rest.li

Rest.li is async and non-blocking

under the hood!

7

Page 8: Async servers and clients in Rest.li

Rest.li

D2

R2

8

Page 9: Async servers and clients in Rest.li

How is R2 async and

non-blocking?

• Netty based async client

• Jetty based server – configuration change (link) needed to run

the server in async mode

Rest.li

D2

R2

9

Page 10: Async servers and clients in Rest.li

How is D2 async and

non-blocking?

• All communication with ZooKeeper uses the asynchronous

APIs

• ZooKeeper pushes data to clients in case of updates

Rest.li

D2

R2

10

Page 11: Async servers and clients in Rest.li

How is Rest.li async

and non-blocking?

• Does not handle I/O

• I/O is taken care of by R2

• R2 is async and non-blocking!

• Uses ParSeq when interacting with and delegating to

application code.

Rest.li

D2

R2

11

Page 12: Async servers and clients in Rest.li

Async Rest.li Servers

12

Page 13: Async servers and clients in Rest.li

Async Server

Implementations

• The Rest.li framework is async and non-blocking under the

hood.

• As a result of this, if you do any blocking work in your method

implementation it can negatively impact your application

throughput as threads are held up by your application which

are needed by Rest.li. (if you are using Rest.li in async

mode)

13

Page 14: Async servers and clients in Rest.li

Async Server

Implementations -

Options

1. Callback based

2. ParSeq based

14

Page 15: Async servers and clients in Rest.li

Async Server – Callback

@RestMethod.Get

public void get(final Long id, @CallbackParam final Callback<Greeting> callback) {

String path = "/data/" + id;

_zkClient.getData(path, false, new DataCallback() {

public void processResult(int i, String s, Object o, byte[] b, Stat st) {

if (b.length == 0) {

callback.onError(new RestLiServiceException(HttpStatus.S_404_NOT_FOUND));

}

else {

callback.onSuccess(buildGreeting(b));

}

}

}, null);

} 15

Page 16: Async servers and clients in Rest.li

Async Server –

Callback Signature

@RestMethod.Get

public void get(final Long id, @CallbackParam final Callback<Greeting> callback)

com.linkedin.common.Callback

16

Page 17: Async servers and clients in Rest.li

Async Server – Filling

out the callback

_zkClient.getData(path, false, new DataCallback() {

public void processResult(int i, String s, Object o, byte[] b, Stat st) {

if (b.length == 0) {

callback.onError(new RestLiServiceException(HttpStatus.S_404_NOT_FOUND));

}

else {

callback.onSuccess(buildGreeting(b));

}

}

}, null);17

Page 18: Async servers and clients in Rest.li

Async Server – Callback

@RestMethod.Get

public void get(final Long id, @CallbackParam final Callback<Greeting> callback) {

String path = "/data/" + id;

_zkClient.getData(path, false, new DataCallback() {

public void processResult(int i, String s, Object o, byte[] b, Stat st) {

if (b.length == 0) {

callback.onError(new RestLiServiceException(HttpStatus.S_404_NOT_FOUND));

}

else {

callback.onSuccess(buildGreeting(b));

}

}

}, null);

} 18

Page 19: Async servers and clients in Rest.li

Async server - ParSeq

19

Page 20: Async servers and clients in Rest.li

Key ParSeq Concepts

• Promise Fully async Java Future + listener mechanism.

• Task Basic unit of work that is similar to Java Callable.

Task<T>

• Engine runs Tasks.

• Context Used by a Task to run sub-Tasks.

• Composition par and seq

(link)

20

Page 21: Async servers and clients in Rest.li

Async Server – ParSeq

@RestMethod.Get

public Task<Greeting> get(final Long id) {

final Task<FileData> fileDataTask = buildFileDataTask();

final Task<Greeting> mainTask = Tasks.callable("main", new Callable<Greeting>() {

@Override

public Greeting call() throws Exception {

FileData fileData = fileDataTask.get();

return buildGreetingFromFileData(id, fileData);

}

});

return Tasks.seq(fileDataTask, mainTask);

}

21

Page 22: Async servers and clients in Rest.li

Async Server – ParSeq

signature

@RestMethod.Get

public Task<Greeting> get(final Long id)

22

Page 23: Async servers and clients in Rest.li

Async Server – ParSeq body

final Task<FileData> fileDataTask = buildFileDataTask();

23

Page 24: Async servers and clients in Rest.li

Async Server – ParSeq body

final Task<Greeting> mainTask = Tasks.callable("main", new Callable<Greeting>() {

@Override

public Greeting call() throws Exception {

FileData fileData = fileDataTask.get();

return buildGreetingFromFileData(id, fileData);

}

});

24

Page 25: Async servers and clients in Rest.li

Async Server –

assembling the Tasks

return Tasks.seq(fileDataTask, mainTask);

25

fileDataTask mainTask

Page 26: Async servers and clients in Rest.li

Async Server – ParSeq

@RestMethod.Get

public Task<Greeting> get(final Long id) {

final Task<FileData> fileDataTask = buildFileDataTask();

final Task<Greeting> mainTask = Tasks.callable("main", new Callable<Greeting>() {

@Override

public Greeting call() throws Exception {

FileData fileData = fileDataTask.get();

return buildGreetingFromFileData(id, fileData);

}

});

return Tasks.seq(fileDataTask, mainTask);

}

26

Page 27: Async servers and clients in Rest.li

Async Server – ParSeq

• Can use this approach to build complex call graphs and

return the final Task. (more on this later).

• Can use ParSeq tracing

• No callback hell!

27

Page 28: Async servers and clients in Rest.li

Async Rest.li Clients

28

Page 29: Async servers and clients in Rest.li

Async Rest.li requests

• RestClient is async and non-blocking under the hood – it

uses ParSeq and Netty.

• Applications can still block the thread if they block on the

results of the Rest.li call!

Response response = _restClient.sendRequest(BUILDER.get().id(1L).build()).get();Fortune fortune = response.getEntity();

Blocking on the result of a Future

29

Page 30: Async servers and clients in Rest.li

Async Rest.li requests

Two Options:

1. Callback based API

2. Use a ParSeqRestClient – This is a wrapper around a

RestClient that returns ParSeq Tasks and Promises.

30

Page 31: Async servers and clients in Rest.li

Async Rest.li requests

– Callbacks

Callback<Response<Greeting>> cb = new Callback() {

void onSuccess(Response<Greeting> response) {

// do something with the returned Greeting

}

void onError(Throwable e) {

// whoops

}

}

Request<Greeting> getRequest = BUILDERS.get().id(1L).build();

_restClient.sendRequest(getRequest, new RequestContext(), cb);

31

Page 32: Async servers and clients in Rest.li

Async Rest.li requests – defining

a Callback

Callback<Response<Greeting>> callback = new Callback() {

void onSuccess(Response<Greeting> response) {

// do something with the returned Greeting

}

void onError(Throwable e) {

// whoops

}

}

32

Page 33: Async servers and clients in Rest.li

Async Rest.li requests – sending

the request

Request<Greeting> getRequest = BUILDERS.get().id(1L).build();

_restClient.sendRequest(getRequest, new RequestContext(), callback);

33

Page 34: Async servers and clients in Rest.li

Async Rest.li requests – using

ParSeq

• Callback based API is good for simple use cases (one or two

requests and you are done.)

• But it is hard to express more complicated call flows using the

CallbackAPI

Callback ParSeq

34

Page 35: Async servers and clients in Rest.li

Async Rest.li requests – using

ParSeq

a1 a2 a3

b1 b2

c1

35

Page 36: Async servers and clients in Rest.li

Async Rest.li requests – using

ParSeq

Task<Response<?>> a1ResponseTask =

_parseqRestClient.createTask(a1Request);

Task<Response<?>> a2ResponseTask =

_parseqRestClient.createTask(a2Request);

Task<Response<?>> a3ResponseTask =

_parseqRestClient.createTask(a3Request); a1 a2 a3

b1 b2

c1

36

Page 37: Async servers and clients in Rest.li

Async Rest.li requests – using

ParSeq

Task<Response<?>> b1ResponseTask = Tasks.callable("", new Callable<Task<Response<?>>() {

@Override

public Task<Response<?>> call() throws Exception {

Response<?> a1Response = a1ResponseTask.get();

// Similarly, access the results from a2 and a3 as well

// use this to build request b1Request

return _parseqRestClient.createTask(b1Request)

}

});

Task<Response<?>> b2ResponseTask = _parseqRestClient.createTask(b2Request);

a1 a2 a3

b1 b2

c1

37

Page 38: Async servers and clients in Rest.li

Async Rest.li requests – using

ParSeq

Task<Response<?>> c1ResponseTask = Tasks.callable("", new Callable<Task<Response<?>>() {

@Override

public Task<Response<?>> call() throws Exception {

Response<?> b1Response =

b1ResponseTask.get();

Response<?> b2Response =

b2ResponseTask.get();

// use b1Response and b2Response for

// c1Request

return _parseqRestClient.createTask(c1Request)

}

});

a1 a2 a3

b1 b2

c1

38

Page 39: Async servers and clients in Rest.li

Async Rest.li requests – using

ParSeq

_engine.run(Tasks.seq(

Tasks.par(a1ResponseTask, a2ResponseTask, a3ResponseTask), Tasks.par(b1ResponseTask, b2ResponseTask),c1ResponseTask));

a1 a2 a3

b1 b2

c1

39

Page 40: Async servers and clients in Rest.li

Conclusion

• Rest.li is async and non-blocking under the hood

• You can use Callbacks and ParSeq Tasks and Promises to

write async Rest.li clients and servers

40

Page 41: Async servers and clients in Rest.li

Links and references

• Rest.li user guide https://github.com/linkedin/rest.li/wiki/Rest.li-

User-Guide

• Asynchronous servers and clients in Rest.li

https://github.com/linkedin/rest.li/wiki/Asynchronous-Servers-

and-Clients-in-Rest.li

• ParSeq https://github.com/linkedin/parseq

41

Page 42: Async servers and clients in Rest.li

Me.

https://www.linkedin.com/in/parikhkaran

https://github.com/karanparikh

http://karanparikh.com/

42

Page 43: Async servers and clients in Rest.li

Thanks!

43