Technologies Supported By Baratine

Baratine is Caucho’s latest project. As more developers have began to use Baratine, we have noticed a common set of questions and have written this response to get users to understand the programming model Baratine presents.

Overview

A large percentage of web applications today are composed as a mix of JavaEE / Spring and similar REST frameworks. These architectures are considered “3-tiered” and can be pictured as below:

Screen Shot 2015-12-16 at 3.43.10 PM

  Throughout this architecture, a developer can expect to find different modules, protocols, and components that use different frameworks or JSRs to accomplish their specific task. Some, for example a cache, may be used to speed up the performance of an application at the added cost of complexity to the overall framework. This architecture also has a certain amount of familiarity as it has been used since the early days of web applications. While this architecture is familiar, it is not without its documented shortcomings (http://microservices.io/patterns/microservices.html).

  Between the load balancer and cache sits a logical separation from what is considered application code versus hardware or software responsible for proxying client requests into the application. Starting at the red line and containing everything within it, is what is best captured by the statement SOA-tier. This code is often complex and critical to an applications uptime & responsiveness. Over the course of the years, developers have looked to standardize, at least conceptually, how this portion of an application should be written (http://www.infoq.com/articles/tilkov-10-soa-principles).

  While these best practices have been coveted by developers, they are seldom implemented. This is in part due to (1) the business demand to prototype or have a partial solution up and running and (2) the learning curve and integration required to use frameworks that offer only a partial benefit and add to the overall complexity.

Enter Baratine

  Baratine is not “yet another framework to learn”. Baratine presents a programming model that most developers already know: Object-Oriented.

Screen Shot 2015-12-17 at 3.32.38 PM

As illustrated by the image above, Baratine has the capabilities to replace or integrate with the SOA-tier of an application’s architecture. While the internals of how Baratine does this is a full discussion worthy of a blog post in itself, each layer above can be described in Baratine as follows:

Cache – There is no cache in Baratine. The data that would normally sit in a cache, instead sits within individual Baratine services. These services can pull from a database, keep everything in-memory, or use a combination of the two. Services use high-performance techniques such as batching & high-throughput queues to maintain performance.

Web Server – Baratine contains a web server capable of communicating through Websockets, HTTP, or Long-Polling. However, clients do not call into a Baratine server directly. Instead, they call into a Baratine service that is deployed on a server. This allows clients to call methods directly on the service.

App Server – Baratine does not need an application server. Baratine processes application business logic in the form of POJOs developers code. Because of this, developers code to standard Java 8 conventions and Baratine handles the wiring, service discovery, and lifecycle of services.

Database – Baratine services can persist data and store data in multiple ways:

  1. They can use an outside entity such as a NoSQL or MySQL database.
  2. They can use a <k,v>  or database store local to the service.
  3. They can store to Baratine’s File System

What does this mean for developers?

What this means to developers, is that they can achieve greater performance, scalability, and resilience with straightforward Java 8 code rather than looking to integrate multiple components from different vendors. Code is more standard and coding is more agile. Baratine does not support any of the JSR technologies directly.

The core features of Baratine allow for services that are polyglot (any client capable of understanding JSON can communicate), individually scalable, and can be embedded within current environments or function as standalone servers.

Baratine is designed for the SOA-tier of applications. Having been in the industry since 1998 and responsible for an application server implementation that predates Tomcat, Caucho has seen both the best practices as well as fallacies of application architecture. Current frameworks, although popular, leave developers exposed to mitigating synchronization errors, thread starvation, database bottlenecks, and a laundry list of others.

Baratine is the SOA layer redesigned from the thread & data locality level up. This model prevents possible integration point failures that exist in current frameworks such as between the web server and cache. Baratine applications implement a set of principles best described by the Reactive Manifesto(http://www.reactivemanifesto.org/).  In short, each service is capable of millions of operations per second per instance, can be individually scaled and sharded, and can have its functionality isolated from bottlenecking or bringing down an entire application. These are principles described in Michael T. Nygard’s book Release It!: Design and Deploy Production-Ready Software

The Baratine API

In Baratine, your POJO is your service and your data. A POJO contains business logic + whatever data it needs to maintain (For example a Counter POJO might contain an instance variable such as: long counter). Once the @Service Annotation is placed on that POJO, it is made into a Baratine Service. A Baratine Service can be pictured as follows with the definition below:

service-inbox-outbox

A Baratine Service is an annotated POJO with:

  • Its own internal storage
  • An inbox that automatically batches method requests
  • An outbox for returning response calls 

Instead of persisting this data to an outside entity (namely a database), the Baratine framework provides access to storage on the service itself. A service will store each instance created at a unique URL. This allows the owning service and data to reside on the same node. For the developer, this provides an easy way to access data for a given service instance:  it takes in a url and uses this id as a unique identifier to store the data for the POJO object at. This is how Baratine is able to maintain state on different object types and continually run methods on these objects in a nonblocking manner. Each server instance is managed on a single thread with batched methods coming through the inbox, because data is only ever accessed on a single thread, the service cannot suffer from possible synchronization issues, thread starvation, or bottlenecked resource consumption.

How services communicate

Baratine allows developers to continue to code object-oriented Java applications. This means that services communicate through normal method calls. Clients in Baratine can connect using Websockets, Http, or fallback to long-polling as a third option. Once a client has established a connection to a service, communication is done through normal Java method calls. The wire protocol responsible for transmitting the message is JAMP. JAMP communication allows a service to speak JSON to any client calling into it, because of this Baratine is a polyglot language.

This style of communication contrasts with the common practice of wiring REST endpoints to Java objects and exposing their methods. Normally, a developer would be concerned about the URLs placed on servlets or other objects answering requests. This is not needed in Baratine. While it is possible to test a hello service(http://doc.baratine.io/v0.8/patterns/hello-tour/#examples-hello-tour) method using curl as such:

curl http://localhost:8080/webapp/hello?m=hello

and receive the following response:

{“status”:”ok”,”value”:”hello”}

This style is only to be used for testing! When implementing clients that actually communicate with services, a client will lookup or build a service reference, and call methods on that returned Service instance as follows:

{

  ServiceManager manager = ServiceManager.current()

  Hello myHello = manager.lookup(“pod://pod/hello”)

                         .as(Hello.class);

  out.println(“Hello: ” + myHello.hello(“world”));

  hello.helloSend(“data”);

}

For a full description and walkthrough of this service see http://doc.baratine.io/v0.8/manual/http-websocket-clients/.

Summary

We hope this overview of the Baratine framework and what technologies it supports contributes to your understanding of the framework. If you have further questions about Baratine, please post them on our Baratine-io Google Group ( https://groups.google.com/forum/#!forum/baratine-io ) or email us directly at sales@caucho.com.