ob1k presentation at java.il
DESCRIPTION
Ob1k is a new open source RPC container. it belongs to a new breed of frameworks that tries to improve on the classic J2EE model by embedding the server and reducing redundant bloatware. Ob1k supports two modes of operations: sync and async, the async mode aims for maximum performance by adopting reactive principals like using non-blocking code and functional composition using futures. Ob1k also aims to be ops/devops friendly by being self contained and easily configured.TRANSCRIPT
![Page 1: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/1.jpg)
⇨ Asy Ronen (A.K.A Async)⇨ Eran Harel (@eran_ha)
![Page 2: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/2.jpg)
Before OB1K...
● Multitenancy on a single Tomcat JVM● Our API hosts actually executed 8 modules
on a single JVM
![Page 3: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/3.jpg)
Before OB1K...
● Applicative logs clutter● Monitoring clutter
![Page 4: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/4.jpg)
Before OB1K...
● Hard to troubleshoot performance issues● Hard to fine tune JVMs● Shared configuration
![Page 5: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/5.jpg)
Before OB1K...
● Deployments means start / stop for several modules
● Sub optimal for CD environment...
![Page 6: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/6.jpg)
Before OB1K...
● The container (Tomcat) was installed by Chef, and had a different life cycle then the web-modules
● Container upgrades were a nightmare
![Page 7: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/7.jpg)
What is OB1K?
![Page 8: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/8.jpg)
Asynchronous IO based on Netty
![Page 9: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/9.jpg)
Synchronous Modules based on Jetty 9
![Page 10: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/10.jpg)
Drop-in replacement for Tomcat apps
![Page 11: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/11.jpg)
Kick A$$ Performance :)
![Page 12: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/12.jpg)
![Page 13: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/13.jpg)
Self Contained
![Page 14: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/14.jpg)
Isolated Services
● Own JVM● Own JVM settings● Own configuration● Own port● Own logs directory● Own log configuration
![Page 15: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/15.jpg)
Full control over your module
● JVM options● Configuration properties● Logging● Ports● Compression● Threads● SSL● Etc
![Page 16: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/16.jpg)
Seamless RPC
● Strongly Typed RPC Client
![Page 17: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/17.jpg)
Seamless RPC
● RPC complexity is transparent to the client
![Page 18: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/18.jpg)
Seamless RPC
● Server implementation only worries about the business logic
![Page 19: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/19.jpg)
Seamless RPC
● Configurable client behavior (e.g. retries)
![Page 20: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/20.jpg)
Seamless RPC
● Built-In serialization supporto MsgPacko JSONo Compression
![Page 21: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/21.jpg)
HTTP Streams
![Page 22: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/22.jpg)
Configuration as code
![Page 23: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/23.jpg)
Free Standard API entry points● /selftest● /version● /help (/)● /properties● /ping● /presence● /jmx● /tailLog● /endPoints
![Page 24: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/24.jpg)
Free Service Monitoring
![Page 25: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/25.jpg)
Service Discovery Integration
![Page 26: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/26.jpg)
Easier upgrades, easier deployment
![Page 27: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/27.jpg)
Same execution path for Dev / Prod / JUnit
![Page 28: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/28.jpg)
Maven Archetype Scaffolding$ mvn archetype:generate -DarchetypeGroupId=com.outbrain -DarchetypeArtifactId=outbrain-ob1k-archetype -DarchetypeVersion=1.0.18 -DinteractiveMode=false -Dversion=trunk -DgroupId=com.outbrain -Dpackage=com.outbrain.YOUR_PACKAGE_NAME -DartifactId=YOUR_SERVICE_NAME
![Page 29: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/29.jpg)
A set of asynchronous modules
● Async memcached client● Async RPC client● Async HTTP client● Async DB query execution● Async Cassandra client● Async Event Stream support● Composable Futures infrastructure
![Page 30: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/30.jpg)
General Flow
![Page 31: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/31.jpg)
![Page 32: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/32.jpg)
The main class
![Page 33: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/33.jpg)
Jetty Serverpublic class GruffaloServer { private static final Logger logger = LoggerFactory.getLogger(GruffaloServer.class);
public static void main(String[] args) { new GruffaloServer().build().start(); logger.info("******** Gruffalo started ********"); }
public Server build() { return new JettyServerBuilder().useConfigurationPorts().setContextPath("/Gruffalo"); }}
![Page 34: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/34.jpg)
Netty Server public static Server buildServer() { final String contextPath = "/Ob1kTemplate";
Context ctx = new SpringContextBuilder(contextPath). addInitParam("self-tests", "properties,zookeeper,url,valid-context"). setMainContext("main", "classpath:applicationContext-Ob1kTemplate-all.xml"). addSubContext("ops", "classpath:WEB-INF/spring/ops-services.xml"). addSubContext("service", "classpath:WEB-INF/spring/Ob1kTemplate-service.xml"). build();
ServerBuilder serverBuilder = new ServerBuilder(). setContextPath(contextPath). setContext(ctx). addStaticPath("/html"). addStaticPath("/css"). addBaseServices("ops"). addServiceFromContext("service", Ob1kService.class, "/api"). createServiceFromContext("service", Ob1kNamedService.class, "/names"). addEndpoint("handleFirstRequest", "/first/{id}"). addEndpoint("handleSecondRequest", "/second/{name}"). addEndpoint("handleThirdRequest", "/third/{state}/{city}"). addService().useConfigurationPorts();
return serverBuilder.build(); }
![Page 35: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/35.jpg)
OB1K Servicepublic class Ob1kService implements Service { private static final Logger log = LoggerFactory.getLogger(Ob1kService.class); private final String greetingMessage;
public Ob1kService(final String greetingMessage) { this.greetingMessage = greetingMessage; }
public ComposableFuture<String> echo(final String name) { return ComposableFutures.fromValue("hello " + name + ". " + greetingMessage); }}
![Page 36: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/36.jpg)
OB1K client
new ClientBuilder<>(IOb1kService.class). setProtocol(ContentType.JSON). setRequestTimeout(requestTimeout). setRetries(retries). addEndpoint("http://somehost:8080/Ob1kApp/Ob1kService"). build();
![Page 37: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/37.jpg)
ComposableFuturepublic interface ComposableFuture<T> extends Future<T> { <R> ComposableFuture<R> continueWith(final ResultHandler<T, R> handler); <R> ComposableFuture<R> continueOnSuccess(final SuccessHandler<? super T, ? extends R> handler); ComposableFuture<T> continueOnError(final ErrorHandler<? extends T> handler);
void onResult(OnResultHandler<T> handler); void onSuccess(OnSuccessHandler<? super T> handler); void onError(OnErrorHandler handler);
ComposableFuture<T> withTimeout(long duration, final TimeUnit unit);}
![Page 38: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/38.jpg)
ComposableFuture ExampleComposableFuture<Response> f1 = client.httpGet("http://www.google.co.il/search?q=term1");ComposableFuture<Response> f2 = client.httpGet("http://www.google.co.il/search?q=term2");ComposableFuture<Response> f3 = client.httpGet("http://www.google.co.il/search?q=term3");
ComposableFuture<List<Response>> combined = all(f1, f2, f3);ComposableFuture<String> res = combined.continueWith((result) -> { // prepare combined result.});
schedule(() -> { return trySomething().continueOnError((error) -> { return getFallback(); });}, 30, TimeUnit.SECONDS);
![Page 39: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/39.jpg)
How does it all works ?
● All IO is non blocking and done via Netty● Basically one thread per core, all working
unless there is nothing to do● Context switch is minimized● Transport is always HTTP, payload may vary● Adjusted Executor for blocking actions(if you
must)
![Page 40: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/40.jpg)
Why Streams ?
● Time to serve is limited, better to serve results as they come
● A stream of results is, well… a stream● Request/response model is not a good fit for all
scenarios, thing twitter streaming API● Streams can be combined in all sorts of wonderful
ways● Implementation uses RxJava● Ask netflix :)
![Page 41: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/41.jpg)
What is the catch?
● Blocking code is (almost)forbidden in the async mode
● Writing asynchronous code has a learning curve
● Libraries have to be adapted
![Page 42: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/42.jpg)
Alternatives
FinagleDrop WizardVert.xPlay FrameworkRESTEasy Etc
![Page 43: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/43.jpg)
Future Features
● Client Side Load Balancing● Client Side Discovery (Consul based)● Aggregation● Scatter-Gather● Throttling● Session Tracing (a-la Zipkin)
![Page 44: Ob1k presentation at Java.IL](https://reader034.vdocument.in/reader034/viewer/2022051609/547e7cf6b4af9f9b158b5707/html5/thumbnails/44.jpg)
* W
e’re
recr
uitin
g ;)