Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Ob1k presentation at Java.IL

1,277 views

Published on

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.

Published in: Software
  • Be the first to comment

Ob1k presentation at Java.IL

  1. 1. ⇨ Asy Ronen (A.K.A Async) ⇨ Eran Harel (@eran_ha)
  2. 2. Before OB1K... ● Multitenancy on a single Tomcat JVM ● Our API hosts actually executed 8 modules on a single JVM
  3. 3. Before OB1K... ● Applicative logs clutter ● Monitoring clutter
  4. 4. Before OB1K... ● Hard to troubleshoot performance issues ● Hard to fine tune JVMs ● Shared configuration
  5. 5. Before OB1K... ● Deployments means start / stop for several modules ● Sub optimal for CD environment...
  6. 6. Before OB1K... ● The container (Tomcat) was installed by Chef, and had a different life cycle then the web-modules ● Container upgrades were a nightmare
  7. 7. What is OB1K?
  8. 8. Asynchronous IO based on Netty
  9. 9. Synchronous Modules based on Jetty 9
  10. 10. Drop-in replacement for Tomcat apps
  11. 11. Kick A$$ Performance :)
  12. 12. Self Contained
  13. 13. Isolated Services ● Own JVM ● Own JVM settings ● Own configuration ● Own port ● Own logs directory ● Own log configuration
  14. 14. Full control over your module ● JVM options ● Configuration properties ● Logging ● Ports ● Compression ● Threads ● SSL ● Etc
  15. 15. Seamless RPC ● Strongly Typed RPC Client
  16. 16. Seamless RPC ● RPC complexity is transparent to the client
  17. 17. Seamless RPC ● Server implementation only worries about the business logic
  18. 18. Seamless RPC ● Configurable client behavior (e.g. retries)
  19. 19. Seamless RPC ● Built-In serialization support o MsgPack o JSON o Compression
  20. 20. HTTP Streams
  21. 21. Configuration as code
  22. 22. Free Standard API entry points ● /selftest ● /version ● /help (/) ● /properties ● /ping ● /presence ● /jmx ● /tailLog ● /endPoints
  23. 23. Free Service Monitoring
  24. 24. Service Discovery Integration
  25. 25. Easier upgrades, easier deployment
  26. 26. Same execution path for Dev / Prod / JUnit
  27. 27. 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
  28. 28. 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
  29. 29. General Flow
  30. 30. The main class
  31. 31. Jetty Server public 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"); }}
  32. 32. 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(); }
  33. 33. OB1K Service public 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); }}
  34. 34. OB1K client new ClientBuilder<>(IOb1kService.class). setProtocol(ContentType.JSON). setRequestTimeout(requestTimeout). setRetries(retries). addEndpoint("http://somehost:8080/Ob1kApp/Ob1kService"). build();
  35. 35. ComposableFuture public 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);}
  36. 36. ComposableFuture Example ComposableFuture<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);
  37. 37. 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)
  38. 38. 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 :)
  39. 39. 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
  40. 40. Alternatives Finagle Drop Wizard Vert.x Play Framework RESTEasy Etc
  41. 41. Future Features ● Client Side Load Balancing ● Client Side Discovery (Consul based) ● Aggregation ● Scatter-Gather ● Throttling ● Session Tracing (a-la Zipkin)

×