Rick

Rick
Rick

Thursday, February 19, 2015

Using QBit Java microservice lib with Spring Boot

You can use Spring Boot and QBit together. You could configure QBit to work with/in Spring MVC, or you can just use QBit as the servlet that handles requests.
Remember this about QBit. It runs standalone with Jetty or Vertx. It can run in any Servlet container.
Here is a basic example combining QBit in the Spring Boot world.

Project structure

$ tree
.
├── build.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── qbit-spring-boot-together.iml
├── settings.gradle
└── src
    └── main
        ├── java
        │   └── io
        │       └── advantageous
        │           └── qbit
        │               └── examples
        │                   └── spring
        │                       ├── Application.java
        │                       ├── DispatcherServlet.java
        │                       └── HelloService.java
        └── resources
            └── default.properties

11 directories, 11 files
We present the above which is a simple project structure. We used gradle but you could easily use maven.
First we define the Application and Configuration bean as follows:
/**
 * @author Geoff Chandler
 * @author  (Rick Hightower)
 */
@Configuration
@EnableAutoConfiguration
@PropertySource(value = {"classpath:default.properties",
        "file:${properties.location}"},
        ignoreResourceNotFound = true)
public class Application extends SpringBootServletInitializer {

    @Autowired
    private Environment environment;

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public String dataDir() {
        return environment.getProperty("data.location");
    }

    @Bean
    public HelloService helloService() {
        return new HelloService();
    }

    @Bean
    public DispatcherServlet dispatcherServlet() {
        return new DispatcherServlet();
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }
}
There are many ways to do this. This example picked a simple approach.
Next we subclass a QBit Servlet as follows:
package io.advantageous.qbit.examples.spring;

import io.advantageous.qbit.http.HttpTransport;
import io.advantageous.qbit.server.ServiceServer;
import io.advantageous.qbit.servlet.QBitHttpServlet;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.ServletConfig;

import static io.advantageous.qbit.server.ServiceServerBuilder.serviceServerBuilder;

/**
 * @author Rick Hightower
 */
public class DispatcherServlet extends QBitHttpServlet {

    public static final String SERVICES_API_PROXY_URI_PREAMBLE = "/services/myapp/";

    @Autowired
    private HelloService helloService;
    //Hit this at http://localhost:8080/services/myapp/helloservice/hello


    private ServiceServer serviceServer;

    public DispatcherServlet() {

    }

    @Override
    protected void stop() {
        serviceServer.stop();
    }

    @Override
    protected void wireHttpServer(final HttpTransport httpTransport,
                                  final ServletConfig servletConfig) {


        serviceServer = serviceServerBuilder().setHttpTransport(httpTransport)
                .setUri(SERVICES_API_PROXY_URI_PREAMBLE)
                .build().initServices(helloService).startServer();

    }

}
Now one could imagine that we could do all sorts of thing with Spring like discover servers and what not. We could also write an adapter so QBit can run inside of Spring MVC. This would not be hard. The above just uses the QBit support for adapting QBit to run inside of a servlet container.
Lastly is our Hello World example which we injected into our Servlet.
import io.advantageous.qbit.annotation.RequestMapping;

@RequestMapping("helloservice")
public class HelloService {


    @RequestMapping("hello")
    public String helloWorld() {
        return "Hello from QBit";
    }
}
If you are skilled with Spring, you could imagine creating lifecycle listeners and do a lot of the service discovery on the fly. (I did this before with Crank and Geoff did it before as well.)
Here is the build file.
apply plugin: 'idea'
apply plugin: 'java'
apply plugin: 'application'


sourceCompatibility = 1.8
version = '1.0'

repositories {
    mavenLocal()
    mavenCentral()
}


dependencies {
    compile group: 'io.advantageous.qbit', name: 'qbit-servlet', version: '0.6.1-SNAPSHOT'
    compile group: 'javax.inject', name: 'javax.inject', version: '1'
    compile('org.springframework.boot:spring-boot-starter-web:1.2.1.RELEASE') {
        exclude module: 'spring-boot-starter-tomcat'
    }
    compile 'org.eclipse.jetty:jetty-webapp:9.+'
    compile 'org.eclipse.jetty:jetty-jsp:9.+'

    testCompile "junit:junit:4.11"
    testCompile "org.slf4j:slf4j-simple:[1.7,1.8)"
}
You can find the complete example in git.





What is QBit again?

QBit is a queuing library for microservices. It is similar to many other projects like Akka, Spring Reactor, etc. QBit is just a library not a platform. QBit has libraries to put a service behind a queue. You can use QBit queues directly or you can create a service. QBit services can be exposed by WebSocket, HTTP, HTTP pipeline, and other types of remoting. A service in QBit is a Java class whose methods are executed behind service queues. QBit implements apartment model threading and is similar to the Actor model or a better description would be Active Objects. QBit does not use a disruptor. It uses regular Java Queues. QBit can do north of 100 million ping pong calls per second which is an amazing speed (seen as high as 200M). QBit also supports calling services via REST, and WebSocket. QBit is microservices in the pure Web sense: JSON, HTTP, WebSocket, etc.

QBit lingo

QBit is a Java microservice lib supporting REST, JSON and WebSocket. It is written in Java but I might one day write a version in Rust or Go or C# (but that would require a large payday).
Service POJO (plain old Java object) behind a queue that can receive method calls via proxy calls or events (May have one thread managing events, method calls, and responses or two one for method calls and events and the other for responses so response handlers do not block service. One is faster unless responses block). Services can use Spring MVC style REST annotations to expose themselves to the outside world via REST and WebSocket.
ServiceBundle Many POJOs behind one response queue and many receive queues. There may be one thread for all responses or not. They also can be one receive queue.
Queue A thread managing a queue. It supports batching. It has events for empty, reachedLimit, startedBatch, idle. You can listen to these events from services that sit behind a queue. You don't have to use Services. You can use Queue's direct.
ServiceServer ServiceBundle that is exposed to REST and WebSocket communication
EventBus EventBus is a way to send a lot of messages to services that may be loosely coupled
ClientProxy Way to invoke service through async interface, service can be inproc (same process) or remoted over WebSocket.
Non-blocking QBit is a non-blocking lib. You use CallBacks via Java 8 Lambdas. You can also send event messages and get replies. Messaging is built into the system so you can easily coordinate complex tasks.
Speed There is a lot of room for improvement with Speed. But already QBit is VERY fast. 200M+ TPS inproc ping pong, 10M-20M+ TPS event bus, 500K TPS RPC calls over WebSocket/JSON, etc. More work needs to be done to improve speed, but now it is fast enough where I am working more with usability.




  • [Detailed Tutorial] QBit microservice example
  • [Detailed Tutorial] Working with inproc MicroServices within QBit.
  • [Doc] Queue Callbacks for QBit queue based services
  • [Doc] Using QBit microservice lib's HttpClient GET, POST, et al, JSON, Java 8 Lambda
  • [Doc] Using QBit microservice lib's WebSocket support
  • [Quick Start] Building a simple Rest web microservice server with QBit
  • [Quick Start] building a single web page application with QBit
  • [Quick Start] Building a TODO web microservice client with QBit
  • [Quick Start] Building a TODO web microservice server with QBit
  • [Quick Start] Building boon for the QBit microservice engine
  • [Quick Start] Building QBit the microservice lib for Java
  • [Quick Start] Working with inproc MicroServices within QBit
  • [Rough Cut] Delivering up Single Page Applications from QBit Java JSON Microservice lib
  • [Rough Cut] QBit Microservices using Service Workers and sharded service workers
  • [Rough Cut] Using QBit microservice lib's REST support with URI Params
  • [Rough Cut] Using QBit microservice lib with Spring Boot
  • [Rough Cut] Working with event bus for QBit the microservice engine
  • [Rough Cut] Working with inproc MicroServices
  • [Rough Cut] Working with private event bus for inproc microservices
  • [Rough Cut] Working with strongly typed event bus proxies for QBit Java Microservice lib
  • [Rough Cut] Working with System Manager for QBit Mircoservice lib
  • [Z Blog] Qbit servlet support also a preview of using jetty and the QBit microservice lib together
  • [Z Notebook] More benchmarking internal
  • [Z Notebook] Performance testing for REST
  • [Z Notebook] Roadmap
  • Home
  • Introduction to QBit
  • Local Service Proxies
  • QBit Boon New Wave of JSON HTTP and Websocket
  • QBit Docs
  • Z [OLD] Don't look at me I am ugly
  • Kafka and Cassandra support, training for AWS EC2 Cassandra 3.0 Training