The Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.
+qbit - The Microservice Lib for Java - JSON, REST, WebSocket, Speed!
+
+
+
+
+Quick overview of QBit
+
+
The Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.
+
+
+
"Precision beats power, and timing beats speed," -McGregor
Everything is a queue. You have a choice. You can embrace it and control it. You can optimize for it.
+Or you can hide behind abstractions. QBit opens you up to peeking into what is going on, and allows you
+to pull some levers without selling your soul.
+
+
QBit is a library not a framework. You can mix and match QBit with Spring, Guice, etc.
+
+
QBit is FAST!
+
+
+
+
+Core Features
+
+
+
Write REST based async microservices
+
Write WebSocket based async microservices (fast async RPC over WebSocket)
+
Actor Service Queues using micro-batching for high-speed message passing
+
Strongly async typed event bus which can be distributed
+
Async low overhead metrics gathering which can be queried and distributed (for doing fast lane analytics)
+
Complex async call coordination (with the Reactor) for reactive programming
+
Built-in support for health checks (and integration with tools like Consul)
+
Built-in support for monitoring (and integration with wire protocols like StatsD)
+
Built-in support for Service Discovery (with integration with health system, DNS SRV records and Consul)
API Gateway support for client generation and consumption via Swagger.
+
Our services can generate Swagger files (like idl for JSON/REST).
+
Remote client proxies for WebSocket (your interface is your IDL)
+
+
+
+Status
+
+
Deployed at several large fortune 100 companies.
+QBit now works with Vertx (standalone or embedded).
+You can also use QBit no non-QBit projects, it is just a lib.
+
+
+License
+
+
Apache 2
+
+
+Java Microservice Lib
+
+
QBit has inproc services, REST microservices and WebSocket microservices as well as an
+in-proc service event bus (which can be per module or per app). It supports workers and in-memory services.
+
+
Before we describe more, here are two sample services:
At the end of the day QBit is a simple library not a framework.
+Your app is not a QBit app but a Java app that uses the QBit lib.
+QBit allows you to work with Java UTIL concurrent, and does not endeavor to hide it from you.
+Just trying to take the sting out of it.
+
+
+Does it work
+
+
We have used techniques in Boon and QBit with great success in high-end, high-performance, high-scalable apps.
+We helped clients handle 10x the load with 1/10th the servers of their competitors using techniques in QBit.
+QBit is us being sick of hand tuning queue access and threads.
+
+
+Boon and QBit humility policy
+
+
Ideas for Boon and QBit often come from all over the web. We make mistakes. Point them out.
+As a developer of Boon and QBit, we are fellow travelers.
+If you have an idea or technique you want to share, we listen.
+
+
+Inspiration
+
+
A big inspiration for Boon/QBit was Vertx, Akka, Go Channels, Active Objects, Apartment Model Threading, Actor,
+and the Mechanical Sympathy papers.
+
+
QBit has ideas that are similar to many frameworks. We are all reading the same papers.
+QBit got inspiration from the LMAX disruptor papers and this blog post about
+link transfer queue versus disruptor. We had some theories about
+queues that blog post inspired us to try them out. Some of these theories are deployed at some of the
+biggest middleware backends and whose name brands are known around the world. And thus QBit was born.
+
+
QBit also took an lot of inspiration by the great work done
+by Tim Fox on Vertx. The first project using something that could actually be called QBit (albeit early QBit)
+ was using Vertx on an web/mobile microservice for an app that could potentially have 80 million users.
+ It was this
+experience with Vertx and early QBit that led to QBit development and evolution. QBit is built on the
+shoulders of giants (Netty/Vertx).
+
+
+Does QBit compete with...
+
+
Spring Disruptor: No. You could use QBit to write plugins for Spring Disruptor I suppose, but QBit does
+not compete with Spring Disruptor.
+Spring Boot/Spring MVC: No. We use the same annotations but QBit is geared for high-speed in-memory
+microservices. It is more like Akka than Spring Boot. QBit has a subset of the features of Spring MVC
+geared only for microservices, i.e., WebSocket RPC, REST, JSON marshaling, etc.
+Akka: No. Well Maybe. Akka has similar concepts but they take a different approach. QBit is more focused
+ on Java, and microservices (REST, JSON, WebSocket) than Akka.
+LMAX Disruptor: No. In fact, we can use disruptor as on of the queues that QBit uses underneath the covers.
+
+
(Early benchmarks have been removed. They were here. QBit got a lot faster.
+ Benchmarking QBit is a moving target at the moment.
+ Links and reports will be created.)
+
+
Code Examples
+
+
+Basic Queue example (REST style services is further down)
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 (but could).
+ 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 uses micro batching to
+ push messages through the pipe (queue, IO, etc.) faster to reduce thread hand-off.
+
+
+QBit lingo
+
+
QBit is a Java microservice lib supporting REST, JSON and WebSocket. It is written in Java but we could
+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. In QBit, you have sender queues and receivers queues. They are separated to
+support micro-batching.
+
+
ServiceEndpointServer
+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
+ClientProxy is a 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.
+QBit takes an object-oriented approach to service development so services look like normal Java services
+that you
+already write, but the services live behind a queue/thread. This is not a new concept. Microsoft did this
+with DCOM/COM and called it active objects. Akka does it with actors and called them strongly typed Actors.
+The important concepts is that you get the speed of reactive and actor style messaging but you develop
+in a natural OOP approach. QBit is not the first. QBit is not the only.
+
+
Speed
+QBit is VERY fast. There is a of course a lot of room for improvement. But already 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 we are focusing more on
+usability.
+The JSON support uses Boon by default which is up to 4x faster than other JSON parsers for the
+REST/JSON, WebSocket/JSON use case.
+
+
Reactive Programming
+QBit provides a Reactor to manage async calls. This allows callbacks to be handled on the same thread that called them and it provides for timeout and error handling. Read Reactor tutorial for creating reactive micro service programming
+
+
Service Discovery
+Built in support for service discovery. This includes integration with Consul.
+
+
StatService
+Built in support for stats. The StatService can be integrated with StatsD (Graphite, Grafana, DataDog, etc.) to publish passive stats. Or you can query the stats engine and react to the stats (counts, timings and levels). The StatsService is a reactive stats system that can be clustered. The StatService is reactive in that your services can publish to it and query it and react based on the results. You can implement things like rate limiting and react to an increased rate of something. The ServiceDiscovery system integrates with the HealthSystem and Consul to roll up each of your internal services that make up you micro service and publish the composite availably of your micro service to a single HTTP endpoint or a dead mans switch in Consul (TTL).
+
+
+CURLable REST services example
+
+
Talk is cheap. Let's look at some code. You can get a detailed walk through in the Wiki.
+We have a lot of documentation already.
+
+
We will create a service that is exposed through REST/JSON.
You can POST/PUT non-JSON and you can capture the body as a String or as a byte[].
+If the content-type is set to anything but application/json and your body is defined a String or byte[].
+This works automatically. (The content-type has to be set.)
By default QBit sends a 200 (OK) for a non-void call (a call that has a return or a Callback). If the REST operation has no return or no callback then QBit sends a 202 (Accepted). There may be times when you want to send a 201 (Created) or some other code that is not an Exception. You can do that by setting code on @RequestMapping. By default the code is -1 which means use the default behavior (200 for success, 202 for one-way message, and 500 for errors).
Why did we pick Spring style annotations?
+1) Spring is not a standard and neither is QBit. 2) We found the Spring annotations to be less verbose.
+3) More people use Spring than Java EE. We wrote QBit for people to use.
+We could easily support JAX-RS style annotations, and we probably will.
+Since QBit focuses on JSON, we do not need all of the complexity of JAX-RS or even all the features of
+the Spring MVC annotations. Also we can literally use the actual Spring annotations. QBit and Boon
+use a non-type safe mechanism for annotations which means they are not tied to a particular lib.
+You can define your own. We hate vendor tie-in even if it is an open source vendor.
+(We also support @POST, @GET which is similar to JAX-RS).
That is it. There is also out of the box WebSocket support with client side proxy generation so
+you can call into services at the rate of millions of calls per second.
You can always invoke QBit services via a WebSocket proxy.
+The advantage of a WebSocket proxy is it allows you execute 1M RPC+ a second (1 million remote calls
+every second).
+
+
+Using a microservice remotely with WebSocket
+
+
/* Start QBit client for WebSocket calls. */
+ finalClient client = clientBuilder()
+ .setPort(7000).setRequestBatchSize(1).build();
+
+
+ /* Create a proxy to the service. */
+ finalAdderServiceClientInterface adderService =
+ client.createProxy(AdderServiceClientInterface.class,
+ "adder-service");
+
+ client.start();
+
+
+
+ /* Call the service */
+ adderService.add(System.out::println, 1, 2);
+
+
+
The output is 3.
+
+
3
+
+
+
The above uses a WebSocket proxy interface to call the service async.
Currently the clientBuilder will load all service endpoints that are registered under the service name,
+and randomly pick one.
+
+
ServiceDiscovery includes Consul based, watching JSON files on disk, and DNS. It is easy to write your own service discovery as well and plug it into QBit.
+
+
In the future we can RoundRobin calls or shard calls to websocket service and/or provide auto fail over if the connection is closed. We do this for the event bus that uses service discovery but it is not baked into WebSocket based client stubs yet.
+
+
+REST call with URI params
+
+
The last client example uses WebSocket. You could also just use REST, and actually use the URI params
+that we setup.
+REST is nice but it is going to be slower than WebSocket support.
+
+
QBit ships with a nice little HTTP client. We can use it.
+
+
You can use it to send async calls and WebSocket messages with the HTTP client.
+
+
Here we will use the http client to invoke our remote method:
+
+
+Using a microservice remotely with REST QBit microservice client
This example has three services: EmployeeHiringService, BenefitsService, and PayrollService.
+
+
These services are inproc services. QBit supports WebSocket, HTTP and REST remote services as well, but for now, let's focus on inproc services. If you understand inproc then you will understand remote.
+
+
The EmployeeHiringService actually fires off the events to other two services.
Notice that we call sendArray so we can send the employee and their salary.
+The listener for PAYROLL_ADJUSTMENT_CHANNEL will have to handle both an employee and an int
+that represents the new employees salary.
+You can also use event bus proxies so you do not have to call into the event bus at all.
+
+
The BenefitsService listens for new employees being hired so it can enroll them into the benefits system.
You can define your own interface to the event bus and you can use your own event buses with QBit.
+ Each module in your service can have its own internal event bus.
Services that can block should use callbacks.
+Thus if loadUser blocked in the following example, it should really use a callback instead of returning a value.
+
+
public class RecommendationService {
+
+
+Queue Callbacks - Simple minded implementation of RecommendationService
+
+
+ privatefinalSimpleLRUCache<String, User> users =
+ newSimpleLRUCache<>(10_000);
+
+ publicList<Recommendation> recommend(finalString userName) {
+ User user = users.get(userName);
+ if (user ==null) {
+ user = loadUser(userName);
+ }
+ return runRulesEngineAgainstUser(user);
+ }
+
+
+
Let's pretend loadUser has to look in a local cache, and if the user is not found, look in an off-heap cache
+and if not found it must ask for the user from the UserService which must check its caches and perhaps fallback
+to loading the user data from a database or from other services.
+In other words, loadUser can potentially block on IO.
+
+
+Queue Callbacks - The first rule of Queue Club - don't block
+
+
Our client does not block, but our service does. Going back to our RecommendationService.
+If we get a lot of cache hits for user loads, perhaps the
+block will not be that long, but it will be there and every time we have to fault in a user, the whole system
+is gummed up. What we want to be able to do is if we can't handle the recommendation request,
+we go ahead and make an async call to the UserDataService. When that async callback comes back, then we
+handle that request. In the mean time, we handle recommendation lists requests as quickly as we can.
+We never block.
+
+
So let's revisit the service. The first thing we are going to do is make the service method take
+a callback. Before we do that, let's set down some rules.
+
+
+The first rule of queue club don't block.
+
+
+The second rule of queue club if you are not ready, use a callback and continue handling stuff you are ready for
+
+
+Queue Callbacks - Adding a CallBack to the RecommendationService inproc microservice
Now we are taking a callback and we can decide when we want to handle this recommendation generation request.
+We can do it right away if there user data we need is in-memory or we can delay it.
+
+
+If the user is found, call the callback right away for RecommendationService inproc microservice
+
+
+ publicvoid recommend(finalCallback<List<Recommendation>> recommendationsCallback,
+ finalString userName) {
+
+ /** Look for user in user cache. */
+ User user = users.get(userName);
+
+ /** If the user not found, load the user from the user service. */
+ if (user ==null) {
+ ...
+ } else {
+ /* Call the callback now because we can handle the callback now. */
+ recommendationsCallback.accept(runRulesEngineAgainstUser(user));
+ }
+
+ }
+
+
+
Notice, if the user is found in the cache, we run our recommendation rules in-memory and call the callback right away
+recommendationsCallback.accept(runRulesEngineAgainstUser(user)).
+
+
The interesting part is what do we do if don't have the user loaded.
+
+
+If the user was not found, load him from the user microservice, but still don't block
+
+
+
+ publicvoid recommend(finalCallback<List<Recommendation>> recommendationsCallback,
+ finalString userName) {
+
+
+ /** Look for user in users cache. */
+ User user = users.get(userName);
+
+ /** If the user not found, load the user from the user service. */
+ if (user ==null) {
+
+ /* Load user using Callback. */
+ userDataService.loadUser(newCallback<User>() {
+ @Override
+ publicvoidaccept(finalUserloadedUser) {
+ handleLoadFromUserDataService(loadedUser,
+ recommendationsCallback);
+ }
+ }, userName);
+
+ }
+ ...
+
+
+
Here we use a CallBack to load the user, and when the user is loaded, we call handleLoadFromUserDataService
+which adds some management about handling the callback so we can still handle this call, just not now.
+
+
+Lambda version of last example
+
+
+
+ publicvoid recommend(finalCallback<List<Recommendation>> recommendationsCallback,
+ finalString userName) {
+
+
+ /** Look for user in users cache. */
+ User user = users.get(userName);
+
+ /** If the user not found, load the user from the user service. */
+ if (user ==null) {
+
+ /* Load user using lambda expression. */
+ userDataService.loadUser(
+ loadedUser -> {
+ handleLoadFromUserDataService(loadedUser,
+ recommendationsCallback);
+ }, userName);
+
+ }
+ ...
+
+
+
Using lambdas like this makes the code more readable and terse, but remember don't deeply nest
+lambda expressions or you will create a code maintenance nightmare. Use them judiciously.
+
+
+Queue Callbacks - Doing something later
+
+
What we want is to handle the request for recommendations after the user service system loads
+the user from its store.
+
+
+Handling UserServiceData callback methods once we get them.
+handleLoadFromUserDataService rewritten using Lambda
+
+
+
+publicclassRecommendationService {
+
+...
+
+ /** Handle defered recommendations based on user loads. */
+ privatevoidhandleLoadFromUserDataService(finalUserloadedUser,
+ finalCallback<List<Recommendation>>recommendationsCallback) {
+
+ /** Add a runnable to the callbacks list. */
+ callbacks.add(() -> {
+ List<Recommendation> recommendations = runRulesEngineAgainstUser(loadedUser);
+ recommendationsCallback.accept(recommendations);
+ });
+
+ }
+
+
+
The important part there is that every time we get a callback call from UserDataService, we then
+perform our CPU intensive recommendation rules and callback our caller. Well not exactly, what we
+do is enqueue an runnable onto our callbacks queue, and later we will iterate through those but when?
+
+
+Queue Callbacks Handling callbacks when our receive queue is empty, a new batch started or we hit a batch limit
+
+
The RecommendationService can be notified when its queue is empty, it has started a new batch and when
+it has reached a batch limit. These are all good times to handle callbacks from the UserDataService.
It is important to remember when handling callbacks from another microservice that you want to handle
+callbacks from the other service before you handle more incomming requests from you clients.
+Essentially you have clients that have been waiting (async waiting but still), and these clients
+might represent an open TCP/IP connection like an HTTP call so it is best to close them out
+before handling more requests and like we said they were already waiting around with an open connection
+for users to load form the user service.
You can compose sharded workers (for in-memory, thread safe, CPU intensive services), or workers for IO
+or talking to foreign services or foreign buses.
+
+
Here is an example that uses a worker pool with three service workers in it:
Now this does some sort of IO and you want to have a bank of these running not just one so you can do
+IO in parallel. After some performance testing, you found out that three is the magic number.
+
+
You want to use your API for accessing this service:
+ ServiceWorkers dispatcher;
+ dispatcher = workers(); //Create a round robin service dispatcher
+ dispatcher.addServices(service1, service2, service3);
+ dispatcher.start(); // start up the workers
+
+
+
You can add services, POJOs and method consumers, method dispatchers to a service bundle.
+The service bundle is an integration point into QBit.
+
+
Let's add our new Service workers. ServiceWorkers is a ServiceMethodDispatcher.
+
+
/* Add the dispatcher to a service bundle. */
+ bundle = serviceBundleBuilder().setAddress("/root").build();
+ bundle.addServiceConsumer("/workers", dispatcher);
+ bundle.start();
+
+
We are probably going to add a helper method to the service bundle so most of this can happen in
+a single call.
+
+
Now you can start using your workers.
+
+
+ /* Start using the workers. */
+ finalMultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, "/workers");
+
+
+
Now you could use Spring or Guice to configure the builders and the service bundle.
+But you can just do it like the above which is good for testing and understanding QBit internals.
+
+
QBit also supports the concept of sharded services which is good for sharding resources like CPU
+(run a rules engine on each CPU core for a user recommendation engine).
+
+
QBit does not know how to shard your services, you have to give it a hint.
+You do this through a shard rule.
We worked on an app where the first argument to the services was the username, and then we used that to
+shard calls to a CPU intensive in-memory rules engine. This technique works. :)
+
+
The ServiceWorkers class has a method for creating a sharded worker pool.
The shardOnBeanPath allows you to create a complex bean path navigation call and use its property to shard on.
+
+
+ /* shard on 2nd arg which is an employee
+ Use the employees department's id property. */
+ dispatcher = shardOnBeanPath("[1].department.id");
+
+ /* Same as above. */
+ dispatcher = shardOnBeanPath("1/department/id");
+
+
+
+
+
+
+
+
+
diff --git a/javascripts/main.js b/javascripts/main.js
new file mode 100644
index 00000000..d8135d37
--- /dev/null
+++ b/javascripts/main.js
@@ -0,0 +1 @@
+console.log('This would be the main JS file.');
diff --git a/params.json b/params.json
new file mode 100644
index 00000000..68cadd4d
--- /dev/null
+++ b/params.json
@@ -0,0 +1,6 @@
+{
+ "name": "QBit - Microservices Lib",
+ "tagline": "The Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.",
+ "body": "[QBit Java Micorservices lib tutorials](https://github.com/MammatusTech/qbit-microservices-examples/wiki)\r\n\r\n#qbit - The Microservice Lib for Java - JSON, REST, WebSocket, Speed! \r\n[](https://travis-ci.org/advantageous/qbit) [](https://gitter.im/advantageous/qbit?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\r\n\r\n## Quick overview of QBit\r\n\r\nThe Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.\r\n\r\n> \"Precision beats power, and timing beats speed,\" -McGregor\r\n\r\n\r\nGot a question? Ask here: [QBit Google Group](https://groups.google.com/forum/#!forum/qbit-microservice).\r\n\r\nEverything is a queue. You have a choice. You can embrace it and control it. You can optimize for it.\r\nOr you can hide behind abstractions. QBit opens you up to peeking into what is going on, and allows you\r\nto pull some levers without selling your soul.\r\n\r\nQBit is a library not a framework. You can mix and match QBit with Spring, Guice, etc.\r\n\r\nQBit is FAST!\r\n\r\n\r\n\r\nCore Features\r\n============\r\n\r\n* Write REST based async microservices\r\n* Write ***WebSocket*** based async microservices (fast async RPC over WebSocket)\r\n* Actor Service Queues using micro-batching for high-speed message passing\r\n* Strongly async typed event bus which can be distributed\r\n* Async low overhead metrics gathering which can be queried and distributed (for doing fast lane analytics)\r\n* Complex async call coordination (with the Reactor) for reactive programming\r\n* Built-in support for ***health checks*** (and integration with tools like Consul)\r\n* Built-in support for ***monitoring*** (and integration with wire protocols like StatsD)\r\n* Built-in support for ***Service Discovery*** (with integration with health system, DNS SRV records and Consul)\r\n* Integration with persistent queues\r\n* [12 factor app port bindings](http://12factor.net/), health checks, KPI gathering, Logging MDC\r\n* API Gateway support for client generation and consumption via [Swagger](http://swagger.io/).\r\n* Our services can generate Swagger files (like idl for JSON/REST).\r\n* Remote client proxies for WebSocket (your interface is your IDL)\r\n\r\n\r\nStatus\r\n=====\r\nDeployed at several large fortune 100 companies. \r\nQBit now works with Vertx (standalone or embedded).\r\nYou can also use QBit no non-QBit projects, it is just a lib.\r\n\r\nLicense\r\n=====\r\nApache 2\r\n\r\n\r\n## Java Microservice Lib\r\n\r\nQBit has inproc services, REST microservices and WebSocket microservices as well as an\r\nin-proc service event bus (which can be per module or per app). It supports workers and in-memory services.\r\n\r\nBefore we describe more, here are two sample services:\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {...\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {...\r\n```\r\n\r\n\r\n#### Adder Service using URI params\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {...\r\n }\r\n```\r\n\r\n\r\n\r\nQBit philosophy:\r\n====\r\nAt the end of the day QBit is a simple library not a framework.\r\nYour app is not a QBit app but a Java app that uses the QBit lib.\r\nQBit allows you to work with Java UTIL concurrent, and does not endeavor to hide it from you.\r\nJust trying to take the sting out of it.\r\n\r\nDoes it work\r\n=====\r\nWe have used techniques in Boon and QBit with great success in high-end, high-performance, high-scalable apps.\r\nWe helped clients handle 10x the load with 1/10th the servers of their competitors using techniques in QBit.\r\nQBit is us being sick of hand tuning queue access and threads.\r\n\r\n\r\nBoon and QBit humility policy\r\n=====\r\nIdeas for Boon and QBit often come from all over the web. We make mistakes. Point them out.\r\nAs a developer of Boon and QBit, we are fellow travelers.\r\nIf you have an idea or technique you want to share, we listen.\r\n\r\n\r\nInspiration\r\n====\r\n\r\nA big inspiration for Boon/QBit was Vertx, Akka, Go Channels, Active Objects, Apartment Model Threading, Actor,\r\nand the Mechanical Sympathy papers.\r\n\r\nQBit has ideas that are similar to many frameworks. We are all reading the same papers.\r\nQBit got inspiration from the LMAX disruptor papers and this blog post about\r\n[link transfer queue versus disruptor](http://php.sabscape.com/blog/?p=557). We had some theories about\r\nqueues that blog post inspired us to try them out. Some of these theories are deployed at some of the\r\nbiggest middleware backends and whose name brands are known around the world. And thus QBit was born.\r\n\r\nQBit also took an lot of inspiration by the great work done\r\nby Tim Fox on Vertx. The first project using something that could actually be called QBit (albeit early QBit)\r\n was using Vertx on an web/mobile microservice for an app that could potentially have 80 million users.\r\n It was this\r\nexperience with Vertx and early QBit that led to QBit development and evolution. QBit is built on the\r\nshoulders of giants (Netty/Vertx).\r\n\r\nDoes QBit compete with...\r\n====\r\nSpring Disruptor: No. You could use QBit to write plugins for Spring Disruptor I suppose, but QBit does\r\nnot compete with Spring Disruptor.\r\nSpring Boot/Spring MVC: No. We use the same annotations but QBit is geared for high-speed in-memory\r\nmicroservices. It is more like Akka than Spring Boot. QBit has a subset of the features of Spring MVC\r\ngeared only for microservices, i.e., WebSocket RPC, REST, JSON marshaling, etc.\r\nAkka: No. Well Maybe. Akka has similar concepts but they take a different approach. QBit is more focused\r\n on Java, and microservices (REST, JSON, WebSocket) than Akka.\r\nLMAX Disruptor: No. In fact, we can use disruptor as on of the queues that QBit uses underneath the covers.\r\n\r\n\r\n(Early benchmarks have been removed. They were here. QBit got a lot faster.\r\n Benchmarking QBit is a moving target at the moment.\r\n Links and reports will be created.)\r\n\r\n\r\nCode Examples\r\n\r\n\r\n## Basic Queue example (REST style services is further down)\r\n\r\n====\r\n\r\n```java\r\n\r\n BasicQueue queue = BasicQueue.create(Integer.class, 1000);\r\n\r\n //Sending threads\r\n\r\n SendQueue sendQueue = queue.sendQueue();\r\n for (int index = 0; index < amount; index++) {\r\n sendQueue.send(index);\r\n }\r\n sendQueue.flushSends();\r\n ...\r\n sendQueue.sendAndFlush(code);\r\n //other methods for sendQueue, writeBatch, writeMany\r\n\r\n\r\n //Receiving Threads\r\n ReceiveQueue receiveQueue = queue.receiveQueue();\r\n Integer item = receiveQueue.take();\r\n //other methods poll(), pollWait(), readBatch(), readBatch(count)\r\n```\r\n\r\n\r\n### What is QBit again?\r\n\r\nQBit is a queuing library for microservices. It is similar to many other projects like Akka, Spring Reactor,\r\netc. QBit is just a library not a platform. QBit has libraries to put a service behind a queue.\r\nYou can use QBit queues directly or you can create a service. QBit services can be exposed by WebSocket,\r\nHTTP, HTTP pipeline, and other types of remoting. A service in QBit is a Java class whose methods are\r\n executed behind service queues. QBit implements apartment model threading and is similar to the\r\n Actor model or a better description would be Active Objects. QBit does not use a disruptor (but could).\r\n It uses regular Java Queues. QBit can do north of 100 million ping pong calls per second which is\r\n an amazing speed (seen as high as 200M). QBit also supports calling services via REST, and WebSocket.\r\n QBit is microservices in the pure Web sense: JSON, HTTP, WebSocket, etc. QBit uses micro batching to\r\n push messages through the pipe (queue, IO, etc.) faster to reduce thread hand-off.\r\n\r\n### QBit lingo\r\n\r\nQBit is a Java microservice lib supporting REST, JSON and WebSocket. It is written in Java but we could\r\none day write a version in Rust or Go or C# (but that would require a large payday).\r\n\r\n**Service**\r\nPOJO (plain old Java object) behind a queue that can receive method calls via proxy calls or events\r\n(May have one thread managing events, method calls, and responses or two one for method calls and events\r\n 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.\r\n\r\n**ServiceBundle**\r\nMany POJOs behind one response queue and many receive queues. There may be one thread for all responses\r\nor not. They also can be one receive queue.\r\n\r\n**Queue**\r\nA thread managing a queue. It supports batching. It has events for empty, reachedLimit, startedBatch,\r\nidle. You can listen to these events from services that sit behind a queue. You don't have to use Services.\r\nYou can use Queue's direct. In QBit, you have sender queues and receivers queues. They are separated to\r\nsupport micro-batching.\r\n\r\n**ServiceEndpointServer**\r\nServiceBundle that is exposed to REST and WebSocket communication.\r\n\r\n**EventBus**\r\nEventBus is a way to send a lot of messages to services that may be loosely coupled.\r\n\r\n**ClientProxy**\r\nClientProxy is a way to invoke service through async interface, service can be inproc (same process) or\r\nremoted over WebSocket.\r\n\r\n**Non-blocking**\r\nQBit is a non-blocking lib. You use CallBacks via Java 8 Lambdas. You can also send event messages and get\r\nreplies. Messaging is built into the system so you can easily coordinate complex tasks.\r\nQBit takes an object-oriented approach to service development so services look like normal Java services\r\nthat you\r\nalready write, but the services live behind a queue/thread. This is not a new concept. Microsoft did this\r\nwith DCOM/COM and called it active objects. Akka does it with actors and called them strongly typed Actors.\r\nThe important concepts is that you get the speed of reactive and actor style messaging but you develop\r\nin a natural OOP approach. QBit is not the first. QBit is not the only.\r\n\r\n\r\n**Speed**\r\nQBit is VERY fast. There is a of course a lot of room for improvement. But already 200M+ TPS inproc ping pong, 10M-20M+ TPS event bus, 500K TPS RPC calls over WebSocket/JSON, etc.\r\nMore work needs to be done to improve speed, but now it is fast enough where we are focusing more on\r\nusability.\r\nThe JSON support uses Boon by default which is up to 4x faster than other JSON parsers for the\r\nREST/JSON, WebSocket/JSON use case.\r\n\r\n**Reactive Programming**\r\nQBit provides a **Reactor** to manage async calls. This allows callbacks to be handled on the same thread that called them and it provides for timeout and error handling. Read [Reactor tutorial for creating reactive micro service programming](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices)\r\n\r\n**Service Discovery**\r\nBuilt in support for service discovery. This includes integration with Consul.\r\n\r\n\r\n**StatService**\r\nBuilt in support for stats. The **StatService** can be integrated with **StatsD** (Graphite, Grafana, DataDog, etc.) to publish passive stats. Or you can query the stats engine and react to the stats (counts, timings and levels). The **StatsService** is a reactive stats system that can be clustered. The StatService is reactive in that your services can publish to it and query it and react based on the results. You can implement things like rate limiting and react to an increased rate of something. The ServiceDiscovery system integrates with the HealthSystem and Consul to roll up each of your internal services that make up you micro service and publish the composite availably of your micro service to a single HTTP endpoint or a dead mans switch in Consul (TTL). \r\n\r\n\r\n\r\n### CURLable REST services example\r\n\r\nTalk is cheap. Let's look at some code. You can get a detailed walk through in the Wiki.\r\nWe have a lot of documentation already.\r\n\r\nWe will create a service that is exposed through REST/JSON.\r\n\r\nTo query the size of the todo list:\r\n\r\n```bash\r\ncurl localhost:8080/services/todo-service/todo/count\r\n```\r\n\r\nTo add a new TODO item.\r\n\r\n```bash\r\ncurl -X POST -H \"Content-Type: application/json\" -d \\\r\n'{\"name\":\"xyz\",\"description\":\"xyz\"}' \\\r\nhttp://localhost:8080/services/todo-service/todo\r\n```\r\n\r\nTo get a list of TODO items\r\n```bash\r\ncurl http://localhost:8080/services/todo-service/todo/\r\n```\r\n\r\nThe TODO example will use and track Todo items.\r\n\r\n#### Todo item POJO sans getter\r\n\r\n```java\r\npackage io.advantageous.qbit.examples;\r\n\r\nimport java.util.Date;\r\n\r\n\r\npublic class TodoItem {\r\n\r\n\r\n private final String description;\r\n private final String name;\r\n private final Date due;\r\n\r\n```\r\n\r\nThe TodoService uses Spring MVC style annotations.\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n\r\n private List todoItemList = new ArrayList<>();\r\n\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {\r\n\r\n return todoItemList.size();\r\n }\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {\r\n\r\n return todoItemList;\r\n }\r\n\r\n @RequestMapping(value = \"/todo\", method = RequestMethod.POST)\r\n public void add(TodoItem item) {\r\n\r\n todoItemList.add(item);\r\n }\r\n\r\n}\r\n\r\n```\r\n\r\n\r\n#### Sending non-JSON\r\n\r\nYou can POST/PUT non-JSON and you can capture the body as a `String` or as a `byte[]`. \r\nIf the content-type is set to anything but `application/json` and your body is defined a String or byte[].\r\nThis works automatically. (The content-type has to be set.)\r\n\r\n```java\r\n @RequestMapping(value = \"/body/bytes\", method = RequestMethod.POST)\r\n public boolean bodyPostBytes( byte[] body) {\r\n String string = new String(body, StandardCharsets.UTF_8);\r\n return string.equals(\"foo\");\r\n }\r\n\r\n @RequestMapping(value = \"/body/string\", method = RequestMethod.POST)\r\n public boolean bodyPostString(String body) {\r\n return body.equals(\"foo\");\r\n }\r\n```\r\n\r\n\r\n#### Sending different response codes for success\r\n\r\nBy default QBit sends a `200` (OK) for a non-void call (a call that has a return or a Callback). If the REST operation has no return or no callback then QBit sends a `202` (Accepted). There may be times when you want to send a 201 (Created) or some other code that is not an Exception. You can do that by setting `code` on `@RequestMapping`. By default the code is -1 which means use the default behavior (200 for success, 202 for one-way message, and 500 for errors).\r\n\r\n\r\n#### Sending different response codes for success\r\n```java\r\n\r\n @RequestMapping(value = \"/helloj7\", code = 221)\r\n public void helloJSend7(Callback>> callback) {\r\n callback.returnThis(JSendResponseBuilder.jSendResponseBuilder(Lists.list(\r\n \"hello \" + System.currentTimeMillis())).build());\r\n }\r\n\r\n```\r\n\r\n`Callbacks` can be used for internal services as well. It is often the case that you use a [CallbackBuilder](https://github.com/advantageous/qbit/wiki/%5BDocument%5D-CallbackBuilder-and-generics-for-Reactive-Java-Microservices) or a QBit [Reactor](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices) to manage service calls. \r\n\r\n#### Working with non JSON responses\r\n\r\nYou do not have to return JSON form rest calls.\r\nYou can return any binary or any text by using `HttpBinaryResponse` and `HttpTextResponse`.\r\n\r\n#### Returning non JSON from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildTextResponse());\r\n }\r\n```\r\n\r\n\r\n#### Returning binary from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildBinaryResponse());\r\n }\r\n```\r\n\r\n#### Side note Why Spring style annotations?\r\nWhy did we pick Spring style annotations?\r\n1) Spring is not a standard and neither is QBit. 2) We found the Spring annotations to be less verbose.\r\n3) More people use Spring than Java EE. We wrote QBit for people to use.\r\nWe could easily support JAX-RS style annotations, and we probably will.\r\nSince QBit focuses on JSON, we do not need all of the complexity of JAX-RS or even all the features of\r\nthe Spring MVC annotations. Also we can literally use the actual Spring annotations. QBit and Boon\r\nuse a non-type safe mechanism for annotations which means they are not tied to a particular lib.\r\nYou can define your own. We hate vendor tie-in even if it is an open source vendor.\r\n(We also support @POST, @GET which is similar to JAX-RS).\r\n\r\nNow just start it up.\r\n\r\n```java\r\n\r\n public static void main(String... args) {\r\n\r\n ServiceEndpointServer server = new EndpointServerBuilder().build();\r\n server.initServices(new TodoService());\r\n server.start();\r\n }\r\n```\r\n\r\n\r\n\r\nThat is it. There is also out of the box WebSocket support with client side proxy generation so\r\nyou can call into services at the rate of millions of calls per second.\r\n\r\n## Using URI Params for QBit microservice\r\n\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {\r\n\r\n return a + b;\r\n }\r\n }\r\n\r\n```\r\n\r\n## WebSocket\r\nYou can always invoke QBit services via a WebSocket proxy.\r\nThe advantage of a WebSocket proxy is it allows you execute 1M RPC+ a second (1 million remote calls\r\nevery second).\r\n\r\n\r\n#### Using a microservice remotely with WebSocket\r\n```java\r\n /* Start QBit client for WebSocket calls. */\r\n final Client client = clientBuilder()\r\n .setPort(7000).setRequestBatchSize(1).build();\r\n\r\n\r\n /* Create a proxy to the service. */\r\n final AdderServiceClientInterface adderService =\r\n client.createProxy(AdderServiceClientInterface.class,\r\n \"adder-service\");\r\n\r\n client.start();\r\n\r\n\r\n\r\n /* Call the service */\r\n adderService.add(System.out::println, 1, 2);\r\n\r\n```\r\n\r\nThe output is 3.\r\n\r\n```output\r\n3\r\n```\r\n\r\n\r\nThe above uses a WebSocket proxy interface to call the service async.\r\n\r\n```java\r\n\r\n interface AdderServiceClientInterface {\r\n\r\n void add(Callback callback, int a, int b);\r\n }\r\n```\r\n\r\n#### ServiceDiscovery aware websocket builders\r\n\r\nCreate websocket service client that is ServiceDiscovery aware.\r\n\r\n\r\n```java\r\n final Client client = clientBuilder.setServiceDiscovery(serviceDiscovery, \"echo\")\r\n .setUri(\"/echo\").setProtocolBatchSize(20).build().startClient();\r\n\r\n\r\n final EchoAsync echoClient = client.createProxy(EchoAsync.class, \"echo\");\r\n```\r\n\r\nCurrently the `clientBuilder` will load all service endpoints that are registered under the service name,\r\nand randomly pick one. \r\n\r\nServiceDiscovery includes Consul based, watching JSON files on disk, and DNS. It is easy to write your own service discovery as well and plug it into QBit.\r\n\r\n\r\nIn the future we can RoundRobin calls or shard calls to websocket service and/or provide auto fail over if the connection is closed. We do this for the event bus that uses service discovery but it is not baked into WebSocket based client stubs yet.\r\n\r\n\r\n## REST call with URI params\r\n\r\nThe last client example uses WebSocket. You could also just use REST, and actually use the URI params\r\nthat we setup.\r\nREST is nice but it is going to be slower than WebSocket support.\r\n\r\nQBit ships with a nice little HTTP client. We can use it.\r\n\r\nYou can use it to send async calls and WebSocket messages with the HTTP client.\r\n\r\n\r\nHere we will use the http client to invoke our remote method:\r\n\r\n#### Using a microservice remotely with REST QBit microservice client\r\n```java\r\n\r\n\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\")\r\n .setPort(7000).build();\r\n\r\n httpClient.start();\r\n String results = httpClient\r\n .get(\"/services/adder-service/add/2/2\").body();\r\n System.out.println(results);\r\n\r\n```\r\n\r\n\r\nThe output is 4.\r\n\r\n```output\r\n4\r\n```\r\n\r\n## Accessing The URI Param example with CURL\r\n\r\nYou can also access the service from curl.\r\n\r\n```bash\r\n$ curl http://localhost:7000/services/adder-service/add/2/2\r\n```\r\n\r\nSee this full example here: [QBit microservice getting started tutorial](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-------------QBit-microservice-example).\r\n\r\n[QBit URI params and WebSocket proxy client](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Using-QBit-microservice-lib's-REST-support-with-URI-Params)\r\n\r\n## Working with WebSocket, HttpClient etc.\r\n\r\nQBit has a library for working with and writing async microservices that is lightweight and fun to use.\r\n\r\n#### WebSocket server and client.\r\n\r\n\r\n#### Create an HTTP server\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n```\r\n\r\n#### Setup server WebSocket support\r\n```java\r\n /* Setup WebSocket Server support. */\r\n httpServer.setWebSocketOnOpenConsumer(webSocket -> {\r\n webSocket.setTextMessageConsumer(message -> {\r\n webSocket.sendText(\"ECHO \" + message);\r\n });\r\n });\r\n\r\n```\r\n\r\n#### Start the server\r\n```java\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n```\r\n\r\n#### Setup the WebSocket client\r\n```java\r\n\r\n /** CLIENT. */\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\n#### Client WebSocket\r\n\r\n```java\r\n\r\n /* Setup the client websocket. */\r\n WebSocket webSocket = httpClient\r\n .createWebSocket(\"/websocket/rocket\");\r\n\r\n /* Setup the text consumer. */\r\n webSocket.setTextMessageConsumer(message -> {\r\n System.out.println(message);\r\n });\r\n webSocket.openAndWait();\r\n\r\n /* Send some messages. */\r\n webSocket.sendText(\"Hi mom\");\r\n webSocket.sendText(\"Hello World!\");\r\n\r\n```\r\n\r\n#### Output\r\n```output\r\n\r\nECHO Hi mom\r\nECHO Hello World!\r\n\r\n```\r\n\r\nNow stop the server and client. Pretty easy eh?\r\n\r\n## High-speed HTTP client and server done microservice style\r\n\r\n\r\n##### Starting up an HTTP server\r\n\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n /* Setting up a request Consumer with Java 8 Lambda expression. */\r\n httpServer.setHttpRequestConsumer(httpRequest -> {\r\n\r\n Map results = new HashMap<>();\r\n results.put(\"method\", httpRequest.getMethod());\r\n results.put(\"uri\", httpRequest.getUri());\r\n results.put(\"body\", httpRequest.getBodyAsString());\r\n results.put(\"headers\", httpRequest.getHeaders());\r\n results.put(\"params\", httpRequest.getParams());\r\n httpRequest.getReceiver()\r\n .response(200, \"application/json\", Boon.toJson(results));\r\n });\r\n\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n\r\n\r\n```\r\n\r\nThe focus is on ease of use and using Java 8 Lambdas for callbacks so the code is tight and small.\r\n\r\n[Find out more about QBit's microservice style WebSocket support here](https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-WebSocket-support)\r\n\r\n\r\n## Using HTTP Client lib\r\n\r\nNow, let's try out our HTTP client.\r\n\r\n##### Starting up an HTTP client\r\n\r\n```java\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\nYou just pass the URL, the port and then call start.\r\n\r\n## Synchronous HTTP calls\r\n\r\nNow you can start sending HTTP requests.\r\n\r\n##### No Param HTTP GET\r\n\r\n```java\r\n /* Send no param get. */\r\n HttpResponse httpResponse = httpClient.get( \"/hello/mom\" );\r\n puts( httpResponse );\r\n```\r\n\r\nAn HTTP response just contains the results from the server.\r\n\r\n\r\n##### No Param HTTP Response\r\n\r\n```java\r\npublic interface HttpResponse {\r\n\r\n MultiMap headers();\r\n\r\n int code();\r\n\r\n String contentType();\r\n\r\n String body();\r\n\r\n}\r\n\r\n```\r\n\r\nThere are helper methods for sync HTTP GET calls.\r\n\r\n\r\n\r\n##### Helper methods for GET\r\n```java\r\n\r\n\r\n /* Send one param get. */\r\n httpResponse = httpClient.getWith1Param(\"/hello/singleParam\",\r\n \"hi\", \"mom\");\r\n puts(\"single param\", httpResponse );\r\n\r\n\r\n /* Send two param get. */\r\n httpResponse = httpClient.getWith2Params(\"/hello/twoParams\",\r\n \"hi\", \"mom\", \"hello\", \"dad\");\r\n puts(\"two params\", httpResponse );\r\n\r\n...\r\n\r\n /* Send five param get. */\r\n httpResponse = httpClient.getWith5Params(\"/hello/5params\",\r\n \"hi\", \"mom\",\r\n \"hello\", \"dad\",\r\n \"greetings\", \"kids\",\r\n \"yo\", \"pets\",\r\n \"hola\", \"neighbors\");\r\n puts(\"5 params\", httpResponse );\r\n\r\n\r\n```\r\n\r\nThe puts method is a helper method it does System.out.println more or less by the way.\r\n\r\nThe first five params are covered. Beyond five, you have to use the HttpBuilder.\r\n\r\n```java\r\n\r\n\r\n /* Send six params with get. */\r\n\r\n final HttpRequest httpRequest = httpRequestBuilder()\r\n .addParam(\"hi\", \"mom\")\r\n .addParam(\"hello\", \"dad\")\r\n .addParam(\"greetings\", \"kids\")\r\n .addParam(\"yo\", \"pets\")\r\n .addParam(\"hola\", \"pets\")\r\n .addParam(\"salutations\", \"all\").build();\r\n\r\n httpResponse = httpClient.sendRequestAndWait(httpRequest);\r\n puts(\"6 params\", httpResponse );\r\n```\r\n\r\n## Http Async HTTP Client\r\n\r\nThere are async calls for GET as well.\r\n\r\n#### Async calls for HTTP GET using Java 8 lambda\r\n\r\n```java\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsync(\"/hi/async\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith1Param(\"/hi/async\", \"hi\", \"mom\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda 1 param\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith2Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 2 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n...\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith5Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n \"p3\", \"v3\",\r\n \"p4\", \"v4\",\r\n \"p5\", \"v5\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 5 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n```\r\n\r\n[Find more about the easy to use, fast microservice HTTP client here]\r\n(https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-HttpClient-GET,-POST,-et-al,-JSON,-Java-8-Lambda).\r\n\r\n## InProc QBit services\r\n\r\nQBit allows for services behind queues to be run in-proc as well.\r\n\r\n```java\r\n\r\n /* POJO service. */\r\n final TodoManager todoManagerImpl = new TodoManager();\r\n\r\n /*\r\n Create the service which manages async calls to todoManagerImpl.\r\n */\r\n final Service service = serviceBuilder()\r\n .setServiceObject(todoManagerImpl)\r\n .build().startServiceQueue();\r\n\r\n\r\n /* Create Asynchronous proxy over Synchronous service. */\r\n final TodoManagerClientInterface todoManager =\r\n service.createProxy(TodoManagerClientInterface.class);\r\n\r\n service.startCallBackHandler();\r\n\r\n\r\n System.out.println(\"This is an async call\");\r\n /* Asynchronous method call. */\r\n todoManager.add(new Todo(\"Call Mom\", \"Give Mom a call\"));\r\n\r\n\r\n AtomicInteger countTracker = new AtomicInteger();\r\n //Hold count from async call to service... for testing and showing it is an async callback\r\n\r\n System.out.println(\"This is an async call to count\");\r\n\r\n todoManager.count(count -> {\r\n System.out.println(\"This lambda expression is the callback \" + count);\r\n\r\n countTracker.set(count);\r\n });\r\n\r\n\r\n todoManager.clientProxyFlush(); //Flush all methods. It batches calls.\r\n\r\n Sys.sleep(100);\r\n\r\n System.out.printf(\"This is the count back from the server %d\\n\", countTracker.get());\r\n\r\n```\r\n\r\n[Detailed tutorial on in-proc services is being written.](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-Working-with-inproc-MicroServices-within-QBit.)\r\n\r\n\r\n## QBit Event Bus\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\nQBit also has a service event bus. This example is a an employee benefits services example.\r\n\r\nWe have two channels.\r\n\r\n```\r\npublic static final String NEW_HIRE_CHANNEL = \"com.mycompnay.employee.new\";\r\n\r\npublic static final String PAYROLL_ADJUSTMENT_CHANNEL = \"com.mycompnay.employee.payroll\";\r\n```\r\n\r\nAn employee object looks like this:\r\n\r\n```java\r\n\r\npublic static class Employee {\r\n final String firstName;\r\n final int employeeId;\r\n```\r\n\r\n\r\nThis example has three services: EmployeeHiringService, BenefitsService, and PayrollService.\r\n\r\nThese services are inproc services. QBit supports WebSocket, HTTP and REST remote services as well, but for now, let's focus on inproc services. If you understand inproc then you will understand remote.\r\n\r\nThe EmployeeHiringService actually fires off the events to other two services.\r\n\r\n```java\r\npublic class EmployeeHiringService {\r\n\r\n\r\n public void hireEmployee(final Employee employee) {\r\n\r\n int salary = 100;\r\n System.out.printf(\"Hired employee %s\\n\", employee);\r\n\r\n //Does stuff to hire employee\r\n\r\n //Sends events\r\n final EventManager eventManager =\r\n serviceContext().eventManager();\r\n eventManager.send(NEW_HIRE_CHANNEL, employee);\r\n\r\n eventManager.sendArray(PAYROLL_ADJUSTMENT_CHANNEL,\r\n employee, salary);\r\n\r\n\r\n }\r\n\r\n }\r\n```\r\n\r\n\r\nNotice that we call sendArray so we can send the employee and their salary.\r\nThe listener for PAYROLL_ADJUSTMENT_CHANNEL will have to handle both an employee and an int\r\nthat represents the new employees salary.\r\nYou can also use event bus proxies so you do not have to call into the event bus at all.\r\n\r\nThe BenefitsService listens for new employees being hired so it can enroll them into the benefits system.\r\n\r\n```java\r\npublic static class BenefitsService {\r\n\r\n @OnEvent(NEW_HIRE_CHANNEL)\r\n public void enroll(final Employee employee) {\r\n\r\n System.out.printf(\"Employee enrolled into benefits system employee %s %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId());\r\n\r\n }\r\n\r\n```\r\n\r\nDaddy needs to get paid.\r\n\r\n```java\r\n public static class PayrollService {\r\n\r\n @OnEvent(PAYROLL_ADJUSTMENT_CHANNEL)\r\n public void addEmployeeToPayroll(final Employee employee, int salary) {\r\n\r\n System.out.printf(\"Employee added to payroll %s %d %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId(), salary);\r\n\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nThe employee is the employee object from the EmployeeHiringService.\r\n\r\nso you can get your benefits, and paid!\r\n\r\nFind more details here:\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\n\r\n## Private event bus and event bus proxies\r\n\r\n You can define your own interface to the event bus and you can use your own event buses with QBit.\r\n Each module in your service can have its own internal event bus.\r\n\r\n To learn more read:\r\n [QBit Microservice working with a private event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-private-event-bus-for-inproc-microservices)\r\n and [QBit Java Microservice lib using your own interface to the event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-strongly-typed-event-bus-proxies-for-QBit-Java-Microservice-lib).\r\n\r\n\r\n\r\n## Queue Callbacks\r\n\r\n To really grasp QBit, one must grasp the concepts of a CallBack.\r\n\r\n A CallBack is a way to get an async response in QBit.\r\n\r\n You call a service method and it calls you back.\r\n\r\n Client proxies can have callbacks:\r\n\r\n\r\n#### Queue Callbacks - RecommendationService client interface\r\n```java\r\n\r\npublic interface RecommendationServiceClient {\r\n\r\n\r\n void recommend(final Callback> recommendationsCallback,\r\n final String userName);\r\n}\r\n\r\n```\r\n\r\nCallbacks are Java 8 Consumers with some optional extra error handling.\r\n\r\n\r\n#### Queue Callbacks - Callback\r\n\r\n```java\r\n\r\n\r\npublic interface Callback extends java.util.function.Consumer {\r\n default void onError(java.lang.Throwable error) { /* compiled code */ }\r\n}\r\n\r\n```\r\n\r\nServices that can block should use callbacks.\r\nThus if loadUser blocked in the following example, it should really use a callback instead of returning a value.\r\n\r\npublic class RecommendationService {\r\n\r\n#### Queue Callbacks - Simple minded implementation of RecommendationService\r\n```java\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n public List recommend(final String userName) {\r\n User user = users.get(userName);\r\n if (user == null) {\r\n user = loadUser(userName);\r\n }\r\n return runRulesEngineAgainstUser(user);\r\n }\r\n\r\n```\r\n\r\n\r\nLet's pretend `loadUser` has to look in a local cache, and if the user is not found, look in an off-heap cache\r\nand if not found it must ask for the user from the UserService which must check its caches and perhaps fallback\r\nto loading the user data from a database or from other services.\r\nIn other words, `loadUser` can potentially block on IO.\r\n\r\n\r\n\r\n### Queue Callbacks - The first rule of Queue Club - don't block\r\n\r\n\r\nOur client does not block, but our service does. Going back to our `RecommendationService`.\r\nIf we get a lot of cache hits for user loads, perhaps the\r\nblock will not be that long, but it will be there and every time we have to fault in a user, the whole system\r\nis gummed up. What we want to be able to do is if we can't handle the recommendation request,\r\nwe go ahead and make an async call to the `UserDataService`. When that async callback comes back, then we\r\nhandle that request. In the mean time, we handle recommendation lists requests as quickly as we can.\r\nWe never block.\r\n\r\n\r\nSo let's revisit the service. The first thing we are going to do is make the service method take\r\na callback. Before we do that, let's set down some rules.\r\n\r\n\r\n#### The first rule of queue club don't block.\r\n#### The second rule of queue club if you are not ready, use a callback and continue handling stuff you are ready for\r\n\r\n\r\n#### Queue Callbacks - Adding a CallBack to the RecommendationService inproc microservice\r\n\r\n```java\r\npublic class RecommendationService {\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n```\r\n\r\n\r\n\r\nNow we are taking a callback and we can decide when we want to handle this recommendation generation request.\r\nWe can do it right away if there user data we need is in-memory or we can delay it.\r\n\r\n\r\n#### If the user is found, call the callback right away for RecommendationService inproc microservice\r\n\r\n```java\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n /** Look for user in user cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n ...\r\n } else {\r\n /* Call the callback now because we can handle the callback now. */\r\n recommendationsCallback.accept(runRulesEngineAgainstUser(user));\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nNotice, if the user is found in the cache, we run our recommendation rules in-memory and call the callback right away\r\n`recommendationsCallback.accept(runRulesEngineAgainstUser(user))`.\r\n\r\nThe interesting part is what do we do if don't have the user loaded.\r\n\r\n\r\n#### If the user was not found, load him from the user microservice, but still don't block\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using Callback. */\r\n userDataService.loadUser(new Callback() {\r\n @Override\r\n public void accept(final User loadedUser) {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nHere we use a CallBack to load the user, and when the user is loaded, we call `handleLoadFromUserDataService`\r\nwhich adds some management about handling the callback so we can still handle this call, just not now.\r\n\r\n\r\n\r\n#### Lambda version of last example\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using lambda expression. */\r\n userDataService.loadUser(\r\n loadedUser -> {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nUsing lambdas like this makes the code more readable and terse, but remember don't deeply nest\r\nlambda expressions or you will create a code maintenance nightmare. Use them judiciously.\r\n\r\n\r\n### Queue Callbacks - Doing something later\r\n\r\nWhat we want is to handle the request for recommendations after the user service system loads\r\nthe user from its store.\r\n\r\n\r\n\r\n#### Handling UserServiceData callback methods once we get them.\r\n\r\n```java\r\n\r\npublic class RecommendationService {\r\n\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n private UserDataServiceClient userDataService;\r\n\r\n\r\n private BlockingQueue callbacks =\r\n new ArrayBlockingQueue(10_000);\r\n\r\n\r\n ...\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n ...\r\n\r\n }\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks queue. */\r\n callbacks.add(new Runnable() {\r\n @Override\r\n public void run() {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n }\r\n });\r\n }\r\n\r\n\r\n\r\n```\r\n\r\n\r\n\r\n\r\n#### handleLoadFromUserDataService rewritten using Lambda\r\n\r\n```java\r\n\r\n\r\npublic class RecommendationService {\r\n\r\n...\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks list. */\r\n callbacks.add(() -> {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n });\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nThe important part there is that every time we get a callback call from `UserDataService`, we then\r\nperform our CPU intensive recommendation rules and callback our caller. Well not exactly, what we\r\ndo is enqueue an runnable onto our callbacks queue, and later we will iterate through those but when?\r\n\r\n\r\n### Queue Callbacks Handling callbacks when our receive queue is empty, a new batch started or we hit a batch limit\r\n\r\nThe `RecommendationService` can be notified when its queue is empty, it has started a new batch and when\r\nit has reached a batch limit. These are all good times to handle callbacks from the `UserDataService`.\r\n\r\n#### Draining our callback queue\r\n```java\r\n\r\n @QueueCallback({\r\n QueueCallbackType.EMPTY,\r\n QueueCallbackType.START_BATCH,\r\n QueueCallbackType.LIMIT})\r\n private void handleCallbacks() {\r\n\r\n flushServiceProxy(userDataService);\r\n Runnable runnable = callbacks.poll();\r\n\r\n while (runnable != null) {\r\n runnable.run();\r\n runnable = callbacks.poll();\r\n }\r\n }\r\n\r\n```\r\n\r\nIt is important to remember when handling callbacks from another microservice that you want to handle\r\ncallbacks from the other service before you handle more incomming requests from you clients.\r\nEssentially you have clients that have been waiting (async waiting but still), and these clients\r\nmight represent an open TCP/IP connection like an HTTP call so it is best to close them out\r\nbefore handling more requests and like we said they were already waiting around with an open connection\r\nfor users to load form the user service.\r\n\r\nTo learn more about CallBacks, plesae read [QBit Java MicroService Lib CallBack fundamentals]([Rough Cut] QBit Microservice Lib Working With CallBacks).\r\n\r\n\r\n\r\n\r\n## Workers - pools and shards\r\n\r\n```java\r\npublic class ServiceWorkers {\r\n\r\n public static RoundRobinServiceDispatcher workers() {...\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {...\r\n```\r\n\r\nYou can compose sharded workers (for in-memory, thread safe, CPU intensive services), or workers for IO\r\nor talking to foreign services or foreign buses.\r\n\r\nHere is an example that uses a worker pool with three service workers in it:\r\n\r\nLet's say you have a service that does something:\r\n\r\n```java\r\n\r\n //Your POJO\r\n public class MultiWorker {\r\n\r\n void doSomeWork(...) {\r\n ...\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nNow this does some sort of IO and you want to have a bank of these running not just one so you can do\r\nIO in parallel. After some performance testing, you found out that three is the magic number.\r\n\r\nYou want to use your API for accessing this service:\r\n\r\n```java\r\n public interface MultiWorkerClient {\r\n void doSomeWork(...);\r\n }\r\n\r\n```\r\n\r\nNow let's create a bank of these and use it.\r\n\r\nFirst create the QBit services which add the thread/queue/microbatch.\r\n\r\n```java\r\n\r\n /* Create a service builder. */\r\n final ServiceBuilder serviceBuilder = serviceBuilder();\r\n\r\n /* Create some qbit services. */\r\n final Service service1 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service2 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service3 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n```\r\n\r\nNow add them to a ServiceWorkers object.\r\n\r\n```java\r\n\r\n ServiceWorkers dispatcher;\r\n dispatcher = workers(); //Create a round robin service dispatcher\r\n dispatcher.addServices(service1, service2, service3);\r\n dispatcher.start(); // start up the workers\r\n\r\n```\r\n\r\nYou can add services, POJOs and method consumers, method dispatchers to a service bundle.\r\nThe service bundle is an integration point into QBit.\r\n\r\nLet's add our new Service workers. ServiceWorkers is a ServiceMethodDispatcher.\r\n\r\n```Java\r\n /* Add the dispatcher to a service bundle. */\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nWe are probably going to add a helper method to the service bundle so most of this can happen in\r\na single call.\r\n\r\nNow you can start using your workers.\r\n\r\n```java\r\n\r\n /* Start using the workers. */\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n```\r\n\r\nNow you could use Spring or Guice to configure the builders and the service bundle.\r\nBut you can just do it like the above which is good for testing and understanding QBit internals.\r\n\r\nQBit also supports the concept of sharded services which is good for sharding resources like CPU\r\n(run a rules engine on each CPU core for a user recommendation engine).\r\n\r\nQBit does not know how to shard your services, you have to give it a hint.\r\nYou do this through a shard rule.\r\n\r\n```java\r\npublic interface ShardRule {\r\n int shard(String methodName, Object[] args, int numWorkers);\r\n}\r\n```\r\nWe worked on an app where the first argument to the services was the username, and then we used that to\r\nshard calls to a CPU intensive in-memory rules engine. This technique works. :)\r\n\r\nThe ServiceWorkers class has a method for creating a sharded worker pool.\r\n\r\n```java\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nTo use you just pass a shard key when you create the service workers.\r\n\r\n```java\r\n\r\n\r\n dispatcher = shardedWorkers((methodName, methodArgs, numWorkers) -> {\r\n String userName = methodArgs[0].toString();\r\n int shardKey = userName.hashCode() % numWorkers;\r\n return shardKey;\r\n });\r\n\r\n```\r\n\r\nThen add your services to the ServiceWorkers composition.\r\n```java\r\n int workerCount = Runtime.getRuntime().availableProcessors();\r\n\r\n for (int index = 0; index < workerCount; index++) {\r\n final Service service = serviceBuilder\r\n .setServiceObject(new ContentRulesEngine()).build();\r\n dispatcher.addServices(service);\r\n\r\n }\r\n```\r\n\r\nThen add it to the service bundle as before.\r\n```java\r\n\r\n dispatcher.start();\r\n\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nThen just use it:\r\n\r\n```java\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n for (int index = 0; index < 100; index++) {\r\n String userName = \"rickhigh\" + index;\r\n worker.pickSuggestions(userName);\r\n }\r\n\r\n```\r\n\r\n### Built in shard rules\r\n\r\n```java\r\n\r\n\r\npublic class ServiceWorkers {\r\n...\r\n public static ShardedMethodDispatcher shardOnFirstArgumentWorkers() {\r\n ...\r\n }\r\n\r\n...\r\n\r\n public static ShardedMethodDispatcher shardOnFifthArgumentWorkers() {\r\n ...\r\n }\r\n\r\n\r\n public static ShardedMethodDispatcher shardOnBeanPath(final String beanPath) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nThe shardOnBeanPath allows you to create a complex bean path navigation call and use its property to shard on.\r\n\r\n```java\r\n\r\n /* shard on 2nd arg which is an employee\r\n Use the employees department's id property. */\r\n dispatcher = shardOnBeanPath(\"[1].department.id\");\r\n\r\n /* Same as above. */\r\n dispatcher = shardOnBeanPath(\"1/department/id\");\r\n\r\n```\r\n\r\n[Read more about Service sharding and service workers here](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-QBit-Microservices-using-Service-Workers-and-sharded-service-workers)\r\n\r\n\r\nYou can find a lot more in the wiki. Also follow the commits.\r\nWe have been busy beavers.\r\n[QBit the microservice lib for Java - JSON, REST, WebSocket](https://github.com/advantageous/qbit/wiki).",
+ "note": "Don't delete this file! It's used internally to help with page regeneration."
+}
\ No newline at end of file
diff --git a/stylesheets/github-light.css b/stylesheets/github-light.css
new file mode 100644
index 00000000..872a6f4b
--- /dev/null
+++ b/stylesheets/github-light.css
@@ -0,0 +1,116 @@
+/*
+ Copyright 2014 GitHub Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+.pl-c /* comment */ {
+ color: #969896;
+}
+
+.pl-c1 /* constant, markup.raw, meta.diff.header, meta.module-reference, meta.property-name, support, support.constant, support.variable, variable.other.constant */,
+.pl-s .pl-v /* string variable */ {
+ color: #0086b3;
+}
+
+.pl-e /* entity */,
+.pl-en /* entity.name */ {
+ color: #795da3;
+}
+
+.pl-s .pl-s1 /* string source */,
+.pl-smi /* storage.modifier.import, storage.modifier.package, storage.type.java, variable.other, variable.parameter.function */ {
+ color: #333;
+}
+
+.pl-ent /* entity.name.tag */ {
+ color: #63a35c;
+}
+
+.pl-k /* keyword, storage, storage.type */ {
+ color: #a71d5d;
+}
+
+.pl-pds /* punctuation.definition.string, string.regexp.character-class */,
+.pl-s /* string */,
+.pl-s .pl-pse .pl-s1 /* string punctuation.section.embedded source */,
+.pl-sr /* string.regexp */,
+.pl-sr .pl-cce /* string.regexp constant.character.escape */,
+.pl-sr .pl-sra /* string.regexp string.regexp.arbitrary-repitition */,
+.pl-sr .pl-sre /* string.regexp source.ruby.embedded */ {
+ color: #183691;
+}
+
+.pl-v /* variable */ {
+ color: #ed6a43;
+}
+
+.pl-id /* invalid.deprecated */ {
+ color: #b52a1d;
+}
+
+.pl-ii /* invalid.illegal */ {
+ background-color: #b52a1d;
+ color: #f8f8f8;
+}
+
+.pl-sr .pl-cce /* string.regexp constant.character.escape */ {
+ color: #63a35c;
+ font-weight: bold;
+}
+
+.pl-ml /* markup.list */ {
+ color: #693a17;
+}
+
+.pl-mh /* markup.heading */,
+.pl-mh .pl-en /* markup.heading entity.name */,
+.pl-ms /* meta.separator */ {
+ color: #1d3e81;
+ font-weight: bold;
+}
+
+.pl-mq /* markup.quote */ {
+ color: #008080;
+}
+
+.pl-mi /* markup.italic */ {
+ color: #333;
+ font-style: italic;
+}
+
+.pl-mb /* markup.bold */ {
+ color: #333;
+ font-weight: bold;
+}
+
+.pl-md /* markup.deleted, meta.diff.header.from-file */ {
+ background-color: #ffecec;
+ color: #bd2c00;
+}
+
+.pl-mi1 /* markup.inserted, meta.diff.header.to-file */ {
+ background-color: #eaffea;
+ color: #55a532;
+}
+
+.pl-mdr /* meta.diff.range */ {
+ color: #795da3;
+ font-weight: bold;
+}
+
+.pl-mo /* meta.output */ {
+ color: #1d3e81;
+}
+
diff --git a/stylesheets/stylesheet.css b/stylesheets/stylesheet.css
new file mode 100644
index 00000000..3da34852
--- /dev/null
+++ b/stylesheets/stylesheet.css
@@ -0,0 +1,425 @@
+/*******************************************************************************
+Slate Theme for GitHub Pages
+by Jason Costello, @jsncostello
+*******************************************************************************/
+
+@import url(github-light.css);
+
+/*******************************************************************************
+MeyerWeb Reset
+*******************************************************************************/
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed,
+figure, figcaption, footer, header, hgroup,
+menu, nav, output, ruby, section, summary,
+time, mark, audio, video {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font: inherit;
+ vertical-align: baseline;
+}
+
+/* HTML5 display-role reset for older browsers */
+article, aside, details, figcaption, figure,
+footer, header, hgroup, menu, nav, section {
+ display: block;
+}
+
+ol, ul {
+ list-style: none;
+}
+
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+/*******************************************************************************
+Theme Styles
+*******************************************************************************/
+
+body {
+ box-sizing: border-box;
+ color:#373737;
+ background: #212121;
+ font-size: 16px;
+ font-family: 'Myriad Pro', Calibri, Helvetica, Arial, sans-serif;
+ line-height: 1.5;
+ -webkit-font-smoothing: antialiased;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ margin: 10px 0;
+ font-weight: 700;
+ color:#222222;
+ font-family: 'Lucida Grande', 'Calibri', Helvetica, Arial, sans-serif;
+ letter-spacing: -1px;
+}
+
+h1 {
+ font-size: 36px;
+ font-weight: 700;
+}
+
+h2 {
+ padding-bottom: 10px;
+ font-size: 32px;
+ background: url('../images/bg_hr.png') repeat-x bottom;
+}
+
+h3 {
+ font-size: 24px;
+}
+
+h4 {
+ font-size: 21px;
+}
+
+h5 {
+ font-size: 18px;
+}
+
+h6 {
+ font-size: 16px;
+}
+
+p {
+ margin: 10px 0 15px 0;
+}
+
+footer p {
+ color: #f2f2f2;
+}
+
+a {
+ text-decoration: none;
+ color: #007edf;
+ text-shadow: none;
+
+ transition: color 0.5s ease;
+ transition: text-shadow 0.5s ease;
+ -webkit-transition: color 0.5s ease;
+ -webkit-transition: text-shadow 0.5s ease;
+ -moz-transition: color 0.5s ease;
+ -moz-transition: text-shadow 0.5s ease;
+ -o-transition: color 0.5s ease;
+ -o-transition: text-shadow 0.5s ease;
+ -ms-transition: color 0.5s ease;
+ -ms-transition: text-shadow 0.5s ease;
+}
+
+a:hover, a:focus {text-decoration: underline;}
+
+footer a {
+ color: #F2F2F2;
+ text-decoration: underline;
+}
+
+em {
+ font-style: italic;
+}
+
+strong {
+ font-weight: bold;
+}
+
+img {
+ position: relative;
+ margin: 0 auto;
+ max-width: 739px;
+ padding: 5px;
+ margin: 10px 0 10px 0;
+ border: 1px solid #ebebeb;
+
+ box-shadow: 0 0 5px #ebebeb;
+ -webkit-box-shadow: 0 0 5px #ebebeb;
+ -moz-box-shadow: 0 0 5px #ebebeb;
+ -o-box-shadow: 0 0 5px #ebebeb;
+ -ms-box-shadow: 0 0 5px #ebebeb;
+}
+
+p img {
+ display: inline;
+ margin: 0;
+ padding: 0;
+ vertical-align: middle;
+ text-align: center;
+ border: none;
+}
+
+pre, code {
+ width: 100%;
+ color: #222;
+ background-color: #fff;
+
+ font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace;
+ font-size: 14px;
+
+ border-radius: 2px;
+ -moz-border-radius: 2px;
+ -webkit-border-radius: 2px;
+}
+
+pre {
+ width: 100%;
+ padding: 10px;
+ box-shadow: 0 0 10px rgba(0,0,0,.1);
+ overflow: auto;
+}
+
+code {
+ padding: 3px;
+ margin: 0 3px;
+ box-shadow: 0 0 10px rgba(0,0,0,.1);
+}
+
+pre code {
+ display: block;
+ box-shadow: none;
+}
+
+blockquote {
+ color: #666;
+ margin-bottom: 20px;
+ padding: 0 0 0 20px;
+ border-left: 3px solid #bbb;
+}
+
+
+ul, ol, dl {
+ margin-bottom: 15px
+}
+
+ul {
+ list-style-position: inside;
+ list-style: disc;
+ padding-left: 20px;
+}
+
+ol {
+ list-style-position: inside;
+ list-style: decimal;
+ padding-left: 20px;
+}
+
+dl dt {
+ font-weight: bold;
+}
+
+dl dd {
+ padding-left: 20px;
+ font-style: italic;
+}
+
+dl p {
+ padding-left: 20px;
+ font-style: italic;
+}
+
+hr {
+ height: 1px;
+ margin-bottom: 5px;
+ border: none;
+ background: url('../images/bg_hr.png') repeat-x center;
+}
+
+table {
+ border: 1px solid #373737;
+ margin-bottom: 20px;
+ text-align: left;
+ }
+
+th {
+ font-family: 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif;
+ padding: 10px;
+ background: #373737;
+ color: #fff;
+ }
+
+td {
+ padding: 10px;
+ border: 1px solid #373737;
+ }
+
+form {
+ background: #f2f2f2;
+ padding: 20px;
+}
+
+/*******************************************************************************
+Full-Width Styles
+*******************************************************************************/
+
+.outer {
+ width: 100%;
+}
+
+.inner {
+ position: relative;
+ max-width: 640px;
+ padding: 20px 10px;
+ margin: 0 auto;
+}
+
+#forkme_banner {
+ display: block;
+ position: absolute;
+ top:0;
+ right: 10px;
+ z-index: 10;
+ padding: 10px 50px 10px 10px;
+ color: #fff;
+ background: url('../images/blacktocat.png') #0090ff no-repeat 95% 50%;
+ font-weight: 700;
+ box-shadow: 0 0 10px rgba(0,0,0,.5);
+ border-bottom-left-radius: 2px;
+ border-bottom-right-radius: 2px;
+}
+
+#header_wrap {
+ background: #212121;
+ background: -moz-linear-gradient(top, #373737, #212121);
+ background: -webkit-linear-gradient(top, #373737, #212121);
+ background: -ms-linear-gradient(top, #373737, #212121);
+ background: -o-linear-gradient(top, #373737, #212121);
+ background: linear-gradient(top, #373737, #212121);
+}
+
+#header_wrap .inner {
+ padding: 50px 10px 30px 10px;
+}
+
+#project_title {
+ margin: 0;
+ color: #fff;
+ font-size: 42px;
+ font-weight: 700;
+ text-shadow: #111 0px 0px 10px;
+}
+
+#project_tagline {
+ color: #fff;
+ font-size: 24px;
+ font-weight: 300;
+ background: none;
+ text-shadow: #111 0px 0px 10px;
+}
+
+#downloads {
+ position: absolute;
+ width: 210px;
+ z-index: 10;
+ bottom: -40px;
+ right: 0;
+ height: 70px;
+ background: url('../images/icon_download.png') no-repeat 0% 90%;
+}
+
+.zip_download_link {
+ display: block;
+ float: right;
+ width: 90px;
+ height:70px;
+ text-indent: -5000px;
+ overflow: hidden;
+ background: url(../images/sprite_download.png) no-repeat bottom left;
+}
+
+.tar_download_link {
+ display: block;
+ float: right;
+ width: 90px;
+ height:70px;
+ text-indent: -5000px;
+ overflow: hidden;
+ background: url(../images/sprite_download.png) no-repeat bottom right;
+ margin-left: 10px;
+}
+
+.zip_download_link:hover {
+ background: url(../images/sprite_download.png) no-repeat top left;
+}
+
+.tar_download_link:hover {
+ background: url(../images/sprite_download.png) no-repeat top right;
+}
+
+#main_content_wrap {
+ background: #f2f2f2;
+ border-top: 1px solid #111;
+ border-bottom: 1px solid #111;
+}
+
+#main_content {
+ padding-top: 40px;
+}
+
+#footer_wrap {
+ background: #212121;
+}
+
+
+
+/*******************************************************************************
+Small Device Styles
+*******************************************************************************/
+
+@media screen and (max-width: 480px) {
+ body {
+ font-size:14px;
+ }
+
+ #downloads {
+ display: none;
+ }
+
+ .inner {
+ min-width: 320px;
+ max-width: 480px;
+ }
+
+ #project_title {
+ font-size: 32px;
+ }
+
+ h1 {
+ font-size: 28px;
+ }
+
+ h2 {
+ font-size: 24px;
+ }
+
+ h3 {
+ font-size: 21px;
+ }
+
+ h4 {
+ font-size: 18px;
+ }
+
+ h5 {
+ font-size: 14px;
+ }
+
+ h6 {
+ font-size: 12px;
+ }
+
+ code, pre {
+ min-width: 320px;
+ max-width: 480px;
+ font-size: 11px;
+ }
+
+}
From 8d52c478f86cac56a89182ad4ae8a37db3cc7c2d Mon Sep 17 00:00:00 2001
From: Richard Hightower
Date: Fri, 8 Apr 2016 20:00:31 -0700
Subject: [PATCH 02/19] Create gh-pages branch via GitHub
---
index.html | 96 +++---
params.json | 2 +-
stylesheets/github-light.css | 34 +-
stylesheets/normalize.css | 424 +++++++++++++++++++++++
stylesheets/stylesheet.css | 638 +++++++++++++----------------------
5 files changed, 723 insertions(+), 471 deletions(-)
create mode 100644 stylesheets/normalize.css
diff --git a/index.html b/index.html
index e738a874..62b30745 100644
--- a/index.html
+++ b/index.html
@@ -1,52 +1,35 @@
-
-
+
-
-
-
-
-
-
- QBit - Microservices Lib
+
+ QBit - Microservices Lib by advantageous
+
+
+
+
+
-
-
-
-
The Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.
The Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.
-qbit - The Microservice Lib for Java - JSON, REST, WebSocket, Speed!
-
-
+Qbit - The Microservice Lib for Java - JSON, REST, WebSocket, Speed!
Quick overview of QBit
The Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.
-
-
"Precision beats power, and timing beats speed," -McGregor
Deployed at several large fortune 100 companies.
QBit now works with Vertx (standalone or embedded).
-You can also use QBit no non-QBit projects, it is just a lib.
+You can also use QBit on non-QBit projects, it is just a lib.
-
-
-
-
+
+
diff --git a/params.json b/params.json
index 68cadd4d..d8d64394 100644
--- a/params.json
+++ b/params.json
@@ -1,6 +1,6 @@
{
"name": "QBit - Microservices Lib",
"tagline": "The Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.",
- "body": "[QBit Java Micorservices lib tutorials](https://github.com/MammatusTech/qbit-microservices-examples/wiki)\r\n\r\n#qbit - The Microservice Lib for Java - JSON, REST, WebSocket, Speed! \r\n[](https://travis-ci.org/advantageous/qbit) [](https://gitter.im/advantageous/qbit?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\r\n\r\n## Quick overview of QBit\r\n\r\nThe Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.\r\n\r\n> \"Precision beats power, and timing beats speed,\" -McGregor\r\n\r\n\r\nGot a question? Ask here: [QBit Google Group](https://groups.google.com/forum/#!forum/qbit-microservice).\r\n\r\nEverything is a queue. You have a choice. You can embrace it and control it. You can optimize for it.\r\nOr you can hide behind abstractions. QBit opens you up to peeking into what is going on, and allows you\r\nto pull some levers without selling your soul.\r\n\r\nQBit is a library not a framework. You can mix and match QBit with Spring, Guice, etc.\r\n\r\nQBit is FAST!\r\n\r\n\r\n\r\nCore Features\r\n============\r\n\r\n* Write REST based async microservices\r\n* Write ***WebSocket*** based async microservices (fast async RPC over WebSocket)\r\n* Actor Service Queues using micro-batching for high-speed message passing\r\n* Strongly async typed event bus which can be distributed\r\n* Async low overhead metrics gathering which can be queried and distributed (for doing fast lane analytics)\r\n* Complex async call coordination (with the Reactor) for reactive programming\r\n* Built-in support for ***health checks*** (and integration with tools like Consul)\r\n* Built-in support for ***monitoring*** (and integration with wire protocols like StatsD)\r\n* Built-in support for ***Service Discovery*** (with integration with health system, DNS SRV records and Consul)\r\n* Integration with persistent queues\r\n* [12 factor app port bindings](http://12factor.net/), health checks, KPI gathering, Logging MDC\r\n* API Gateway support for client generation and consumption via [Swagger](http://swagger.io/).\r\n* Our services can generate Swagger files (like idl for JSON/REST).\r\n* Remote client proxies for WebSocket (your interface is your IDL)\r\n\r\n\r\nStatus\r\n=====\r\nDeployed at several large fortune 100 companies. \r\nQBit now works with Vertx (standalone or embedded).\r\nYou can also use QBit no non-QBit projects, it is just a lib.\r\n\r\nLicense\r\n=====\r\nApache 2\r\n\r\n\r\n## Java Microservice Lib\r\n\r\nQBit has inproc services, REST microservices and WebSocket microservices as well as an\r\nin-proc service event bus (which can be per module or per app). It supports workers and in-memory services.\r\n\r\nBefore we describe more, here are two sample services:\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {...\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {...\r\n```\r\n\r\n\r\n#### Adder Service using URI params\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {...\r\n }\r\n```\r\n\r\n\r\n\r\nQBit philosophy:\r\n====\r\nAt the end of the day QBit is a simple library not a framework.\r\nYour app is not a QBit app but a Java app that uses the QBit lib.\r\nQBit allows you to work with Java UTIL concurrent, and does not endeavor to hide it from you.\r\nJust trying to take the sting out of it.\r\n\r\nDoes it work\r\n=====\r\nWe have used techniques in Boon and QBit with great success in high-end, high-performance, high-scalable apps.\r\nWe helped clients handle 10x the load with 1/10th the servers of their competitors using techniques in QBit.\r\nQBit is us being sick of hand tuning queue access and threads.\r\n\r\n\r\nBoon and QBit humility policy\r\n=====\r\nIdeas for Boon and QBit often come from all over the web. We make mistakes. Point them out.\r\nAs a developer of Boon and QBit, we are fellow travelers.\r\nIf you have an idea or technique you want to share, we listen.\r\n\r\n\r\nInspiration\r\n====\r\n\r\nA big inspiration for Boon/QBit was Vertx, Akka, Go Channels, Active Objects, Apartment Model Threading, Actor,\r\nand the Mechanical Sympathy papers.\r\n\r\nQBit has ideas that are similar to many frameworks. We are all reading the same papers.\r\nQBit got inspiration from the LMAX disruptor papers and this blog post about\r\n[link transfer queue versus disruptor](http://php.sabscape.com/blog/?p=557). We had some theories about\r\nqueues that blog post inspired us to try them out. Some of these theories are deployed at some of the\r\nbiggest middleware backends and whose name brands are known around the world. And thus QBit was born.\r\n\r\nQBit also took an lot of inspiration by the great work done\r\nby Tim Fox on Vertx. The first project using something that could actually be called QBit (albeit early QBit)\r\n was using Vertx on an web/mobile microservice for an app that could potentially have 80 million users.\r\n It was this\r\nexperience with Vertx and early QBit that led to QBit development and evolution. QBit is built on the\r\nshoulders of giants (Netty/Vertx).\r\n\r\nDoes QBit compete with...\r\n====\r\nSpring Disruptor: No. You could use QBit to write plugins for Spring Disruptor I suppose, but QBit does\r\nnot compete with Spring Disruptor.\r\nSpring Boot/Spring MVC: No. We use the same annotations but QBit is geared for high-speed in-memory\r\nmicroservices. It is more like Akka than Spring Boot. QBit has a subset of the features of Spring MVC\r\ngeared only for microservices, i.e., WebSocket RPC, REST, JSON marshaling, etc.\r\nAkka: No. Well Maybe. Akka has similar concepts but they take a different approach. QBit is more focused\r\n on Java, and microservices (REST, JSON, WebSocket) than Akka.\r\nLMAX Disruptor: No. In fact, we can use disruptor as on of the queues that QBit uses underneath the covers.\r\n\r\n\r\n(Early benchmarks have been removed. They were here. QBit got a lot faster.\r\n Benchmarking QBit is a moving target at the moment.\r\n Links and reports will be created.)\r\n\r\n\r\nCode Examples\r\n\r\n\r\n## Basic Queue example (REST style services is further down)\r\n\r\n====\r\n\r\n```java\r\n\r\n BasicQueue queue = BasicQueue.create(Integer.class, 1000);\r\n\r\n //Sending threads\r\n\r\n SendQueue sendQueue = queue.sendQueue();\r\n for (int index = 0; index < amount; index++) {\r\n sendQueue.send(index);\r\n }\r\n sendQueue.flushSends();\r\n ...\r\n sendQueue.sendAndFlush(code);\r\n //other methods for sendQueue, writeBatch, writeMany\r\n\r\n\r\n //Receiving Threads\r\n ReceiveQueue receiveQueue = queue.receiveQueue();\r\n Integer item = receiveQueue.take();\r\n //other methods poll(), pollWait(), readBatch(), readBatch(count)\r\n```\r\n\r\n\r\n### What is QBit again?\r\n\r\nQBit is a queuing library for microservices. It is similar to many other projects like Akka, Spring Reactor,\r\netc. QBit is just a library not a platform. QBit has libraries to put a service behind a queue.\r\nYou can use QBit queues directly or you can create a service. QBit services can be exposed by WebSocket,\r\nHTTP, HTTP pipeline, and other types of remoting. A service in QBit is a Java class whose methods are\r\n executed behind service queues. QBit implements apartment model threading and is similar to the\r\n Actor model or a better description would be Active Objects. QBit does not use a disruptor (but could).\r\n It uses regular Java Queues. QBit can do north of 100 million ping pong calls per second which is\r\n an amazing speed (seen as high as 200M). QBit also supports calling services via REST, and WebSocket.\r\n QBit is microservices in the pure Web sense: JSON, HTTP, WebSocket, etc. QBit uses micro batching to\r\n push messages through the pipe (queue, IO, etc.) faster to reduce thread hand-off.\r\n\r\n### QBit lingo\r\n\r\nQBit is a Java microservice lib supporting REST, JSON and WebSocket. It is written in Java but we could\r\none day write a version in Rust or Go or C# (but that would require a large payday).\r\n\r\n**Service**\r\nPOJO (plain old Java object) behind a queue that can receive method calls via proxy calls or events\r\n(May have one thread managing events, method calls, and responses or two one for method calls and events\r\n 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.\r\n\r\n**ServiceBundle**\r\nMany POJOs behind one response queue and many receive queues. There may be one thread for all responses\r\nor not. They also can be one receive queue.\r\n\r\n**Queue**\r\nA thread managing a queue. It supports batching. It has events for empty, reachedLimit, startedBatch,\r\nidle. You can listen to these events from services that sit behind a queue. You don't have to use Services.\r\nYou can use Queue's direct. In QBit, you have sender queues and receivers queues. They are separated to\r\nsupport micro-batching.\r\n\r\n**ServiceEndpointServer**\r\nServiceBundle that is exposed to REST and WebSocket communication.\r\n\r\n**EventBus**\r\nEventBus is a way to send a lot of messages to services that may be loosely coupled.\r\n\r\n**ClientProxy**\r\nClientProxy is a way to invoke service through async interface, service can be inproc (same process) or\r\nremoted over WebSocket.\r\n\r\n**Non-blocking**\r\nQBit is a non-blocking lib. You use CallBacks via Java 8 Lambdas. You can also send event messages and get\r\nreplies. Messaging is built into the system so you can easily coordinate complex tasks.\r\nQBit takes an object-oriented approach to service development so services look like normal Java services\r\nthat you\r\nalready write, but the services live behind a queue/thread. This is not a new concept. Microsoft did this\r\nwith DCOM/COM and called it active objects. Akka does it with actors and called them strongly typed Actors.\r\nThe important concepts is that you get the speed of reactive and actor style messaging but you develop\r\nin a natural OOP approach. QBit is not the first. QBit is not the only.\r\n\r\n\r\n**Speed**\r\nQBit is VERY fast. There is a of course a lot of room for improvement. But already 200M+ TPS inproc ping pong, 10M-20M+ TPS event bus, 500K TPS RPC calls over WebSocket/JSON, etc.\r\nMore work needs to be done to improve speed, but now it is fast enough where we are focusing more on\r\nusability.\r\nThe JSON support uses Boon by default which is up to 4x faster than other JSON parsers for the\r\nREST/JSON, WebSocket/JSON use case.\r\n\r\n**Reactive Programming**\r\nQBit provides a **Reactor** to manage async calls. This allows callbacks to be handled on the same thread that called them and it provides for timeout and error handling. Read [Reactor tutorial for creating reactive micro service programming](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices)\r\n\r\n**Service Discovery**\r\nBuilt in support for service discovery. This includes integration with Consul.\r\n\r\n\r\n**StatService**\r\nBuilt in support for stats. The **StatService** can be integrated with **StatsD** (Graphite, Grafana, DataDog, etc.) to publish passive stats. Or you can query the stats engine and react to the stats (counts, timings and levels). The **StatsService** is a reactive stats system that can be clustered. The StatService is reactive in that your services can publish to it and query it and react based on the results. You can implement things like rate limiting and react to an increased rate of something. The ServiceDiscovery system integrates with the HealthSystem and Consul to roll up each of your internal services that make up you micro service and publish the composite availably of your micro service to a single HTTP endpoint or a dead mans switch in Consul (TTL). \r\n\r\n\r\n\r\n### CURLable REST services example\r\n\r\nTalk is cheap. Let's look at some code. You can get a detailed walk through in the Wiki.\r\nWe have a lot of documentation already.\r\n\r\nWe will create a service that is exposed through REST/JSON.\r\n\r\nTo query the size of the todo list:\r\n\r\n```bash\r\ncurl localhost:8080/services/todo-service/todo/count\r\n```\r\n\r\nTo add a new TODO item.\r\n\r\n```bash\r\ncurl -X POST -H \"Content-Type: application/json\" -d \\\r\n'{\"name\":\"xyz\",\"description\":\"xyz\"}' \\\r\nhttp://localhost:8080/services/todo-service/todo\r\n```\r\n\r\nTo get a list of TODO items\r\n```bash\r\ncurl http://localhost:8080/services/todo-service/todo/\r\n```\r\n\r\nThe TODO example will use and track Todo items.\r\n\r\n#### Todo item POJO sans getter\r\n\r\n```java\r\npackage io.advantageous.qbit.examples;\r\n\r\nimport java.util.Date;\r\n\r\n\r\npublic class TodoItem {\r\n\r\n\r\n private final String description;\r\n private final String name;\r\n private final Date due;\r\n\r\n```\r\n\r\nThe TodoService uses Spring MVC style annotations.\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n\r\n private List todoItemList = new ArrayList<>();\r\n\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {\r\n\r\n return todoItemList.size();\r\n }\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {\r\n\r\n return todoItemList;\r\n }\r\n\r\n @RequestMapping(value = \"/todo\", method = RequestMethod.POST)\r\n public void add(TodoItem item) {\r\n\r\n todoItemList.add(item);\r\n }\r\n\r\n}\r\n\r\n```\r\n\r\n\r\n#### Sending non-JSON\r\n\r\nYou can POST/PUT non-JSON and you can capture the body as a `String` or as a `byte[]`. \r\nIf the content-type is set to anything but `application/json` and your body is defined a String or byte[].\r\nThis works automatically. (The content-type has to be set.)\r\n\r\n```java\r\n @RequestMapping(value = \"/body/bytes\", method = RequestMethod.POST)\r\n public boolean bodyPostBytes( byte[] body) {\r\n String string = new String(body, StandardCharsets.UTF_8);\r\n return string.equals(\"foo\");\r\n }\r\n\r\n @RequestMapping(value = \"/body/string\", method = RequestMethod.POST)\r\n public boolean bodyPostString(String body) {\r\n return body.equals(\"foo\");\r\n }\r\n```\r\n\r\n\r\n#### Sending different response codes for success\r\n\r\nBy default QBit sends a `200` (OK) for a non-void call (a call that has a return or a Callback). If the REST operation has no return or no callback then QBit sends a `202` (Accepted). There may be times when you want to send a 201 (Created) or some other code that is not an Exception. You can do that by setting `code` on `@RequestMapping`. By default the code is -1 which means use the default behavior (200 for success, 202 for one-way message, and 500 for errors).\r\n\r\n\r\n#### Sending different response codes for success\r\n```java\r\n\r\n @RequestMapping(value = \"/helloj7\", code = 221)\r\n public void helloJSend7(Callback>> callback) {\r\n callback.returnThis(JSendResponseBuilder.jSendResponseBuilder(Lists.list(\r\n \"hello \" + System.currentTimeMillis())).build());\r\n }\r\n\r\n```\r\n\r\n`Callbacks` can be used for internal services as well. It is often the case that you use a [CallbackBuilder](https://github.com/advantageous/qbit/wiki/%5BDocument%5D-CallbackBuilder-and-generics-for-Reactive-Java-Microservices) or a QBit [Reactor](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices) to manage service calls. \r\n\r\n#### Working with non JSON responses\r\n\r\nYou do not have to return JSON form rest calls.\r\nYou can return any binary or any text by using `HttpBinaryResponse` and `HttpTextResponse`.\r\n\r\n#### Returning non JSON from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildTextResponse());\r\n }\r\n```\r\n\r\n\r\n#### Returning binary from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildBinaryResponse());\r\n }\r\n```\r\n\r\n#### Side note Why Spring style annotations?\r\nWhy did we pick Spring style annotations?\r\n1) Spring is not a standard and neither is QBit. 2) We found the Spring annotations to be less verbose.\r\n3) More people use Spring than Java EE. We wrote QBit for people to use.\r\nWe could easily support JAX-RS style annotations, and we probably will.\r\nSince QBit focuses on JSON, we do not need all of the complexity of JAX-RS or even all the features of\r\nthe Spring MVC annotations. Also we can literally use the actual Spring annotations. QBit and Boon\r\nuse a non-type safe mechanism for annotations which means they are not tied to a particular lib.\r\nYou can define your own. We hate vendor tie-in even if it is an open source vendor.\r\n(We also support @POST, @GET which is similar to JAX-RS).\r\n\r\nNow just start it up.\r\n\r\n```java\r\n\r\n public static void main(String... args) {\r\n\r\n ServiceEndpointServer server = new EndpointServerBuilder().build();\r\n server.initServices(new TodoService());\r\n server.start();\r\n }\r\n```\r\n\r\n\r\n\r\nThat is it. There is also out of the box WebSocket support with client side proxy generation so\r\nyou can call into services at the rate of millions of calls per second.\r\n\r\n## Using URI Params for QBit microservice\r\n\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {\r\n\r\n return a + b;\r\n }\r\n }\r\n\r\n```\r\n\r\n## WebSocket\r\nYou can always invoke QBit services via a WebSocket proxy.\r\nThe advantage of a WebSocket proxy is it allows you execute 1M RPC+ a second (1 million remote calls\r\nevery second).\r\n\r\n\r\n#### Using a microservice remotely with WebSocket\r\n```java\r\n /* Start QBit client for WebSocket calls. */\r\n final Client client = clientBuilder()\r\n .setPort(7000).setRequestBatchSize(1).build();\r\n\r\n\r\n /* Create a proxy to the service. */\r\n final AdderServiceClientInterface adderService =\r\n client.createProxy(AdderServiceClientInterface.class,\r\n \"adder-service\");\r\n\r\n client.start();\r\n\r\n\r\n\r\n /* Call the service */\r\n adderService.add(System.out::println, 1, 2);\r\n\r\n```\r\n\r\nThe output is 3.\r\n\r\n```output\r\n3\r\n```\r\n\r\n\r\nThe above uses a WebSocket proxy interface to call the service async.\r\n\r\n```java\r\n\r\n interface AdderServiceClientInterface {\r\n\r\n void add(Callback callback, int a, int b);\r\n }\r\n```\r\n\r\n#### ServiceDiscovery aware websocket builders\r\n\r\nCreate websocket service client that is ServiceDiscovery aware.\r\n\r\n\r\n```java\r\n final Client client = clientBuilder.setServiceDiscovery(serviceDiscovery, \"echo\")\r\n .setUri(\"/echo\").setProtocolBatchSize(20).build().startClient();\r\n\r\n\r\n final EchoAsync echoClient = client.createProxy(EchoAsync.class, \"echo\");\r\n```\r\n\r\nCurrently the `clientBuilder` will load all service endpoints that are registered under the service name,\r\nand randomly pick one. \r\n\r\nServiceDiscovery includes Consul based, watching JSON files on disk, and DNS. It is easy to write your own service discovery as well and plug it into QBit.\r\n\r\n\r\nIn the future we can RoundRobin calls or shard calls to websocket service and/or provide auto fail over if the connection is closed. We do this for the event bus that uses service discovery but it is not baked into WebSocket based client stubs yet.\r\n\r\n\r\n## REST call with URI params\r\n\r\nThe last client example uses WebSocket. You could also just use REST, and actually use the URI params\r\nthat we setup.\r\nREST is nice but it is going to be slower than WebSocket support.\r\n\r\nQBit ships with a nice little HTTP client. We can use it.\r\n\r\nYou can use it to send async calls and WebSocket messages with the HTTP client.\r\n\r\n\r\nHere we will use the http client to invoke our remote method:\r\n\r\n#### Using a microservice remotely with REST QBit microservice client\r\n```java\r\n\r\n\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\")\r\n .setPort(7000).build();\r\n\r\n httpClient.start();\r\n String results = httpClient\r\n .get(\"/services/adder-service/add/2/2\").body();\r\n System.out.println(results);\r\n\r\n```\r\n\r\n\r\nThe output is 4.\r\n\r\n```output\r\n4\r\n```\r\n\r\n## Accessing The URI Param example with CURL\r\n\r\nYou can also access the service from curl.\r\n\r\n```bash\r\n$ curl http://localhost:7000/services/adder-service/add/2/2\r\n```\r\n\r\nSee this full example here: [QBit microservice getting started tutorial](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-------------QBit-microservice-example).\r\n\r\n[QBit URI params and WebSocket proxy client](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Using-QBit-microservice-lib's-REST-support-with-URI-Params)\r\n\r\n## Working with WebSocket, HttpClient etc.\r\n\r\nQBit has a library for working with and writing async microservices that is lightweight and fun to use.\r\n\r\n#### WebSocket server and client.\r\n\r\n\r\n#### Create an HTTP server\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n```\r\n\r\n#### Setup server WebSocket support\r\n```java\r\n /* Setup WebSocket Server support. */\r\n httpServer.setWebSocketOnOpenConsumer(webSocket -> {\r\n webSocket.setTextMessageConsumer(message -> {\r\n webSocket.sendText(\"ECHO \" + message);\r\n });\r\n });\r\n\r\n```\r\n\r\n#### Start the server\r\n```java\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n```\r\n\r\n#### Setup the WebSocket client\r\n```java\r\n\r\n /** CLIENT. */\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\n#### Client WebSocket\r\n\r\n```java\r\n\r\n /* Setup the client websocket. */\r\n WebSocket webSocket = httpClient\r\n .createWebSocket(\"/websocket/rocket\");\r\n\r\n /* Setup the text consumer. */\r\n webSocket.setTextMessageConsumer(message -> {\r\n System.out.println(message);\r\n });\r\n webSocket.openAndWait();\r\n\r\n /* Send some messages. */\r\n webSocket.sendText(\"Hi mom\");\r\n webSocket.sendText(\"Hello World!\");\r\n\r\n```\r\n\r\n#### Output\r\n```output\r\n\r\nECHO Hi mom\r\nECHO Hello World!\r\n\r\n```\r\n\r\nNow stop the server and client. Pretty easy eh?\r\n\r\n## High-speed HTTP client and server done microservice style\r\n\r\n\r\n##### Starting up an HTTP server\r\n\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n /* Setting up a request Consumer with Java 8 Lambda expression. */\r\n httpServer.setHttpRequestConsumer(httpRequest -> {\r\n\r\n Map results = new HashMap<>();\r\n results.put(\"method\", httpRequest.getMethod());\r\n results.put(\"uri\", httpRequest.getUri());\r\n results.put(\"body\", httpRequest.getBodyAsString());\r\n results.put(\"headers\", httpRequest.getHeaders());\r\n results.put(\"params\", httpRequest.getParams());\r\n httpRequest.getReceiver()\r\n .response(200, \"application/json\", Boon.toJson(results));\r\n });\r\n\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n\r\n\r\n```\r\n\r\nThe focus is on ease of use and using Java 8 Lambdas for callbacks so the code is tight and small.\r\n\r\n[Find out more about QBit's microservice style WebSocket support here](https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-WebSocket-support)\r\n\r\n\r\n## Using HTTP Client lib\r\n\r\nNow, let's try out our HTTP client.\r\n\r\n##### Starting up an HTTP client\r\n\r\n```java\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\nYou just pass the URL, the port and then call start.\r\n\r\n## Synchronous HTTP calls\r\n\r\nNow you can start sending HTTP requests.\r\n\r\n##### No Param HTTP GET\r\n\r\n```java\r\n /* Send no param get. */\r\n HttpResponse httpResponse = httpClient.get( \"/hello/mom\" );\r\n puts( httpResponse );\r\n```\r\n\r\nAn HTTP response just contains the results from the server.\r\n\r\n\r\n##### No Param HTTP Response\r\n\r\n```java\r\npublic interface HttpResponse {\r\n\r\n MultiMap headers();\r\n\r\n int code();\r\n\r\n String contentType();\r\n\r\n String body();\r\n\r\n}\r\n\r\n```\r\n\r\nThere are helper methods for sync HTTP GET calls.\r\n\r\n\r\n\r\n##### Helper methods for GET\r\n```java\r\n\r\n\r\n /* Send one param get. */\r\n httpResponse = httpClient.getWith1Param(\"/hello/singleParam\",\r\n \"hi\", \"mom\");\r\n puts(\"single param\", httpResponse );\r\n\r\n\r\n /* Send two param get. */\r\n httpResponse = httpClient.getWith2Params(\"/hello/twoParams\",\r\n \"hi\", \"mom\", \"hello\", \"dad\");\r\n puts(\"two params\", httpResponse );\r\n\r\n...\r\n\r\n /* Send five param get. */\r\n httpResponse = httpClient.getWith5Params(\"/hello/5params\",\r\n \"hi\", \"mom\",\r\n \"hello\", \"dad\",\r\n \"greetings\", \"kids\",\r\n \"yo\", \"pets\",\r\n \"hola\", \"neighbors\");\r\n puts(\"5 params\", httpResponse );\r\n\r\n\r\n```\r\n\r\nThe puts method is a helper method it does System.out.println more or less by the way.\r\n\r\nThe first five params are covered. Beyond five, you have to use the HttpBuilder.\r\n\r\n```java\r\n\r\n\r\n /* Send six params with get. */\r\n\r\n final HttpRequest httpRequest = httpRequestBuilder()\r\n .addParam(\"hi\", \"mom\")\r\n .addParam(\"hello\", \"dad\")\r\n .addParam(\"greetings\", \"kids\")\r\n .addParam(\"yo\", \"pets\")\r\n .addParam(\"hola\", \"pets\")\r\n .addParam(\"salutations\", \"all\").build();\r\n\r\n httpResponse = httpClient.sendRequestAndWait(httpRequest);\r\n puts(\"6 params\", httpResponse );\r\n```\r\n\r\n## Http Async HTTP Client\r\n\r\nThere are async calls for GET as well.\r\n\r\n#### Async calls for HTTP GET using Java 8 lambda\r\n\r\n```java\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsync(\"/hi/async\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith1Param(\"/hi/async\", \"hi\", \"mom\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda 1 param\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith2Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 2 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n...\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith5Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n \"p3\", \"v3\",\r\n \"p4\", \"v4\",\r\n \"p5\", \"v5\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 5 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n```\r\n\r\n[Find more about the easy to use, fast microservice HTTP client here]\r\n(https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-HttpClient-GET,-POST,-et-al,-JSON,-Java-8-Lambda).\r\n\r\n## InProc QBit services\r\n\r\nQBit allows for services behind queues to be run in-proc as well.\r\n\r\n```java\r\n\r\n /* POJO service. */\r\n final TodoManager todoManagerImpl = new TodoManager();\r\n\r\n /*\r\n Create the service which manages async calls to todoManagerImpl.\r\n */\r\n final Service service = serviceBuilder()\r\n .setServiceObject(todoManagerImpl)\r\n .build().startServiceQueue();\r\n\r\n\r\n /* Create Asynchronous proxy over Synchronous service. */\r\n final TodoManagerClientInterface todoManager =\r\n service.createProxy(TodoManagerClientInterface.class);\r\n\r\n service.startCallBackHandler();\r\n\r\n\r\n System.out.println(\"This is an async call\");\r\n /* Asynchronous method call. */\r\n todoManager.add(new Todo(\"Call Mom\", \"Give Mom a call\"));\r\n\r\n\r\n AtomicInteger countTracker = new AtomicInteger();\r\n //Hold count from async call to service... for testing and showing it is an async callback\r\n\r\n System.out.println(\"This is an async call to count\");\r\n\r\n todoManager.count(count -> {\r\n System.out.println(\"This lambda expression is the callback \" + count);\r\n\r\n countTracker.set(count);\r\n });\r\n\r\n\r\n todoManager.clientProxyFlush(); //Flush all methods. It batches calls.\r\n\r\n Sys.sleep(100);\r\n\r\n System.out.printf(\"This is the count back from the server %d\\n\", countTracker.get());\r\n\r\n```\r\n\r\n[Detailed tutorial on in-proc services is being written.](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-Working-with-inproc-MicroServices-within-QBit.)\r\n\r\n\r\n## QBit Event Bus\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\nQBit also has a service event bus. This example is a an employee benefits services example.\r\n\r\nWe have two channels.\r\n\r\n```\r\npublic static final String NEW_HIRE_CHANNEL = \"com.mycompnay.employee.new\";\r\n\r\npublic static final String PAYROLL_ADJUSTMENT_CHANNEL = \"com.mycompnay.employee.payroll\";\r\n```\r\n\r\nAn employee object looks like this:\r\n\r\n```java\r\n\r\npublic static class Employee {\r\n final String firstName;\r\n final int employeeId;\r\n```\r\n\r\n\r\nThis example has three services: EmployeeHiringService, BenefitsService, and PayrollService.\r\n\r\nThese services are inproc services. QBit supports WebSocket, HTTP and REST remote services as well, but for now, let's focus on inproc services. If you understand inproc then you will understand remote.\r\n\r\nThe EmployeeHiringService actually fires off the events to other two services.\r\n\r\n```java\r\npublic class EmployeeHiringService {\r\n\r\n\r\n public void hireEmployee(final Employee employee) {\r\n\r\n int salary = 100;\r\n System.out.printf(\"Hired employee %s\\n\", employee);\r\n\r\n //Does stuff to hire employee\r\n\r\n //Sends events\r\n final EventManager eventManager =\r\n serviceContext().eventManager();\r\n eventManager.send(NEW_HIRE_CHANNEL, employee);\r\n\r\n eventManager.sendArray(PAYROLL_ADJUSTMENT_CHANNEL,\r\n employee, salary);\r\n\r\n\r\n }\r\n\r\n }\r\n```\r\n\r\n\r\nNotice that we call sendArray so we can send the employee and their salary.\r\nThe listener for PAYROLL_ADJUSTMENT_CHANNEL will have to handle both an employee and an int\r\nthat represents the new employees salary.\r\nYou can also use event bus proxies so you do not have to call into the event bus at all.\r\n\r\nThe BenefitsService listens for new employees being hired so it can enroll them into the benefits system.\r\n\r\n```java\r\npublic static class BenefitsService {\r\n\r\n @OnEvent(NEW_HIRE_CHANNEL)\r\n public void enroll(final Employee employee) {\r\n\r\n System.out.printf(\"Employee enrolled into benefits system employee %s %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId());\r\n\r\n }\r\n\r\n```\r\n\r\nDaddy needs to get paid.\r\n\r\n```java\r\n public static class PayrollService {\r\n\r\n @OnEvent(PAYROLL_ADJUSTMENT_CHANNEL)\r\n public void addEmployeeToPayroll(final Employee employee, int salary) {\r\n\r\n System.out.printf(\"Employee added to payroll %s %d %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId(), salary);\r\n\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nThe employee is the employee object from the EmployeeHiringService.\r\n\r\nso you can get your benefits, and paid!\r\n\r\nFind more details here:\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\n\r\n## Private event bus and event bus proxies\r\n\r\n You can define your own interface to the event bus and you can use your own event buses with QBit.\r\n Each module in your service can have its own internal event bus.\r\n\r\n To learn more read:\r\n [QBit Microservice working with a private event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-private-event-bus-for-inproc-microservices)\r\n and [QBit Java Microservice lib using your own interface to the event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-strongly-typed-event-bus-proxies-for-QBit-Java-Microservice-lib).\r\n\r\n\r\n\r\n## Queue Callbacks\r\n\r\n To really grasp QBit, one must grasp the concepts of a CallBack.\r\n\r\n A CallBack is a way to get an async response in QBit.\r\n\r\n You call a service method and it calls you back.\r\n\r\n Client proxies can have callbacks:\r\n\r\n\r\n#### Queue Callbacks - RecommendationService client interface\r\n```java\r\n\r\npublic interface RecommendationServiceClient {\r\n\r\n\r\n void recommend(final Callback> recommendationsCallback,\r\n final String userName);\r\n}\r\n\r\n```\r\n\r\nCallbacks are Java 8 Consumers with some optional extra error handling.\r\n\r\n\r\n#### Queue Callbacks - Callback\r\n\r\n```java\r\n\r\n\r\npublic interface Callback extends java.util.function.Consumer {\r\n default void onError(java.lang.Throwable error) { /* compiled code */ }\r\n}\r\n\r\n```\r\n\r\nServices that can block should use callbacks.\r\nThus if loadUser blocked in the following example, it should really use a callback instead of returning a value.\r\n\r\npublic class RecommendationService {\r\n\r\n#### Queue Callbacks - Simple minded implementation of RecommendationService\r\n```java\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n public List recommend(final String userName) {\r\n User user = users.get(userName);\r\n if (user == null) {\r\n user = loadUser(userName);\r\n }\r\n return runRulesEngineAgainstUser(user);\r\n }\r\n\r\n```\r\n\r\n\r\nLet's pretend `loadUser` has to look in a local cache, and if the user is not found, look in an off-heap cache\r\nand if not found it must ask for the user from the UserService which must check its caches and perhaps fallback\r\nto loading the user data from a database or from other services.\r\nIn other words, `loadUser` can potentially block on IO.\r\n\r\n\r\n\r\n### Queue Callbacks - The first rule of Queue Club - don't block\r\n\r\n\r\nOur client does not block, but our service does. Going back to our `RecommendationService`.\r\nIf we get a lot of cache hits for user loads, perhaps the\r\nblock will not be that long, but it will be there and every time we have to fault in a user, the whole system\r\nis gummed up. What we want to be able to do is if we can't handle the recommendation request,\r\nwe go ahead and make an async call to the `UserDataService`. When that async callback comes back, then we\r\nhandle that request. In the mean time, we handle recommendation lists requests as quickly as we can.\r\nWe never block.\r\n\r\n\r\nSo let's revisit the service. The first thing we are going to do is make the service method take\r\na callback. Before we do that, let's set down some rules.\r\n\r\n\r\n#### The first rule of queue club don't block.\r\n#### The second rule of queue club if you are not ready, use a callback and continue handling stuff you are ready for\r\n\r\n\r\n#### Queue Callbacks - Adding a CallBack to the RecommendationService inproc microservice\r\n\r\n```java\r\npublic class RecommendationService {\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n```\r\n\r\n\r\n\r\nNow we are taking a callback and we can decide when we want to handle this recommendation generation request.\r\nWe can do it right away if there user data we need is in-memory or we can delay it.\r\n\r\n\r\n#### If the user is found, call the callback right away for RecommendationService inproc microservice\r\n\r\n```java\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n /** Look for user in user cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n ...\r\n } else {\r\n /* Call the callback now because we can handle the callback now. */\r\n recommendationsCallback.accept(runRulesEngineAgainstUser(user));\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nNotice, if the user is found in the cache, we run our recommendation rules in-memory and call the callback right away\r\n`recommendationsCallback.accept(runRulesEngineAgainstUser(user))`.\r\n\r\nThe interesting part is what do we do if don't have the user loaded.\r\n\r\n\r\n#### If the user was not found, load him from the user microservice, but still don't block\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using Callback. */\r\n userDataService.loadUser(new Callback() {\r\n @Override\r\n public void accept(final User loadedUser) {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nHere we use a CallBack to load the user, and when the user is loaded, we call `handleLoadFromUserDataService`\r\nwhich adds some management about handling the callback so we can still handle this call, just not now.\r\n\r\n\r\n\r\n#### Lambda version of last example\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using lambda expression. */\r\n userDataService.loadUser(\r\n loadedUser -> {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nUsing lambdas like this makes the code more readable and terse, but remember don't deeply nest\r\nlambda expressions or you will create a code maintenance nightmare. Use them judiciously.\r\n\r\n\r\n### Queue Callbacks - Doing something later\r\n\r\nWhat we want is to handle the request for recommendations after the user service system loads\r\nthe user from its store.\r\n\r\n\r\n\r\n#### Handling UserServiceData callback methods once we get them.\r\n\r\n```java\r\n\r\npublic class RecommendationService {\r\n\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n private UserDataServiceClient userDataService;\r\n\r\n\r\n private BlockingQueue callbacks =\r\n new ArrayBlockingQueue(10_000);\r\n\r\n\r\n ...\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n ...\r\n\r\n }\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks queue. */\r\n callbacks.add(new Runnable() {\r\n @Override\r\n public void run() {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n }\r\n });\r\n }\r\n\r\n\r\n\r\n```\r\n\r\n\r\n\r\n\r\n#### handleLoadFromUserDataService rewritten using Lambda\r\n\r\n```java\r\n\r\n\r\npublic class RecommendationService {\r\n\r\n...\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks list. */\r\n callbacks.add(() -> {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n });\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nThe important part there is that every time we get a callback call from `UserDataService`, we then\r\nperform our CPU intensive recommendation rules and callback our caller. Well not exactly, what we\r\ndo is enqueue an runnable onto our callbacks queue, and later we will iterate through those but when?\r\n\r\n\r\n### Queue Callbacks Handling callbacks when our receive queue is empty, a new batch started or we hit a batch limit\r\n\r\nThe `RecommendationService` can be notified when its queue is empty, it has started a new batch and when\r\nit has reached a batch limit. These are all good times to handle callbacks from the `UserDataService`.\r\n\r\n#### Draining our callback queue\r\n```java\r\n\r\n @QueueCallback({\r\n QueueCallbackType.EMPTY,\r\n QueueCallbackType.START_BATCH,\r\n QueueCallbackType.LIMIT})\r\n private void handleCallbacks() {\r\n\r\n flushServiceProxy(userDataService);\r\n Runnable runnable = callbacks.poll();\r\n\r\n while (runnable != null) {\r\n runnable.run();\r\n runnable = callbacks.poll();\r\n }\r\n }\r\n\r\n```\r\n\r\nIt is important to remember when handling callbacks from another microservice that you want to handle\r\ncallbacks from the other service before you handle more incomming requests from you clients.\r\nEssentially you have clients that have been waiting (async waiting but still), and these clients\r\nmight represent an open TCP/IP connection like an HTTP call so it is best to close them out\r\nbefore handling more requests and like we said they were already waiting around with an open connection\r\nfor users to load form the user service.\r\n\r\nTo learn more about CallBacks, plesae read [QBit Java MicroService Lib CallBack fundamentals]([Rough Cut] QBit Microservice Lib Working With CallBacks).\r\n\r\n\r\n\r\n\r\n## Workers - pools and shards\r\n\r\n```java\r\npublic class ServiceWorkers {\r\n\r\n public static RoundRobinServiceDispatcher workers() {...\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {...\r\n```\r\n\r\nYou can compose sharded workers (for in-memory, thread safe, CPU intensive services), or workers for IO\r\nor talking to foreign services or foreign buses.\r\n\r\nHere is an example that uses a worker pool with three service workers in it:\r\n\r\nLet's say you have a service that does something:\r\n\r\n```java\r\n\r\n //Your POJO\r\n public class MultiWorker {\r\n\r\n void doSomeWork(...) {\r\n ...\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nNow this does some sort of IO and you want to have a bank of these running not just one so you can do\r\nIO in parallel. After some performance testing, you found out that three is the magic number.\r\n\r\nYou want to use your API for accessing this service:\r\n\r\n```java\r\n public interface MultiWorkerClient {\r\n void doSomeWork(...);\r\n }\r\n\r\n```\r\n\r\nNow let's create a bank of these and use it.\r\n\r\nFirst create the QBit services which add the thread/queue/microbatch.\r\n\r\n```java\r\n\r\n /* Create a service builder. */\r\n final ServiceBuilder serviceBuilder = serviceBuilder();\r\n\r\n /* Create some qbit services. */\r\n final Service service1 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service2 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service3 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n```\r\n\r\nNow add them to a ServiceWorkers object.\r\n\r\n```java\r\n\r\n ServiceWorkers dispatcher;\r\n dispatcher = workers(); //Create a round robin service dispatcher\r\n dispatcher.addServices(service1, service2, service3);\r\n dispatcher.start(); // start up the workers\r\n\r\n```\r\n\r\nYou can add services, POJOs and method consumers, method dispatchers to a service bundle.\r\nThe service bundle is an integration point into QBit.\r\n\r\nLet's add our new Service workers. ServiceWorkers is a ServiceMethodDispatcher.\r\n\r\n```Java\r\n /* Add the dispatcher to a service bundle. */\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nWe are probably going to add a helper method to the service bundle so most of this can happen in\r\na single call.\r\n\r\nNow you can start using your workers.\r\n\r\n```java\r\n\r\n /* Start using the workers. */\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n```\r\n\r\nNow you could use Spring or Guice to configure the builders and the service bundle.\r\nBut you can just do it like the above which is good for testing and understanding QBit internals.\r\n\r\nQBit also supports the concept of sharded services which is good for sharding resources like CPU\r\n(run a rules engine on each CPU core for a user recommendation engine).\r\n\r\nQBit does not know how to shard your services, you have to give it a hint.\r\nYou do this through a shard rule.\r\n\r\n```java\r\npublic interface ShardRule {\r\n int shard(String methodName, Object[] args, int numWorkers);\r\n}\r\n```\r\nWe worked on an app where the first argument to the services was the username, and then we used that to\r\nshard calls to a CPU intensive in-memory rules engine. This technique works. :)\r\n\r\nThe ServiceWorkers class has a method for creating a sharded worker pool.\r\n\r\n```java\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nTo use you just pass a shard key when you create the service workers.\r\n\r\n```java\r\n\r\n\r\n dispatcher = shardedWorkers((methodName, methodArgs, numWorkers) -> {\r\n String userName = methodArgs[0].toString();\r\n int shardKey = userName.hashCode() % numWorkers;\r\n return shardKey;\r\n });\r\n\r\n```\r\n\r\nThen add your services to the ServiceWorkers composition.\r\n```java\r\n int workerCount = Runtime.getRuntime().availableProcessors();\r\n\r\n for (int index = 0; index < workerCount; index++) {\r\n final Service service = serviceBuilder\r\n .setServiceObject(new ContentRulesEngine()).build();\r\n dispatcher.addServices(service);\r\n\r\n }\r\n```\r\n\r\nThen add it to the service bundle as before.\r\n```java\r\n\r\n dispatcher.start();\r\n\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nThen just use it:\r\n\r\n```java\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n for (int index = 0; index < 100; index++) {\r\n String userName = \"rickhigh\" + index;\r\n worker.pickSuggestions(userName);\r\n }\r\n\r\n```\r\n\r\n### Built in shard rules\r\n\r\n```java\r\n\r\n\r\npublic class ServiceWorkers {\r\n...\r\n public static ShardedMethodDispatcher shardOnFirstArgumentWorkers() {\r\n ...\r\n }\r\n\r\n...\r\n\r\n public static ShardedMethodDispatcher shardOnFifthArgumentWorkers() {\r\n ...\r\n }\r\n\r\n\r\n public static ShardedMethodDispatcher shardOnBeanPath(final String beanPath) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nThe shardOnBeanPath allows you to create a complex bean path navigation call and use its property to shard on.\r\n\r\n```java\r\n\r\n /* shard on 2nd arg which is an employee\r\n Use the employees department's id property. */\r\n dispatcher = shardOnBeanPath(\"[1].department.id\");\r\n\r\n /* Same as above. */\r\n dispatcher = shardOnBeanPath(\"1/department/id\");\r\n\r\n```\r\n\r\n[Read more about Service sharding and service workers here](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-QBit-Microservices-using-Service-Workers-and-sharded-service-workers)\r\n\r\n\r\nYou can find a lot more in the wiki. Also follow the commits.\r\nWe have been busy beavers.\r\n[QBit the microservice lib for Java - JSON, REST, WebSocket](https://github.com/advantageous/qbit/wiki).",
+ "body": "[QBit Java Micorservices lib tutorials](https://github.com/MammatusTech/qbit-microservices-examples/wiki)|\r\n[QBit Website](http://advantageous.github.io/qbit/)\r\n\r\n#Qbit - The Microservice Lib for Java - JSON, REST, WebSocket, Speed! \r\n\r\n## Quick overview of QBit\r\n\r\nThe Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.\r\n\r\nGot a question? Ask here: [QBit Google Group](https://groups.google.com/forum/#!forum/qbit-microservice).\r\n\r\nEverything is a queue. You have a choice. You can embrace it and control it. You can optimize for it.\r\nOr you can hide behind abstractions. QBit opens you up to peeking into what is going on, and allows you\r\nto pull some levers without selling your soul.\r\n\r\nQBit is a library not a framework. You can mix and match QBit with Spring, Guice, etc.\r\n\r\nQBit is FAST!\r\n\r\n\r\n\r\n#### Using from maven\r\n```xml\r\n\r\n io.advantageous.qbit\r\n qbit-admin\r\n 0.9.4.RELEASE\r\n\r\n\r\n io.advantageous.qbit\r\n qbit-vertx\r\n 0.9.4.RELEASE\r\n\r\n```\r\n\r\n#### Using from gradle\r\n```java\r\ncompile 'io.advantageous.qbit:qbit-admin:0.9.4.RELEASE'\r\ncompile 'io.advantageous.qbit:qbit-vertx:0.9.4.RELEASE'\r\n```\r\n\r\nCore Features\r\n============\r\n\r\n* Write REST based async microservices\r\n* Write ***WebSocket*** based async microservices (fast async RPC over WebSocket)\r\n* Actor Service Queues using micro-batching for high-speed message passing\r\n* Strongly async typed event bus which can be distributed\r\n* Async low overhead metrics gathering which can be queried and distributed (for doing fast lane analytics)\r\n* Complex async call coordination (with the Reactor) for reactive programming\r\n* Built-in support for ***health checks*** (and integration with tools like Consul)\r\n* Built-in support for ***monitoring*** (and integration with wire protocols like StatsD)\r\n* Built-in support for ***Service Discovery*** (with integration with health system, DNS SRV records and Consul)\r\n* Integration with persistent queues\r\n* [12 factor app port bindings](http://12factor.net/), health checks, KPI gathering, Logging MDC\r\n* API Gateway support for client generation and consumption via [Swagger](http://swagger.io/).\r\n* Our services can generate Swagger files (like idl for JSON/REST).\r\n* Remote client proxies for WebSocket (your interface is your IDL)\r\n\r\n\r\nStatus\r\n=====\r\nDeployed at several large fortune 100 companies. \r\nQBit now works with Vertx (standalone or embedded).\r\nYou can also use QBit on non-QBit projects, it is just a lib.\r\n\r\nLicense\r\n=====\r\nApache 2\r\n\r\n\r\n## Java Microservice Lib\r\n\r\nQBit has inproc services, REST microservices and WebSocket microservices as well as an\r\nin-proc service event bus (which can be per module or per app). It supports workers and in-memory services.\r\n\r\nBefore we describe more, here are two sample services:\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {...\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {...\r\n```\r\n\r\n\r\n#### Adder Service using URI params\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {...\r\n }\r\n```\r\n\r\n\r\n\r\nQBit philosophy:\r\n====\r\nAt the end of the day QBit is a simple library not a framework.\r\nYour app is not a QBit app but a Java app that uses the QBit lib.\r\nQBit allows you to work with Java UTIL concurrent, and does not endeavor to hide it from you.\r\nJust trying to take the sting out of it.\r\n\r\nDoes it work\r\n=====\r\nWe have used techniques in Boon and QBit with great success in high-end, high-performance, high-scalable apps.\r\nWe helped clients handle 10x the load with 1/10th the servers of their competitors using techniques in QBit.\r\nQBit is us being sick of hand tuning queue access and threads.\r\n\r\n\r\nBoon and QBit humility policy\r\n=====\r\nIdeas for Boon and QBit often come from all over the web. We make mistakes. Point them out.\r\nAs a developer of Boon and QBit, we are fellow travelers.\r\nIf you have an idea or technique you want to share, we listen.\r\n\r\n\r\nInspiration\r\n====\r\n\r\nA big inspiration for Boon/QBit was Vertx, Akka, Go Channels, Active Objects, Apartment Model Threading, Actor,\r\nand the Mechanical Sympathy papers.\r\n\r\nQBit has ideas that are similar to many frameworks. We are all reading the same papers.\r\nQBit got inspiration from the LMAX disruptor papers and this blog post about\r\n[link transfer queue versus disruptor](http://php.sabscape.com/blog/?p=557). We had some theories about\r\nqueues that blog post inspired us to try them out. Some of these theories are deployed at some of the\r\nbiggest middleware backends and whose name brands are known around the world. And thus QBit was born.\r\n\r\nQBit also took an lot of inspiration by the great work done\r\nby Tim Fox on Vertx. The first project using something that could actually be called QBit (albeit early QBit)\r\n was using Vertx on an web/mobile microservice for an app that could potentially have 80 million users.\r\n It was this\r\nexperience with Vertx and early QBit that led to QBit development and evolution. QBit is built on the\r\nshoulders of giants (Netty/Vertx).\r\n\r\nDoes QBit compete with...\r\n====\r\nSpring Disruptor: No. You could use QBit to write plugins for Spring Disruptor I suppose, but QBit does\r\nnot compete with Spring Disruptor.\r\nSpring Boot/Spring MVC: No. We use the same annotations but QBit is geared for high-speed in-memory\r\nmicroservices. It is more like Akka than Spring Boot. QBit has a subset of the features of Spring MVC\r\ngeared only for microservices, i.e., WebSocket RPC, REST, JSON marshaling, etc.\r\nAkka: No. Well Maybe. Akka has similar concepts but they take a different approach. QBit is more focused\r\n on Java, and microservices (REST, JSON, WebSocket) than Akka.\r\nLMAX Disruptor: No. In fact, we can use disruptor as on of the queues that QBit uses underneath the covers.\r\n\r\n\r\n(Early benchmarks have been removed. They were here. QBit got a lot faster.\r\n Benchmarking QBit is a moving target at the moment.\r\n Links and reports will be created.)\r\n\r\n\r\nCode Examples\r\n\r\n\r\n## Basic Queue example (REST style services is further down)\r\n\r\n====\r\n\r\n```java\r\n\r\n BasicQueue queue = BasicQueue.create(Integer.class, 1000);\r\n\r\n //Sending threads\r\n\r\n SendQueue sendQueue = queue.sendQueue();\r\n for (int index = 0; index < amount; index++) {\r\n sendQueue.send(index);\r\n }\r\n sendQueue.flushSends();\r\n ...\r\n sendQueue.sendAndFlush(code);\r\n //other methods for sendQueue, writeBatch, writeMany\r\n\r\n\r\n //Receiving Threads\r\n ReceiveQueue receiveQueue = queue.receiveQueue();\r\n Integer item = receiveQueue.take();\r\n //other methods poll(), pollWait(), readBatch(), readBatch(count)\r\n```\r\n\r\n\r\n### What is QBit again?\r\n\r\nQBit is a queuing library for microservices. It is similar to many other projects like Akka, Spring Reactor,\r\netc. QBit is just a library not a platform. QBit has libraries to put a service behind a queue.\r\nYou can use QBit queues directly or you can create a service. QBit services can be exposed by WebSocket,\r\nHTTP, HTTP pipeline, and other types of remoting. A service in QBit is a Java class whose methods are\r\n executed behind service queues. QBit implements apartment model threading and is similar to the\r\n Actor model or a better description would be Active Objects. QBit does not use a disruptor (but could).\r\n It uses regular Java Queues. QBit can do north of 100 million ping pong calls per second which is\r\n an amazing speed (seen as high as 200M). QBit also supports calling services via REST, and WebSocket.\r\n QBit is microservices in the pure Web sense: JSON, HTTP, WebSocket, etc. QBit uses micro batching to\r\n push messages through the pipe (queue, IO, etc.) faster to reduce thread hand-off.\r\n\r\n### QBit lingo\r\n\r\nQBit is a Java microservice lib supporting REST, JSON and WebSocket. It is written in Java but we could\r\none day write a version in Rust or Go or C# (but that would require a large payday).\r\n\r\n**Service**\r\nPOJO (plain old Java object) behind a queue that can receive method calls via proxy calls or events\r\n(May have one thread managing events, method calls, and responses or two one for method calls and events\r\n 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.\r\n\r\n**ServiceBundle**\r\nMany POJOs behind one response queue and many receive queues. There may be one thread for all responses\r\nor not. They also can be one receive queue.\r\n\r\n**Queue**\r\nA thread managing a queue. It supports batching. It has events for empty, reachedLimit, startedBatch,\r\nidle. You can listen to these events from services that sit behind a queue. You don't have to use Services.\r\nYou can use Queue's direct. In QBit, you have sender queues and receivers queues. They are separated to\r\nsupport micro-batching.\r\n\r\n**ServiceEndpointServer**\r\nServiceBundle that is exposed to REST and WebSocket communication.\r\n\r\n**EventBus**\r\nEventBus is a way to send a lot of messages to services that may be loosely coupled.\r\n\r\n**ClientProxy**\r\nClientProxy is a way to invoke service through async interface, service can be inproc (same process) or\r\nremoted over WebSocket.\r\n\r\n**Non-blocking**\r\nQBit is a non-blocking lib. You use CallBacks via Java 8 Lambdas. You can also send event messages and get\r\nreplies. Messaging is built into the system so you can easily coordinate complex tasks.\r\nQBit takes an object-oriented approach to service development so services look like normal Java services\r\nthat you\r\nalready write, but the services live behind a queue/thread. This is not a new concept. Microsoft did this\r\nwith DCOM/COM and called it active objects. Akka does it with actors and called them strongly typed Actors.\r\nThe important concepts is that you get the speed of reactive and actor style messaging but you develop\r\nin a natural OOP approach. QBit is not the first. QBit is not the only.\r\n\r\n\r\n**Speed**\r\nQBit is VERY fast. There is a of course a lot of room for improvement. But already 200M+ TPS inproc ping pong, 10M-20M+ TPS event bus, 500K TPS RPC calls over WebSocket/JSON, etc.\r\nMore work needs to be done to improve speed, but now it is fast enough where we are focusing more on\r\nusability.\r\nThe JSON support uses Boon by default which is up to 4x faster than other JSON parsers for the\r\nREST/JSON, WebSocket/JSON use case.\r\n\r\n**Reactive Programming**\r\nQBit provides a **Reactor** to manage async calls. This allows callbacks to be handled on the same thread that called them and it provides for timeout and error handling. Read [Reactor tutorial for creating reactive micro service programming](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices)\r\n\r\n**Service Discovery**\r\nBuilt in support for service discovery. This includes integration with Consul.\r\n\r\n\r\n**StatService**\r\nBuilt in support for stats. The **StatService** can be integrated with **StatsD** (Graphite, Grafana, DataDog, etc.) to publish passive stats. Or you can query the stats engine and react to the stats (counts, timings and levels). The **StatsService** is a reactive stats system that can be clustered. The StatService is reactive in that your services can publish to it and query it and react based on the results. You can implement things like rate limiting and react to an increased rate of something. The ServiceDiscovery system integrates with the HealthSystem and Consul to roll up each of your internal services that make up you micro service and publish the composite availably of your micro service to a single HTTP endpoint or a dead mans switch in Consul (TTL). \r\n\r\n\r\n\r\n### CURLable REST services example\r\n\r\nTalk is cheap. Let's look at some code. You can get a detailed walk through in the Wiki.\r\nWe have a lot of documentation already.\r\n\r\nWe will create a service that is exposed through REST/JSON.\r\n\r\nTo query the size of the todo list:\r\n\r\n```bash\r\ncurl localhost:8080/services/todo-service/todo/count\r\n```\r\n\r\nTo add a new TODO item.\r\n\r\n```bash\r\ncurl -X POST -H \"Content-Type: application/json\" -d \\\r\n'{\"name\":\"xyz\",\"description\":\"xyz\"}' \\\r\nhttp://localhost:8080/services/todo-service/todo\r\n```\r\n\r\nTo get a list of TODO items\r\n```bash\r\ncurl http://localhost:8080/services/todo-service/todo/\r\n```\r\n\r\nThe TODO example will use and track Todo items.\r\n\r\n#### Todo item POJO sans getter\r\n\r\n```java\r\npackage io.advantageous.qbit.examples;\r\n\r\nimport java.util.Date;\r\n\r\n\r\npublic class TodoItem {\r\n\r\n\r\n private final String description;\r\n private final String name;\r\n private final Date due;\r\n\r\n```\r\n\r\nThe TodoService uses Spring MVC style annotations.\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n\r\n private List todoItemList = new ArrayList<>();\r\n\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {\r\n\r\n return todoItemList.size();\r\n }\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {\r\n\r\n return todoItemList;\r\n }\r\n\r\n @RequestMapping(value = \"/todo\", method = RequestMethod.POST)\r\n public void add(TodoItem item) {\r\n\r\n todoItemList.add(item);\r\n }\r\n\r\n}\r\n\r\n```\r\n\r\n\r\n#### Sending non-JSON\r\n\r\nYou can POST/PUT non-JSON and you can capture the body as a `String` or as a `byte[]`. \r\nIf the content-type is set to anything but `application/json` and your body is defined a String or byte[].\r\nThis works automatically. (The content-type has to be set.)\r\n\r\n```java\r\n @RequestMapping(value = \"/body/bytes\", method = RequestMethod.POST)\r\n public boolean bodyPostBytes( byte[] body) {\r\n String string = new String(body, StandardCharsets.UTF_8);\r\n return string.equals(\"foo\");\r\n }\r\n\r\n @RequestMapping(value = \"/body/string\", method = RequestMethod.POST)\r\n public boolean bodyPostString(String body) {\r\n return body.equals(\"foo\");\r\n }\r\n```\r\n\r\n\r\n#### Sending different response codes for success\r\n\r\nBy default QBit sends a `200` (OK) for a non-void call (a call that has a return or a Callback). If the REST operation has no return or no callback then QBit sends a `202` (Accepted). There may be times when you want to send a 201 (Created) or some other code that is not an Exception. You can do that by setting `code` on `@RequestMapping`. By default the code is -1 which means use the default behavior (200 for success, 202 for one-way message, and 500 for errors).\r\n\r\n\r\n#### Sending different response codes for success\r\n```java\r\n\r\n @RequestMapping(value = \"/helloj7\", code = 221)\r\n public void helloJSend7(Callback>> callback) {\r\n callback.returnThis(JSendResponseBuilder.jSendResponseBuilder(Lists.list(\r\n \"hello \" + System.currentTimeMillis())).build());\r\n }\r\n\r\n```\r\n\r\n`Callbacks` can be used for internal services as well. It is often the case that you use a [CallbackBuilder](https://github.com/advantageous/qbit/wiki/%5BDocument%5D-CallbackBuilder-and-generics-for-Reactive-Java-Microservices) or a QBit [Reactor](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices) to manage service calls. \r\n\r\n#### Working with non JSON responses\r\n\r\nYou do not have to return JSON form rest calls.\r\nYou can return any binary or any text by using `HttpBinaryResponse` and `HttpTextResponse`.\r\n\r\n#### Returning non JSON from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildTextResponse());\r\n }\r\n```\r\n\r\n\r\n#### Returning binary from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildBinaryResponse());\r\n }\r\n```\r\n\r\n#### Side note Why Spring style annotations?\r\nWhy did we pick Spring style annotations?\r\n1) Spring is not a standard and neither is QBit. 2) We found the Spring annotations to be less verbose.\r\n3) More people use Spring than Java EE. We wrote QBit for people to use.\r\nWe could easily support JAX-RS style annotations, and we probably will.\r\nSince QBit focuses on JSON, we do not need all of the complexity of JAX-RS or even all the features of\r\nthe Spring MVC annotations. Also we can literally use the actual Spring annotations. QBit and Boon\r\nuse a non-type safe mechanism for annotations which means they are not tied to a particular lib.\r\nYou can define your own. We hate vendor tie-in even if it is an open source vendor.\r\n(We also support @POST, @GET which is similar to JAX-RS).\r\n\r\nNow just start it up.\r\n\r\n```java\r\n\r\n public static void main(String... args) {\r\n\r\n ServiceEndpointServer server = new EndpointServerBuilder().build();\r\n server.initServices(new TodoService());\r\n server.start();\r\n }\r\n```\r\n\r\n\r\n\r\nThat is it. There is also out of the box WebSocket support with client side proxy generation so\r\nyou can call into services at the rate of millions of calls per second.\r\n\r\n## Using URI Params for QBit microservice\r\n\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {\r\n\r\n return a + b;\r\n }\r\n }\r\n\r\n```\r\n\r\n## WebSocket\r\nYou can always invoke QBit services via a WebSocket proxy.\r\nThe advantage of a WebSocket proxy is it allows you execute 1M RPC+ a second (1 million remote calls\r\nevery second).\r\n\r\n\r\n#### Using a microservice remotely with WebSocket\r\n```java\r\n /* Start QBit client for WebSocket calls. */\r\n final Client client = clientBuilder()\r\n .setPort(7000).setRequestBatchSize(1).build();\r\n\r\n\r\n /* Create a proxy to the service. */\r\n final AdderServiceClientInterface adderService =\r\n client.createProxy(AdderServiceClientInterface.class,\r\n \"adder-service\");\r\n\r\n client.start();\r\n\r\n\r\n\r\n /* Call the service */\r\n adderService.add(System.out::println, 1, 2);\r\n\r\n```\r\n\r\nThe output is 3.\r\n\r\n```output\r\n3\r\n```\r\n\r\n\r\nThe above uses a WebSocket proxy interface to call the service async.\r\n\r\n```java\r\n\r\n interface AdderServiceClientInterface {\r\n\r\n void add(Callback callback, int a, int b);\r\n }\r\n```\r\n\r\n#### ServiceDiscovery aware websocket builders\r\n\r\nCreate websocket service client that is ServiceDiscovery aware.\r\n\r\n\r\n```java\r\n final Client client = clientBuilder.setServiceDiscovery(serviceDiscovery, \"echo\")\r\n .setUri(\"/echo\").setProtocolBatchSize(20).build().startClient();\r\n\r\n\r\n final EchoAsync echoClient = client.createProxy(EchoAsync.class, \"echo\");\r\n```\r\n\r\nCurrently the `clientBuilder` will load all service endpoints that are registered under the service name,\r\nand randomly pick one. \r\n\r\nServiceDiscovery includes Consul based, watching JSON files on disk, and DNS. It is easy to write your own service discovery as well and plug it into QBit.\r\n\r\n\r\nIn the future we can RoundRobin calls or shard calls to websocket service and/or provide auto fail over if the connection is closed. We do this for the event bus that uses service discovery but it is not baked into WebSocket based client stubs yet.\r\n\r\n\r\n## REST call with URI params\r\n\r\nThe last client example uses WebSocket. You could also just use REST, and actually use the URI params\r\nthat we setup.\r\nREST is nice but it is going to be slower than WebSocket support.\r\n\r\nQBit ships with a nice little HTTP client. We can use it.\r\n\r\nYou can use it to send async calls and WebSocket messages with the HTTP client.\r\n\r\n\r\nHere we will use the http client to invoke our remote method:\r\n\r\n#### Using a microservice remotely with REST QBit microservice client\r\n```java\r\n\r\n\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\")\r\n .setPort(7000).build();\r\n\r\n httpClient.start();\r\n String results = httpClient\r\n .get(\"/services/adder-service/add/2/2\").body();\r\n System.out.println(results);\r\n\r\n```\r\n\r\n\r\nThe output is 4.\r\n\r\n```output\r\n4\r\n```\r\n\r\n## Accessing The URI Param example with CURL\r\n\r\nYou can also access the service from curl.\r\n\r\n```bash\r\n$ curl http://localhost:7000/services/adder-service/add/2/2\r\n```\r\n\r\nSee this full example here: [QBit microservice getting started tutorial](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-------------QBit-microservice-example).\r\n\r\n[QBit URI params and WebSocket proxy client](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Using-QBit-microservice-lib's-REST-support-with-URI-Params)\r\n\r\n## Working with WebSocket, HttpClient etc.\r\n\r\nQBit has a library for working with and writing async microservices that is lightweight and fun to use.\r\n\r\n#### WebSocket server and client.\r\n\r\n\r\n#### Create an HTTP server\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n```\r\n\r\n#### Setup server WebSocket support\r\n```java\r\n /* Setup WebSocket Server support. */\r\n httpServer.setWebSocketOnOpenConsumer(webSocket -> {\r\n webSocket.setTextMessageConsumer(message -> {\r\n webSocket.sendText(\"ECHO \" + message);\r\n });\r\n });\r\n\r\n```\r\n\r\n#### Start the server\r\n```java\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n```\r\n\r\n#### Setup the WebSocket client\r\n```java\r\n\r\n /** CLIENT. */\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\n#### Client WebSocket\r\n\r\n```java\r\n\r\n /* Setup the client websocket. */\r\n WebSocket webSocket = httpClient\r\n .createWebSocket(\"/websocket/rocket\");\r\n\r\n /* Setup the text consumer. */\r\n webSocket.setTextMessageConsumer(message -> {\r\n System.out.println(message);\r\n });\r\n webSocket.openAndWait();\r\n\r\n /* Send some messages. */\r\n webSocket.sendText(\"Hi mom\");\r\n webSocket.sendText(\"Hello World!\");\r\n\r\n```\r\n\r\n#### Output\r\n```output\r\n\r\nECHO Hi mom\r\nECHO Hello World!\r\n\r\n```\r\n\r\nNow stop the server and client. Pretty easy eh?\r\n\r\n## High-speed HTTP client and server done microservice style\r\n\r\n\r\n##### Starting up an HTTP server\r\n\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n /* Setting up a request Consumer with Java 8 Lambda expression. */\r\n httpServer.setHttpRequestConsumer(httpRequest -> {\r\n\r\n Map results = new HashMap<>();\r\n results.put(\"method\", httpRequest.getMethod());\r\n results.put(\"uri\", httpRequest.getUri());\r\n results.put(\"body\", httpRequest.getBodyAsString());\r\n results.put(\"headers\", httpRequest.getHeaders());\r\n results.put(\"params\", httpRequest.getParams());\r\n httpRequest.getReceiver()\r\n .response(200, \"application/json\", Boon.toJson(results));\r\n });\r\n\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n\r\n\r\n```\r\n\r\nThe focus is on ease of use and using Java 8 Lambdas for callbacks so the code is tight and small.\r\n\r\n[Find out more about QBit's microservice style WebSocket support here](https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-WebSocket-support)\r\n\r\n\r\n## Using HTTP Client lib\r\n\r\nNow, let's try out our HTTP client.\r\n\r\n##### Starting up an HTTP client\r\n\r\n```java\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\nYou just pass the URL, the port and then call start.\r\n\r\n## Synchronous HTTP calls\r\n\r\nNow you can start sending HTTP requests.\r\n\r\n##### No Param HTTP GET\r\n\r\n```java\r\n /* Send no param get. */\r\n HttpResponse httpResponse = httpClient.get( \"/hello/mom\" );\r\n puts( httpResponse );\r\n```\r\n\r\nAn HTTP response just contains the results from the server.\r\n\r\n\r\n##### No Param HTTP Response\r\n\r\n```java\r\npublic interface HttpResponse {\r\n\r\n MultiMap headers();\r\n\r\n int code();\r\n\r\n String contentType();\r\n\r\n String body();\r\n\r\n}\r\n\r\n```\r\n\r\nThere are helper methods for sync HTTP GET calls.\r\n\r\n\r\n\r\n##### Helper methods for GET\r\n```java\r\n\r\n\r\n /* Send one param get. */\r\n httpResponse = httpClient.getWith1Param(\"/hello/singleParam\",\r\n \"hi\", \"mom\");\r\n puts(\"single param\", httpResponse );\r\n\r\n\r\n /* Send two param get. */\r\n httpResponse = httpClient.getWith2Params(\"/hello/twoParams\",\r\n \"hi\", \"mom\", \"hello\", \"dad\");\r\n puts(\"two params\", httpResponse );\r\n\r\n...\r\n\r\n /* Send five param get. */\r\n httpResponse = httpClient.getWith5Params(\"/hello/5params\",\r\n \"hi\", \"mom\",\r\n \"hello\", \"dad\",\r\n \"greetings\", \"kids\",\r\n \"yo\", \"pets\",\r\n \"hola\", \"neighbors\");\r\n puts(\"5 params\", httpResponse );\r\n\r\n\r\n```\r\n\r\nThe puts method is a helper method it does System.out.println more or less by the way.\r\n\r\nThe first five params are covered. Beyond five, you have to use the HttpBuilder.\r\n\r\n```java\r\n\r\n\r\n /* Send six params with get. */\r\n\r\n final HttpRequest httpRequest = httpRequestBuilder()\r\n .addParam(\"hi\", \"mom\")\r\n .addParam(\"hello\", \"dad\")\r\n .addParam(\"greetings\", \"kids\")\r\n .addParam(\"yo\", \"pets\")\r\n .addParam(\"hola\", \"pets\")\r\n .addParam(\"salutations\", \"all\").build();\r\n\r\n httpResponse = httpClient.sendRequestAndWait(httpRequest);\r\n puts(\"6 params\", httpResponse );\r\n```\r\n\r\n## Http Async HTTP Client\r\n\r\nThere are async calls for GET as well.\r\n\r\n#### Async calls for HTTP GET using Java 8 lambda\r\n\r\n```java\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsync(\"/hi/async\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith1Param(\"/hi/async\", \"hi\", \"mom\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda 1 param\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith2Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 2 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n...\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith5Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n \"p3\", \"v3\",\r\n \"p4\", \"v4\",\r\n \"p5\", \"v5\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 5 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n```\r\n\r\n[Find more about the easy to use, fast microservice HTTP client here]\r\n(https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-HttpClient-GET,-POST,-et-al,-JSON,-Java-8-Lambda).\r\n\r\n## InProc QBit services\r\n\r\nQBit allows for services behind queues to be run in-proc as well.\r\n\r\n```java\r\n\r\n /* POJO service. */\r\n final TodoManager todoManagerImpl = new TodoManager();\r\n\r\n /*\r\n Create the service which manages async calls to todoManagerImpl.\r\n */\r\n final Service service = serviceBuilder()\r\n .setServiceObject(todoManagerImpl)\r\n .build().startServiceQueue();\r\n\r\n\r\n /* Create Asynchronous proxy over Synchronous service. */\r\n final TodoManagerClientInterface todoManager =\r\n service.createProxy(TodoManagerClientInterface.class);\r\n\r\n service.startCallBackHandler();\r\n\r\n\r\n System.out.println(\"This is an async call\");\r\n /* Asynchronous method call. */\r\n todoManager.add(new Todo(\"Call Mom\", \"Give Mom a call\"));\r\n\r\n\r\n AtomicInteger countTracker = new AtomicInteger();\r\n //Hold count from async call to service... for testing and showing it is an async callback\r\n\r\n System.out.println(\"This is an async call to count\");\r\n\r\n todoManager.count(count -> {\r\n System.out.println(\"This lambda expression is the callback \" + count);\r\n\r\n countTracker.set(count);\r\n });\r\n\r\n\r\n todoManager.clientProxyFlush(); //Flush all methods. It batches calls.\r\n\r\n Sys.sleep(100);\r\n\r\n System.out.printf(\"This is the count back from the server %d\\n\", countTracker.get());\r\n\r\n```\r\n\r\n[Detailed tutorial on in-proc services is being written.](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-Working-with-inproc-MicroServices-within-QBit.)\r\n\r\n\r\n## QBit Event Bus\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\nQBit also has a service event bus. This example is a an employee benefits services example.\r\n\r\nWe have two channels.\r\n\r\n```\r\npublic static final String NEW_HIRE_CHANNEL = \"com.mycompnay.employee.new\";\r\n\r\npublic static final String PAYROLL_ADJUSTMENT_CHANNEL = \"com.mycompnay.employee.payroll\";\r\n```\r\n\r\nAn employee object looks like this:\r\n\r\n```java\r\n\r\npublic static class Employee {\r\n final String firstName;\r\n final int employeeId;\r\n```\r\n\r\n\r\nThis example has three services: EmployeeHiringService, BenefitsService, and PayrollService.\r\n\r\nThese services are inproc services. QBit supports WebSocket, HTTP and REST remote services as well, but for now, let's focus on inproc services. If you understand inproc then you will understand remote.\r\n\r\nThe EmployeeHiringService actually fires off the events to other two services.\r\n\r\n```java\r\npublic class EmployeeHiringService {\r\n\r\n\r\n public void hireEmployee(final Employee employee) {\r\n\r\n int salary = 100;\r\n System.out.printf(\"Hired employee %s\\n\", employee);\r\n\r\n //Does stuff to hire employee\r\n\r\n //Sends events\r\n final EventManager eventManager =\r\n serviceContext().eventManager();\r\n eventManager.send(NEW_HIRE_CHANNEL, employee);\r\n\r\n eventManager.sendArray(PAYROLL_ADJUSTMENT_CHANNEL,\r\n employee, salary);\r\n\r\n\r\n }\r\n\r\n }\r\n```\r\n\r\n\r\nNotice that we call sendArray so we can send the employee and their salary.\r\nThe listener for PAYROLL_ADJUSTMENT_CHANNEL will have to handle both an employee and an int\r\nthat represents the new employees salary.\r\nYou can also use event bus proxies so you do not have to call into the event bus at all.\r\n\r\nThe BenefitsService listens for new employees being hired so it can enroll them into the benefits system.\r\n\r\n```java\r\npublic static class BenefitsService {\r\n\r\n @OnEvent(NEW_HIRE_CHANNEL)\r\n public void enroll(final Employee employee) {\r\n\r\n System.out.printf(\"Employee enrolled into benefits system employee %s %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId());\r\n\r\n }\r\n\r\n```\r\n\r\nDaddy needs to get paid.\r\n\r\n```java\r\n public static class PayrollService {\r\n\r\n @OnEvent(PAYROLL_ADJUSTMENT_CHANNEL)\r\n public void addEmployeeToPayroll(final Employee employee, int salary) {\r\n\r\n System.out.printf(\"Employee added to payroll %s %d %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId(), salary);\r\n\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nThe employee is the employee object from the EmployeeHiringService.\r\n\r\nso you can get your benefits, and paid!\r\n\r\nFind more details here:\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\n\r\n## Private event bus and event bus proxies\r\n\r\n You can define your own interface to the event bus and you can use your own event buses with QBit.\r\n Each module in your service can have its own internal event bus.\r\n\r\n To learn more read:\r\n [QBit Microservice working with a private event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-private-event-bus-for-inproc-microservices)\r\n and [QBit Java Microservice lib using your own interface to the event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-strongly-typed-event-bus-proxies-for-QBit-Java-Microservice-lib).\r\n\r\n\r\n\r\n## Queue Callbacks\r\n\r\n To really grasp QBit, one must grasp the concepts of a CallBack.\r\n\r\n A CallBack is a way to get an async response in QBit.\r\n\r\n You call a service method and it calls you back.\r\n\r\n Client proxies can have callbacks:\r\n\r\n\r\n#### Queue Callbacks - RecommendationService client interface\r\n```java\r\n\r\npublic interface RecommendationServiceClient {\r\n\r\n\r\n void recommend(final Callback> recommendationsCallback,\r\n final String userName);\r\n}\r\n\r\n```\r\n\r\nCallbacks are Java 8 Consumers with some optional extra error handling.\r\n\r\n\r\n#### Queue Callbacks - Callback\r\n\r\n```java\r\n\r\n\r\npublic interface Callback extends java.util.function.Consumer {\r\n default void onError(java.lang.Throwable error) { /* compiled code */ }\r\n}\r\n\r\n```\r\n\r\nServices that can block should use callbacks.\r\nThus if loadUser blocked in the following example, it should really use a callback instead of returning a value.\r\n\r\npublic class RecommendationService {\r\n\r\n#### Queue Callbacks - Simple minded implementation of RecommendationService\r\n```java\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n public List recommend(final String userName) {\r\n User user = users.get(userName);\r\n if (user == null) {\r\n user = loadUser(userName);\r\n }\r\n return runRulesEngineAgainstUser(user);\r\n }\r\n\r\n```\r\n\r\n\r\nLet's pretend `loadUser` has to look in a local cache, and if the user is not found, look in an off-heap cache\r\nand if not found it must ask for the user from the UserService which must check its caches and perhaps fallback\r\nto loading the user data from a database or from other services.\r\nIn other words, `loadUser` can potentially block on IO.\r\n\r\n\r\n\r\n### Queue Callbacks - The first rule of Queue Club - don't block\r\n\r\n\r\nOur client does not block, but our service does. Going back to our `RecommendationService`.\r\nIf we get a lot of cache hits for user loads, perhaps the\r\nblock will not be that long, but it will be there and every time we have to fault in a user, the whole system\r\nis gummed up. What we want to be able to do is if we can't handle the recommendation request,\r\nwe go ahead and make an async call to the `UserDataService`. When that async callback comes back, then we\r\nhandle that request. In the mean time, we handle recommendation lists requests as quickly as we can.\r\nWe never block.\r\n\r\n\r\nSo let's revisit the service. The first thing we are going to do is make the service method take\r\na callback. Before we do that, let's set down some rules.\r\n\r\n\r\n#### The first rule of queue club don't block.\r\n#### The second rule of queue club if you are not ready, use a callback and continue handling stuff you are ready for\r\n\r\n\r\n#### Queue Callbacks - Adding a CallBack to the RecommendationService inproc microservice\r\n\r\n```java\r\npublic class RecommendationService {\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n```\r\n\r\n\r\n\r\nNow we are taking a callback and we can decide when we want to handle this recommendation generation request.\r\nWe can do it right away if there user data we need is in-memory or we can delay it.\r\n\r\n\r\n#### If the user is found, call the callback right away for RecommendationService inproc microservice\r\n\r\n```java\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n /** Look for user in user cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n ...\r\n } else {\r\n /* Call the callback now because we can handle the callback now. */\r\n recommendationsCallback.accept(runRulesEngineAgainstUser(user));\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nNotice, if the user is found in the cache, we run our recommendation rules in-memory and call the callback right away\r\n`recommendationsCallback.accept(runRulesEngineAgainstUser(user))`.\r\n\r\nThe interesting part is what do we do if don't have the user loaded.\r\n\r\n\r\n#### If the user was not found, load him from the user microservice, but still don't block\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using Callback. */\r\n userDataService.loadUser(new Callback() {\r\n @Override\r\n public void accept(final User loadedUser) {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nHere we use a CallBack to load the user, and when the user is loaded, we call `handleLoadFromUserDataService`\r\nwhich adds some management about handling the callback so we can still handle this call, just not now.\r\n\r\n\r\n\r\n#### Lambda version of last example\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using lambda expression. */\r\n userDataService.loadUser(\r\n loadedUser -> {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nUsing lambdas like this makes the code more readable and terse, but remember don't deeply nest\r\nlambda expressions or you will create a code maintenance nightmare. Use them judiciously.\r\n\r\n\r\n### Queue Callbacks - Doing something later\r\n\r\nWhat we want is to handle the request for recommendations after the user service system loads\r\nthe user from its store.\r\n\r\n\r\n\r\n#### Handling UserServiceData callback methods once we get them.\r\n\r\n```java\r\n\r\npublic class RecommendationService {\r\n\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n private UserDataServiceClient userDataService;\r\n\r\n\r\n private BlockingQueue callbacks =\r\n new ArrayBlockingQueue(10_000);\r\n\r\n\r\n ...\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n ...\r\n\r\n }\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks queue. */\r\n callbacks.add(new Runnable() {\r\n @Override\r\n public void run() {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n }\r\n });\r\n }\r\n\r\n\r\n\r\n```\r\n\r\n\r\n\r\n\r\n#### handleLoadFromUserDataService rewritten using Lambda\r\n\r\n```java\r\n\r\n\r\npublic class RecommendationService {\r\n\r\n...\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks list. */\r\n callbacks.add(() -> {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n });\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nThe important part there is that every time we get a callback call from `UserDataService`, we then\r\nperform our CPU intensive recommendation rules and callback our caller. Well not exactly, what we\r\ndo is enqueue an runnable onto our callbacks queue, and later we will iterate through those but when?\r\n\r\n\r\n### Queue Callbacks Handling callbacks when our receive queue is empty, a new batch started or we hit a batch limit\r\n\r\nThe `RecommendationService` can be notified when its queue is empty, it has started a new batch and when\r\nit has reached a batch limit. These are all good times to handle callbacks from the `UserDataService`.\r\n\r\n#### Draining our callback queue\r\n```java\r\n\r\n @QueueCallback({\r\n QueueCallbackType.EMPTY,\r\n QueueCallbackType.START_BATCH,\r\n QueueCallbackType.LIMIT})\r\n private void handleCallbacks() {\r\n\r\n flushServiceProxy(userDataService);\r\n Runnable runnable = callbacks.poll();\r\n\r\n while (runnable != null) {\r\n runnable.run();\r\n runnable = callbacks.poll();\r\n }\r\n }\r\n\r\n```\r\n\r\nIt is important to remember when handling callbacks from another microservice that you want to handle\r\ncallbacks from the other service before you handle more incomming requests from you clients.\r\nEssentially you have clients that have been waiting (async waiting but still), and these clients\r\nmight represent an open TCP/IP connection like an HTTP call so it is best to close them out\r\nbefore handling more requests and like we said they were already waiting around with an open connection\r\nfor users to load form the user service.\r\n\r\nTo learn more about CallBacks, plesae read [QBit Java MicroService Lib CallBack fundamentals]([Rough Cut] QBit Microservice Lib Working With CallBacks).\r\n\r\n\r\n\r\n\r\n## Workers - pools and shards\r\n\r\n```java\r\npublic class ServiceWorkers {\r\n\r\n public static RoundRobinServiceDispatcher workers() {...\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {...\r\n```\r\n\r\nYou can compose sharded workers (for in-memory, thread safe, CPU intensive services), or workers for IO\r\nor talking to foreign services or foreign buses.\r\n\r\nHere is an example that uses a worker pool with three service workers in it:\r\n\r\nLet's say you have a service that does something:\r\n\r\n```java\r\n\r\n //Your POJO\r\n public class MultiWorker {\r\n\r\n void doSomeWork(...) {\r\n ...\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nNow this does some sort of IO and you want to have a bank of these running not just one so you can do\r\nIO in parallel. After some performance testing, you found out that three is the magic number.\r\n\r\nYou want to use your API for accessing this service:\r\n\r\n```java\r\n public interface MultiWorkerClient {\r\n void doSomeWork(...);\r\n }\r\n\r\n```\r\n\r\nNow let's create a bank of these and use it.\r\n\r\nFirst create the QBit services which add the thread/queue/microbatch.\r\n\r\n```java\r\n\r\n /* Create a service builder. */\r\n final ServiceBuilder serviceBuilder = serviceBuilder();\r\n\r\n /* Create some qbit services. */\r\n final Service service1 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service2 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service3 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n```\r\n\r\nNow add them to a ServiceWorkers object.\r\n\r\n```java\r\n\r\n ServiceWorkers dispatcher;\r\n dispatcher = workers(); //Create a round robin service dispatcher\r\n dispatcher.addServices(service1, service2, service3);\r\n dispatcher.start(); // start up the workers\r\n\r\n```\r\n\r\nYou can add services, POJOs and method consumers, method dispatchers to a service bundle.\r\nThe service bundle is an integration point into QBit.\r\n\r\nLet's add our new Service workers. ServiceWorkers is a ServiceMethodDispatcher.\r\n\r\n```Java\r\n /* Add the dispatcher to a service bundle. */\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nWe are probably going to add a helper method to the service bundle so most of this can happen in\r\na single call.\r\n\r\nNow you can start using your workers.\r\n\r\n```java\r\n\r\n /* Start using the workers. */\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n```\r\n\r\nNow you could use Spring or Guice to configure the builders and the service bundle.\r\nBut you can just do it like the above which is good for testing and understanding QBit internals.\r\n\r\nQBit also supports the concept of sharded services which is good for sharding resources like CPU\r\n(run a rules engine on each CPU core for a user recommendation engine).\r\n\r\nQBit does not know how to shard your services, you have to give it a hint.\r\nYou do this through a shard rule.\r\n\r\n```java\r\npublic interface ShardRule {\r\n int shard(String methodName, Object[] args, int numWorkers);\r\n}\r\n```\r\nWe worked on an app where the first argument to the services was the username, and then we used that to\r\nshard calls to a CPU intensive in-memory rules engine. This technique works. :)\r\n\r\nThe ServiceWorkers class has a method for creating a sharded worker pool.\r\n\r\n```java\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nTo use you just pass a shard key when you create the service workers.\r\n\r\n```java\r\n\r\n\r\n dispatcher = shardedWorkers((methodName, methodArgs, numWorkers) -> {\r\n String userName = methodArgs[0].toString();\r\n int shardKey = userName.hashCode() % numWorkers;\r\n return shardKey;\r\n });\r\n\r\n```\r\n\r\nThen add your services to the ServiceWorkers composition.\r\n```java\r\n int workerCount = Runtime.getRuntime().availableProcessors();\r\n\r\n for (int index = 0; index < workerCount; index++) {\r\n final Service service = serviceBuilder\r\n .setServiceObject(new ContentRulesEngine()).build();\r\n dispatcher.addServices(service);\r\n\r\n }\r\n```\r\n\r\nThen add it to the service bundle as before.\r\n```java\r\n\r\n dispatcher.start();\r\n\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nThen just use it:\r\n\r\n```java\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n for (int index = 0; index < 100; index++) {\r\n String userName = \"rickhigh\" + index;\r\n worker.pickSuggestions(userName);\r\n }\r\n\r\n```\r\n\r\n### Built in shard rules\r\n\r\n```java\r\n\r\n\r\npublic class ServiceWorkers {\r\n...\r\n public static ShardedMethodDispatcher shardOnFirstArgumentWorkers() {\r\n ...\r\n }\r\n\r\n...\r\n\r\n public static ShardedMethodDispatcher shardOnFifthArgumentWorkers() {\r\n ...\r\n }\r\n\r\n\r\n public static ShardedMethodDispatcher shardOnBeanPath(final String beanPath) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nThe shardOnBeanPath allows you to create a complex bean path navigation call and use its property to shard on.\r\n\r\n```java\r\n\r\n /* shard on 2nd arg which is an employee\r\n Use the employees department's id property. */\r\n dispatcher = shardOnBeanPath(\"[1].department.id\");\r\n\r\n /* Same as above. */\r\n dispatcher = shardOnBeanPath(\"1/department/id\");\r\n\r\n```\r\n\r\n[Read more about Service sharding and service workers here](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-QBit-Microservices-using-Service-Workers-and-sharded-service-workers)\r\n\r\n\r\nYou can find a lot more in the wiki. Also follow the commits.\r\nWe have been busy beavers.\r\n[QBit the microservice lib for Java - JSON, REST, WebSocket](https://github.com/advantageous/qbit/wiki).\r\n",
"note": "Don't delete this file! It's used internally to help with page regeneration."
}
\ No newline at end of file
diff --git a/stylesheets/github-light.css b/stylesheets/github-light.css
index 872a6f4b..d64ba5df 100644
--- a/stylesheets/github-light.css
+++ b/stylesheets/github-light.css
@@ -1,17 +1,25 @@
/*
- Copyright 2014 GitHub Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+The MIT License (MIT)
+
+Copyright (c) 2015 GitHub, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
*/
diff --git a/stylesheets/normalize.css b/stylesheets/normalize.css
new file mode 100644
index 00000000..30366a6e
--- /dev/null
+++ b/stylesheets/normalize.css
@@ -0,0 +1,424 @@
+/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
+
+/**
+ * 1. Set default font family to sans-serif.
+ * 2. Prevent iOS text size adjust after orientation change, without disabling
+ * user zoom.
+ */
+
+html {
+ font-family: sans-serif; /* 1 */
+ -ms-text-size-adjust: 100%; /* 2 */
+ -webkit-text-size-adjust: 100%; /* 2 */
+}
+
+/**
+ * Remove default margin.
+ */
+
+body {
+ margin: 0;
+}
+
+/* HTML5 display definitions
+ ========================================================================== */
+
+/**
+ * Correct `block` display not defined for any HTML5 element in IE 8/9.
+ * Correct `block` display not defined for `details` or `summary` in IE 10/11
+ * and Firefox.
+ * Correct `block` display not defined for `main` in IE 11.
+ */
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+menu,
+nav,
+section,
+summary {
+ display: block;
+}
+
+/**
+ * 1. Correct `inline-block` display not defined in IE 8/9.
+ * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
+ */
+
+audio,
+canvas,
+progress,
+video {
+ display: inline-block; /* 1 */
+ vertical-align: baseline; /* 2 */
+}
+
+/**
+ * Prevent modern browsers from displaying `audio` without controls.
+ * Remove excess height in iOS 5 devices.
+ */
+
+audio:not([controls]) {
+ display: none;
+ height: 0;
+}
+
+/**
+ * Address `[hidden]` styling not present in IE 8/9/10.
+ * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
+ */
+
+[hidden],
+template {
+ display: none;
+}
+
+/* Links
+ ========================================================================== */
+
+/**
+ * Remove the gray background color from active links in IE 10.
+ */
+
+a {
+ background-color: transparent;
+}
+
+/**
+ * Improve readability when focused and also mouse hovered in all browsers.
+ */
+
+a:active,
+a:hover {
+ outline: 0;
+}
+
+/* Text-level semantics
+ ========================================================================== */
+
+/**
+ * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
+ */
+
+abbr[title] {
+ border-bottom: 1px dotted;
+}
+
+/**
+ * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
+ */
+
+b,
+strong {
+ font-weight: bold;
+}
+
+/**
+ * Address styling not present in Safari and Chrome.
+ */
+
+dfn {
+ font-style: italic;
+}
+
+/**
+ * Address variable `h1` font-size and margin within `section` and `article`
+ * contexts in Firefox 4+, Safari, and Chrome.
+ */
+
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+
+/**
+ * Address styling not present in IE 8/9.
+ */
+
+mark {
+ background: #ff0;
+ color: #000;
+}
+
+/**
+ * Address inconsistent and variable font size in all browsers.
+ */
+
+small {
+ font-size: 80%;
+}
+
+/**
+ * Prevent `sub` and `sup` affecting `line-height` in all browsers.
+ */
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sup {
+ top: -0.5em;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+/* Embedded content
+ ========================================================================== */
+
+/**
+ * Remove border when inside `a` element in IE 8/9/10.
+ */
+
+img {
+ border: 0;
+}
+
+/**
+ * Correct overflow not hidden in IE 9/10/11.
+ */
+
+svg:not(:root) {
+ overflow: hidden;
+}
+
+/* Grouping content
+ ========================================================================== */
+
+/**
+ * Address margin not present in IE 8/9 and Safari.
+ */
+
+figure {
+ margin: 1em 40px;
+}
+
+/**
+ * Address differences between Firefox and other browsers.
+ */
+
+hr {
+ box-sizing: content-box;
+ height: 0;
+}
+
+/**
+ * Contain overflow in all browsers.
+ */
+
+pre {
+ overflow: auto;
+}
+
+/**
+ * Address odd `em`-unit font size rendering in all browsers.
+ */
+
+code,
+kbd,
+pre,
+samp {
+ font-family: monospace, monospace;
+ font-size: 1em;
+}
+
+/* Forms
+ ========================================================================== */
+
+/**
+ * Known limitation: by default, Chrome and Safari on OS X allow very limited
+ * styling of `select`, unless a `border` property is set.
+ */
+
+/**
+ * 1. Correct color not being inherited.
+ * Known issue: affects color of disabled elements.
+ * 2. Correct font properties not being inherited.
+ * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
+ */
+
+button,
+input,
+optgroup,
+select,
+textarea {
+ color: inherit; /* 1 */
+ font: inherit; /* 2 */
+ margin: 0; /* 3 */
+}
+
+/**
+ * Address `overflow` set to `hidden` in IE 8/9/10/11.
+ */
+
+button {
+ overflow: visible;
+}
+
+/**
+ * Address inconsistent `text-transform` inheritance for `button` and `select`.
+ * All other form control elements do not inherit `text-transform` values.
+ * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
+ * Correct `select` style inheritance in Firefox.
+ */
+
+button,
+select {
+ text-transform: none;
+}
+
+/**
+ * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
+ * and `video` controls.
+ * 2. Correct inability to style clickable `input` types in iOS.
+ * 3. Improve usability and consistency of cursor style between image-type
+ * `input` and others.
+ */
+
+button,
+html input[type="button"], /* 1 */
+input[type="reset"],
+input[type="submit"] {
+ -webkit-appearance: button; /* 2 */
+ cursor: pointer; /* 3 */
+}
+
+/**
+ * Re-set default cursor for disabled elements.
+ */
+
+button[disabled],
+html input[disabled] {
+ cursor: default;
+}
+
+/**
+ * Remove inner padding and border in Firefox 4+.
+ */
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+
+/**
+ * Address Firefox 4+ setting `line-height` on `input` using `!important` in
+ * the UA stylesheet.
+ */
+
+input {
+ line-height: normal;
+}
+
+/**
+ * It's recommended that you don't attempt to style these elements.
+ * Firefox's implementation doesn't respect box-sizing, padding, or width.
+ *
+ * 1. Address box sizing set to `content-box` in IE 8/9/10.
+ * 2. Remove excess padding in IE 8/9/10.
+ */
+
+input[type="checkbox"],
+input[type="radio"] {
+ box-sizing: border-box; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Fix the cursor style for Chrome's increment/decrement buttons. For certain
+ * `font-size` values of the `input`, it causes the cursor style of the
+ * decrement button to change from `default` to `text`.
+ */
+
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+
+/**
+ * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
+ * 2. Address `box-sizing` set to `border-box` in Safari and Chrome
+ * (include `-moz` to future-proof).
+ */
+
+input[type="search"] {
+ -webkit-appearance: textfield; /* 1 */ /* 2 */
+ box-sizing: content-box;
+}
+
+/**
+ * Remove inner padding and search cancel button in Safari and Chrome on OS X.
+ * Safari (but not Chrome) clips the cancel button when the search input has
+ * padding (and `textfield` appearance).
+ */
+
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+/**
+ * Define consistent border, margin, and padding.
+ */
+
+fieldset {
+ border: 1px solid #c0c0c0;
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em;
+}
+
+/**
+ * 1. Correct `color` not being inherited in IE 8/9/10/11.
+ * 2. Remove padding so people aren't caught out if they zero out fieldsets.
+ */
+
+legend {
+ border: 0; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Remove default vertical scrollbar in IE 8/9/10/11.
+ */
+
+textarea {
+ overflow: auto;
+}
+
+/**
+ * Don't inherit the `font-weight` (applied by a rule above).
+ * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
+ */
+
+optgroup {
+ font-weight: bold;
+}
+
+/* Tables
+ ========================================================================== */
+
+/**
+ * Remove most spacing between table cells.
+ */
+
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+td,
+th {
+ padding: 0;
+}
diff --git a/stylesheets/stylesheet.css b/stylesheets/stylesheet.css
index 3da34852..b5f20c23 100644
--- a/stylesheets/stylesheet.css
+++ b/stylesheets/stylesheet.css
@@ -1,425 +1,245 @@
-/*******************************************************************************
-Slate Theme for GitHub Pages
-by Jason Costello, @jsncostello
-*******************************************************************************/
-
-@import url(github-light.css);
-
-/*******************************************************************************
-MeyerWeb Reset
-*******************************************************************************/
-
-html, body, div, span, applet, object, iframe,
-h1, h2, h3, h4, h5, h6, p, blockquote, pre,
-a, abbr, acronym, address, big, cite, code,
-del, dfn, em, img, ins, kbd, q, s, samp,
-small, strike, strong, sub, sup, tt, var,
-b, u, i, center,
-dl, dt, dd, ol, ul, li,
-fieldset, form, label, legend,
-table, caption, tbody, tfoot, thead, tr, th, td,
-article, aside, canvas, details, embed,
-figure, figcaption, footer, header, hgroup,
-menu, nav, output, ruby, section, summary,
-time, mark, audio, video {
- margin: 0;
- padding: 0;
- border: 0;
- font: inherit;
- vertical-align: baseline;
-}
-
-/* HTML5 display-role reset for older browsers */
-article, aside, details, figcaption, figure,
-footer, header, hgroup, menu, nav, section {
- display: block;
-}
-
-ol, ul {
- list-style: none;
-}
-
-table {
- border-collapse: collapse;
- border-spacing: 0;
-}
-
-/*******************************************************************************
-Theme Styles
-*******************************************************************************/
+* {
+ box-sizing: border-box; }
body {
- box-sizing: border-box;
- color:#373737;
- background: #212121;
+ padding: 0;
+ margin: 0;
+ font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 16px;
- font-family: 'Myriad Pro', Calibri, Helvetica, Arial, sans-serif;
line-height: 1.5;
- -webkit-font-smoothing: antialiased;
-}
-
-h1, h2, h3, h4, h5, h6 {
- margin: 10px 0;
- font-weight: 700;
- color:#222222;
- font-family: 'Lucida Grande', 'Calibri', Helvetica, Arial, sans-serif;
- letter-spacing: -1px;
-}
-
-h1 {
- font-size: 36px;
- font-weight: 700;
-}
-
-h2 {
- padding-bottom: 10px;
- font-size: 32px;
- background: url('../images/bg_hr.png') repeat-x bottom;
-}
-
-h3 {
- font-size: 24px;
-}
-
-h4 {
- font-size: 21px;
-}
-
-h5 {
- font-size: 18px;
-}
-
-h6 {
- font-size: 16px;
-}
-
-p {
- margin: 10px 0 15px 0;
-}
-
-footer p {
- color: #f2f2f2;
-}
+ color: #606c71; }
a {
+ color: #1e6bb8;
+ text-decoration: none; }
+ a:hover {
+ text-decoration: underline; }
+
+.btn {
+ display: inline-block;
+ margin-bottom: 1rem;
+ color: rgba(255, 255, 255, 0.7);
+ background-color: rgba(255, 255, 255, 0.08);
+ border-color: rgba(255, 255, 255, 0.2);
+ border-style: solid;
+ border-width: 1px;
+ border-radius: 0.3rem;
+ transition: color 0.2s, background-color 0.2s, border-color 0.2s; }
+ .btn + .btn {
+ margin-left: 1rem; }
+
+.btn:hover {
+ color: rgba(255, 255, 255, 0.8);
text-decoration: none;
- color: #007edf;
- text-shadow: none;
-
- transition: color 0.5s ease;
- transition: text-shadow 0.5s ease;
- -webkit-transition: color 0.5s ease;
- -webkit-transition: text-shadow 0.5s ease;
- -moz-transition: color 0.5s ease;
- -moz-transition: text-shadow 0.5s ease;
- -o-transition: color 0.5s ease;
- -o-transition: text-shadow 0.5s ease;
- -ms-transition: color 0.5s ease;
- -ms-transition: text-shadow 0.5s ease;
-}
-
-a:hover, a:focus {text-decoration: underline;}
-
-footer a {
- color: #F2F2F2;
- text-decoration: underline;
-}
-
-em {
- font-style: italic;
-}
-
-strong {
- font-weight: bold;
-}
-
-img {
- position: relative;
- margin: 0 auto;
- max-width: 739px;
- padding: 5px;
- margin: 10px 0 10px 0;
- border: 1px solid #ebebeb;
-
- box-shadow: 0 0 5px #ebebeb;
- -webkit-box-shadow: 0 0 5px #ebebeb;
- -moz-box-shadow: 0 0 5px #ebebeb;
- -o-box-shadow: 0 0 5px #ebebeb;
- -ms-box-shadow: 0 0 5px #ebebeb;
-}
-
-p img {
- display: inline;
- margin: 0;
- padding: 0;
- vertical-align: middle;
+ background-color: rgba(255, 255, 255, 0.2);
+ border-color: rgba(255, 255, 255, 0.3); }
+
+@media screen and (min-width: 64em) {
+ .btn {
+ padding: 0.75rem 1rem; } }
+
+@media screen and (min-width: 42em) and (max-width: 64em) {
+ .btn {
+ padding: 0.6rem 0.9rem;
+ font-size: 0.9rem; } }
+
+@media screen and (max-width: 42em) {
+ .btn {
+ display: block;
+ width: 100%;
+ padding: 0.75rem;
+ font-size: 0.9rem; }
+ .btn + .btn {
+ margin-top: 1rem;
+ margin-left: 0; } }
+
+.page-header {
+ color: #fff;
text-align: center;
- border: none;
-}
-
-pre, code {
- width: 100%;
- color: #222;
- background-color: #fff;
-
- font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace;
- font-size: 14px;
-
- border-radius: 2px;
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
-}
-
-pre {
- width: 100%;
- padding: 10px;
- box-shadow: 0 0 10px rgba(0,0,0,.1);
+ background-color: #159957;
+ background-image: linear-gradient(120deg, #155799, #159957); }
+
+@media screen and (min-width: 64em) {
+ .page-header {
+ padding: 5rem 6rem; } }
+
+@media screen and (min-width: 42em) and (max-width: 64em) {
+ .page-header {
+ padding: 3rem 4rem; } }
+
+@media screen and (max-width: 42em) {
+ .page-header {
+ padding: 2rem 1rem; } }
+
+.project-name {
+ margin-top: 0;
+ margin-bottom: 0.1rem; }
+
+@media screen and (min-width: 64em) {
+ .project-name {
+ font-size: 3.25rem; } }
+
+@media screen and (min-width: 42em) and (max-width: 64em) {
+ .project-name {
+ font-size: 2.25rem; } }
+
+@media screen and (max-width: 42em) {
+ .project-name {
+ font-size: 1.75rem; } }
+
+.project-tagline {
+ margin-bottom: 2rem;
+ font-weight: normal;
+ opacity: 0.7; }
+
+@media screen and (min-width: 64em) {
+ .project-tagline {
+ font-size: 1.25rem; } }
+
+@media screen and (min-width: 42em) and (max-width: 64em) {
+ .project-tagline {
+ font-size: 1.15rem; } }
+
+@media screen and (max-width: 42em) {
+ .project-tagline {
+ font-size: 1rem; } }
+
+.main-content :first-child {
+ margin-top: 0; }
+.main-content img {
+ max-width: 100%; }
+.main-content h1, .main-content h2, .main-content h3, .main-content h4, .main-content h5, .main-content h6 {
+ margin-top: 2rem;
+ margin-bottom: 1rem;
+ font-weight: normal;
+ color: #159957; }
+.main-content p {
+ margin-bottom: 1em; }
+.main-content code {
+ padding: 2px 4px;
+ font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
+ font-size: 0.9rem;
+ color: #383e41;
+ background-color: #f3f6fa;
+ border-radius: 0.3rem; }
+.main-content pre {
+ padding: 0.8rem;
+ margin-top: 0;
+ margin-bottom: 1rem;
+ font: 1rem Consolas, "Liberation Mono", Menlo, Courier, monospace;
+ color: #567482;
+ word-wrap: normal;
+ background-color: #f3f6fa;
+ border: solid 1px #dce6f0;
+ border-radius: 0.3rem; }
+ .main-content pre > code {
+ padding: 0;
+ margin: 0;
+ font-size: 0.9rem;
+ color: #567482;
+ word-break: normal;
+ white-space: pre;
+ background: transparent;
+ border: 0; }
+.main-content .highlight {
+ margin-bottom: 1rem; }
+ .main-content .highlight pre {
+ margin-bottom: 0;
+ word-break: normal; }
+.main-content .highlight pre, .main-content pre {
+ padding: 0.8rem;
overflow: auto;
-}
-
-code {
- padding: 3px;
- margin: 0 3px;
- box-shadow: 0 0 10px rgba(0,0,0,.1);
-}
-
-pre code {
- display: block;
- box-shadow: none;
-}
-
-blockquote {
- color: #666;
- margin-bottom: 20px;
- padding: 0 0 0 20px;
- border-left: 3px solid #bbb;
-}
-
-
-ul, ol, dl {
- margin-bottom: 15px
-}
-
-ul {
- list-style-position: inside;
- list-style: disc;
- padding-left: 20px;
-}
-
-ol {
- list-style-position: inside;
- list-style: decimal;
- padding-left: 20px;
-}
-
-dl dt {
- font-weight: bold;
-}
-
-dl dd {
- padding-left: 20px;
- font-style: italic;
-}
-
-dl p {
- padding-left: 20px;
- font-style: italic;
-}
-
-hr {
- height: 1px;
- margin-bottom: 5px;
- border: none;
- background: url('../images/bg_hr.png') repeat-x center;
-}
-
-table {
- border: 1px solid #373737;
- margin-bottom: 20px;
- text-align: left;
- }
-
-th {
- font-family: 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif;
- padding: 10px;
- background: #373737;
- color: #fff;
- }
-
-td {
- padding: 10px;
- border: 1px solid #373737;
- }
-
-form {
- background: #f2f2f2;
- padding: 20px;
-}
-
-/*******************************************************************************
-Full-Width Styles
-*******************************************************************************/
-
-.outer {
- width: 100%;
-}
-
-.inner {
- position: relative;
- max-width: 640px;
- padding: 20px 10px;
- margin: 0 auto;
-}
-
-#forkme_banner {
- display: block;
- position: absolute;
- top:0;
- right: 10px;
- z-index: 10;
- padding: 10px 50px 10px 10px;
- color: #fff;
- background: url('../images/blacktocat.png') #0090ff no-repeat 95% 50%;
- font-weight: 700;
- box-shadow: 0 0 10px rgba(0,0,0,.5);
- border-bottom-left-radius: 2px;
- border-bottom-right-radius: 2px;
-}
-
-#header_wrap {
- background: #212121;
- background: -moz-linear-gradient(top, #373737, #212121);
- background: -webkit-linear-gradient(top, #373737, #212121);
- background: -ms-linear-gradient(top, #373737, #212121);
- background: -o-linear-gradient(top, #373737, #212121);
- background: linear-gradient(top, #373737, #212121);
-}
-
-#header_wrap .inner {
- padding: 50px 10px 30px 10px;
-}
-
-#project_title {
+ font-size: 0.9rem;
+ line-height: 1.45;
+ border-radius: 0.3rem; }
+.main-content pre code, .main-content pre tt {
+ display: inline;
+ max-width: initial;
+ padding: 0;
margin: 0;
- color: #fff;
- font-size: 42px;
- font-weight: 700;
- text-shadow: #111 0px 0px 10px;
-}
-
-#project_tagline {
- color: #fff;
- font-size: 24px;
- font-weight: 300;
- background: none;
- text-shadow: #111 0px 0px 10px;
-}
-
-#downloads {
- position: absolute;
- width: 210px;
- z-index: 10;
- bottom: -40px;
- right: 0;
- height: 70px;
- background: url('../images/icon_download.png') no-repeat 0% 90%;
-}
-
-.zip_download_link {
+ overflow: initial;
+ line-height: inherit;
+ word-wrap: normal;
+ background-color: transparent;
+ border: 0; }
+ .main-content pre code:before, .main-content pre code:after, .main-content pre tt:before, .main-content pre tt:after {
+ content: normal; }
+.main-content ul, .main-content ol {
+ margin-top: 0; }
+.main-content blockquote {
+ padding: 0 1rem;
+ margin-left: 0;
+ color: #819198;
+ border-left: 0.3rem solid #dce6f0; }
+ .main-content blockquote > :first-child {
+ margin-top: 0; }
+ .main-content blockquote > :last-child {
+ margin-bottom: 0; }
+.main-content table {
display: block;
- float: right;
- width: 90px;
- height:70px;
- text-indent: -5000px;
- overflow: hidden;
- background: url(../images/sprite_download.png) no-repeat bottom left;
-}
-
-.tar_download_link {
+ width: 100%;
+ overflow: auto;
+ word-break: normal;
+ word-break: keep-all; }
+ .main-content table th {
+ font-weight: bold; }
+ .main-content table th, .main-content table td {
+ padding: 0.5rem 1rem;
+ border: 1px solid #e9ebec; }
+.main-content dl {
+ padding: 0; }
+ .main-content dl dt {
+ padding: 0;
+ margin-top: 1rem;
+ font-size: 1rem;
+ font-weight: bold; }
+ .main-content dl dd {
+ padding: 0;
+ margin-bottom: 1rem; }
+.main-content hr {
+ height: 2px;
+ padding: 0;
+ margin: 1rem 0;
+ background-color: #eff0f1;
+ border: 0; }
+
+@media screen and (min-width: 64em) {
+ .main-content {
+ max-width: 64rem;
+ padding: 2rem 6rem;
+ margin: 0 auto;
+ font-size: 1.1rem; } }
+
+@media screen and (min-width: 42em) and (max-width: 64em) {
+ .main-content {
+ padding: 2rem 4rem;
+ font-size: 1.1rem; } }
+
+@media screen and (max-width: 42em) {
+ .main-content {
+ padding: 2rem 1rem;
+ font-size: 1rem; } }
+
+.site-footer {
+ padding-top: 2rem;
+ margin-top: 2rem;
+ border-top: solid 1px #eff0f1; }
+
+.site-footer-owner {
display: block;
- float: right;
- width: 90px;
- height:70px;
- text-indent: -5000px;
- overflow: hidden;
- background: url(../images/sprite_download.png) no-repeat bottom right;
- margin-left: 10px;
-}
-
-.zip_download_link:hover {
- background: url(../images/sprite_download.png) no-repeat top left;
-}
-
-.tar_download_link:hover {
- background: url(../images/sprite_download.png) no-repeat top right;
-}
-
-#main_content_wrap {
- background: #f2f2f2;
- border-top: 1px solid #111;
- border-bottom: 1px solid #111;
-}
-
-#main_content {
- padding-top: 40px;
-}
-
-#footer_wrap {
- background: #212121;
-}
-
-
-
-/*******************************************************************************
-Small Device Styles
-*******************************************************************************/
-
-@media screen and (max-width: 480px) {
- body {
- font-size:14px;
- }
-
- #downloads {
- display: none;
- }
-
- .inner {
- min-width: 320px;
- max-width: 480px;
- }
-
- #project_title {
- font-size: 32px;
- }
-
- h1 {
- font-size: 28px;
- }
-
- h2 {
- font-size: 24px;
- }
-
- h3 {
- font-size: 21px;
- }
-
- h4 {
- font-size: 18px;
- }
+ font-weight: bold; }
- h5 {
- font-size: 14px;
- }
+.site-footer-credits {
+ color: #819198; }
- h6 {
- font-size: 12px;
- }
+@media screen and (min-width: 64em) {
+ .site-footer {
+ font-size: 1rem; } }
- code, pre {
- min-width: 320px;
- max-width: 480px;
- font-size: 11px;
- }
+@media screen and (min-width: 42em) and (max-width: 64em) {
+ .site-footer {
+ font-size: 1rem; } }
-}
+@media screen and (max-width: 42em) {
+ .site-footer {
+ font-size: 0.9rem; } }
From 74a3936441194da4008a855325ab453bde575df3 Mon Sep 17 00:00:00 2001
From: Richard Hightower
Date: Fri, 8 Apr 2016 20:01:25 -0700
Subject: [PATCH 03/19] Create gh-pages branch via GitHub
---
index.html | 2 +-
params.json | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/index.html b/index.html
index 62b30745..78eaddb8 100644
--- a/index.html
+++ b/index.html
@@ -23,7 +23,7 @@
The Java microservice lib. QBit is a reactive progra
QBit Website
-Qbit - The Microservice Lib for Java - JSON, REST, WebSocket, Speed!
+QBit - The Microservice Lib for Java - JSON, REST, WebSocket, Speed!
Quick overview of QBit
diff --git a/params.json b/params.json
index d8d64394..abe54d56 100644
--- a/params.json
+++ b/params.json
@@ -1,6 +1,6 @@
{
"name": "QBit - Microservices Lib",
"tagline": "The Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.",
- "body": "[QBit Java Micorservices lib tutorials](https://github.com/MammatusTech/qbit-microservices-examples/wiki)|\r\n[QBit Website](http://advantageous.github.io/qbit/)\r\n\r\n#Qbit - The Microservice Lib for Java - JSON, REST, WebSocket, Speed! \r\n\r\n## Quick overview of QBit\r\n\r\nThe Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.\r\n\r\nGot a question? Ask here: [QBit Google Group](https://groups.google.com/forum/#!forum/qbit-microservice).\r\n\r\nEverything is a queue. You have a choice. You can embrace it and control it. You can optimize for it.\r\nOr you can hide behind abstractions. QBit opens you up to peeking into what is going on, and allows you\r\nto pull some levers without selling your soul.\r\n\r\nQBit is a library not a framework. You can mix and match QBit with Spring, Guice, etc.\r\n\r\nQBit is FAST!\r\n\r\n\r\n\r\n#### Using from maven\r\n```xml\r\n\r\n io.advantageous.qbit\r\n qbit-admin\r\n 0.9.4.RELEASE\r\n\r\n\r\n io.advantageous.qbit\r\n qbit-vertx\r\n 0.9.4.RELEASE\r\n\r\n```\r\n\r\n#### Using from gradle\r\n```java\r\ncompile 'io.advantageous.qbit:qbit-admin:0.9.4.RELEASE'\r\ncompile 'io.advantageous.qbit:qbit-vertx:0.9.4.RELEASE'\r\n```\r\n\r\nCore Features\r\n============\r\n\r\n* Write REST based async microservices\r\n* Write ***WebSocket*** based async microservices (fast async RPC over WebSocket)\r\n* Actor Service Queues using micro-batching for high-speed message passing\r\n* Strongly async typed event bus which can be distributed\r\n* Async low overhead metrics gathering which can be queried and distributed (for doing fast lane analytics)\r\n* Complex async call coordination (with the Reactor) for reactive programming\r\n* Built-in support for ***health checks*** (and integration with tools like Consul)\r\n* Built-in support for ***monitoring*** (and integration with wire protocols like StatsD)\r\n* Built-in support for ***Service Discovery*** (with integration with health system, DNS SRV records and Consul)\r\n* Integration with persistent queues\r\n* [12 factor app port bindings](http://12factor.net/), health checks, KPI gathering, Logging MDC\r\n* API Gateway support for client generation and consumption via [Swagger](http://swagger.io/).\r\n* Our services can generate Swagger files (like idl for JSON/REST).\r\n* Remote client proxies for WebSocket (your interface is your IDL)\r\n\r\n\r\nStatus\r\n=====\r\nDeployed at several large fortune 100 companies. \r\nQBit now works with Vertx (standalone or embedded).\r\nYou can also use QBit on non-QBit projects, it is just a lib.\r\n\r\nLicense\r\n=====\r\nApache 2\r\n\r\n\r\n## Java Microservice Lib\r\n\r\nQBit has inproc services, REST microservices and WebSocket microservices as well as an\r\nin-proc service event bus (which can be per module or per app). It supports workers and in-memory services.\r\n\r\nBefore we describe more, here are two sample services:\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {...\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {...\r\n```\r\n\r\n\r\n#### Adder Service using URI params\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {...\r\n }\r\n```\r\n\r\n\r\n\r\nQBit philosophy:\r\n====\r\nAt the end of the day QBit is a simple library not a framework.\r\nYour app is not a QBit app but a Java app that uses the QBit lib.\r\nQBit allows you to work with Java UTIL concurrent, and does not endeavor to hide it from you.\r\nJust trying to take the sting out of it.\r\n\r\nDoes it work\r\n=====\r\nWe have used techniques in Boon and QBit with great success in high-end, high-performance, high-scalable apps.\r\nWe helped clients handle 10x the load with 1/10th the servers of their competitors using techniques in QBit.\r\nQBit is us being sick of hand tuning queue access and threads.\r\n\r\n\r\nBoon and QBit humility policy\r\n=====\r\nIdeas for Boon and QBit often come from all over the web. We make mistakes. Point them out.\r\nAs a developer of Boon and QBit, we are fellow travelers.\r\nIf you have an idea or technique you want to share, we listen.\r\n\r\n\r\nInspiration\r\n====\r\n\r\nA big inspiration for Boon/QBit was Vertx, Akka, Go Channels, Active Objects, Apartment Model Threading, Actor,\r\nand the Mechanical Sympathy papers.\r\n\r\nQBit has ideas that are similar to many frameworks. We are all reading the same papers.\r\nQBit got inspiration from the LMAX disruptor papers and this blog post about\r\n[link transfer queue versus disruptor](http://php.sabscape.com/blog/?p=557). We had some theories about\r\nqueues that blog post inspired us to try them out. Some of these theories are deployed at some of the\r\nbiggest middleware backends and whose name brands are known around the world. And thus QBit was born.\r\n\r\nQBit also took an lot of inspiration by the great work done\r\nby Tim Fox on Vertx. The first project using something that could actually be called QBit (albeit early QBit)\r\n was using Vertx on an web/mobile microservice for an app that could potentially have 80 million users.\r\n It was this\r\nexperience with Vertx and early QBit that led to QBit development and evolution. QBit is built on the\r\nshoulders of giants (Netty/Vertx).\r\n\r\nDoes QBit compete with...\r\n====\r\nSpring Disruptor: No. You could use QBit to write plugins for Spring Disruptor I suppose, but QBit does\r\nnot compete with Spring Disruptor.\r\nSpring Boot/Spring MVC: No. We use the same annotations but QBit is geared for high-speed in-memory\r\nmicroservices. It is more like Akka than Spring Boot. QBit has a subset of the features of Spring MVC\r\ngeared only for microservices, i.e., WebSocket RPC, REST, JSON marshaling, etc.\r\nAkka: No. Well Maybe. Akka has similar concepts but they take a different approach. QBit is more focused\r\n on Java, and microservices (REST, JSON, WebSocket) than Akka.\r\nLMAX Disruptor: No. In fact, we can use disruptor as on of the queues that QBit uses underneath the covers.\r\n\r\n\r\n(Early benchmarks have been removed. They were here. QBit got a lot faster.\r\n Benchmarking QBit is a moving target at the moment.\r\n Links and reports will be created.)\r\n\r\n\r\nCode Examples\r\n\r\n\r\n## Basic Queue example (REST style services is further down)\r\n\r\n====\r\n\r\n```java\r\n\r\n BasicQueue queue = BasicQueue.create(Integer.class, 1000);\r\n\r\n //Sending threads\r\n\r\n SendQueue sendQueue = queue.sendQueue();\r\n for (int index = 0; index < amount; index++) {\r\n sendQueue.send(index);\r\n }\r\n sendQueue.flushSends();\r\n ...\r\n sendQueue.sendAndFlush(code);\r\n //other methods for sendQueue, writeBatch, writeMany\r\n\r\n\r\n //Receiving Threads\r\n ReceiveQueue receiveQueue = queue.receiveQueue();\r\n Integer item = receiveQueue.take();\r\n //other methods poll(), pollWait(), readBatch(), readBatch(count)\r\n```\r\n\r\n\r\n### What is QBit again?\r\n\r\nQBit is a queuing library for microservices. It is similar to many other projects like Akka, Spring Reactor,\r\netc. QBit is just a library not a platform. QBit has libraries to put a service behind a queue.\r\nYou can use QBit queues directly or you can create a service. QBit services can be exposed by WebSocket,\r\nHTTP, HTTP pipeline, and other types of remoting. A service in QBit is a Java class whose methods are\r\n executed behind service queues. QBit implements apartment model threading and is similar to the\r\n Actor model or a better description would be Active Objects. QBit does not use a disruptor (but could).\r\n It uses regular Java Queues. QBit can do north of 100 million ping pong calls per second which is\r\n an amazing speed (seen as high as 200M). QBit also supports calling services via REST, and WebSocket.\r\n QBit is microservices in the pure Web sense: JSON, HTTP, WebSocket, etc. QBit uses micro batching to\r\n push messages through the pipe (queue, IO, etc.) faster to reduce thread hand-off.\r\n\r\n### QBit lingo\r\n\r\nQBit is a Java microservice lib supporting REST, JSON and WebSocket. It is written in Java but we could\r\none day write a version in Rust or Go or C# (but that would require a large payday).\r\n\r\n**Service**\r\nPOJO (plain old Java object) behind a queue that can receive method calls via proxy calls or events\r\n(May have one thread managing events, method calls, and responses or two one for method calls and events\r\n 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.\r\n\r\n**ServiceBundle**\r\nMany POJOs behind one response queue and many receive queues. There may be one thread for all responses\r\nor not. They also can be one receive queue.\r\n\r\n**Queue**\r\nA thread managing a queue. It supports batching. It has events for empty, reachedLimit, startedBatch,\r\nidle. You can listen to these events from services that sit behind a queue. You don't have to use Services.\r\nYou can use Queue's direct. In QBit, you have sender queues and receivers queues. They are separated to\r\nsupport micro-batching.\r\n\r\n**ServiceEndpointServer**\r\nServiceBundle that is exposed to REST and WebSocket communication.\r\n\r\n**EventBus**\r\nEventBus is a way to send a lot of messages to services that may be loosely coupled.\r\n\r\n**ClientProxy**\r\nClientProxy is a way to invoke service through async interface, service can be inproc (same process) or\r\nremoted over WebSocket.\r\n\r\n**Non-blocking**\r\nQBit is a non-blocking lib. You use CallBacks via Java 8 Lambdas. You can also send event messages and get\r\nreplies. Messaging is built into the system so you can easily coordinate complex tasks.\r\nQBit takes an object-oriented approach to service development so services look like normal Java services\r\nthat you\r\nalready write, but the services live behind a queue/thread. This is not a new concept. Microsoft did this\r\nwith DCOM/COM and called it active objects. Akka does it with actors and called them strongly typed Actors.\r\nThe important concepts is that you get the speed of reactive and actor style messaging but you develop\r\nin a natural OOP approach. QBit is not the first. QBit is not the only.\r\n\r\n\r\n**Speed**\r\nQBit is VERY fast. There is a of course a lot of room for improvement. But already 200M+ TPS inproc ping pong, 10M-20M+ TPS event bus, 500K TPS RPC calls over WebSocket/JSON, etc.\r\nMore work needs to be done to improve speed, but now it is fast enough where we are focusing more on\r\nusability.\r\nThe JSON support uses Boon by default which is up to 4x faster than other JSON parsers for the\r\nREST/JSON, WebSocket/JSON use case.\r\n\r\n**Reactive Programming**\r\nQBit provides a **Reactor** to manage async calls. This allows callbacks to be handled on the same thread that called them and it provides for timeout and error handling. Read [Reactor tutorial for creating reactive micro service programming](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices)\r\n\r\n**Service Discovery**\r\nBuilt in support for service discovery. This includes integration with Consul.\r\n\r\n\r\n**StatService**\r\nBuilt in support for stats. The **StatService** can be integrated with **StatsD** (Graphite, Grafana, DataDog, etc.) to publish passive stats. Or you can query the stats engine and react to the stats (counts, timings and levels). The **StatsService** is a reactive stats system that can be clustered. The StatService is reactive in that your services can publish to it and query it and react based on the results. You can implement things like rate limiting and react to an increased rate of something. The ServiceDiscovery system integrates with the HealthSystem and Consul to roll up each of your internal services that make up you micro service and publish the composite availably of your micro service to a single HTTP endpoint or a dead mans switch in Consul (TTL). \r\n\r\n\r\n\r\n### CURLable REST services example\r\n\r\nTalk is cheap. Let's look at some code. You can get a detailed walk through in the Wiki.\r\nWe have a lot of documentation already.\r\n\r\nWe will create a service that is exposed through REST/JSON.\r\n\r\nTo query the size of the todo list:\r\n\r\n```bash\r\ncurl localhost:8080/services/todo-service/todo/count\r\n```\r\n\r\nTo add a new TODO item.\r\n\r\n```bash\r\ncurl -X POST -H \"Content-Type: application/json\" -d \\\r\n'{\"name\":\"xyz\",\"description\":\"xyz\"}' \\\r\nhttp://localhost:8080/services/todo-service/todo\r\n```\r\n\r\nTo get a list of TODO items\r\n```bash\r\ncurl http://localhost:8080/services/todo-service/todo/\r\n```\r\n\r\nThe TODO example will use and track Todo items.\r\n\r\n#### Todo item POJO sans getter\r\n\r\n```java\r\npackage io.advantageous.qbit.examples;\r\n\r\nimport java.util.Date;\r\n\r\n\r\npublic class TodoItem {\r\n\r\n\r\n private final String description;\r\n private final String name;\r\n private final Date due;\r\n\r\n```\r\n\r\nThe TodoService uses Spring MVC style annotations.\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n\r\n private List todoItemList = new ArrayList<>();\r\n\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {\r\n\r\n return todoItemList.size();\r\n }\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {\r\n\r\n return todoItemList;\r\n }\r\n\r\n @RequestMapping(value = \"/todo\", method = RequestMethod.POST)\r\n public void add(TodoItem item) {\r\n\r\n todoItemList.add(item);\r\n }\r\n\r\n}\r\n\r\n```\r\n\r\n\r\n#### Sending non-JSON\r\n\r\nYou can POST/PUT non-JSON and you can capture the body as a `String` or as a `byte[]`. \r\nIf the content-type is set to anything but `application/json` and your body is defined a String or byte[].\r\nThis works automatically. (The content-type has to be set.)\r\n\r\n```java\r\n @RequestMapping(value = \"/body/bytes\", method = RequestMethod.POST)\r\n public boolean bodyPostBytes( byte[] body) {\r\n String string = new String(body, StandardCharsets.UTF_8);\r\n return string.equals(\"foo\");\r\n }\r\n\r\n @RequestMapping(value = \"/body/string\", method = RequestMethod.POST)\r\n public boolean bodyPostString(String body) {\r\n return body.equals(\"foo\");\r\n }\r\n```\r\n\r\n\r\n#### Sending different response codes for success\r\n\r\nBy default QBit sends a `200` (OK) for a non-void call (a call that has a return or a Callback). If the REST operation has no return or no callback then QBit sends a `202` (Accepted). There may be times when you want to send a 201 (Created) or some other code that is not an Exception. You can do that by setting `code` on `@RequestMapping`. By default the code is -1 which means use the default behavior (200 for success, 202 for one-way message, and 500 for errors).\r\n\r\n\r\n#### Sending different response codes for success\r\n```java\r\n\r\n @RequestMapping(value = \"/helloj7\", code = 221)\r\n public void helloJSend7(Callback>> callback) {\r\n callback.returnThis(JSendResponseBuilder.jSendResponseBuilder(Lists.list(\r\n \"hello \" + System.currentTimeMillis())).build());\r\n }\r\n\r\n```\r\n\r\n`Callbacks` can be used for internal services as well. It is often the case that you use a [CallbackBuilder](https://github.com/advantageous/qbit/wiki/%5BDocument%5D-CallbackBuilder-and-generics-for-Reactive-Java-Microservices) or a QBit [Reactor](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices) to manage service calls. \r\n\r\n#### Working with non JSON responses\r\n\r\nYou do not have to return JSON form rest calls.\r\nYou can return any binary or any text by using `HttpBinaryResponse` and `HttpTextResponse`.\r\n\r\n#### Returning non JSON from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildTextResponse());\r\n }\r\n```\r\n\r\n\r\n#### Returning binary from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildBinaryResponse());\r\n }\r\n```\r\n\r\n#### Side note Why Spring style annotations?\r\nWhy did we pick Spring style annotations?\r\n1) Spring is not a standard and neither is QBit. 2) We found the Spring annotations to be less verbose.\r\n3) More people use Spring than Java EE. We wrote QBit for people to use.\r\nWe could easily support JAX-RS style annotations, and we probably will.\r\nSince QBit focuses on JSON, we do not need all of the complexity of JAX-RS or even all the features of\r\nthe Spring MVC annotations. Also we can literally use the actual Spring annotations. QBit and Boon\r\nuse a non-type safe mechanism for annotations which means they are not tied to a particular lib.\r\nYou can define your own. We hate vendor tie-in even if it is an open source vendor.\r\n(We also support @POST, @GET which is similar to JAX-RS).\r\n\r\nNow just start it up.\r\n\r\n```java\r\n\r\n public static void main(String... args) {\r\n\r\n ServiceEndpointServer server = new EndpointServerBuilder().build();\r\n server.initServices(new TodoService());\r\n server.start();\r\n }\r\n```\r\n\r\n\r\n\r\nThat is it. There is also out of the box WebSocket support with client side proxy generation so\r\nyou can call into services at the rate of millions of calls per second.\r\n\r\n## Using URI Params for QBit microservice\r\n\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {\r\n\r\n return a + b;\r\n }\r\n }\r\n\r\n```\r\n\r\n## WebSocket\r\nYou can always invoke QBit services via a WebSocket proxy.\r\nThe advantage of a WebSocket proxy is it allows you execute 1M RPC+ a second (1 million remote calls\r\nevery second).\r\n\r\n\r\n#### Using a microservice remotely with WebSocket\r\n```java\r\n /* Start QBit client for WebSocket calls. */\r\n final Client client = clientBuilder()\r\n .setPort(7000).setRequestBatchSize(1).build();\r\n\r\n\r\n /* Create a proxy to the service. */\r\n final AdderServiceClientInterface adderService =\r\n client.createProxy(AdderServiceClientInterface.class,\r\n \"adder-service\");\r\n\r\n client.start();\r\n\r\n\r\n\r\n /* Call the service */\r\n adderService.add(System.out::println, 1, 2);\r\n\r\n```\r\n\r\nThe output is 3.\r\n\r\n```output\r\n3\r\n```\r\n\r\n\r\nThe above uses a WebSocket proxy interface to call the service async.\r\n\r\n```java\r\n\r\n interface AdderServiceClientInterface {\r\n\r\n void add(Callback callback, int a, int b);\r\n }\r\n```\r\n\r\n#### ServiceDiscovery aware websocket builders\r\n\r\nCreate websocket service client that is ServiceDiscovery aware.\r\n\r\n\r\n```java\r\n final Client client = clientBuilder.setServiceDiscovery(serviceDiscovery, \"echo\")\r\n .setUri(\"/echo\").setProtocolBatchSize(20).build().startClient();\r\n\r\n\r\n final EchoAsync echoClient = client.createProxy(EchoAsync.class, \"echo\");\r\n```\r\n\r\nCurrently the `clientBuilder` will load all service endpoints that are registered under the service name,\r\nand randomly pick one. \r\n\r\nServiceDiscovery includes Consul based, watching JSON files on disk, and DNS. It is easy to write your own service discovery as well and plug it into QBit.\r\n\r\n\r\nIn the future we can RoundRobin calls or shard calls to websocket service and/or provide auto fail over if the connection is closed. We do this for the event bus that uses service discovery but it is not baked into WebSocket based client stubs yet.\r\n\r\n\r\n## REST call with URI params\r\n\r\nThe last client example uses WebSocket. You could also just use REST, and actually use the URI params\r\nthat we setup.\r\nREST is nice but it is going to be slower than WebSocket support.\r\n\r\nQBit ships with a nice little HTTP client. We can use it.\r\n\r\nYou can use it to send async calls and WebSocket messages with the HTTP client.\r\n\r\n\r\nHere we will use the http client to invoke our remote method:\r\n\r\n#### Using a microservice remotely with REST QBit microservice client\r\n```java\r\n\r\n\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\")\r\n .setPort(7000).build();\r\n\r\n httpClient.start();\r\n String results = httpClient\r\n .get(\"/services/adder-service/add/2/2\").body();\r\n System.out.println(results);\r\n\r\n```\r\n\r\n\r\nThe output is 4.\r\n\r\n```output\r\n4\r\n```\r\n\r\n## Accessing The URI Param example with CURL\r\n\r\nYou can also access the service from curl.\r\n\r\n```bash\r\n$ curl http://localhost:7000/services/adder-service/add/2/2\r\n```\r\n\r\nSee this full example here: [QBit microservice getting started tutorial](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-------------QBit-microservice-example).\r\n\r\n[QBit URI params and WebSocket proxy client](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Using-QBit-microservice-lib's-REST-support-with-URI-Params)\r\n\r\n## Working with WebSocket, HttpClient etc.\r\n\r\nQBit has a library for working with and writing async microservices that is lightweight and fun to use.\r\n\r\n#### WebSocket server and client.\r\n\r\n\r\n#### Create an HTTP server\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n```\r\n\r\n#### Setup server WebSocket support\r\n```java\r\n /* Setup WebSocket Server support. */\r\n httpServer.setWebSocketOnOpenConsumer(webSocket -> {\r\n webSocket.setTextMessageConsumer(message -> {\r\n webSocket.sendText(\"ECHO \" + message);\r\n });\r\n });\r\n\r\n```\r\n\r\n#### Start the server\r\n```java\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n```\r\n\r\n#### Setup the WebSocket client\r\n```java\r\n\r\n /** CLIENT. */\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\n#### Client WebSocket\r\n\r\n```java\r\n\r\n /* Setup the client websocket. */\r\n WebSocket webSocket = httpClient\r\n .createWebSocket(\"/websocket/rocket\");\r\n\r\n /* Setup the text consumer. */\r\n webSocket.setTextMessageConsumer(message -> {\r\n System.out.println(message);\r\n });\r\n webSocket.openAndWait();\r\n\r\n /* Send some messages. */\r\n webSocket.sendText(\"Hi mom\");\r\n webSocket.sendText(\"Hello World!\");\r\n\r\n```\r\n\r\n#### Output\r\n```output\r\n\r\nECHO Hi mom\r\nECHO Hello World!\r\n\r\n```\r\n\r\nNow stop the server and client. Pretty easy eh?\r\n\r\n## High-speed HTTP client and server done microservice style\r\n\r\n\r\n##### Starting up an HTTP server\r\n\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n /* Setting up a request Consumer with Java 8 Lambda expression. */\r\n httpServer.setHttpRequestConsumer(httpRequest -> {\r\n\r\n Map results = new HashMap<>();\r\n results.put(\"method\", httpRequest.getMethod());\r\n results.put(\"uri\", httpRequest.getUri());\r\n results.put(\"body\", httpRequest.getBodyAsString());\r\n results.put(\"headers\", httpRequest.getHeaders());\r\n results.put(\"params\", httpRequest.getParams());\r\n httpRequest.getReceiver()\r\n .response(200, \"application/json\", Boon.toJson(results));\r\n });\r\n\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n\r\n\r\n```\r\n\r\nThe focus is on ease of use and using Java 8 Lambdas for callbacks so the code is tight and small.\r\n\r\n[Find out more about QBit's microservice style WebSocket support here](https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-WebSocket-support)\r\n\r\n\r\n## Using HTTP Client lib\r\n\r\nNow, let's try out our HTTP client.\r\n\r\n##### Starting up an HTTP client\r\n\r\n```java\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\nYou just pass the URL, the port and then call start.\r\n\r\n## Synchronous HTTP calls\r\n\r\nNow you can start sending HTTP requests.\r\n\r\n##### No Param HTTP GET\r\n\r\n```java\r\n /* Send no param get. */\r\n HttpResponse httpResponse = httpClient.get( \"/hello/mom\" );\r\n puts( httpResponse );\r\n```\r\n\r\nAn HTTP response just contains the results from the server.\r\n\r\n\r\n##### No Param HTTP Response\r\n\r\n```java\r\npublic interface HttpResponse {\r\n\r\n MultiMap headers();\r\n\r\n int code();\r\n\r\n String contentType();\r\n\r\n String body();\r\n\r\n}\r\n\r\n```\r\n\r\nThere are helper methods for sync HTTP GET calls.\r\n\r\n\r\n\r\n##### Helper methods for GET\r\n```java\r\n\r\n\r\n /* Send one param get. */\r\n httpResponse = httpClient.getWith1Param(\"/hello/singleParam\",\r\n \"hi\", \"mom\");\r\n puts(\"single param\", httpResponse );\r\n\r\n\r\n /* Send two param get. */\r\n httpResponse = httpClient.getWith2Params(\"/hello/twoParams\",\r\n \"hi\", \"mom\", \"hello\", \"dad\");\r\n puts(\"two params\", httpResponse );\r\n\r\n...\r\n\r\n /* Send five param get. */\r\n httpResponse = httpClient.getWith5Params(\"/hello/5params\",\r\n \"hi\", \"mom\",\r\n \"hello\", \"dad\",\r\n \"greetings\", \"kids\",\r\n \"yo\", \"pets\",\r\n \"hola\", \"neighbors\");\r\n puts(\"5 params\", httpResponse );\r\n\r\n\r\n```\r\n\r\nThe puts method is a helper method it does System.out.println more or less by the way.\r\n\r\nThe first five params are covered. Beyond five, you have to use the HttpBuilder.\r\n\r\n```java\r\n\r\n\r\n /* Send six params with get. */\r\n\r\n final HttpRequest httpRequest = httpRequestBuilder()\r\n .addParam(\"hi\", \"mom\")\r\n .addParam(\"hello\", \"dad\")\r\n .addParam(\"greetings\", \"kids\")\r\n .addParam(\"yo\", \"pets\")\r\n .addParam(\"hola\", \"pets\")\r\n .addParam(\"salutations\", \"all\").build();\r\n\r\n httpResponse = httpClient.sendRequestAndWait(httpRequest);\r\n puts(\"6 params\", httpResponse );\r\n```\r\n\r\n## Http Async HTTP Client\r\n\r\nThere are async calls for GET as well.\r\n\r\n#### Async calls for HTTP GET using Java 8 lambda\r\n\r\n```java\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsync(\"/hi/async\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith1Param(\"/hi/async\", \"hi\", \"mom\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda 1 param\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith2Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 2 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n...\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith5Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n \"p3\", \"v3\",\r\n \"p4\", \"v4\",\r\n \"p5\", \"v5\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 5 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n```\r\n\r\n[Find more about the easy to use, fast microservice HTTP client here]\r\n(https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-HttpClient-GET,-POST,-et-al,-JSON,-Java-8-Lambda).\r\n\r\n## InProc QBit services\r\n\r\nQBit allows for services behind queues to be run in-proc as well.\r\n\r\n```java\r\n\r\n /* POJO service. */\r\n final TodoManager todoManagerImpl = new TodoManager();\r\n\r\n /*\r\n Create the service which manages async calls to todoManagerImpl.\r\n */\r\n final Service service = serviceBuilder()\r\n .setServiceObject(todoManagerImpl)\r\n .build().startServiceQueue();\r\n\r\n\r\n /* Create Asynchronous proxy over Synchronous service. */\r\n final TodoManagerClientInterface todoManager =\r\n service.createProxy(TodoManagerClientInterface.class);\r\n\r\n service.startCallBackHandler();\r\n\r\n\r\n System.out.println(\"This is an async call\");\r\n /* Asynchronous method call. */\r\n todoManager.add(new Todo(\"Call Mom\", \"Give Mom a call\"));\r\n\r\n\r\n AtomicInteger countTracker = new AtomicInteger();\r\n //Hold count from async call to service... for testing and showing it is an async callback\r\n\r\n System.out.println(\"This is an async call to count\");\r\n\r\n todoManager.count(count -> {\r\n System.out.println(\"This lambda expression is the callback \" + count);\r\n\r\n countTracker.set(count);\r\n });\r\n\r\n\r\n todoManager.clientProxyFlush(); //Flush all methods. It batches calls.\r\n\r\n Sys.sleep(100);\r\n\r\n System.out.printf(\"This is the count back from the server %d\\n\", countTracker.get());\r\n\r\n```\r\n\r\n[Detailed tutorial on in-proc services is being written.](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-Working-with-inproc-MicroServices-within-QBit.)\r\n\r\n\r\n## QBit Event Bus\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\nQBit also has a service event bus. This example is a an employee benefits services example.\r\n\r\nWe have two channels.\r\n\r\n```\r\npublic static final String NEW_HIRE_CHANNEL = \"com.mycompnay.employee.new\";\r\n\r\npublic static final String PAYROLL_ADJUSTMENT_CHANNEL = \"com.mycompnay.employee.payroll\";\r\n```\r\n\r\nAn employee object looks like this:\r\n\r\n```java\r\n\r\npublic static class Employee {\r\n final String firstName;\r\n final int employeeId;\r\n```\r\n\r\n\r\nThis example has three services: EmployeeHiringService, BenefitsService, and PayrollService.\r\n\r\nThese services are inproc services. QBit supports WebSocket, HTTP and REST remote services as well, but for now, let's focus on inproc services. If you understand inproc then you will understand remote.\r\n\r\nThe EmployeeHiringService actually fires off the events to other two services.\r\n\r\n```java\r\npublic class EmployeeHiringService {\r\n\r\n\r\n public void hireEmployee(final Employee employee) {\r\n\r\n int salary = 100;\r\n System.out.printf(\"Hired employee %s\\n\", employee);\r\n\r\n //Does stuff to hire employee\r\n\r\n //Sends events\r\n final EventManager eventManager =\r\n serviceContext().eventManager();\r\n eventManager.send(NEW_HIRE_CHANNEL, employee);\r\n\r\n eventManager.sendArray(PAYROLL_ADJUSTMENT_CHANNEL,\r\n employee, salary);\r\n\r\n\r\n }\r\n\r\n }\r\n```\r\n\r\n\r\nNotice that we call sendArray so we can send the employee and their salary.\r\nThe listener for PAYROLL_ADJUSTMENT_CHANNEL will have to handle both an employee and an int\r\nthat represents the new employees salary.\r\nYou can also use event bus proxies so you do not have to call into the event bus at all.\r\n\r\nThe BenefitsService listens for new employees being hired so it can enroll them into the benefits system.\r\n\r\n```java\r\npublic static class BenefitsService {\r\n\r\n @OnEvent(NEW_HIRE_CHANNEL)\r\n public void enroll(final Employee employee) {\r\n\r\n System.out.printf(\"Employee enrolled into benefits system employee %s %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId());\r\n\r\n }\r\n\r\n```\r\n\r\nDaddy needs to get paid.\r\n\r\n```java\r\n public static class PayrollService {\r\n\r\n @OnEvent(PAYROLL_ADJUSTMENT_CHANNEL)\r\n public void addEmployeeToPayroll(final Employee employee, int salary) {\r\n\r\n System.out.printf(\"Employee added to payroll %s %d %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId(), salary);\r\n\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nThe employee is the employee object from the EmployeeHiringService.\r\n\r\nso you can get your benefits, and paid!\r\n\r\nFind more details here:\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\n\r\n## Private event bus and event bus proxies\r\n\r\n You can define your own interface to the event bus and you can use your own event buses with QBit.\r\n Each module in your service can have its own internal event bus.\r\n\r\n To learn more read:\r\n [QBit Microservice working with a private event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-private-event-bus-for-inproc-microservices)\r\n and [QBit Java Microservice lib using your own interface to the event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-strongly-typed-event-bus-proxies-for-QBit-Java-Microservice-lib).\r\n\r\n\r\n\r\n## Queue Callbacks\r\n\r\n To really grasp QBit, one must grasp the concepts of a CallBack.\r\n\r\n A CallBack is a way to get an async response in QBit.\r\n\r\n You call a service method and it calls you back.\r\n\r\n Client proxies can have callbacks:\r\n\r\n\r\n#### Queue Callbacks - RecommendationService client interface\r\n```java\r\n\r\npublic interface RecommendationServiceClient {\r\n\r\n\r\n void recommend(final Callback> recommendationsCallback,\r\n final String userName);\r\n}\r\n\r\n```\r\n\r\nCallbacks are Java 8 Consumers with some optional extra error handling.\r\n\r\n\r\n#### Queue Callbacks - Callback\r\n\r\n```java\r\n\r\n\r\npublic interface Callback extends java.util.function.Consumer {\r\n default void onError(java.lang.Throwable error) { /* compiled code */ }\r\n}\r\n\r\n```\r\n\r\nServices that can block should use callbacks.\r\nThus if loadUser blocked in the following example, it should really use a callback instead of returning a value.\r\n\r\npublic class RecommendationService {\r\n\r\n#### Queue Callbacks - Simple minded implementation of RecommendationService\r\n```java\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n public List recommend(final String userName) {\r\n User user = users.get(userName);\r\n if (user == null) {\r\n user = loadUser(userName);\r\n }\r\n return runRulesEngineAgainstUser(user);\r\n }\r\n\r\n```\r\n\r\n\r\nLet's pretend `loadUser` has to look in a local cache, and if the user is not found, look in an off-heap cache\r\nand if not found it must ask for the user from the UserService which must check its caches and perhaps fallback\r\nto loading the user data from a database or from other services.\r\nIn other words, `loadUser` can potentially block on IO.\r\n\r\n\r\n\r\n### Queue Callbacks - The first rule of Queue Club - don't block\r\n\r\n\r\nOur client does not block, but our service does. Going back to our `RecommendationService`.\r\nIf we get a lot of cache hits for user loads, perhaps the\r\nblock will not be that long, but it will be there and every time we have to fault in a user, the whole system\r\nis gummed up. What we want to be able to do is if we can't handle the recommendation request,\r\nwe go ahead and make an async call to the `UserDataService`. When that async callback comes back, then we\r\nhandle that request. In the mean time, we handle recommendation lists requests as quickly as we can.\r\nWe never block.\r\n\r\n\r\nSo let's revisit the service. The first thing we are going to do is make the service method take\r\na callback. Before we do that, let's set down some rules.\r\n\r\n\r\n#### The first rule of queue club don't block.\r\n#### The second rule of queue club if you are not ready, use a callback and continue handling stuff you are ready for\r\n\r\n\r\n#### Queue Callbacks - Adding a CallBack to the RecommendationService inproc microservice\r\n\r\n```java\r\npublic class RecommendationService {\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n```\r\n\r\n\r\n\r\nNow we are taking a callback and we can decide when we want to handle this recommendation generation request.\r\nWe can do it right away if there user data we need is in-memory or we can delay it.\r\n\r\n\r\n#### If the user is found, call the callback right away for RecommendationService inproc microservice\r\n\r\n```java\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n /** Look for user in user cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n ...\r\n } else {\r\n /* Call the callback now because we can handle the callback now. */\r\n recommendationsCallback.accept(runRulesEngineAgainstUser(user));\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nNotice, if the user is found in the cache, we run our recommendation rules in-memory and call the callback right away\r\n`recommendationsCallback.accept(runRulesEngineAgainstUser(user))`.\r\n\r\nThe interesting part is what do we do if don't have the user loaded.\r\n\r\n\r\n#### If the user was not found, load him from the user microservice, but still don't block\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using Callback. */\r\n userDataService.loadUser(new Callback() {\r\n @Override\r\n public void accept(final User loadedUser) {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nHere we use a CallBack to load the user, and when the user is loaded, we call `handleLoadFromUserDataService`\r\nwhich adds some management about handling the callback so we can still handle this call, just not now.\r\n\r\n\r\n\r\n#### Lambda version of last example\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using lambda expression. */\r\n userDataService.loadUser(\r\n loadedUser -> {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nUsing lambdas like this makes the code more readable and terse, but remember don't deeply nest\r\nlambda expressions or you will create a code maintenance nightmare. Use them judiciously.\r\n\r\n\r\n### Queue Callbacks - Doing something later\r\n\r\nWhat we want is to handle the request for recommendations after the user service system loads\r\nthe user from its store.\r\n\r\n\r\n\r\n#### Handling UserServiceData callback methods once we get them.\r\n\r\n```java\r\n\r\npublic class RecommendationService {\r\n\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n private UserDataServiceClient userDataService;\r\n\r\n\r\n private BlockingQueue callbacks =\r\n new ArrayBlockingQueue(10_000);\r\n\r\n\r\n ...\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n ...\r\n\r\n }\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks queue. */\r\n callbacks.add(new Runnable() {\r\n @Override\r\n public void run() {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n }\r\n });\r\n }\r\n\r\n\r\n\r\n```\r\n\r\n\r\n\r\n\r\n#### handleLoadFromUserDataService rewritten using Lambda\r\n\r\n```java\r\n\r\n\r\npublic class RecommendationService {\r\n\r\n...\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks list. */\r\n callbacks.add(() -> {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n });\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nThe important part there is that every time we get a callback call from `UserDataService`, we then\r\nperform our CPU intensive recommendation rules and callback our caller. Well not exactly, what we\r\ndo is enqueue an runnable onto our callbacks queue, and later we will iterate through those but when?\r\n\r\n\r\n### Queue Callbacks Handling callbacks when our receive queue is empty, a new batch started or we hit a batch limit\r\n\r\nThe `RecommendationService` can be notified when its queue is empty, it has started a new batch and when\r\nit has reached a batch limit. These are all good times to handle callbacks from the `UserDataService`.\r\n\r\n#### Draining our callback queue\r\n```java\r\n\r\n @QueueCallback({\r\n QueueCallbackType.EMPTY,\r\n QueueCallbackType.START_BATCH,\r\n QueueCallbackType.LIMIT})\r\n private void handleCallbacks() {\r\n\r\n flushServiceProxy(userDataService);\r\n Runnable runnable = callbacks.poll();\r\n\r\n while (runnable != null) {\r\n runnable.run();\r\n runnable = callbacks.poll();\r\n }\r\n }\r\n\r\n```\r\n\r\nIt is important to remember when handling callbacks from another microservice that you want to handle\r\ncallbacks from the other service before you handle more incomming requests from you clients.\r\nEssentially you have clients that have been waiting (async waiting but still), and these clients\r\nmight represent an open TCP/IP connection like an HTTP call so it is best to close them out\r\nbefore handling more requests and like we said they were already waiting around with an open connection\r\nfor users to load form the user service.\r\n\r\nTo learn more about CallBacks, plesae read [QBit Java MicroService Lib CallBack fundamentals]([Rough Cut] QBit Microservice Lib Working With CallBacks).\r\n\r\n\r\n\r\n\r\n## Workers - pools and shards\r\n\r\n```java\r\npublic class ServiceWorkers {\r\n\r\n public static RoundRobinServiceDispatcher workers() {...\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {...\r\n```\r\n\r\nYou can compose sharded workers (for in-memory, thread safe, CPU intensive services), or workers for IO\r\nor talking to foreign services or foreign buses.\r\n\r\nHere is an example that uses a worker pool with three service workers in it:\r\n\r\nLet's say you have a service that does something:\r\n\r\n```java\r\n\r\n //Your POJO\r\n public class MultiWorker {\r\n\r\n void doSomeWork(...) {\r\n ...\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nNow this does some sort of IO and you want to have a bank of these running not just one so you can do\r\nIO in parallel. After some performance testing, you found out that three is the magic number.\r\n\r\nYou want to use your API for accessing this service:\r\n\r\n```java\r\n public interface MultiWorkerClient {\r\n void doSomeWork(...);\r\n }\r\n\r\n```\r\n\r\nNow let's create a bank of these and use it.\r\n\r\nFirst create the QBit services which add the thread/queue/microbatch.\r\n\r\n```java\r\n\r\n /* Create a service builder. */\r\n final ServiceBuilder serviceBuilder = serviceBuilder();\r\n\r\n /* Create some qbit services. */\r\n final Service service1 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service2 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service3 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n```\r\n\r\nNow add them to a ServiceWorkers object.\r\n\r\n```java\r\n\r\n ServiceWorkers dispatcher;\r\n dispatcher = workers(); //Create a round robin service dispatcher\r\n dispatcher.addServices(service1, service2, service3);\r\n dispatcher.start(); // start up the workers\r\n\r\n```\r\n\r\nYou can add services, POJOs and method consumers, method dispatchers to a service bundle.\r\nThe service bundle is an integration point into QBit.\r\n\r\nLet's add our new Service workers. ServiceWorkers is a ServiceMethodDispatcher.\r\n\r\n```Java\r\n /* Add the dispatcher to a service bundle. */\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nWe are probably going to add a helper method to the service bundle so most of this can happen in\r\na single call.\r\n\r\nNow you can start using your workers.\r\n\r\n```java\r\n\r\n /* Start using the workers. */\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n```\r\n\r\nNow you could use Spring or Guice to configure the builders and the service bundle.\r\nBut you can just do it like the above which is good for testing and understanding QBit internals.\r\n\r\nQBit also supports the concept of sharded services which is good for sharding resources like CPU\r\n(run a rules engine on each CPU core for a user recommendation engine).\r\n\r\nQBit does not know how to shard your services, you have to give it a hint.\r\nYou do this through a shard rule.\r\n\r\n```java\r\npublic interface ShardRule {\r\n int shard(String methodName, Object[] args, int numWorkers);\r\n}\r\n```\r\nWe worked on an app where the first argument to the services was the username, and then we used that to\r\nshard calls to a CPU intensive in-memory rules engine. This technique works. :)\r\n\r\nThe ServiceWorkers class has a method for creating a sharded worker pool.\r\n\r\n```java\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nTo use you just pass a shard key when you create the service workers.\r\n\r\n```java\r\n\r\n\r\n dispatcher = shardedWorkers((methodName, methodArgs, numWorkers) -> {\r\n String userName = methodArgs[0].toString();\r\n int shardKey = userName.hashCode() % numWorkers;\r\n return shardKey;\r\n });\r\n\r\n```\r\n\r\nThen add your services to the ServiceWorkers composition.\r\n```java\r\n int workerCount = Runtime.getRuntime().availableProcessors();\r\n\r\n for (int index = 0; index < workerCount; index++) {\r\n final Service service = serviceBuilder\r\n .setServiceObject(new ContentRulesEngine()).build();\r\n dispatcher.addServices(service);\r\n\r\n }\r\n```\r\n\r\nThen add it to the service bundle as before.\r\n```java\r\n\r\n dispatcher.start();\r\n\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nThen just use it:\r\n\r\n```java\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n for (int index = 0; index < 100; index++) {\r\n String userName = \"rickhigh\" + index;\r\n worker.pickSuggestions(userName);\r\n }\r\n\r\n```\r\n\r\n### Built in shard rules\r\n\r\n```java\r\n\r\n\r\npublic class ServiceWorkers {\r\n...\r\n public static ShardedMethodDispatcher shardOnFirstArgumentWorkers() {\r\n ...\r\n }\r\n\r\n...\r\n\r\n public static ShardedMethodDispatcher shardOnFifthArgumentWorkers() {\r\n ...\r\n }\r\n\r\n\r\n public static ShardedMethodDispatcher shardOnBeanPath(final String beanPath) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nThe shardOnBeanPath allows you to create a complex bean path navigation call and use its property to shard on.\r\n\r\n```java\r\n\r\n /* shard on 2nd arg which is an employee\r\n Use the employees department's id property. */\r\n dispatcher = shardOnBeanPath(\"[1].department.id\");\r\n\r\n /* Same as above. */\r\n dispatcher = shardOnBeanPath(\"1/department/id\");\r\n\r\n```\r\n\r\n[Read more about Service sharding and service workers here](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-QBit-Microservices-using-Service-Workers-and-sharded-service-workers)\r\n\r\n\r\nYou can find a lot more in the wiki. Also follow the commits.\r\nWe have been busy beavers.\r\n[QBit the microservice lib for Java - JSON, REST, WebSocket](https://github.com/advantageous/qbit/wiki).\r\n",
+ "body": "[QBit Java Micorservices lib tutorials](https://github.com/MammatusTech/qbit-microservices-examples/wiki)|\r\n[QBit Website](http://advantageous.github.io/qbit/)\r\n\r\n#QBit - The Microservice Lib for Java - JSON, REST, WebSocket, Speed! \r\n\r\n## Quick overview of QBit\r\n\r\nThe Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.\r\n\r\nGot a question? Ask here: [QBit Google Group](https://groups.google.com/forum/#!forum/qbit-microservice).\r\n\r\nEverything is a queue. You have a choice. You can embrace it and control it. You can optimize for it.\r\nOr you can hide behind abstractions. QBit opens you up to peeking into what is going on, and allows you\r\nto pull some levers without selling your soul.\r\n\r\nQBit is a library not a framework. You can mix and match QBit with Spring, Guice, etc.\r\n\r\nQBit is FAST!\r\n\r\n\r\n\r\n#### Using from maven\r\n```xml\r\n\r\n io.advantageous.qbit\r\n qbit-admin\r\n 0.9.4.RELEASE\r\n\r\n\r\n io.advantageous.qbit\r\n qbit-vertx\r\n 0.9.4.RELEASE\r\n\r\n```\r\n\r\n#### Using from gradle\r\n```java\r\ncompile 'io.advantageous.qbit:qbit-admin:0.9.4.RELEASE'\r\ncompile 'io.advantageous.qbit:qbit-vertx:0.9.4.RELEASE'\r\n```\r\n\r\nCore Features\r\n============\r\n\r\n* Write REST based async microservices\r\n* Write ***WebSocket*** based async microservices (fast async RPC over WebSocket)\r\n* Actor Service Queues using micro-batching for high-speed message passing\r\n* Strongly async typed event bus which can be distributed\r\n* Async low overhead metrics gathering which can be queried and distributed (for doing fast lane analytics)\r\n* Complex async call coordination (with the Reactor) for reactive programming\r\n* Built-in support for ***health checks*** (and integration with tools like Consul)\r\n* Built-in support for ***monitoring*** (and integration with wire protocols like StatsD)\r\n* Built-in support for ***Service Discovery*** (with integration with health system, DNS SRV records and Consul)\r\n* Integration with persistent queues\r\n* [12 factor app port bindings](http://12factor.net/), health checks, KPI gathering, Logging MDC\r\n* API Gateway support for client generation and consumption via [Swagger](http://swagger.io/).\r\n* Our services can generate Swagger files (like idl for JSON/REST).\r\n* Remote client proxies for WebSocket (your interface is your IDL)\r\n\r\n\r\nStatus\r\n=====\r\nDeployed at several large fortune 100 companies. \r\nQBit now works with Vertx (standalone or embedded).\r\nYou can also use QBit on non-QBit projects, it is just a lib.\r\n\r\nLicense\r\n=====\r\nApache 2\r\n\r\n\r\n## Java Microservice Lib\r\n\r\nQBit has inproc services, REST microservices and WebSocket microservices as well as an\r\nin-proc service event bus (which can be per module or per app). It supports workers and in-memory services.\r\n\r\nBefore we describe more, here are two sample services:\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {...\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {...\r\n```\r\n\r\n\r\n#### Adder Service using URI params\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {...\r\n }\r\n```\r\n\r\n\r\n\r\nQBit philosophy:\r\n====\r\nAt the end of the day QBit is a simple library not a framework.\r\nYour app is not a QBit app but a Java app that uses the QBit lib.\r\nQBit allows you to work with Java UTIL concurrent, and does not endeavor to hide it from you.\r\nJust trying to take the sting out of it.\r\n\r\nDoes it work\r\n=====\r\nWe have used techniques in Boon and QBit with great success in high-end, high-performance, high-scalable apps.\r\nWe helped clients handle 10x the load with 1/10th the servers of their competitors using techniques in QBit.\r\nQBit is us being sick of hand tuning queue access and threads.\r\n\r\n\r\nBoon and QBit humility policy\r\n=====\r\nIdeas for Boon and QBit often come from all over the web. We make mistakes. Point them out.\r\nAs a developer of Boon and QBit, we are fellow travelers.\r\nIf you have an idea or technique you want to share, we listen.\r\n\r\n\r\nInspiration\r\n====\r\n\r\nA big inspiration for Boon/QBit was Vertx, Akka, Go Channels, Active Objects, Apartment Model Threading, Actor,\r\nand the Mechanical Sympathy papers.\r\n\r\nQBit has ideas that are similar to many frameworks. We are all reading the same papers.\r\nQBit got inspiration from the LMAX disruptor papers and this blog post about\r\n[link transfer queue versus disruptor](http://php.sabscape.com/blog/?p=557). We had some theories about\r\nqueues that blog post inspired us to try them out. Some of these theories are deployed at some of the\r\nbiggest middleware backends and whose name brands are known around the world. And thus QBit was born.\r\n\r\nQBit also took an lot of inspiration by the great work done\r\nby Tim Fox on Vertx. The first project using something that could actually be called QBit (albeit early QBit)\r\n was using Vertx on an web/mobile microservice for an app that could potentially have 80 million users.\r\n It was this\r\nexperience with Vertx and early QBit that led to QBit development and evolution. QBit is built on the\r\nshoulders of giants (Netty/Vertx).\r\n\r\nDoes QBit compete with...\r\n====\r\nSpring Disruptor: No. You could use QBit to write plugins for Spring Disruptor I suppose, but QBit does\r\nnot compete with Spring Disruptor.\r\nSpring Boot/Spring MVC: No. We use the same annotations but QBit is geared for high-speed in-memory\r\nmicroservices. It is more like Akka than Spring Boot. QBit has a subset of the features of Spring MVC\r\ngeared only for microservices, i.e., WebSocket RPC, REST, JSON marshaling, etc.\r\nAkka: No. Well Maybe. Akka has similar concepts but they take a different approach. QBit is more focused\r\n on Java, and microservices (REST, JSON, WebSocket) than Akka.\r\nLMAX Disruptor: No. In fact, we can use disruptor as on of the queues that QBit uses underneath the covers.\r\n\r\n\r\n(Early benchmarks have been removed. They were here. QBit got a lot faster.\r\n Benchmarking QBit is a moving target at the moment.\r\n Links and reports will be created.)\r\n\r\n\r\nCode Examples\r\n\r\n\r\n## Basic Queue example (REST style services is further down)\r\n\r\n====\r\n\r\n```java\r\n\r\n BasicQueue queue = BasicQueue.create(Integer.class, 1000);\r\n\r\n //Sending threads\r\n\r\n SendQueue sendQueue = queue.sendQueue();\r\n for (int index = 0; index < amount; index++) {\r\n sendQueue.send(index);\r\n }\r\n sendQueue.flushSends();\r\n ...\r\n sendQueue.sendAndFlush(code);\r\n //other methods for sendQueue, writeBatch, writeMany\r\n\r\n\r\n //Receiving Threads\r\n ReceiveQueue receiveQueue = queue.receiveQueue();\r\n Integer item = receiveQueue.take();\r\n //other methods poll(), pollWait(), readBatch(), readBatch(count)\r\n```\r\n\r\n\r\n### What is QBit again?\r\n\r\nQBit is a queuing library for microservices. It is similar to many other projects like Akka, Spring Reactor,\r\netc. QBit is just a library not a platform. QBit has libraries to put a service behind a queue.\r\nYou can use QBit queues directly or you can create a service. QBit services can be exposed by WebSocket,\r\nHTTP, HTTP pipeline, and other types of remoting. A service in QBit is a Java class whose methods are\r\n executed behind service queues. QBit implements apartment model threading and is similar to the\r\n Actor model or a better description would be Active Objects. QBit does not use a disruptor (but could).\r\n It uses regular Java Queues. QBit can do north of 100 million ping pong calls per second which is\r\n an amazing speed (seen as high as 200M). QBit also supports calling services via REST, and WebSocket.\r\n QBit is microservices in the pure Web sense: JSON, HTTP, WebSocket, etc. QBit uses micro batching to\r\n push messages through the pipe (queue, IO, etc.) faster to reduce thread hand-off.\r\n\r\n### QBit lingo\r\n\r\nQBit is a Java microservice lib supporting REST, JSON and WebSocket. It is written in Java but we could\r\none day write a version in Rust or Go or C# (but that would require a large payday).\r\n\r\n**Service**\r\nPOJO (plain old Java object) behind a queue that can receive method calls via proxy calls or events\r\n(May have one thread managing events, method calls, and responses or two one for method calls and events\r\n 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.\r\n\r\n**ServiceBundle**\r\nMany POJOs behind one response queue and many receive queues. There may be one thread for all responses\r\nor not. They also can be one receive queue.\r\n\r\n**Queue**\r\nA thread managing a queue. It supports batching. It has events for empty, reachedLimit, startedBatch,\r\nidle. You can listen to these events from services that sit behind a queue. You don't have to use Services.\r\nYou can use Queue's direct. In QBit, you have sender queues and receivers queues. They are separated to\r\nsupport micro-batching.\r\n\r\n**ServiceEndpointServer**\r\nServiceBundle that is exposed to REST and WebSocket communication.\r\n\r\n**EventBus**\r\nEventBus is a way to send a lot of messages to services that may be loosely coupled.\r\n\r\n**ClientProxy**\r\nClientProxy is a way to invoke service through async interface, service can be inproc (same process) or\r\nremoted over WebSocket.\r\n\r\n**Non-blocking**\r\nQBit is a non-blocking lib. You use CallBacks via Java 8 Lambdas. You can also send event messages and get\r\nreplies. Messaging is built into the system so you can easily coordinate complex tasks.\r\nQBit takes an object-oriented approach to service development so services look like normal Java services\r\nthat you\r\nalready write, but the services live behind a queue/thread. This is not a new concept. Microsoft did this\r\nwith DCOM/COM and called it active objects. Akka does it with actors and called them strongly typed Actors.\r\nThe important concepts is that you get the speed of reactive and actor style messaging but you develop\r\nin a natural OOP approach. QBit is not the first. QBit is not the only.\r\n\r\n\r\n**Speed**\r\nQBit is VERY fast. There is a of course a lot of room for improvement. But already 200M+ TPS inproc ping pong, 10M-20M+ TPS event bus, 500K TPS RPC calls over WebSocket/JSON, etc.\r\nMore work needs to be done to improve speed, but now it is fast enough where we are focusing more on\r\nusability.\r\nThe JSON support uses Boon by default which is up to 4x faster than other JSON parsers for the\r\nREST/JSON, WebSocket/JSON use case.\r\n\r\n**Reactive Programming**\r\nQBit provides a **Reactor** to manage async calls. This allows callbacks to be handled on the same thread that called them and it provides for timeout and error handling. Read [Reactor tutorial for creating reactive micro service programming](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices)\r\n\r\n**Service Discovery**\r\nBuilt in support for service discovery. This includes integration with Consul.\r\n\r\n\r\n**StatService**\r\nBuilt in support for stats. The **StatService** can be integrated with **StatsD** (Graphite, Grafana, DataDog, etc.) to publish passive stats. Or you can query the stats engine and react to the stats (counts, timings and levels). The **StatsService** is a reactive stats system that can be clustered. The StatService is reactive in that your services can publish to it and query it and react based on the results. You can implement things like rate limiting and react to an increased rate of something. The ServiceDiscovery system integrates with the HealthSystem and Consul to roll up each of your internal services that make up you micro service and publish the composite availably of your micro service to a single HTTP endpoint or a dead mans switch in Consul (TTL). \r\n\r\n\r\n\r\n### CURLable REST services example\r\n\r\nTalk is cheap. Let's look at some code. You can get a detailed walk through in the Wiki.\r\nWe have a lot of documentation already.\r\n\r\nWe will create a service that is exposed through REST/JSON.\r\n\r\nTo query the size of the todo list:\r\n\r\n```bash\r\ncurl localhost:8080/services/todo-service/todo/count\r\n```\r\n\r\nTo add a new TODO item.\r\n\r\n```bash\r\ncurl -X POST -H \"Content-Type: application/json\" -d \\\r\n'{\"name\":\"xyz\",\"description\":\"xyz\"}' \\\r\nhttp://localhost:8080/services/todo-service/todo\r\n```\r\n\r\nTo get a list of TODO items\r\n```bash\r\ncurl http://localhost:8080/services/todo-service/todo/\r\n```\r\n\r\nThe TODO example will use and track Todo items.\r\n\r\n#### Todo item POJO sans getter\r\n\r\n```java\r\npackage io.advantageous.qbit.examples;\r\n\r\nimport java.util.Date;\r\n\r\n\r\npublic class TodoItem {\r\n\r\n\r\n private final String description;\r\n private final String name;\r\n private final Date due;\r\n\r\n```\r\n\r\nThe TodoService uses Spring MVC style annotations.\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n\r\n private List todoItemList = new ArrayList<>();\r\n\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {\r\n\r\n return todoItemList.size();\r\n }\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {\r\n\r\n return todoItemList;\r\n }\r\n\r\n @RequestMapping(value = \"/todo\", method = RequestMethod.POST)\r\n public void add(TodoItem item) {\r\n\r\n todoItemList.add(item);\r\n }\r\n\r\n}\r\n\r\n```\r\n\r\n\r\n#### Sending non-JSON\r\n\r\nYou can POST/PUT non-JSON and you can capture the body as a `String` or as a `byte[]`. \r\nIf the content-type is set to anything but `application/json` and your body is defined a String or byte[].\r\nThis works automatically. (The content-type has to be set.)\r\n\r\n```java\r\n @RequestMapping(value = \"/body/bytes\", method = RequestMethod.POST)\r\n public boolean bodyPostBytes( byte[] body) {\r\n String string = new String(body, StandardCharsets.UTF_8);\r\n return string.equals(\"foo\");\r\n }\r\n\r\n @RequestMapping(value = \"/body/string\", method = RequestMethod.POST)\r\n public boolean bodyPostString(String body) {\r\n return body.equals(\"foo\");\r\n }\r\n```\r\n\r\n\r\n#### Sending different response codes for success\r\n\r\nBy default QBit sends a `200` (OK) for a non-void call (a call that has a return or a Callback). If the REST operation has no return or no callback then QBit sends a `202` (Accepted). There may be times when you want to send a 201 (Created) or some other code that is not an Exception. You can do that by setting `code` on `@RequestMapping`. By default the code is -1 which means use the default behavior (200 for success, 202 for one-way message, and 500 for errors).\r\n\r\n\r\n#### Sending different response codes for success\r\n```java\r\n\r\n @RequestMapping(value = \"/helloj7\", code = 221)\r\n public void helloJSend7(Callback>> callback) {\r\n callback.returnThis(JSendResponseBuilder.jSendResponseBuilder(Lists.list(\r\n \"hello \" + System.currentTimeMillis())).build());\r\n }\r\n\r\n```\r\n\r\n`Callbacks` can be used for internal services as well. It is often the case that you use a [CallbackBuilder](https://github.com/advantageous/qbit/wiki/%5BDocument%5D-CallbackBuilder-and-generics-for-Reactive-Java-Microservices) or a QBit [Reactor](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices) to manage service calls. \r\n\r\n#### Working with non JSON responses\r\n\r\nYou do not have to return JSON form rest calls.\r\nYou can return any binary or any text by using `HttpBinaryResponse` and `HttpTextResponse`.\r\n\r\n#### Returning non JSON from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildTextResponse());\r\n }\r\n```\r\n\r\n\r\n#### Returning binary from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildBinaryResponse());\r\n }\r\n```\r\n\r\n#### Side note Why Spring style annotations?\r\nWhy did we pick Spring style annotations?\r\n1) Spring is not a standard and neither is QBit. 2) We found the Spring annotations to be less verbose.\r\n3) More people use Spring than Java EE. We wrote QBit for people to use.\r\nWe could easily support JAX-RS style annotations, and we probably will.\r\nSince QBit focuses on JSON, we do not need all of the complexity of JAX-RS or even all the features of\r\nthe Spring MVC annotations. Also we can literally use the actual Spring annotations. QBit and Boon\r\nuse a non-type safe mechanism for annotations which means they are not tied to a particular lib.\r\nYou can define your own. We hate vendor tie-in even if it is an open source vendor.\r\n(We also support @POST, @GET which is similar to JAX-RS).\r\n\r\nNow just start it up.\r\n\r\n```java\r\n\r\n public static void main(String... args) {\r\n\r\n ServiceEndpointServer server = new EndpointServerBuilder().build();\r\n server.initServices(new TodoService());\r\n server.start();\r\n }\r\n```\r\n\r\n\r\n\r\nThat is it. There is also out of the box WebSocket support with client side proxy generation so\r\nyou can call into services at the rate of millions of calls per second.\r\n\r\n## Using URI Params for QBit microservice\r\n\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {\r\n\r\n return a + b;\r\n }\r\n }\r\n\r\n```\r\n\r\n## WebSocket\r\nYou can always invoke QBit services via a WebSocket proxy.\r\nThe advantage of a WebSocket proxy is it allows you execute 1M RPC+ a second (1 million remote calls\r\nevery second).\r\n\r\n\r\n#### Using a microservice remotely with WebSocket\r\n```java\r\n /* Start QBit client for WebSocket calls. */\r\n final Client client = clientBuilder()\r\n .setPort(7000).setRequestBatchSize(1).build();\r\n\r\n\r\n /* Create a proxy to the service. */\r\n final AdderServiceClientInterface adderService =\r\n client.createProxy(AdderServiceClientInterface.class,\r\n \"adder-service\");\r\n\r\n client.start();\r\n\r\n\r\n\r\n /* Call the service */\r\n adderService.add(System.out::println, 1, 2);\r\n\r\n```\r\n\r\nThe output is 3.\r\n\r\n```output\r\n3\r\n```\r\n\r\n\r\nThe above uses a WebSocket proxy interface to call the service async.\r\n\r\n```java\r\n\r\n interface AdderServiceClientInterface {\r\n\r\n void add(Callback callback, int a, int b);\r\n }\r\n```\r\n\r\n#### ServiceDiscovery aware websocket builders\r\n\r\nCreate websocket service client that is ServiceDiscovery aware.\r\n\r\n\r\n```java\r\n final Client client = clientBuilder.setServiceDiscovery(serviceDiscovery, \"echo\")\r\n .setUri(\"/echo\").setProtocolBatchSize(20).build().startClient();\r\n\r\n\r\n final EchoAsync echoClient = client.createProxy(EchoAsync.class, \"echo\");\r\n```\r\n\r\nCurrently the `clientBuilder` will load all service endpoints that are registered under the service name,\r\nand randomly pick one. \r\n\r\nServiceDiscovery includes Consul based, watching JSON files on disk, and DNS. It is easy to write your own service discovery as well and plug it into QBit.\r\n\r\n\r\nIn the future we can RoundRobin calls or shard calls to websocket service and/or provide auto fail over if the connection is closed. We do this for the event bus that uses service discovery but it is not baked into WebSocket based client stubs yet.\r\n\r\n\r\n## REST call with URI params\r\n\r\nThe last client example uses WebSocket. You could also just use REST, and actually use the URI params\r\nthat we setup.\r\nREST is nice but it is going to be slower than WebSocket support.\r\n\r\nQBit ships with a nice little HTTP client. We can use it.\r\n\r\nYou can use it to send async calls and WebSocket messages with the HTTP client.\r\n\r\n\r\nHere we will use the http client to invoke our remote method:\r\n\r\n#### Using a microservice remotely with REST QBit microservice client\r\n```java\r\n\r\n\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\")\r\n .setPort(7000).build();\r\n\r\n httpClient.start();\r\n String results = httpClient\r\n .get(\"/services/adder-service/add/2/2\").body();\r\n System.out.println(results);\r\n\r\n```\r\n\r\n\r\nThe output is 4.\r\n\r\n```output\r\n4\r\n```\r\n\r\n## Accessing The URI Param example with CURL\r\n\r\nYou can also access the service from curl.\r\n\r\n```bash\r\n$ curl http://localhost:7000/services/adder-service/add/2/2\r\n```\r\n\r\nSee this full example here: [QBit microservice getting started tutorial](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-------------QBit-microservice-example).\r\n\r\n[QBit URI params and WebSocket proxy client](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Using-QBit-microservice-lib's-REST-support-with-URI-Params)\r\n\r\n## Working with WebSocket, HttpClient etc.\r\n\r\nQBit has a library for working with and writing async microservices that is lightweight and fun to use.\r\n\r\n#### WebSocket server and client.\r\n\r\n\r\n#### Create an HTTP server\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n```\r\n\r\n#### Setup server WebSocket support\r\n```java\r\n /* Setup WebSocket Server support. */\r\n httpServer.setWebSocketOnOpenConsumer(webSocket -> {\r\n webSocket.setTextMessageConsumer(message -> {\r\n webSocket.sendText(\"ECHO \" + message);\r\n });\r\n });\r\n\r\n```\r\n\r\n#### Start the server\r\n```java\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n```\r\n\r\n#### Setup the WebSocket client\r\n```java\r\n\r\n /** CLIENT. */\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\n#### Client WebSocket\r\n\r\n```java\r\n\r\n /* Setup the client websocket. */\r\n WebSocket webSocket = httpClient\r\n .createWebSocket(\"/websocket/rocket\");\r\n\r\n /* Setup the text consumer. */\r\n webSocket.setTextMessageConsumer(message -> {\r\n System.out.println(message);\r\n });\r\n webSocket.openAndWait();\r\n\r\n /* Send some messages. */\r\n webSocket.sendText(\"Hi mom\");\r\n webSocket.sendText(\"Hello World!\");\r\n\r\n```\r\n\r\n#### Output\r\n```output\r\n\r\nECHO Hi mom\r\nECHO Hello World!\r\n\r\n```\r\n\r\nNow stop the server and client. Pretty easy eh?\r\n\r\n## High-speed HTTP client and server done microservice style\r\n\r\n\r\n##### Starting up an HTTP server\r\n\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n /* Setting up a request Consumer with Java 8 Lambda expression. */\r\n httpServer.setHttpRequestConsumer(httpRequest -> {\r\n\r\n Map results = new HashMap<>();\r\n results.put(\"method\", httpRequest.getMethod());\r\n results.put(\"uri\", httpRequest.getUri());\r\n results.put(\"body\", httpRequest.getBodyAsString());\r\n results.put(\"headers\", httpRequest.getHeaders());\r\n results.put(\"params\", httpRequest.getParams());\r\n httpRequest.getReceiver()\r\n .response(200, \"application/json\", Boon.toJson(results));\r\n });\r\n\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n\r\n\r\n```\r\n\r\nThe focus is on ease of use and using Java 8 Lambdas for callbacks so the code is tight and small.\r\n\r\n[Find out more about QBit's microservice style WebSocket support here](https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-WebSocket-support)\r\n\r\n\r\n## Using HTTP Client lib\r\n\r\nNow, let's try out our HTTP client.\r\n\r\n##### Starting up an HTTP client\r\n\r\n```java\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\nYou just pass the URL, the port and then call start.\r\n\r\n## Synchronous HTTP calls\r\n\r\nNow you can start sending HTTP requests.\r\n\r\n##### No Param HTTP GET\r\n\r\n```java\r\n /* Send no param get. */\r\n HttpResponse httpResponse = httpClient.get( \"/hello/mom\" );\r\n puts( httpResponse );\r\n```\r\n\r\nAn HTTP response just contains the results from the server.\r\n\r\n\r\n##### No Param HTTP Response\r\n\r\n```java\r\npublic interface HttpResponse {\r\n\r\n MultiMap headers();\r\n\r\n int code();\r\n\r\n String contentType();\r\n\r\n String body();\r\n\r\n}\r\n\r\n```\r\n\r\nThere are helper methods for sync HTTP GET calls.\r\n\r\n\r\n\r\n##### Helper methods for GET\r\n```java\r\n\r\n\r\n /* Send one param get. */\r\n httpResponse = httpClient.getWith1Param(\"/hello/singleParam\",\r\n \"hi\", \"mom\");\r\n puts(\"single param\", httpResponse );\r\n\r\n\r\n /* Send two param get. */\r\n httpResponse = httpClient.getWith2Params(\"/hello/twoParams\",\r\n \"hi\", \"mom\", \"hello\", \"dad\");\r\n puts(\"two params\", httpResponse );\r\n\r\n...\r\n\r\n /* Send five param get. */\r\n httpResponse = httpClient.getWith5Params(\"/hello/5params\",\r\n \"hi\", \"mom\",\r\n \"hello\", \"dad\",\r\n \"greetings\", \"kids\",\r\n \"yo\", \"pets\",\r\n \"hola\", \"neighbors\");\r\n puts(\"5 params\", httpResponse );\r\n\r\n\r\n```\r\n\r\nThe puts method is a helper method it does System.out.println more or less by the way.\r\n\r\nThe first five params are covered. Beyond five, you have to use the HttpBuilder.\r\n\r\n```java\r\n\r\n\r\n /* Send six params with get. */\r\n\r\n final HttpRequest httpRequest = httpRequestBuilder()\r\n .addParam(\"hi\", \"mom\")\r\n .addParam(\"hello\", \"dad\")\r\n .addParam(\"greetings\", \"kids\")\r\n .addParam(\"yo\", \"pets\")\r\n .addParam(\"hola\", \"pets\")\r\n .addParam(\"salutations\", \"all\").build();\r\n\r\n httpResponse = httpClient.sendRequestAndWait(httpRequest);\r\n puts(\"6 params\", httpResponse );\r\n```\r\n\r\n## Http Async HTTP Client\r\n\r\nThere are async calls for GET as well.\r\n\r\n#### Async calls for HTTP GET using Java 8 lambda\r\n\r\n```java\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsync(\"/hi/async\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith1Param(\"/hi/async\", \"hi\", \"mom\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda 1 param\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith2Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 2 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n...\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith5Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n \"p3\", \"v3\",\r\n \"p4\", \"v4\",\r\n \"p5\", \"v5\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 5 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n```\r\n\r\n[Find more about the easy to use, fast microservice HTTP client here]\r\n(https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-HttpClient-GET,-POST,-et-al,-JSON,-Java-8-Lambda).\r\n\r\n## InProc QBit services\r\n\r\nQBit allows for services behind queues to be run in-proc as well.\r\n\r\n```java\r\n\r\n /* POJO service. */\r\n final TodoManager todoManagerImpl = new TodoManager();\r\n\r\n /*\r\n Create the service which manages async calls to todoManagerImpl.\r\n */\r\n final Service service = serviceBuilder()\r\n .setServiceObject(todoManagerImpl)\r\n .build().startServiceQueue();\r\n\r\n\r\n /* Create Asynchronous proxy over Synchronous service. */\r\n final TodoManagerClientInterface todoManager =\r\n service.createProxy(TodoManagerClientInterface.class);\r\n\r\n service.startCallBackHandler();\r\n\r\n\r\n System.out.println(\"This is an async call\");\r\n /* Asynchronous method call. */\r\n todoManager.add(new Todo(\"Call Mom\", \"Give Mom a call\"));\r\n\r\n\r\n AtomicInteger countTracker = new AtomicInteger();\r\n //Hold count from async call to service... for testing and showing it is an async callback\r\n\r\n System.out.println(\"This is an async call to count\");\r\n\r\n todoManager.count(count -> {\r\n System.out.println(\"This lambda expression is the callback \" + count);\r\n\r\n countTracker.set(count);\r\n });\r\n\r\n\r\n todoManager.clientProxyFlush(); //Flush all methods. It batches calls.\r\n\r\n Sys.sleep(100);\r\n\r\n System.out.printf(\"This is the count back from the server %d\\n\", countTracker.get());\r\n\r\n```\r\n\r\n[Detailed tutorial on in-proc services is being written.](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-Working-with-inproc-MicroServices-within-QBit.)\r\n\r\n\r\n## QBit Event Bus\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\nQBit also has a service event bus. This example is a an employee benefits services example.\r\n\r\nWe have two channels.\r\n\r\n```\r\npublic static final String NEW_HIRE_CHANNEL = \"com.mycompnay.employee.new\";\r\n\r\npublic static final String PAYROLL_ADJUSTMENT_CHANNEL = \"com.mycompnay.employee.payroll\";\r\n```\r\n\r\nAn employee object looks like this:\r\n\r\n```java\r\n\r\npublic static class Employee {\r\n final String firstName;\r\n final int employeeId;\r\n```\r\n\r\n\r\nThis example has three services: EmployeeHiringService, BenefitsService, and PayrollService.\r\n\r\nThese services are inproc services. QBit supports WebSocket, HTTP and REST remote services as well, but for now, let's focus on inproc services. If you understand inproc then you will understand remote.\r\n\r\nThe EmployeeHiringService actually fires off the events to other two services.\r\n\r\n```java\r\npublic class EmployeeHiringService {\r\n\r\n\r\n public void hireEmployee(final Employee employee) {\r\n\r\n int salary = 100;\r\n System.out.printf(\"Hired employee %s\\n\", employee);\r\n\r\n //Does stuff to hire employee\r\n\r\n //Sends events\r\n final EventManager eventManager =\r\n serviceContext().eventManager();\r\n eventManager.send(NEW_HIRE_CHANNEL, employee);\r\n\r\n eventManager.sendArray(PAYROLL_ADJUSTMENT_CHANNEL,\r\n employee, salary);\r\n\r\n\r\n }\r\n\r\n }\r\n```\r\n\r\n\r\nNotice that we call sendArray so we can send the employee and their salary.\r\nThe listener for PAYROLL_ADJUSTMENT_CHANNEL will have to handle both an employee and an int\r\nthat represents the new employees salary.\r\nYou can also use event bus proxies so you do not have to call into the event bus at all.\r\n\r\nThe BenefitsService listens for new employees being hired so it can enroll them into the benefits system.\r\n\r\n```java\r\npublic static class BenefitsService {\r\n\r\n @OnEvent(NEW_HIRE_CHANNEL)\r\n public void enroll(final Employee employee) {\r\n\r\n System.out.printf(\"Employee enrolled into benefits system employee %s %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId());\r\n\r\n }\r\n\r\n```\r\n\r\nDaddy needs to get paid.\r\n\r\n```java\r\n public static class PayrollService {\r\n\r\n @OnEvent(PAYROLL_ADJUSTMENT_CHANNEL)\r\n public void addEmployeeToPayroll(final Employee employee, int salary) {\r\n\r\n System.out.printf(\"Employee added to payroll %s %d %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId(), salary);\r\n\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nThe employee is the employee object from the EmployeeHiringService.\r\n\r\nso you can get your benefits, and paid!\r\n\r\nFind more details here:\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\n\r\n## Private event bus and event bus proxies\r\n\r\n You can define your own interface to the event bus and you can use your own event buses with QBit.\r\n Each module in your service can have its own internal event bus.\r\n\r\n To learn more read:\r\n [QBit Microservice working with a private event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-private-event-bus-for-inproc-microservices)\r\n and [QBit Java Microservice lib using your own interface to the event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-strongly-typed-event-bus-proxies-for-QBit-Java-Microservice-lib).\r\n\r\n\r\n\r\n## Queue Callbacks\r\n\r\n To really grasp QBit, one must grasp the concepts of a CallBack.\r\n\r\n A CallBack is a way to get an async response in QBit.\r\n\r\n You call a service method and it calls you back.\r\n\r\n Client proxies can have callbacks:\r\n\r\n\r\n#### Queue Callbacks - RecommendationService client interface\r\n```java\r\n\r\npublic interface RecommendationServiceClient {\r\n\r\n\r\n void recommend(final Callback> recommendationsCallback,\r\n final String userName);\r\n}\r\n\r\n```\r\n\r\nCallbacks are Java 8 Consumers with some optional extra error handling.\r\n\r\n\r\n#### Queue Callbacks - Callback\r\n\r\n```java\r\n\r\n\r\npublic interface Callback extends java.util.function.Consumer {\r\n default void onError(java.lang.Throwable error) { /* compiled code */ }\r\n}\r\n\r\n```\r\n\r\nServices that can block should use callbacks.\r\nThus if loadUser blocked in the following example, it should really use a callback instead of returning a value.\r\n\r\npublic class RecommendationService {\r\n\r\n#### Queue Callbacks - Simple minded implementation of RecommendationService\r\n```java\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n public List recommend(final String userName) {\r\n User user = users.get(userName);\r\n if (user == null) {\r\n user = loadUser(userName);\r\n }\r\n return runRulesEngineAgainstUser(user);\r\n }\r\n\r\n```\r\n\r\n\r\nLet's pretend `loadUser` has to look in a local cache, and if the user is not found, look in an off-heap cache\r\nand if not found it must ask for the user from the UserService which must check its caches and perhaps fallback\r\nto loading the user data from a database or from other services.\r\nIn other words, `loadUser` can potentially block on IO.\r\n\r\n\r\n\r\n### Queue Callbacks - The first rule of Queue Club - don't block\r\n\r\n\r\nOur client does not block, but our service does. Going back to our `RecommendationService`.\r\nIf we get a lot of cache hits for user loads, perhaps the\r\nblock will not be that long, but it will be there and every time we have to fault in a user, the whole system\r\nis gummed up. What we want to be able to do is if we can't handle the recommendation request,\r\nwe go ahead and make an async call to the `UserDataService`. When that async callback comes back, then we\r\nhandle that request. In the mean time, we handle recommendation lists requests as quickly as we can.\r\nWe never block.\r\n\r\n\r\nSo let's revisit the service. The first thing we are going to do is make the service method take\r\na callback. Before we do that, let's set down some rules.\r\n\r\n\r\n#### The first rule of queue club don't block.\r\n#### The second rule of queue club if you are not ready, use a callback and continue handling stuff you are ready for\r\n\r\n\r\n#### Queue Callbacks - Adding a CallBack to the RecommendationService inproc microservice\r\n\r\n```java\r\npublic class RecommendationService {\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n```\r\n\r\n\r\n\r\nNow we are taking a callback and we can decide when we want to handle this recommendation generation request.\r\nWe can do it right away if there user data we need is in-memory or we can delay it.\r\n\r\n\r\n#### If the user is found, call the callback right away for RecommendationService inproc microservice\r\n\r\n```java\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n /** Look for user in user cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n ...\r\n } else {\r\n /* Call the callback now because we can handle the callback now. */\r\n recommendationsCallback.accept(runRulesEngineAgainstUser(user));\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nNotice, if the user is found in the cache, we run our recommendation rules in-memory and call the callback right away\r\n`recommendationsCallback.accept(runRulesEngineAgainstUser(user))`.\r\n\r\nThe interesting part is what do we do if don't have the user loaded.\r\n\r\n\r\n#### If the user was not found, load him from the user microservice, but still don't block\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using Callback. */\r\n userDataService.loadUser(new Callback() {\r\n @Override\r\n public void accept(final User loadedUser) {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nHere we use a CallBack to load the user, and when the user is loaded, we call `handleLoadFromUserDataService`\r\nwhich adds some management about handling the callback so we can still handle this call, just not now.\r\n\r\n\r\n\r\n#### Lambda version of last example\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using lambda expression. */\r\n userDataService.loadUser(\r\n loadedUser -> {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nUsing lambdas like this makes the code more readable and terse, but remember don't deeply nest\r\nlambda expressions or you will create a code maintenance nightmare. Use them judiciously.\r\n\r\n\r\n### Queue Callbacks - Doing something later\r\n\r\nWhat we want is to handle the request for recommendations after the user service system loads\r\nthe user from its store.\r\n\r\n\r\n\r\n#### Handling UserServiceData callback methods once we get them.\r\n\r\n```java\r\n\r\npublic class RecommendationService {\r\n\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n private UserDataServiceClient userDataService;\r\n\r\n\r\n private BlockingQueue callbacks =\r\n new ArrayBlockingQueue(10_000);\r\n\r\n\r\n ...\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n ...\r\n\r\n }\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks queue. */\r\n callbacks.add(new Runnable() {\r\n @Override\r\n public void run() {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n }\r\n });\r\n }\r\n\r\n\r\n\r\n```\r\n\r\n\r\n\r\n\r\n#### handleLoadFromUserDataService rewritten using Lambda\r\n\r\n```java\r\n\r\n\r\npublic class RecommendationService {\r\n\r\n...\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks list. */\r\n callbacks.add(() -> {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n });\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nThe important part there is that every time we get a callback call from `UserDataService`, we then\r\nperform our CPU intensive recommendation rules and callback our caller. Well not exactly, what we\r\ndo is enqueue an runnable onto our callbacks queue, and later we will iterate through those but when?\r\n\r\n\r\n### Queue Callbacks Handling callbacks when our receive queue is empty, a new batch started or we hit a batch limit\r\n\r\nThe `RecommendationService` can be notified when its queue is empty, it has started a new batch and when\r\nit has reached a batch limit. These are all good times to handle callbacks from the `UserDataService`.\r\n\r\n#### Draining our callback queue\r\n```java\r\n\r\n @QueueCallback({\r\n QueueCallbackType.EMPTY,\r\n QueueCallbackType.START_BATCH,\r\n QueueCallbackType.LIMIT})\r\n private void handleCallbacks() {\r\n\r\n flushServiceProxy(userDataService);\r\n Runnable runnable = callbacks.poll();\r\n\r\n while (runnable != null) {\r\n runnable.run();\r\n runnable = callbacks.poll();\r\n }\r\n }\r\n\r\n```\r\n\r\nIt is important to remember when handling callbacks from another microservice that you want to handle\r\ncallbacks from the other service before you handle more incomming requests from you clients.\r\nEssentially you have clients that have been waiting (async waiting but still), and these clients\r\nmight represent an open TCP/IP connection like an HTTP call so it is best to close them out\r\nbefore handling more requests and like we said they were already waiting around with an open connection\r\nfor users to load form the user service.\r\n\r\nTo learn more about CallBacks, plesae read [QBit Java MicroService Lib CallBack fundamentals]([Rough Cut] QBit Microservice Lib Working With CallBacks).\r\n\r\n\r\n\r\n\r\n## Workers - pools and shards\r\n\r\n```java\r\npublic class ServiceWorkers {\r\n\r\n public static RoundRobinServiceDispatcher workers() {...\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {...\r\n```\r\n\r\nYou can compose sharded workers (for in-memory, thread safe, CPU intensive services), or workers for IO\r\nor talking to foreign services or foreign buses.\r\n\r\nHere is an example that uses a worker pool with three service workers in it:\r\n\r\nLet's say you have a service that does something:\r\n\r\n```java\r\n\r\n //Your POJO\r\n public class MultiWorker {\r\n\r\n void doSomeWork(...) {\r\n ...\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nNow this does some sort of IO and you want to have a bank of these running not just one so you can do\r\nIO in parallel. After some performance testing, you found out that three is the magic number.\r\n\r\nYou want to use your API for accessing this service:\r\n\r\n```java\r\n public interface MultiWorkerClient {\r\n void doSomeWork(...);\r\n }\r\n\r\n```\r\n\r\nNow let's create a bank of these and use it.\r\n\r\nFirst create the QBit services which add the thread/queue/microbatch.\r\n\r\n```java\r\n\r\n /* Create a service builder. */\r\n final ServiceBuilder serviceBuilder = serviceBuilder();\r\n\r\n /* Create some qbit services. */\r\n final Service service1 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service2 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service3 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n```\r\n\r\nNow add them to a ServiceWorkers object.\r\n\r\n```java\r\n\r\n ServiceWorkers dispatcher;\r\n dispatcher = workers(); //Create a round robin service dispatcher\r\n dispatcher.addServices(service1, service2, service3);\r\n dispatcher.start(); // start up the workers\r\n\r\n```\r\n\r\nYou can add services, POJOs and method consumers, method dispatchers to a service bundle.\r\nThe service bundle is an integration point into QBit.\r\n\r\nLet's add our new Service workers. ServiceWorkers is a ServiceMethodDispatcher.\r\n\r\n```Java\r\n /* Add the dispatcher to a service bundle. */\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nWe are probably going to add a helper method to the service bundle so most of this can happen in\r\na single call.\r\n\r\nNow you can start using your workers.\r\n\r\n```java\r\n\r\n /* Start using the workers. */\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n```\r\n\r\nNow you could use Spring or Guice to configure the builders and the service bundle.\r\nBut you can just do it like the above which is good for testing and understanding QBit internals.\r\n\r\nQBit also supports the concept of sharded services which is good for sharding resources like CPU\r\n(run a rules engine on each CPU core for a user recommendation engine).\r\n\r\nQBit does not know how to shard your services, you have to give it a hint.\r\nYou do this through a shard rule.\r\n\r\n```java\r\npublic interface ShardRule {\r\n int shard(String methodName, Object[] args, int numWorkers);\r\n}\r\n```\r\nWe worked on an app where the first argument to the services was the username, and then we used that to\r\nshard calls to a CPU intensive in-memory rules engine. This technique works. :)\r\n\r\nThe ServiceWorkers class has a method for creating a sharded worker pool.\r\n\r\n```java\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nTo use you just pass a shard key when you create the service workers.\r\n\r\n```java\r\n\r\n\r\n dispatcher = shardedWorkers((methodName, methodArgs, numWorkers) -> {\r\n String userName = methodArgs[0].toString();\r\n int shardKey = userName.hashCode() % numWorkers;\r\n return shardKey;\r\n });\r\n\r\n```\r\n\r\nThen add your services to the ServiceWorkers composition.\r\n```java\r\n int workerCount = Runtime.getRuntime().availableProcessors();\r\n\r\n for (int index = 0; index < workerCount; index++) {\r\n final Service service = serviceBuilder\r\n .setServiceObject(new ContentRulesEngine()).build();\r\n dispatcher.addServices(service);\r\n\r\n }\r\n```\r\n\r\nThen add it to the service bundle as before.\r\n```java\r\n\r\n dispatcher.start();\r\n\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nThen just use it:\r\n\r\n```java\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n for (int index = 0; index < 100; index++) {\r\n String userName = \"rickhigh\" + index;\r\n worker.pickSuggestions(userName);\r\n }\r\n\r\n```\r\n\r\n### Built in shard rules\r\n\r\n```java\r\n\r\n\r\npublic class ServiceWorkers {\r\n...\r\n public static ShardedMethodDispatcher shardOnFirstArgumentWorkers() {\r\n ...\r\n }\r\n\r\n...\r\n\r\n public static ShardedMethodDispatcher shardOnFifthArgumentWorkers() {\r\n ...\r\n }\r\n\r\n\r\n public static ShardedMethodDispatcher shardOnBeanPath(final String beanPath) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nThe shardOnBeanPath allows you to create a complex bean path navigation call and use its property to shard on.\r\n\r\n```java\r\n\r\n /* shard on 2nd arg which is an employee\r\n Use the employees department's id property. */\r\n dispatcher = shardOnBeanPath(\"[1].department.id\");\r\n\r\n /* Same as above. */\r\n dispatcher = shardOnBeanPath(\"1/department/id\");\r\n\r\n```\r\n\r\n[Read more about Service sharding and service workers here](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-QBit-Microservices-using-Service-Workers-and-sharded-service-workers)\r\n\r\n\r\nYou can find a lot more in the wiki. Also follow the commits.\r\nWe have been busy beavers.\r\n[QBit the microservice lib for Java - JSON, REST, WebSocket](https://github.com/advantageous/qbit/wiki).\r\n",
"note": "Don't delete this file! It's used internally to help with page regeneration."
}
\ No newline at end of file
From 2a41d848abe078cdc45a7434ff16bb7e5b71ea01 Mon Sep 17 00:00:00 2001
From: Richard Hightower
Date: Fri, 8 Apr 2016 20:01:57 -0700
Subject: [PATCH 04/19] Create gh-pages branch via GitHub
From a8be8af7959ad62fdcdd6611f1b2473aaee5761a Mon Sep 17 00:00:00 2001
From: Richard Hightower
Date: Tue, 12 Apr 2016 20:02:14 -0700
Subject: [PATCH 05/19] Create gh-pages branch via GitHub
---
index.html | 8 ++++----
params.json | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/index.html b/index.html
index 78eaddb8..fa620ac0 100644
--- a/index.html
+++ b/index.html
@@ -48,19 +48,19 @@
diff --git a/params.json b/params.json
index abe54d56..05e9efdc 100644
--- a/params.json
+++ b/params.json
@@ -1,6 +1,6 @@
{
"name": "QBit - Microservices Lib",
"tagline": "The Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.",
- "body": "[QBit Java Micorservices lib tutorials](https://github.com/MammatusTech/qbit-microservices-examples/wiki)|\r\n[QBit Website](http://advantageous.github.io/qbit/)\r\n\r\n#QBit - The Microservice Lib for Java - JSON, REST, WebSocket, Speed! \r\n\r\n## Quick overview of QBit\r\n\r\nThe Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.\r\n\r\nGot a question? Ask here: [QBit Google Group](https://groups.google.com/forum/#!forum/qbit-microservice).\r\n\r\nEverything is a queue. You have a choice. You can embrace it and control it. You can optimize for it.\r\nOr you can hide behind abstractions. QBit opens you up to peeking into what is going on, and allows you\r\nto pull some levers without selling your soul.\r\n\r\nQBit is a library not a framework. You can mix and match QBit with Spring, Guice, etc.\r\n\r\nQBit is FAST!\r\n\r\n\r\n\r\n#### Using from maven\r\n```xml\r\n\r\n io.advantageous.qbit\r\n qbit-admin\r\n 0.9.4.RELEASE\r\n\r\n\r\n io.advantageous.qbit\r\n qbit-vertx\r\n 0.9.4.RELEASE\r\n\r\n```\r\n\r\n#### Using from gradle\r\n```java\r\ncompile 'io.advantageous.qbit:qbit-admin:0.9.4.RELEASE'\r\ncompile 'io.advantageous.qbit:qbit-vertx:0.9.4.RELEASE'\r\n```\r\n\r\nCore Features\r\n============\r\n\r\n* Write REST based async microservices\r\n* Write ***WebSocket*** based async microservices (fast async RPC over WebSocket)\r\n* Actor Service Queues using micro-batching for high-speed message passing\r\n* Strongly async typed event bus which can be distributed\r\n* Async low overhead metrics gathering which can be queried and distributed (for doing fast lane analytics)\r\n* Complex async call coordination (with the Reactor) for reactive programming\r\n* Built-in support for ***health checks*** (and integration with tools like Consul)\r\n* Built-in support for ***monitoring*** (and integration with wire protocols like StatsD)\r\n* Built-in support for ***Service Discovery*** (with integration with health system, DNS SRV records and Consul)\r\n* Integration with persistent queues\r\n* [12 factor app port bindings](http://12factor.net/), health checks, KPI gathering, Logging MDC\r\n* API Gateway support for client generation and consumption via [Swagger](http://swagger.io/).\r\n* Our services can generate Swagger files (like idl for JSON/REST).\r\n* Remote client proxies for WebSocket (your interface is your IDL)\r\n\r\n\r\nStatus\r\n=====\r\nDeployed at several large fortune 100 companies. \r\nQBit now works with Vertx (standalone or embedded).\r\nYou can also use QBit on non-QBit projects, it is just a lib.\r\n\r\nLicense\r\n=====\r\nApache 2\r\n\r\n\r\n## Java Microservice Lib\r\n\r\nQBit has inproc services, REST microservices and WebSocket microservices as well as an\r\nin-proc service event bus (which can be per module or per app). It supports workers and in-memory services.\r\n\r\nBefore we describe more, here are two sample services:\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {...\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {...\r\n```\r\n\r\n\r\n#### Adder Service using URI params\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {...\r\n }\r\n```\r\n\r\n\r\n\r\nQBit philosophy:\r\n====\r\nAt the end of the day QBit is a simple library not a framework.\r\nYour app is not a QBit app but a Java app that uses the QBit lib.\r\nQBit allows you to work with Java UTIL concurrent, and does not endeavor to hide it from you.\r\nJust trying to take the sting out of it.\r\n\r\nDoes it work\r\n=====\r\nWe have used techniques in Boon and QBit with great success in high-end, high-performance, high-scalable apps.\r\nWe helped clients handle 10x the load with 1/10th the servers of their competitors using techniques in QBit.\r\nQBit is us being sick of hand tuning queue access and threads.\r\n\r\n\r\nBoon and QBit humility policy\r\n=====\r\nIdeas for Boon and QBit often come from all over the web. We make mistakes. Point them out.\r\nAs a developer of Boon and QBit, we are fellow travelers.\r\nIf you have an idea or technique you want to share, we listen.\r\n\r\n\r\nInspiration\r\n====\r\n\r\nA big inspiration for Boon/QBit was Vertx, Akka, Go Channels, Active Objects, Apartment Model Threading, Actor,\r\nand the Mechanical Sympathy papers.\r\n\r\nQBit has ideas that are similar to many frameworks. We are all reading the same papers.\r\nQBit got inspiration from the LMAX disruptor papers and this blog post about\r\n[link transfer queue versus disruptor](http://php.sabscape.com/blog/?p=557). We had some theories about\r\nqueues that blog post inspired us to try them out. Some of these theories are deployed at some of the\r\nbiggest middleware backends and whose name brands are known around the world. And thus QBit was born.\r\n\r\nQBit also took an lot of inspiration by the great work done\r\nby Tim Fox on Vertx. The first project using something that could actually be called QBit (albeit early QBit)\r\n was using Vertx on an web/mobile microservice for an app that could potentially have 80 million users.\r\n It was this\r\nexperience with Vertx and early QBit that led to QBit development and evolution. QBit is built on the\r\nshoulders of giants (Netty/Vertx).\r\n\r\nDoes QBit compete with...\r\n====\r\nSpring Disruptor: No. You could use QBit to write plugins for Spring Disruptor I suppose, but QBit does\r\nnot compete with Spring Disruptor.\r\nSpring Boot/Spring MVC: No. We use the same annotations but QBit is geared for high-speed in-memory\r\nmicroservices. It is more like Akka than Spring Boot. QBit has a subset of the features of Spring MVC\r\ngeared only for microservices, i.e., WebSocket RPC, REST, JSON marshaling, etc.\r\nAkka: No. Well Maybe. Akka has similar concepts but they take a different approach. QBit is more focused\r\n on Java, and microservices (REST, JSON, WebSocket) than Akka.\r\nLMAX Disruptor: No. In fact, we can use disruptor as on of the queues that QBit uses underneath the covers.\r\n\r\n\r\n(Early benchmarks have been removed. They were here. QBit got a lot faster.\r\n Benchmarking QBit is a moving target at the moment.\r\n Links and reports will be created.)\r\n\r\n\r\nCode Examples\r\n\r\n\r\n## Basic Queue example (REST style services is further down)\r\n\r\n====\r\n\r\n```java\r\n\r\n BasicQueue queue = BasicQueue.create(Integer.class, 1000);\r\n\r\n //Sending threads\r\n\r\n SendQueue sendQueue = queue.sendQueue();\r\n for (int index = 0; index < amount; index++) {\r\n sendQueue.send(index);\r\n }\r\n sendQueue.flushSends();\r\n ...\r\n sendQueue.sendAndFlush(code);\r\n //other methods for sendQueue, writeBatch, writeMany\r\n\r\n\r\n //Receiving Threads\r\n ReceiveQueue receiveQueue = queue.receiveQueue();\r\n Integer item = receiveQueue.take();\r\n //other methods poll(), pollWait(), readBatch(), readBatch(count)\r\n```\r\n\r\n\r\n### What is QBit again?\r\n\r\nQBit is a queuing library for microservices. It is similar to many other projects like Akka, Spring Reactor,\r\netc. QBit is just a library not a platform. QBit has libraries to put a service behind a queue.\r\nYou can use QBit queues directly or you can create a service. QBit services can be exposed by WebSocket,\r\nHTTP, HTTP pipeline, and other types of remoting. A service in QBit is a Java class whose methods are\r\n executed behind service queues. QBit implements apartment model threading and is similar to the\r\n Actor model or a better description would be Active Objects. QBit does not use a disruptor (but could).\r\n It uses regular Java Queues. QBit can do north of 100 million ping pong calls per second which is\r\n an amazing speed (seen as high as 200M). QBit also supports calling services via REST, and WebSocket.\r\n QBit is microservices in the pure Web sense: JSON, HTTP, WebSocket, etc. QBit uses micro batching to\r\n push messages through the pipe (queue, IO, etc.) faster to reduce thread hand-off.\r\n\r\n### QBit lingo\r\n\r\nQBit is a Java microservice lib supporting REST, JSON and WebSocket. It is written in Java but we could\r\none day write a version in Rust or Go or C# (but that would require a large payday).\r\n\r\n**Service**\r\nPOJO (plain old Java object) behind a queue that can receive method calls via proxy calls or events\r\n(May have one thread managing events, method calls, and responses or two one for method calls and events\r\n 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.\r\n\r\n**ServiceBundle**\r\nMany POJOs behind one response queue and many receive queues. There may be one thread for all responses\r\nor not. They also can be one receive queue.\r\n\r\n**Queue**\r\nA thread managing a queue. It supports batching. It has events for empty, reachedLimit, startedBatch,\r\nidle. You can listen to these events from services that sit behind a queue. You don't have to use Services.\r\nYou can use Queue's direct. In QBit, you have sender queues and receivers queues. They are separated to\r\nsupport micro-batching.\r\n\r\n**ServiceEndpointServer**\r\nServiceBundle that is exposed to REST and WebSocket communication.\r\n\r\n**EventBus**\r\nEventBus is a way to send a lot of messages to services that may be loosely coupled.\r\n\r\n**ClientProxy**\r\nClientProxy is a way to invoke service through async interface, service can be inproc (same process) or\r\nremoted over WebSocket.\r\n\r\n**Non-blocking**\r\nQBit is a non-blocking lib. You use CallBacks via Java 8 Lambdas. You can also send event messages and get\r\nreplies. Messaging is built into the system so you can easily coordinate complex tasks.\r\nQBit takes an object-oriented approach to service development so services look like normal Java services\r\nthat you\r\nalready write, but the services live behind a queue/thread. This is not a new concept. Microsoft did this\r\nwith DCOM/COM and called it active objects. Akka does it with actors and called them strongly typed Actors.\r\nThe important concepts is that you get the speed of reactive and actor style messaging but you develop\r\nin a natural OOP approach. QBit is not the first. QBit is not the only.\r\n\r\n\r\n**Speed**\r\nQBit is VERY fast. There is a of course a lot of room for improvement. But already 200M+ TPS inproc ping pong, 10M-20M+ TPS event bus, 500K TPS RPC calls over WebSocket/JSON, etc.\r\nMore work needs to be done to improve speed, but now it is fast enough where we are focusing more on\r\nusability.\r\nThe JSON support uses Boon by default which is up to 4x faster than other JSON parsers for the\r\nREST/JSON, WebSocket/JSON use case.\r\n\r\n**Reactive Programming**\r\nQBit provides a **Reactor** to manage async calls. This allows callbacks to be handled on the same thread that called them and it provides for timeout and error handling. Read [Reactor tutorial for creating reactive micro service programming](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices)\r\n\r\n**Service Discovery**\r\nBuilt in support for service discovery. This includes integration with Consul.\r\n\r\n\r\n**StatService**\r\nBuilt in support for stats. The **StatService** can be integrated with **StatsD** (Graphite, Grafana, DataDog, etc.) to publish passive stats. Or you can query the stats engine and react to the stats (counts, timings and levels). The **StatsService** is a reactive stats system that can be clustered. The StatService is reactive in that your services can publish to it and query it and react based on the results. You can implement things like rate limiting and react to an increased rate of something. The ServiceDiscovery system integrates with the HealthSystem and Consul to roll up each of your internal services that make up you micro service and publish the composite availably of your micro service to a single HTTP endpoint or a dead mans switch in Consul (TTL). \r\n\r\n\r\n\r\n### CURLable REST services example\r\n\r\nTalk is cheap. Let's look at some code. You can get a detailed walk through in the Wiki.\r\nWe have a lot of documentation already.\r\n\r\nWe will create a service that is exposed through REST/JSON.\r\n\r\nTo query the size of the todo list:\r\n\r\n```bash\r\ncurl localhost:8080/services/todo-service/todo/count\r\n```\r\n\r\nTo add a new TODO item.\r\n\r\n```bash\r\ncurl -X POST -H \"Content-Type: application/json\" -d \\\r\n'{\"name\":\"xyz\",\"description\":\"xyz\"}' \\\r\nhttp://localhost:8080/services/todo-service/todo\r\n```\r\n\r\nTo get a list of TODO items\r\n```bash\r\ncurl http://localhost:8080/services/todo-service/todo/\r\n```\r\n\r\nThe TODO example will use and track Todo items.\r\n\r\n#### Todo item POJO sans getter\r\n\r\n```java\r\npackage io.advantageous.qbit.examples;\r\n\r\nimport java.util.Date;\r\n\r\n\r\npublic class TodoItem {\r\n\r\n\r\n private final String description;\r\n private final String name;\r\n private final Date due;\r\n\r\n```\r\n\r\nThe TodoService uses Spring MVC style annotations.\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n\r\n private List todoItemList = new ArrayList<>();\r\n\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {\r\n\r\n return todoItemList.size();\r\n }\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {\r\n\r\n return todoItemList;\r\n }\r\n\r\n @RequestMapping(value = \"/todo\", method = RequestMethod.POST)\r\n public void add(TodoItem item) {\r\n\r\n todoItemList.add(item);\r\n }\r\n\r\n}\r\n\r\n```\r\n\r\n\r\n#### Sending non-JSON\r\n\r\nYou can POST/PUT non-JSON and you can capture the body as a `String` or as a `byte[]`. \r\nIf the content-type is set to anything but `application/json` and your body is defined a String or byte[].\r\nThis works automatically. (The content-type has to be set.)\r\n\r\n```java\r\n @RequestMapping(value = \"/body/bytes\", method = RequestMethod.POST)\r\n public boolean bodyPostBytes( byte[] body) {\r\n String string = new String(body, StandardCharsets.UTF_8);\r\n return string.equals(\"foo\");\r\n }\r\n\r\n @RequestMapping(value = \"/body/string\", method = RequestMethod.POST)\r\n public boolean bodyPostString(String body) {\r\n return body.equals(\"foo\");\r\n }\r\n```\r\n\r\n\r\n#### Sending different response codes for success\r\n\r\nBy default QBit sends a `200` (OK) for a non-void call (a call that has a return or a Callback). If the REST operation has no return or no callback then QBit sends a `202` (Accepted). There may be times when you want to send a 201 (Created) or some other code that is not an Exception. You can do that by setting `code` on `@RequestMapping`. By default the code is -1 which means use the default behavior (200 for success, 202 for one-way message, and 500 for errors).\r\n\r\n\r\n#### Sending different response codes for success\r\n```java\r\n\r\n @RequestMapping(value = \"/helloj7\", code = 221)\r\n public void helloJSend7(Callback>> callback) {\r\n callback.returnThis(JSendResponseBuilder.jSendResponseBuilder(Lists.list(\r\n \"hello \" + System.currentTimeMillis())).build());\r\n }\r\n\r\n```\r\n\r\n`Callbacks` can be used for internal services as well. It is often the case that you use a [CallbackBuilder](https://github.com/advantageous/qbit/wiki/%5BDocument%5D-CallbackBuilder-and-generics-for-Reactive-Java-Microservices) or a QBit [Reactor](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices) to manage service calls. \r\n\r\n#### Working with non JSON responses\r\n\r\nYou do not have to return JSON form rest calls.\r\nYou can return any binary or any text by using `HttpBinaryResponse` and `HttpTextResponse`.\r\n\r\n#### Returning non JSON from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildTextResponse());\r\n }\r\n```\r\n\r\n\r\n#### Returning binary from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildBinaryResponse());\r\n }\r\n```\r\n\r\n#### Side note Why Spring style annotations?\r\nWhy did we pick Spring style annotations?\r\n1) Spring is not a standard and neither is QBit. 2) We found the Spring annotations to be less verbose.\r\n3) More people use Spring than Java EE. We wrote QBit for people to use.\r\nWe could easily support JAX-RS style annotations, and we probably will.\r\nSince QBit focuses on JSON, we do not need all of the complexity of JAX-RS or even all the features of\r\nthe Spring MVC annotations. Also we can literally use the actual Spring annotations. QBit and Boon\r\nuse a non-type safe mechanism for annotations which means they are not tied to a particular lib.\r\nYou can define your own. We hate vendor tie-in even if it is an open source vendor.\r\n(We also support @POST, @GET which is similar to JAX-RS).\r\n\r\nNow just start it up.\r\n\r\n```java\r\n\r\n public static void main(String... args) {\r\n\r\n ServiceEndpointServer server = new EndpointServerBuilder().build();\r\n server.initServices(new TodoService());\r\n server.start();\r\n }\r\n```\r\n\r\n\r\n\r\nThat is it. There is also out of the box WebSocket support with client side proxy generation so\r\nyou can call into services at the rate of millions of calls per second.\r\n\r\n## Using URI Params for QBit microservice\r\n\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {\r\n\r\n return a + b;\r\n }\r\n }\r\n\r\n```\r\n\r\n## WebSocket\r\nYou can always invoke QBit services via a WebSocket proxy.\r\nThe advantage of a WebSocket proxy is it allows you execute 1M RPC+ a second (1 million remote calls\r\nevery second).\r\n\r\n\r\n#### Using a microservice remotely with WebSocket\r\n```java\r\n /* Start QBit client for WebSocket calls. */\r\n final Client client = clientBuilder()\r\n .setPort(7000).setRequestBatchSize(1).build();\r\n\r\n\r\n /* Create a proxy to the service. */\r\n final AdderServiceClientInterface adderService =\r\n client.createProxy(AdderServiceClientInterface.class,\r\n \"adder-service\");\r\n\r\n client.start();\r\n\r\n\r\n\r\n /* Call the service */\r\n adderService.add(System.out::println, 1, 2);\r\n\r\n```\r\n\r\nThe output is 3.\r\n\r\n```output\r\n3\r\n```\r\n\r\n\r\nThe above uses a WebSocket proxy interface to call the service async.\r\n\r\n```java\r\n\r\n interface AdderServiceClientInterface {\r\n\r\n void add(Callback callback, int a, int b);\r\n }\r\n```\r\n\r\n#### ServiceDiscovery aware websocket builders\r\n\r\nCreate websocket service client that is ServiceDiscovery aware.\r\n\r\n\r\n```java\r\n final Client client = clientBuilder.setServiceDiscovery(serviceDiscovery, \"echo\")\r\n .setUri(\"/echo\").setProtocolBatchSize(20).build().startClient();\r\n\r\n\r\n final EchoAsync echoClient = client.createProxy(EchoAsync.class, \"echo\");\r\n```\r\n\r\nCurrently the `clientBuilder` will load all service endpoints that are registered under the service name,\r\nand randomly pick one. \r\n\r\nServiceDiscovery includes Consul based, watching JSON files on disk, and DNS. It is easy to write your own service discovery as well and plug it into QBit.\r\n\r\n\r\nIn the future we can RoundRobin calls or shard calls to websocket service and/or provide auto fail over if the connection is closed. We do this for the event bus that uses service discovery but it is not baked into WebSocket based client stubs yet.\r\n\r\n\r\n## REST call with URI params\r\n\r\nThe last client example uses WebSocket. You could also just use REST, and actually use the URI params\r\nthat we setup.\r\nREST is nice but it is going to be slower than WebSocket support.\r\n\r\nQBit ships with a nice little HTTP client. We can use it.\r\n\r\nYou can use it to send async calls and WebSocket messages with the HTTP client.\r\n\r\n\r\nHere we will use the http client to invoke our remote method:\r\n\r\n#### Using a microservice remotely with REST QBit microservice client\r\n```java\r\n\r\n\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\")\r\n .setPort(7000).build();\r\n\r\n httpClient.start();\r\n String results = httpClient\r\n .get(\"/services/adder-service/add/2/2\").body();\r\n System.out.println(results);\r\n\r\n```\r\n\r\n\r\nThe output is 4.\r\n\r\n```output\r\n4\r\n```\r\n\r\n## Accessing The URI Param example with CURL\r\n\r\nYou can also access the service from curl.\r\n\r\n```bash\r\n$ curl http://localhost:7000/services/adder-service/add/2/2\r\n```\r\n\r\nSee this full example here: [QBit microservice getting started tutorial](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-------------QBit-microservice-example).\r\n\r\n[QBit URI params and WebSocket proxy client](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Using-QBit-microservice-lib's-REST-support-with-URI-Params)\r\n\r\n## Working with WebSocket, HttpClient etc.\r\n\r\nQBit has a library for working with and writing async microservices that is lightweight and fun to use.\r\n\r\n#### WebSocket server and client.\r\n\r\n\r\n#### Create an HTTP server\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n```\r\n\r\n#### Setup server WebSocket support\r\n```java\r\n /* Setup WebSocket Server support. */\r\n httpServer.setWebSocketOnOpenConsumer(webSocket -> {\r\n webSocket.setTextMessageConsumer(message -> {\r\n webSocket.sendText(\"ECHO \" + message);\r\n });\r\n });\r\n\r\n```\r\n\r\n#### Start the server\r\n```java\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n```\r\n\r\n#### Setup the WebSocket client\r\n```java\r\n\r\n /** CLIENT. */\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\n#### Client WebSocket\r\n\r\n```java\r\n\r\n /* Setup the client websocket. */\r\n WebSocket webSocket = httpClient\r\n .createWebSocket(\"/websocket/rocket\");\r\n\r\n /* Setup the text consumer. */\r\n webSocket.setTextMessageConsumer(message -> {\r\n System.out.println(message);\r\n });\r\n webSocket.openAndWait();\r\n\r\n /* Send some messages. */\r\n webSocket.sendText(\"Hi mom\");\r\n webSocket.sendText(\"Hello World!\");\r\n\r\n```\r\n\r\n#### Output\r\n```output\r\n\r\nECHO Hi mom\r\nECHO Hello World!\r\n\r\n```\r\n\r\nNow stop the server and client. Pretty easy eh?\r\n\r\n## High-speed HTTP client and server done microservice style\r\n\r\n\r\n##### Starting up an HTTP server\r\n\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n /* Setting up a request Consumer with Java 8 Lambda expression. */\r\n httpServer.setHttpRequestConsumer(httpRequest -> {\r\n\r\n Map results = new HashMap<>();\r\n results.put(\"method\", httpRequest.getMethod());\r\n results.put(\"uri\", httpRequest.getUri());\r\n results.put(\"body\", httpRequest.getBodyAsString());\r\n results.put(\"headers\", httpRequest.getHeaders());\r\n results.put(\"params\", httpRequest.getParams());\r\n httpRequest.getReceiver()\r\n .response(200, \"application/json\", Boon.toJson(results));\r\n });\r\n\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n\r\n\r\n```\r\n\r\nThe focus is on ease of use and using Java 8 Lambdas for callbacks so the code is tight and small.\r\n\r\n[Find out more about QBit's microservice style WebSocket support here](https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-WebSocket-support)\r\n\r\n\r\n## Using HTTP Client lib\r\n\r\nNow, let's try out our HTTP client.\r\n\r\n##### Starting up an HTTP client\r\n\r\n```java\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\nYou just pass the URL, the port and then call start.\r\n\r\n## Synchronous HTTP calls\r\n\r\nNow you can start sending HTTP requests.\r\n\r\n##### No Param HTTP GET\r\n\r\n```java\r\n /* Send no param get. */\r\n HttpResponse httpResponse = httpClient.get( \"/hello/mom\" );\r\n puts( httpResponse );\r\n```\r\n\r\nAn HTTP response just contains the results from the server.\r\n\r\n\r\n##### No Param HTTP Response\r\n\r\n```java\r\npublic interface HttpResponse {\r\n\r\n MultiMap headers();\r\n\r\n int code();\r\n\r\n String contentType();\r\n\r\n String body();\r\n\r\n}\r\n\r\n```\r\n\r\nThere are helper methods for sync HTTP GET calls.\r\n\r\n\r\n\r\n##### Helper methods for GET\r\n```java\r\n\r\n\r\n /* Send one param get. */\r\n httpResponse = httpClient.getWith1Param(\"/hello/singleParam\",\r\n \"hi\", \"mom\");\r\n puts(\"single param\", httpResponse );\r\n\r\n\r\n /* Send two param get. */\r\n httpResponse = httpClient.getWith2Params(\"/hello/twoParams\",\r\n \"hi\", \"mom\", \"hello\", \"dad\");\r\n puts(\"two params\", httpResponse );\r\n\r\n...\r\n\r\n /* Send five param get. */\r\n httpResponse = httpClient.getWith5Params(\"/hello/5params\",\r\n \"hi\", \"mom\",\r\n \"hello\", \"dad\",\r\n \"greetings\", \"kids\",\r\n \"yo\", \"pets\",\r\n \"hola\", \"neighbors\");\r\n puts(\"5 params\", httpResponse );\r\n\r\n\r\n```\r\n\r\nThe puts method is a helper method it does System.out.println more or less by the way.\r\n\r\nThe first five params are covered. Beyond five, you have to use the HttpBuilder.\r\n\r\n```java\r\n\r\n\r\n /* Send six params with get. */\r\n\r\n final HttpRequest httpRequest = httpRequestBuilder()\r\n .addParam(\"hi\", \"mom\")\r\n .addParam(\"hello\", \"dad\")\r\n .addParam(\"greetings\", \"kids\")\r\n .addParam(\"yo\", \"pets\")\r\n .addParam(\"hola\", \"pets\")\r\n .addParam(\"salutations\", \"all\").build();\r\n\r\n httpResponse = httpClient.sendRequestAndWait(httpRequest);\r\n puts(\"6 params\", httpResponse );\r\n```\r\n\r\n## Http Async HTTP Client\r\n\r\nThere are async calls for GET as well.\r\n\r\n#### Async calls for HTTP GET using Java 8 lambda\r\n\r\n```java\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsync(\"/hi/async\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith1Param(\"/hi/async\", \"hi\", \"mom\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda 1 param\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith2Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 2 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n...\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith5Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n \"p3\", \"v3\",\r\n \"p4\", \"v4\",\r\n \"p5\", \"v5\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 5 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n```\r\n\r\n[Find more about the easy to use, fast microservice HTTP client here]\r\n(https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-HttpClient-GET,-POST,-et-al,-JSON,-Java-8-Lambda).\r\n\r\n## InProc QBit services\r\n\r\nQBit allows for services behind queues to be run in-proc as well.\r\n\r\n```java\r\n\r\n /* POJO service. */\r\n final TodoManager todoManagerImpl = new TodoManager();\r\n\r\n /*\r\n Create the service which manages async calls to todoManagerImpl.\r\n */\r\n final Service service = serviceBuilder()\r\n .setServiceObject(todoManagerImpl)\r\n .build().startServiceQueue();\r\n\r\n\r\n /* Create Asynchronous proxy over Synchronous service. */\r\n final TodoManagerClientInterface todoManager =\r\n service.createProxy(TodoManagerClientInterface.class);\r\n\r\n service.startCallBackHandler();\r\n\r\n\r\n System.out.println(\"This is an async call\");\r\n /* Asynchronous method call. */\r\n todoManager.add(new Todo(\"Call Mom\", \"Give Mom a call\"));\r\n\r\n\r\n AtomicInteger countTracker = new AtomicInteger();\r\n //Hold count from async call to service... for testing and showing it is an async callback\r\n\r\n System.out.println(\"This is an async call to count\");\r\n\r\n todoManager.count(count -> {\r\n System.out.println(\"This lambda expression is the callback \" + count);\r\n\r\n countTracker.set(count);\r\n });\r\n\r\n\r\n todoManager.clientProxyFlush(); //Flush all methods. It batches calls.\r\n\r\n Sys.sleep(100);\r\n\r\n System.out.printf(\"This is the count back from the server %d\\n\", countTracker.get());\r\n\r\n```\r\n\r\n[Detailed tutorial on in-proc services is being written.](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-Working-with-inproc-MicroServices-within-QBit.)\r\n\r\n\r\n## QBit Event Bus\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\nQBit also has a service event bus. This example is a an employee benefits services example.\r\n\r\nWe have two channels.\r\n\r\n```\r\npublic static final String NEW_HIRE_CHANNEL = \"com.mycompnay.employee.new\";\r\n\r\npublic static final String PAYROLL_ADJUSTMENT_CHANNEL = \"com.mycompnay.employee.payroll\";\r\n```\r\n\r\nAn employee object looks like this:\r\n\r\n```java\r\n\r\npublic static class Employee {\r\n final String firstName;\r\n final int employeeId;\r\n```\r\n\r\n\r\nThis example has three services: EmployeeHiringService, BenefitsService, and PayrollService.\r\n\r\nThese services are inproc services. QBit supports WebSocket, HTTP and REST remote services as well, but for now, let's focus on inproc services. If you understand inproc then you will understand remote.\r\n\r\nThe EmployeeHiringService actually fires off the events to other two services.\r\n\r\n```java\r\npublic class EmployeeHiringService {\r\n\r\n\r\n public void hireEmployee(final Employee employee) {\r\n\r\n int salary = 100;\r\n System.out.printf(\"Hired employee %s\\n\", employee);\r\n\r\n //Does stuff to hire employee\r\n\r\n //Sends events\r\n final EventManager eventManager =\r\n serviceContext().eventManager();\r\n eventManager.send(NEW_HIRE_CHANNEL, employee);\r\n\r\n eventManager.sendArray(PAYROLL_ADJUSTMENT_CHANNEL,\r\n employee, salary);\r\n\r\n\r\n }\r\n\r\n }\r\n```\r\n\r\n\r\nNotice that we call sendArray so we can send the employee and their salary.\r\nThe listener for PAYROLL_ADJUSTMENT_CHANNEL will have to handle both an employee and an int\r\nthat represents the new employees salary.\r\nYou can also use event bus proxies so you do not have to call into the event bus at all.\r\n\r\nThe BenefitsService listens for new employees being hired so it can enroll them into the benefits system.\r\n\r\n```java\r\npublic static class BenefitsService {\r\n\r\n @OnEvent(NEW_HIRE_CHANNEL)\r\n public void enroll(final Employee employee) {\r\n\r\n System.out.printf(\"Employee enrolled into benefits system employee %s %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId());\r\n\r\n }\r\n\r\n```\r\n\r\nDaddy needs to get paid.\r\n\r\n```java\r\n public static class PayrollService {\r\n\r\n @OnEvent(PAYROLL_ADJUSTMENT_CHANNEL)\r\n public void addEmployeeToPayroll(final Employee employee, int salary) {\r\n\r\n System.out.printf(\"Employee added to payroll %s %d %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId(), salary);\r\n\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nThe employee is the employee object from the EmployeeHiringService.\r\n\r\nso you can get your benefits, and paid!\r\n\r\nFind more details here:\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\n\r\n## Private event bus and event bus proxies\r\n\r\n You can define your own interface to the event bus and you can use your own event buses with QBit.\r\n Each module in your service can have its own internal event bus.\r\n\r\n To learn more read:\r\n [QBit Microservice working with a private event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-private-event-bus-for-inproc-microservices)\r\n and [QBit Java Microservice lib using your own interface to the event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-strongly-typed-event-bus-proxies-for-QBit-Java-Microservice-lib).\r\n\r\n\r\n\r\n## Queue Callbacks\r\n\r\n To really grasp QBit, one must grasp the concepts of a CallBack.\r\n\r\n A CallBack is a way to get an async response in QBit.\r\n\r\n You call a service method and it calls you back.\r\n\r\n Client proxies can have callbacks:\r\n\r\n\r\n#### Queue Callbacks - RecommendationService client interface\r\n```java\r\n\r\npublic interface RecommendationServiceClient {\r\n\r\n\r\n void recommend(final Callback> recommendationsCallback,\r\n final String userName);\r\n}\r\n\r\n```\r\n\r\nCallbacks are Java 8 Consumers with some optional extra error handling.\r\n\r\n\r\n#### Queue Callbacks - Callback\r\n\r\n```java\r\n\r\n\r\npublic interface Callback extends java.util.function.Consumer {\r\n default void onError(java.lang.Throwable error) { /* compiled code */ }\r\n}\r\n\r\n```\r\n\r\nServices that can block should use callbacks.\r\nThus if loadUser blocked in the following example, it should really use a callback instead of returning a value.\r\n\r\npublic class RecommendationService {\r\n\r\n#### Queue Callbacks - Simple minded implementation of RecommendationService\r\n```java\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n public List recommend(final String userName) {\r\n User user = users.get(userName);\r\n if (user == null) {\r\n user = loadUser(userName);\r\n }\r\n return runRulesEngineAgainstUser(user);\r\n }\r\n\r\n```\r\n\r\n\r\nLet's pretend `loadUser` has to look in a local cache, and if the user is not found, look in an off-heap cache\r\nand if not found it must ask for the user from the UserService which must check its caches and perhaps fallback\r\nto loading the user data from a database or from other services.\r\nIn other words, `loadUser` can potentially block on IO.\r\n\r\n\r\n\r\n### Queue Callbacks - The first rule of Queue Club - don't block\r\n\r\n\r\nOur client does not block, but our service does. Going back to our `RecommendationService`.\r\nIf we get a lot of cache hits for user loads, perhaps the\r\nblock will not be that long, but it will be there and every time we have to fault in a user, the whole system\r\nis gummed up. What we want to be able to do is if we can't handle the recommendation request,\r\nwe go ahead and make an async call to the `UserDataService`. When that async callback comes back, then we\r\nhandle that request. In the mean time, we handle recommendation lists requests as quickly as we can.\r\nWe never block.\r\n\r\n\r\nSo let's revisit the service. The first thing we are going to do is make the service method take\r\na callback. Before we do that, let's set down some rules.\r\n\r\n\r\n#### The first rule of queue club don't block.\r\n#### The second rule of queue club if you are not ready, use a callback and continue handling stuff you are ready for\r\n\r\n\r\n#### Queue Callbacks - Adding a CallBack to the RecommendationService inproc microservice\r\n\r\n```java\r\npublic class RecommendationService {\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n```\r\n\r\n\r\n\r\nNow we are taking a callback and we can decide when we want to handle this recommendation generation request.\r\nWe can do it right away if there user data we need is in-memory or we can delay it.\r\n\r\n\r\n#### If the user is found, call the callback right away for RecommendationService inproc microservice\r\n\r\n```java\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n /** Look for user in user cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n ...\r\n } else {\r\n /* Call the callback now because we can handle the callback now. */\r\n recommendationsCallback.accept(runRulesEngineAgainstUser(user));\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nNotice, if the user is found in the cache, we run our recommendation rules in-memory and call the callback right away\r\n`recommendationsCallback.accept(runRulesEngineAgainstUser(user))`.\r\n\r\nThe interesting part is what do we do if don't have the user loaded.\r\n\r\n\r\n#### If the user was not found, load him from the user microservice, but still don't block\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using Callback. */\r\n userDataService.loadUser(new Callback() {\r\n @Override\r\n public void accept(final User loadedUser) {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nHere we use a CallBack to load the user, and when the user is loaded, we call `handleLoadFromUserDataService`\r\nwhich adds some management about handling the callback so we can still handle this call, just not now.\r\n\r\n\r\n\r\n#### Lambda version of last example\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using lambda expression. */\r\n userDataService.loadUser(\r\n loadedUser -> {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nUsing lambdas like this makes the code more readable and terse, but remember don't deeply nest\r\nlambda expressions or you will create a code maintenance nightmare. Use them judiciously.\r\n\r\n\r\n### Queue Callbacks - Doing something later\r\n\r\nWhat we want is to handle the request for recommendations after the user service system loads\r\nthe user from its store.\r\n\r\n\r\n\r\n#### Handling UserServiceData callback methods once we get them.\r\n\r\n```java\r\n\r\npublic class RecommendationService {\r\n\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n private UserDataServiceClient userDataService;\r\n\r\n\r\n private BlockingQueue callbacks =\r\n new ArrayBlockingQueue(10_000);\r\n\r\n\r\n ...\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n ...\r\n\r\n }\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks queue. */\r\n callbacks.add(new Runnable() {\r\n @Override\r\n public void run() {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n }\r\n });\r\n }\r\n\r\n\r\n\r\n```\r\n\r\n\r\n\r\n\r\n#### handleLoadFromUserDataService rewritten using Lambda\r\n\r\n```java\r\n\r\n\r\npublic class RecommendationService {\r\n\r\n...\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks list. */\r\n callbacks.add(() -> {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n });\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nThe important part there is that every time we get a callback call from `UserDataService`, we then\r\nperform our CPU intensive recommendation rules and callback our caller. Well not exactly, what we\r\ndo is enqueue an runnable onto our callbacks queue, and later we will iterate through those but when?\r\n\r\n\r\n### Queue Callbacks Handling callbacks when our receive queue is empty, a new batch started or we hit a batch limit\r\n\r\nThe `RecommendationService` can be notified when its queue is empty, it has started a new batch and when\r\nit has reached a batch limit. These are all good times to handle callbacks from the `UserDataService`.\r\n\r\n#### Draining our callback queue\r\n```java\r\n\r\n @QueueCallback({\r\n QueueCallbackType.EMPTY,\r\n QueueCallbackType.START_BATCH,\r\n QueueCallbackType.LIMIT})\r\n private void handleCallbacks() {\r\n\r\n flushServiceProxy(userDataService);\r\n Runnable runnable = callbacks.poll();\r\n\r\n while (runnable != null) {\r\n runnable.run();\r\n runnable = callbacks.poll();\r\n }\r\n }\r\n\r\n```\r\n\r\nIt is important to remember when handling callbacks from another microservice that you want to handle\r\ncallbacks from the other service before you handle more incomming requests from you clients.\r\nEssentially you have clients that have been waiting (async waiting but still), and these clients\r\nmight represent an open TCP/IP connection like an HTTP call so it is best to close them out\r\nbefore handling more requests and like we said they were already waiting around with an open connection\r\nfor users to load form the user service.\r\n\r\nTo learn more about CallBacks, plesae read [QBit Java MicroService Lib CallBack fundamentals]([Rough Cut] QBit Microservice Lib Working With CallBacks).\r\n\r\n\r\n\r\n\r\n## Workers - pools and shards\r\n\r\n```java\r\npublic class ServiceWorkers {\r\n\r\n public static RoundRobinServiceDispatcher workers() {...\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {...\r\n```\r\n\r\nYou can compose sharded workers (for in-memory, thread safe, CPU intensive services), or workers for IO\r\nor talking to foreign services or foreign buses.\r\n\r\nHere is an example that uses a worker pool with three service workers in it:\r\n\r\nLet's say you have a service that does something:\r\n\r\n```java\r\n\r\n //Your POJO\r\n public class MultiWorker {\r\n\r\n void doSomeWork(...) {\r\n ...\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nNow this does some sort of IO and you want to have a bank of these running not just one so you can do\r\nIO in parallel. After some performance testing, you found out that three is the magic number.\r\n\r\nYou want to use your API for accessing this service:\r\n\r\n```java\r\n public interface MultiWorkerClient {\r\n void doSomeWork(...);\r\n }\r\n\r\n```\r\n\r\nNow let's create a bank of these and use it.\r\n\r\nFirst create the QBit services which add the thread/queue/microbatch.\r\n\r\n```java\r\n\r\n /* Create a service builder. */\r\n final ServiceBuilder serviceBuilder = serviceBuilder();\r\n\r\n /* Create some qbit services. */\r\n final Service service1 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service2 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service3 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n```\r\n\r\nNow add them to a ServiceWorkers object.\r\n\r\n```java\r\n\r\n ServiceWorkers dispatcher;\r\n dispatcher = workers(); //Create a round robin service dispatcher\r\n dispatcher.addServices(service1, service2, service3);\r\n dispatcher.start(); // start up the workers\r\n\r\n```\r\n\r\nYou can add services, POJOs and method consumers, method dispatchers to a service bundle.\r\nThe service bundle is an integration point into QBit.\r\n\r\nLet's add our new Service workers. ServiceWorkers is a ServiceMethodDispatcher.\r\n\r\n```Java\r\n /* Add the dispatcher to a service bundle. */\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nWe are probably going to add a helper method to the service bundle so most of this can happen in\r\na single call.\r\n\r\nNow you can start using your workers.\r\n\r\n```java\r\n\r\n /* Start using the workers. */\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n```\r\n\r\nNow you could use Spring or Guice to configure the builders and the service bundle.\r\nBut you can just do it like the above which is good for testing and understanding QBit internals.\r\n\r\nQBit also supports the concept of sharded services which is good for sharding resources like CPU\r\n(run a rules engine on each CPU core for a user recommendation engine).\r\n\r\nQBit does not know how to shard your services, you have to give it a hint.\r\nYou do this through a shard rule.\r\n\r\n```java\r\npublic interface ShardRule {\r\n int shard(String methodName, Object[] args, int numWorkers);\r\n}\r\n```\r\nWe worked on an app where the first argument to the services was the username, and then we used that to\r\nshard calls to a CPU intensive in-memory rules engine. This technique works. :)\r\n\r\nThe ServiceWorkers class has a method for creating a sharded worker pool.\r\n\r\n```java\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nTo use you just pass a shard key when you create the service workers.\r\n\r\n```java\r\n\r\n\r\n dispatcher = shardedWorkers((methodName, methodArgs, numWorkers) -> {\r\n String userName = methodArgs[0].toString();\r\n int shardKey = userName.hashCode() % numWorkers;\r\n return shardKey;\r\n });\r\n\r\n```\r\n\r\nThen add your services to the ServiceWorkers composition.\r\n```java\r\n int workerCount = Runtime.getRuntime().availableProcessors();\r\n\r\n for (int index = 0; index < workerCount; index++) {\r\n final Service service = serviceBuilder\r\n .setServiceObject(new ContentRulesEngine()).build();\r\n dispatcher.addServices(service);\r\n\r\n }\r\n```\r\n\r\nThen add it to the service bundle as before.\r\n```java\r\n\r\n dispatcher.start();\r\n\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nThen just use it:\r\n\r\n```java\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n for (int index = 0; index < 100; index++) {\r\n String userName = \"rickhigh\" + index;\r\n worker.pickSuggestions(userName);\r\n }\r\n\r\n```\r\n\r\n### Built in shard rules\r\n\r\n```java\r\n\r\n\r\npublic class ServiceWorkers {\r\n...\r\n public static ShardedMethodDispatcher shardOnFirstArgumentWorkers() {\r\n ...\r\n }\r\n\r\n...\r\n\r\n public static ShardedMethodDispatcher shardOnFifthArgumentWorkers() {\r\n ...\r\n }\r\n\r\n\r\n public static ShardedMethodDispatcher shardOnBeanPath(final String beanPath) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nThe shardOnBeanPath allows you to create a complex bean path navigation call and use its property to shard on.\r\n\r\n```java\r\n\r\n /* shard on 2nd arg which is an employee\r\n Use the employees department's id property. */\r\n dispatcher = shardOnBeanPath(\"[1].department.id\");\r\n\r\n /* Same as above. */\r\n dispatcher = shardOnBeanPath(\"1/department/id\");\r\n\r\n```\r\n\r\n[Read more about Service sharding and service workers here](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-QBit-Microservices-using-Service-Workers-and-sharded-service-workers)\r\n\r\n\r\nYou can find a lot more in the wiki. Also follow the commits.\r\nWe have been busy beavers.\r\n[QBit the microservice lib for Java - JSON, REST, WebSocket](https://github.com/advantageous/qbit/wiki).\r\n",
+ "body": "[QBit Java Micorservices lib tutorials](https://github.com/MammatusTech/qbit-microservices-examples/wiki)|\r\n[QBit Website](http://advantageous.github.io/qbit/)\r\n\r\n#QBit - The Microservice Lib for Java - JSON, REST, WebSocket, Speed! \r\n\r\n## Quick overview of QBit\r\n\r\nThe Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.\r\n\r\nGot a question? Ask here: [QBit Google Group](https://groups.google.com/forum/#!forum/qbit-microservice).\r\n\r\nEverything is a queue. You have a choice. You can embrace it and control it. You can optimize for it.\r\nOr you can hide behind abstractions. QBit opens you up to peeking into what is going on, and allows you\r\nto pull some levers without selling your soul.\r\n\r\nQBit is a library not a framework. You can mix and match QBit with Spring, Guice, etc.\r\n\r\nQBit is FAST!\r\n\r\n\r\n\r\n#### Using from maven\r\n```xml\r\n\r\n io.advantageous.qbit\r\n qbit-admin\r\n 1.0.0.RELEASE\r\n\r\n\r\n io.advantageous.qbit\r\n qbit-vertx\r\n 1.0.0.RELEASE\r\n\r\n```\r\n\r\n#### Using from gradle\r\n```java\r\ncompile 'io.advantageous.qbit:qbit-admin:1.0.0.RELEASE'\r\ncompile 'io.advantageous.qbit:qbit-vertx:1.0.0.RELEASE'\r\n```\r\n\r\nCore Features\r\n============\r\n\r\n* Write REST based async microservices\r\n* Write ***WebSocket*** based async microservices (fast async RPC over WebSocket)\r\n* Actor Service Queues using micro-batching for high-speed message passing\r\n* Strongly async typed event bus which can be distributed\r\n* Async low overhead metrics gathering which can be queried and distributed (for doing fast lane analytics)\r\n* Complex async call coordination (with the Reactor) for reactive programming\r\n* Built-in support for ***health checks*** (and integration with tools like Consul)\r\n* Built-in support for ***monitoring*** (and integration with wire protocols like StatsD)\r\n* Built-in support for ***Service Discovery*** (with integration with health system, DNS SRV records and Consul)\r\n* Integration with persistent queues\r\n* [12 factor app port bindings](http://12factor.net/), health checks, KPI gathering, Logging MDC\r\n* API Gateway support for client generation and consumption via [Swagger](http://swagger.io/).\r\n* Our services can generate Swagger files (like idl for JSON/REST).\r\n* Remote client proxies for WebSocket (your interface is your IDL)\r\n\r\n\r\nStatus\r\n=====\r\nDeployed at several large fortune 100 companies. \r\nQBit now works with Vertx (standalone or embedded).\r\nYou can also use QBit on non-QBit projects, it is just a lib.\r\n\r\nLicense\r\n=====\r\nApache 2\r\n\r\n\r\n## Java Microservice Lib\r\n\r\nQBit has inproc services, REST microservices and WebSocket microservices as well as an\r\nin-proc service event bus (which can be per module or per app). It supports workers and in-memory services.\r\n\r\nBefore we describe more, here are two sample services:\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {...\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {...\r\n```\r\n\r\n\r\n#### Adder Service using URI params\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {...\r\n }\r\n```\r\n\r\n\r\n\r\nQBit philosophy:\r\n====\r\nAt the end of the day QBit is a simple library not a framework.\r\nYour app is not a QBit app but a Java app that uses the QBit lib.\r\nQBit allows you to work with Java UTIL concurrent, and does not endeavor to hide it from you.\r\nJust trying to take the sting out of it.\r\n\r\nDoes it work\r\n=====\r\nWe have used techniques in Boon and QBit with great success in high-end, high-performance, high-scalable apps.\r\nWe helped clients handle 10x the load with 1/10th the servers of their competitors using techniques in QBit.\r\nQBit is us being sick of hand tuning queue access and threads.\r\n\r\n\r\nBoon and QBit humility policy\r\n=====\r\nIdeas for Boon and QBit often come from all over the web. We make mistakes. Point them out.\r\nAs a developer of Boon and QBit, we are fellow travelers.\r\nIf you have an idea or technique you want to share, we listen.\r\n\r\n\r\nInspiration\r\n====\r\n\r\nA big inspiration for Boon/QBit was Vertx, Akka, Go Channels, Active Objects, Apartment Model Threading, Actor,\r\nand the Mechanical Sympathy papers.\r\n\r\nQBit has ideas that are similar to many frameworks. We are all reading the same papers.\r\nQBit got inspiration from the LMAX disruptor papers and this blog post about\r\n[link transfer queue versus disruptor](http://php.sabscape.com/blog/?p=557). We had some theories about\r\nqueues that blog post inspired us to try them out. Some of these theories are deployed at some of the\r\nbiggest middleware backends and whose name brands are known around the world. And thus QBit was born.\r\n\r\nQBit also took an lot of inspiration by the great work done\r\nby Tim Fox on Vertx. The first project using something that could actually be called QBit (albeit early QBit)\r\n was using Vertx on an web/mobile microservice for an app that could potentially have 80 million users.\r\n It was this\r\nexperience with Vertx and early QBit that led to QBit development and evolution. QBit is built on the\r\nshoulders of giants (Netty/Vertx).\r\n\r\nDoes QBit compete with...\r\n====\r\nSpring Disruptor: No. You could use QBit to write plugins for Spring Disruptor I suppose, but QBit does\r\nnot compete with Spring Disruptor.\r\nSpring Boot/Spring MVC: No. We use the same annotations but QBit is geared for high-speed in-memory\r\nmicroservices. It is more like Akka than Spring Boot. QBit has a subset of the features of Spring MVC\r\ngeared only for microservices, i.e., WebSocket RPC, REST, JSON marshaling, etc.\r\nAkka: No. Well Maybe. Akka has similar concepts but they take a different approach. QBit is more focused\r\n on Java, and microservices (REST, JSON, WebSocket) than Akka.\r\nLMAX Disruptor: No. In fact, we can use disruptor as on of the queues that QBit uses underneath the covers.\r\n\r\n\r\n(Early benchmarks have been removed. They were here. QBit got a lot faster.\r\n Benchmarking QBit is a moving target at the moment.\r\n Links and reports will be created.)\r\n\r\n\r\nCode Examples\r\n\r\n\r\n## Basic Queue example (REST style services is further down)\r\n\r\n====\r\n\r\n```java\r\n\r\n BasicQueue queue = BasicQueue.create(Integer.class, 1000);\r\n\r\n //Sending threads\r\n\r\n SendQueue sendQueue = queue.sendQueue();\r\n for (int index = 0; index < amount; index++) {\r\n sendQueue.send(index);\r\n }\r\n sendQueue.flushSends();\r\n ...\r\n sendQueue.sendAndFlush(code);\r\n //other methods for sendQueue, writeBatch, writeMany\r\n\r\n\r\n //Receiving Threads\r\n ReceiveQueue receiveQueue = queue.receiveQueue();\r\n Integer item = receiveQueue.take();\r\n //other methods poll(), pollWait(), readBatch(), readBatch(count)\r\n```\r\n\r\n\r\n### What is QBit again?\r\n\r\nQBit is a queuing library for microservices. It is similar to many other projects like Akka, Spring Reactor,\r\netc. QBit is just a library not a platform. QBit has libraries to put a service behind a queue.\r\nYou can use QBit queues directly or you can create a service. QBit services can be exposed by WebSocket,\r\nHTTP, HTTP pipeline, and other types of remoting. A service in QBit is a Java class whose methods are\r\n executed behind service queues. QBit implements apartment model threading and is similar to the\r\n Actor model or a better description would be Active Objects. QBit does not use a disruptor (but could).\r\n It uses regular Java Queues. QBit can do north of 100 million ping pong calls per second which is\r\n an amazing speed (seen as high as 200M). QBit also supports calling services via REST, and WebSocket.\r\n QBit is microservices in the pure Web sense: JSON, HTTP, WebSocket, etc. QBit uses micro batching to\r\n push messages through the pipe (queue, IO, etc.) faster to reduce thread hand-off.\r\n\r\n### QBit lingo\r\n\r\nQBit is a Java microservice lib supporting REST, JSON and WebSocket. It is written in Java but we could\r\none day write a version in Rust or Go or C# (but that would require a large payday).\r\n\r\n**Service**\r\nPOJO (plain old Java object) behind a queue that can receive method calls via proxy calls or events\r\n(May have one thread managing events, method calls, and responses or two one for method calls and events\r\n 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.\r\n\r\n**ServiceBundle**\r\nMany POJOs behind one response queue and many receive queues. There may be one thread for all responses\r\nor not. They also can be one receive queue.\r\n\r\n**Queue**\r\nA thread managing a queue. It supports batching. It has events for empty, reachedLimit, startedBatch,\r\nidle. You can listen to these events from services that sit behind a queue. You don't have to use Services.\r\nYou can use Queue's direct. In QBit, you have sender queues and receivers queues. They are separated to\r\nsupport micro-batching.\r\n\r\n**ServiceEndpointServer**\r\nServiceBundle that is exposed to REST and WebSocket communication.\r\n\r\n**EventBus**\r\nEventBus is a way to send a lot of messages to services that may be loosely coupled.\r\n\r\n**ClientProxy**\r\nClientProxy is a way to invoke service through async interface, service can be inproc (same process) or\r\nremoted over WebSocket.\r\n\r\n**Non-blocking**\r\nQBit is a non-blocking lib. You use CallBacks via Java 8 Lambdas. You can also send event messages and get\r\nreplies. Messaging is built into the system so you can easily coordinate complex tasks.\r\nQBit takes an object-oriented approach to service development so services look like normal Java services\r\nthat you\r\nalready write, but the services live behind a queue/thread. This is not a new concept. Microsoft did this\r\nwith DCOM/COM and called it active objects. Akka does it with actors and called them strongly typed Actors.\r\nThe important concepts is that you get the speed of reactive and actor style messaging but you develop\r\nin a natural OOP approach. QBit is not the first. QBit is not the only.\r\n\r\n\r\n**Speed**\r\nQBit is VERY fast. There is a of course a lot of room for improvement. But already 200M+ TPS inproc ping pong, 10M-20M+ TPS event bus, 500K TPS RPC calls over WebSocket/JSON, etc.\r\nMore work needs to be done to improve speed, but now it is fast enough where we are focusing more on\r\nusability.\r\nThe JSON support uses Boon by default which is up to 4x faster than other JSON parsers for the\r\nREST/JSON, WebSocket/JSON use case.\r\n\r\n**Reactive Programming**\r\nQBit provides a **Reactor** to manage async calls. This allows callbacks to be handled on the same thread that called them and it provides for timeout and error handling. Read [Reactor tutorial for creating reactive micro service programming](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices)\r\n\r\n**Service Discovery**\r\nBuilt in support for service discovery. This includes integration with Consul.\r\n\r\n\r\n**StatService**\r\nBuilt in support for stats. The **StatService** can be integrated with **StatsD** (Graphite, Grafana, DataDog, etc.) to publish passive stats. Or you can query the stats engine and react to the stats (counts, timings and levels). The **StatsService** is a reactive stats system that can be clustered. The StatService is reactive in that your services can publish to it and query it and react based on the results. You can implement things like rate limiting and react to an increased rate of something. The ServiceDiscovery system integrates with the HealthSystem and Consul to roll up each of your internal services that make up you micro service and publish the composite availably of your micro service to a single HTTP endpoint or a dead mans switch in Consul (TTL). \r\n\r\n\r\n\r\n### CURLable REST services example\r\n\r\nTalk is cheap. Let's look at some code. You can get a detailed walk through in the Wiki.\r\nWe have a lot of documentation already.\r\n\r\nWe will create a service that is exposed through REST/JSON.\r\n\r\nTo query the size of the todo list:\r\n\r\n```bash\r\ncurl localhost:8080/services/todo-service/todo/count\r\n```\r\n\r\nTo add a new TODO item.\r\n\r\n```bash\r\ncurl -X POST -H \"Content-Type: application/json\" -d \\\r\n'{\"name\":\"xyz\",\"description\":\"xyz\"}' \\\r\nhttp://localhost:8080/services/todo-service/todo\r\n```\r\n\r\nTo get a list of TODO items\r\n```bash\r\ncurl http://localhost:8080/services/todo-service/todo/\r\n```\r\n\r\nThe TODO example will use and track Todo items.\r\n\r\n#### Todo item POJO sans getter\r\n\r\n```java\r\npackage io.advantageous.qbit.examples;\r\n\r\nimport java.util.Date;\r\n\r\n\r\npublic class TodoItem {\r\n\r\n\r\n private final String description;\r\n private final String name;\r\n private final Date due;\r\n\r\n```\r\n\r\nThe TodoService uses Spring MVC style annotations.\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n\r\n private List todoItemList = new ArrayList<>();\r\n\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {\r\n\r\n return todoItemList.size();\r\n }\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {\r\n\r\n return todoItemList;\r\n }\r\n\r\n @RequestMapping(value = \"/todo\", method = RequestMethod.POST)\r\n public void add(TodoItem item) {\r\n\r\n todoItemList.add(item);\r\n }\r\n\r\n}\r\n\r\n```\r\n\r\n\r\n#### Sending non-JSON\r\n\r\nYou can POST/PUT non-JSON and you can capture the body as a `String` or as a `byte[]`. \r\nIf the content-type is set to anything but `application/json` and your body is defined a String or byte[].\r\nThis works automatically. (The content-type has to be set.)\r\n\r\n```java\r\n @RequestMapping(value = \"/body/bytes\", method = RequestMethod.POST)\r\n public boolean bodyPostBytes( byte[] body) {\r\n String string = new String(body, StandardCharsets.UTF_8);\r\n return string.equals(\"foo\");\r\n }\r\n\r\n @RequestMapping(value = \"/body/string\", method = RequestMethod.POST)\r\n public boolean bodyPostString(String body) {\r\n return body.equals(\"foo\");\r\n }\r\n```\r\n\r\n\r\n#### Sending different response codes for success\r\n\r\nBy default QBit sends a `200` (OK) for a non-void call (a call that has a return or a Callback). If the REST operation has no return or no callback then QBit sends a `202` (Accepted). There may be times when you want to send a 201 (Created) or some other code that is not an Exception. You can do that by setting `code` on `@RequestMapping`. By default the code is -1 which means use the default behavior (200 for success, 202 for one-way message, and 500 for errors).\r\n\r\n\r\n#### Sending different response codes for success\r\n```java\r\n\r\n @RequestMapping(value = \"/helloj7\", code = 221)\r\n public void helloJSend7(Callback>> callback) {\r\n callback.returnThis(JSendResponseBuilder.jSendResponseBuilder(Lists.list(\r\n \"hello \" + System.currentTimeMillis())).build());\r\n }\r\n\r\n```\r\n\r\n`Callbacks` can be used for internal services as well. It is often the case that you use a [CallbackBuilder](https://github.com/advantageous/qbit/wiki/%5BDocument%5D-CallbackBuilder-and-generics-for-Reactive-Java-Microservices) or a QBit [Reactor](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices) to manage service calls. \r\n\r\n#### Working with non JSON responses\r\n\r\nYou do not have to return JSON form rest calls.\r\nYou can return any binary or any text by using `HttpBinaryResponse` and `HttpTextResponse`.\r\n\r\n#### Returning non JSON from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildTextResponse());\r\n }\r\n```\r\n\r\n\r\n#### Returning binary from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildBinaryResponse());\r\n }\r\n```\r\n\r\n#### Side note Why Spring style annotations?\r\nWhy did we pick Spring style annotations?\r\n1) Spring is not a standard and neither is QBit. 2) We found the Spring annotations to be less verbose.\r\n3) More people use Spring than Java EE. We wrote QBit for people to use.\r\nWe could easily support JAX-RS style annotations, and we probably will.\r\nSince QBit focuses on JSON, we do not need all of the complexity of JAX-RS or even all the features of\r\nthe Spring MVC annotations. Also we can literally use the actual Spring annotations. QBit and Boon\r\nuse a non-type safe mechanism for annotations which means they are not tied to a particular lib.\r\nYou can define your own. We hate vendor tie-in even if it is an open source vendor.\r\n(We also support @POST, @GET which is similar to JAX-RS).\r\n\r\nNow just start it up.\r\n\r\n```java\r\n\r\n public static void main(String... args) {\r\n\r\n ServiceEndpointServer server = new EndpointServerBuilder().build();\r\n server.initServices(new TodoService());\r\n server.start();\r\n }\r\n```\r\n\r\n\r\n\r\nThat is it. There is also out of the box WebSocket support with client side proxy generation so\r\nyou can call into services at the rate of millions of calls per second.\r\n\r\n## Using URI Params for QBit microservice\r\n\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {\r\n\r\n return a + b;\r\n }\r\n }\r\n\r\n```\r\n\r\n## WebSocket\r\nYou can always invoke QBit services via a WebSocket proxy.\r\nThe advantage of a WebSocket proxy is it allows you execute 1M RPC+ a second (1 million remote calls\r\nevery second).\r\n\r\n\r\n#### Using a microservice remotely with WebSocket\r\n```java\r\n /* Start QBit client for WebSocket calls. */\r\n final Client client = clientBuilder()\r\n .setPort(7000).setRequestBatchSize(1).build();\r\n\r\n\r\n /* Create a proxy to the service. */\r\n final AdderServiceClientInterface adderService =\r\n client.createProxy(AdderServiceClientInterface.class,\r\n \"adder-service\");\r\n\r\n client.start();\r\n\r\n\r\n\r\n /* Call the service */\r\n adderService.add(System.out::println, 1, 2);\r\n\r\n```\r\n\r\nThe output is 3.\r\n\r\n```output\r\n3\r\n```\r\n\r\n\r\nThe above uses a WebSocket proxy interface to call the service async.\r\n\r\n```java\r\n\r\n interface AdderServiceClientInterface {\r\n\r\n void add(Callback callback, int a, int b);\r\n }\r\n```\r\n\r\n#### ServiceDiscovery aware websocket builders\r\n\r\nCreate websocket service client that is ServiceDiscovery aware.\r\n\r\n\r\n```java\r\n final Client client = clientBuilder.setServiceDiscovery(serviceDiscovery, \"echo\")\r\n .setUri(\"/echo\").setProtocolBatchSize(20).build().startClient();\r\n\r\n\r\n final EchoAsync echoClient = client.createProxy(EchoAsync.class, \"echo\");\r\n```\r\n\r\nCurrently the `clientBuilder` will load all service endpoints that are registered under the service name,\r\nand randomly pick one. \r\n\r\nServiceDiscovery includes Consul based, watching JSON files on disk, and DNS. It is easy to write your own service discovery as well and plug it into QBit.\r\n\r\n\r\nIn the future we can RoundRobin calls or shard calls to websocket service and/or provide auto fail over if the connection is closed. We do this for the event bus that uses service discovery but it is not baked into WebSocket based client stubs yet.\r\n\r\n\r\n## REST call with URI params\r\n\r\nThe last client example uses WebSocket. You could also just use REST, and actually use the URI params\r\nthat we setup.\r\nREST is nice but it is going to be slower than WebSocket support.\r\n\r\nQBit ships with a nice little HTTP client. We can use it.\r\n\r\nYou can use it to send async calls and WebSocket messages with the HTTP client.\r\n\r\n\r\nHere we will use the http client to invoke our remote method:\r\n\r\n#### Using a microservice remotely with REST QBit microservice client\r\n```java\r\n\r\n\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\")\r\n .setPort(7000).build();\r\n\r\n httpClient.start();\r\n String results = httpClient\r\n .get(\"/services/adder-service/add/2/2\").body();\r\n System.out.println(results);\r\n\r\n```\r\n\r\n\r\nThe output is 4.\r\n\r\n```output\r\n4\r\n```\r\n\r\n## Accessing The URI Param example with CURL\r\n\r\nYou can also access the service from curl.\r\n\r\n```bash\r\n$ curl http://localhost:7000/services/adder-service/add/2/2\r\n```\r\n\r\nSee this full example here: [QBit microservice getting started tutorial](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-------------QBit-microservice-example).\r\n\r\n[QBit URI params and WebSocket proxy client](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Using-QBit-microservice-lib's-REST-support-with-URI-Params)\r\n\r\n## Working with WebSocket, HttpClient etc.\r\n\r\nQBit has a library for working with and writing async microservices that is lightweight and fun to use.\r\n\r\n#### WebSocket server and client.\r\n\r\n\r\n#### Create an HTTP server\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n```\r\n\r\n#### Setup server WebSocket support\r\n```java\r\n /* Setup WebSocket Server support. */\r\n httpServer.setWebSocketOnOpenConsumer(webSocket -> {\r\n webSocket.setTextMessageConsumer(message -> {\r\n webSocket.sendText(\"ECHO \" + message);\r\n });\r\n });\r\n\r\n```\r\n\r\n#### Start the server\r\n```java\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n```\r\n\r\n#### Setup the WebSocket client\r\n```java\r\n\r\n /** CLIENT. */\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\n#### Client WebSocket\r\n\r\n```java\r\n\r\n /* Setup the client websocket. */\r\n WebSocket webSocket = httpClient\r\n .createWebSocket(\"/websocket/rocket\");\r\n\r\n /* Setup the text consumer. */\r\n webSocket.setTextMessageConsumer(message -> {\r\n System.out.println(message);\r\n });\r\n webSocket.openAndWait();\r\n\r\n /* Send some messages. */\r\n webSocket.sendText(\"Hi mom\");\r\n webSocket.sendText(\"Hello World!\");\r\n\r\n```\r\n\r\n#### Output\r\n```output\r\n\r\nECHO Hi mom\r\nECHO Hello World!\r\n\r\n```\r\n\r\nNow stop the server and client. Pretty easy eh?\r\n\r\n## High-speed HTTP client and server done microservice style\r\n\r\n\r\n##### Starting up an HTTP server\r\n\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n /* Setting up a request Consumer with Java 8 Lambda expression. */\r\n httpServer.setHttpRequestConsumer(httpRequest -> {\r\n\r\n Map results = new HashMap<>();\r\n results.put(\"method\", httpRequest.getMethod());\r\n results.put(\"uri\", httpRequest.getUri());\r\n results.put(\"body\", httpRequest.getBodyAsString());\r\n results.put(\"headers\", httpRequest.getHeaders());\r\n results.put(\"params\", httpRequest.getParams());\r\n httpRequest.getReceiver()\r\n .response(200, \"application/json\", Boon.toJson(results));\r\n });\r\n\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n\r\n\r\n```\r\n\r\nThe focus is on ease of use and using Java 8 Lambdas for callbacks so the code is tight and small.\r\n\r\n[Find out more about QBit's microservice style WebSocket support here](https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-WebSocket-support)\r\n\r\n\r\n## Using HTTP Client lib\r\n\r\nNow, let's try out our HTTP client.\r\n\r\n##### Starting up an HTTP client\r\n\r\n```java\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\nYou just pass the URL, the port and then call start.\r\n\r\n## Synchronous HTTP calls\r\n\r\nNow you can start sending HTTP requests.\r\n\r\n##### No Param HTTP GET\r\n\r\n```java\r\n /* Send no param get. */\r\n HttpResponse httpResponse = httpClient.get( \"/hello/mom\" );\r\n puts( httpResponse );\r\n```\r\n\r\nAn HTTP response just contains the results from the server.\r\n\r\n\r\n##### No Param HTTP Response\r\n\r\n```java\r\npublic interface HttpResponse {\r\n\r\n MultiMap headers();\r\n\r\n int code();\r\n\r\n String contentType();\r\n\r\n String body();\r\n\r\n}\r\n\r\n```\r\n\r\nThere are helper methods for sync HTTP GET calls.\r\n\r\n\r\n\r\n##### Helper methods for GET\r\n```java\r\n\r\n\r\n /* Send one param get. */\r\n httpResponse = httpClient.getWith1Param(\"/hello/singleParam\",\r\n \"hi\", \"mom\");\r\n puts(\"single param\", httpResponse );\r\n\r\n\r\n /* Send two param get. */\r\n httpResponse = httpClient.getWith2Params(\"/hello/twoParams\",\r\n \"hi\", \"mom\", \"hello\", \"dad\");\r\n puts(\"two params\", httpResponse );\r\n\r\n...\r\n\r\n /* Send five param get. */\r\n httpResponse = httpClient.getWith5Params(\"/hello/5params\",\r\n \"hi\", \"mom\",\r\n \"hello\", \"dad\",\r\n \"greetings\", \"kids\",\r\n \"yo\", \"pets\",\r\n \"hola\", \"neighbors\");\r\n puts(\"5 params\", httpResponse );\r\n\r\n\r\n```\r\n\r\nThe puts method is a helper method it does System.out.println more or less by the way.\r\n\r\nThe first five params are covered. Beyond five, you have to use the HttpBuilder.\r\n\r\n```java\r\n\r\n\r\n /* Send six params with get. */\r\n\r\n final HttpRequest httpRequest = httpRequestBuilder()\r\n .addParam(\"hi\", \"mom\")\r\n .addParam(\"hello\", \"dad\")\r\n .addParam(\"greetings\", \"kids\")\r\n .addParam(\"yo\", \"pets\")\r\n .addParam(\"hola\", \"pets\")\r\n .addParam(\"salutations\", \"all\").build();\r\n\r\n httpResponse = httpClient.sendRequestAndWait(httpRequest);\r\n puts(\"6 params\", httpResponse );\r\n```\r\n\r\n## Http Async HTTP Client\r\n\r\nThere are async calls for GET as well.\r\n\r\n#### Async calls for HTTP GET using Java 8 lambda\r\n\r\n```java\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsync(\"/hi/async\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith1Param(\"/hi/async\", \"hi\", \"mom\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda 1 param\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith2Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 2 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n...\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith5Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n \"p3\", \"v3\",\r\n \"p4\", \"v4\",\r\n \"p5\", \"v5\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 5 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n```\r\n\r\n[Find more about the easy to use, fast microservice HTTP client here]\r\n(https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-HttpClient-GET,-POST,-et-al,-JSON,-Java-8-Lambda).\r\n\r\n## InProc QBit services\r\n\r\nQBit allows for services behind queues to be run in-proc as well.\r\n\r\n```java\r\n\r\n /* POJO service. */\r\n final TodoManager todoManagerImpl = new TodoManager();\r\n\r\n /*\r\n Create the service which manages async calls to todoManagerImpl.\r\n */\r\n final Service service = serviceBuilder()\r\n .setServiceObject(todoManagerImpl)\r\n .build().startServiceQueue();\r\n\r\n\r\n /* Create Asynchronous proxy over Synchronous service. */\r\n final TodoManagerClientInterface todoManager =\r\n service.createProxy(TodoManagerClientInterface.class);\r\n\r\n service.startCallBackHandler();\r\n\r\n\r\n System.out.println(\"This is an async call\");\r\n /* Asynchronous method call. */\r\n todoManager.add(new Todo(\"Call Mom\", \"Give Mom a call\"));\r\n\r\n\r\n AtomicInteger countTracker = new AtomicInteger();\r\n //Hold count from async call to service... for testing and showing it is an async callback\r\n\r\n System.out.println(\"This is an async call to count\");\r\n\r\n todoManager.count(count -> {\r\n System.out.println(\"This lambda expression is the callback \" + count);\r\n\r\n countTracker.set(count);\r\n });\r\n\r\n\r\n todoManager.clientProxyFlush(); //Flush all methods. It batches calls.\r\n\r\n Sys.sleep(100);\r\n\r\n System.out.printf(\"This is the count back from the server %d\\n\", countTracker.get());\r\n\r\n```\r\n\r\n[Detailed tutorial on in-proc services is being written.](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-Working-with-inproc-MicroServices-within-QBit.)\r\n\r\n\r\n## QBit Event Bus\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\nQBit also has a service event bus. This example is a an employee benefits services example.\r\n\r\nWe have two channels.\r\n\r\n```\r\npublic static final String NEW_HIRE_CHANNEL = \"com.mycompnay.employee.new\";\r\n\r\npublic static final String PAYROLL_ADJUSTMENT_CHANNEL = \"com.mycompnay.employee.payroll\";\r\n```\r\n\r\nAn employee object looks like this:\r\n\r\n```java\r\n\r\npublic static class Employee {\r\n final String firstName;\r\n final int employeeId;\r\n```\r\n\r\n\r\nThis example has three services: EmployeeHiringService, BenefitsService, and PayrollService.\r\n\r\nThese services are inproc services. QBit supports WebSocket, HTTP and REST remote services as well, but for now, let's focus on inproc services. If you understand inproc then you will understand remote.\r\n\r\nThe EmployeeHiringService actually fires off the events to other two services.\r\n\r\n```java\r\npublic class EmployeeHiringService {\r\n\r\n\r\n public void hireEmployee(final Employee employee) {\r\n\r\n int salary = 100;\r\n System.out.printf(\"Hired employee %s\\n\", employee);\r\n\r\n //Does stuff to hire employee\r\n\r\n //Sends events\r\n final EventManager eventManager =\r\n serviceContext().eventManager();\r\n eventManager.send(NEW_HIRE_CHANNEL, employee);\r\n\r\n eventManager.sendArray(PAYROLL_ADJUSTMENT_CHANNEL,\r\n employee, salary);\r\n\r\n\r\n }\r\n\r\n }\r\n```\r\n\r\n\r\nNotice that we call sendArray so we can send the employee and their salary.\r\nThe listener for PAYROLL_ADJUSTMENT_CHANNEL will have to handle both an employee and an int\r\nthat represents the new employees salary.\r\nYou can also use event bus proxies so you do not have to call into the event bus at all.\r\n\r\nThe BenefitsService listens for new employees being hired so it can enroll them into the benefits system.\r\n\r\n```java\r\npublic static class BenefitsService {\r\n\r\n @OnEvent(NEW_HIRE_CHANNEL)\r\n public void enroll(final Employee employee) {\r\n\r\n System.out.printf(\"Employee enrolled into benefits system employee %s %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId());\r\n\r\n }\r\n\r\n```\r\n\r\nDaddy needs to get paid.\r\n\r\n```java\r\n public static class PayrollService {\r\n\r\n @OnEvent(PAYROLL_ADJUSTMENT_CHANNEL)\r\n public void addEmployeeToPayroll(final Employee employee, int salary) {\r\n\r\n System.out.printf(\"Employee added to payroll %s %d %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId(), salary);\r\n\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nThe employee is the employee object from the EmployeeHiringService.\r\n\r\nso you can get your benefits, and paid!\r\n\r\nFind more details here:\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\n\r\n## Private event bus and event bus proxies\r\n\r\n You can define your own interface to the event bus and you can use your own event buses with QBit.\r\n Each module in your service can have its own internal event bus.\r\n\r\n To learn more read:\r\n [QBit Microservice working with a private event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-private-event-bus-for-inproc-microservices)\r\n and [QBit Java Microservice lib using your own interface to the event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-strongly-typed-event-bus-proxies-for-QBit-Java-Microservice-lib).\r\n\r\n\r\n\r\n## Queue Callbacks\r\n\r\n To really grasp QBit, one must grasp the concepts of a CallBack.\r\n\r\n A CallBack is a way to get an async response in QBit.\r\n\r\n You call a service method and it calls you back.\r\n\r\n Client proxies can have callbacks:\r\n\r\n\r\n#### Queue Callbacks - RecommendationService client interface\r\n```java\r\n\r\npublic interface RecommendationServiceClient {\r\n\r\n\r\n void recommend(final Callback> recommendationsCallback,\r\n final String userName);\r\n}\r\n\r\n```\r\n\r\nCallbacks are Java 8 Consumers with some optional extra error handling.\r\n\r\n\r\n#### Queue Callbacks - Callback\r\n\r\n```java\r\n\r\n\r\npublic interface Callback extends java.util.function.Consumer {\r\n default void onError(java.lang.Throwable error) { /* compiled code */ }\r\n}\r\n\r\n```\r\n\r\nServices that can block should use callbacks.\r\nThus if loadUser blocked in the following example, it should really use a callback instead of returning a value.\r\n\r\npublic class RecommendationService {\r\n\r\n#### Queue Callbacks - Simple minded implementation of RecommendationService\r\n```java\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n public List recommend(final String userName) {\r\n User user = users.get(userName);\r\n if (user == null) {\r\n user = loadUser(userName);\r\n }\r\n return runRulesEngineAgainstUser(user);\r\n }\r\n\r\n```\r\n\r\n\r\nLet's pretend `loadUser` has to look in a local cache, and if the user is not found, look in an off-heap cache\r\nand if not found it must ask for the user from the UserService which must check its caches and perhaps fallback\r\nto loading the user data from a database or from other services.\r\nIn other words, `loadUser` can potentially block on IO.\r\n\r\n\r\n\r\n### Queue Callbacks - The first rule of Queue Club - don't block\r\n\r\n\r\nOur client does not block, but our service does. Going back to our `RecommendationService`.\r\nIf we get a lot of cache hits for user loads, perhaps the\r\nblock will not be that long, but it will be there and every time we have to fault in a user, the whole system\r\nis gummed up. What we want to be able to do is if we can't handle the recommendation request,\r\nwe go ahead and make an async call to the `UserDataService`. When that async callback comes back, then we\r\nhandle that request. In the mean time, we handle recommendation lists requests as quickly as we can.\r\nWe never block.\r\n\r\n\r\nSo let's revisit the service. The first thing we are going to do is make the service method take\r\na callback. Before we do that, let's set down some rules.\r\n\r\n\r\n#### The first rule of queue club don't block.\r\n#### The second rule of queue club if you are not ready, use a callback and continue handling stuff you are ready for\r\n\r\n\r\n#### Queue Callbacks - Adding a CallBack to the RecommendationService inproc microservice\r\n\r\n```java\r\npublic class RecommendationService {\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n```\r\n\r\n\r\n\r\nNow we are taking a callback and we can decide when we want to handle this recommendation generation request.\r\nWe can do it right away if there user data we need is in-memory or we can delay it.\r\n\r\n\r\n#### If the user is found, call the callback right away for RecommendationService inproc microservice\r\n\r\n```java\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n /** Look for user in user cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n ...\r\n } else {\r\n /* Call the callback now because we can handle the callback now. */\r\n recommendationsCallback.accept(runRulesEngineAgainstUser(user));\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nNotice, if the user is found in the cache, we run our recommendation rules in-memory and call the callback right away\r\n`recommendationsCallback.accept(runRulesEngineAgainstUser(user))`.\r\n\r\nThe interesting part is what do we do if don't have the user loaded.\r\n\r\n\r\n#### If the user was not found, load him from the user microservice, but still don't block\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using Callback. */\r\n userDataService.loadUser(new Callback() {\r\n @Override\r\n public void accept(final User loadedUser) {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nHere we use a CallBack to load the user, and when the user is loaded, we call `handleLoadFromUserDataService`\r\nwhich adds some management about handling the callback so we can still handle this call, just not now.\r\n\r\n\r\n\r\n#### Lambda version of last example\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using lambda expression. */\r\n userDataService.loadUser(\r\n loadedUser -> {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nUsing lambdas like this makes the code more readable and terse, but remember don't deeply nest\r\nlambda expressions or you will create a code maintenance nightmare. Use them judiciously.\r\n\r\n\r\n### Queue Callbacks - Doing something later\r\n\r\nWhat we want is to handle the request for recommendations after the user service system loads\r\nthe user from its store.\r\n\r\n\r\n\r\n#### Handling UserServiceData callback methods once we get them.\r\n\r\n```java\r\n\r\npublic class RecommendationService {\r\n\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n private UserDataServiceClient userDataService;\r\n\r\n\r\n private BlockingQueue callbacks =\r\n new ArrayBlockingQueue(10_000);\r\n\r\n\r\n ...\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n ...\r\n\r\n }\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks queue. */\r\n callbacks.add(new Runnable() {\r\n @Override\r\n public void run() {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n }\r\n });\r\n }\r\n\r\n\r\n\r\n```\r\n\r\n\r\n\r\n\r\n#### handleLoadFromUserDataService rewritten using Lambda\r\n\r\n```java\r\n\r\n\r\npublic class RecommendationService {\r\n\r\n...\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks list. */\r\n callbacks.add(() -> {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n });\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nThe important part there is that every time we get a callback call from `UserDataService`, we then\r\nperform our CPU intensive recommendation rules and callback our caller. Well not exactly, what we\r\ndo is enqueue an runnable onto our callbacks queue, and later we will iterate through those but when?\r\n\r\n\r\n### Queue Callbacks Handling callbacks when our receive queue is empty, a new batch started or we hit a batch limit\r\n\r\nThe `RecommendationService` can be notified when its queue is empty, it has started a new batch and when\r\nit has reached a batch limit. These are all good times to handle callbacks from the `UserDataService`.\r\n\r\n#### Draining our callback queue\r\n```java\r\n\r\n @QueueCallback({\r\n QueueCallbackType.EMPTY,\r\n QueueCallbackType.START_BATCH,\r\n QueueCallbackType.LIMIT})\r\n private void handleCallbacks() {\r\n\r\n flushServiceProxy(userDataService);\r\n Runnable runnable = callbacks.poll();\r\n\r\n while (runnable != null) {\r\n runnable.run();\r\n runnable = callbacks.poll();\r\n }\r\n }\r\n\r\n```\r\n\r\nIt is important to remember when handling callbacks from another microservice that you want to handle\r\ncallbacks from the other service before you handle more incomming requests from you clients.\r\nEssentially you have clients that have been waiting (async waiting but still), and these clients\r\nmight represent an open TCP/IP connection like an HTTP call so it is best to close them out\r\nbefore handling more requests and like we said they were already waiting around with an open connection\r\nfor users to load form the user service.\r\n\r\nTo learn more about CallBacks, plesae read [QBit Java MicroService Lib CallBack fundamentals]([Rough Cut] QBit Microservice Lib Working With CallBacks).\r\n\r\n\r\n\r\n\r\n## Workers - pools and shards\r\n\r\n```java\r\npublic class ServiceWorkers {\r\n\r\n public static RoundRobinServiceDispatcher workers() {...\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {...\r\n```\r\n\r\nYou can compose sharded workers (for in-memory, thread safe, CPU intensive services), or workers for IO\r\nor talking to foreign services or foreign buses.\r\n\r\nHere is an example that uses a worker pool with three service workers in it:\r\n\r\nLet's say you have a service that does something:\r\n\r\n```java\r\n\r\n //Your POJO\r\n public class MultiWorker {\r\n\r\n void doSomeWork(...) {\r\n ...\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nNow this does some sort of IO and you want to have a bank of these running not just one so you can do\r\nIO in parallel. After some performance testing, you found out that three is the magic number.\r\n\r\nYou want to use your API for accessing this service:\r\n\r\n```java\r\n public interface MultiWorkerClient {\r\n void doSomeWork(...);\r\n }\r\n\r\n```\r\n\r\nNow let's create a bank of these and use it.\r\n\r\nFirst create the QBit services which add the thread/queue/microbatch.\r\n\r\n```java\r\n\r\n /* Create a service builder. */\r\n final ServiceBuilder serviceBuilder = serviceBuilder();\r\n\r\n /* Create some qbit services. */\r\n final Service service1 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service2 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service3 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n```\r\n\r\nNow add them to a ServiceWorkers object.\r\n\r\n```java\r\n\r\n ServiceWorkers dispatcher;\r\n dispatcher = workers(); //Create a round robin service dispatcher\r\n dispatcher.addServices(service1, service2, service3);\r\n dispatcher.start(); // start up the workers\r\n\r\n```\r\n\r\nYou can add services, POJOs and method consumers, method dispatchers to a service bundle.\r\nThe service bundle is an integration point into QBit.\r\n\r\nLet's add our new Service workers. ServiceWorkers is a ServiceMethodDispatcher.\r\n\r\n```Java\r\n /* Add the dispatcher to a service bundle. */\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nWe are probably going to add a helper method to the service bundle so most of this can happen in\r\na single call.\r\n\r\nNow you can start using your workers.\r\n\r\n```java\r\n\r\n /* Start using the workers. */\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n```\r\n\r\nNow you could use Spring or Guice to configure the builders and the service bundle.\r\nBut you can just do it like the above which is good for testing and understanding QBit internals.\r\n\r\nQBit also supports the concept of sharded services which is good for sharding resources like CPU\r\n(run a rules engine on each CPU core for a user recommendation engine).\r\n\r\nQBit does not know how to shard your services, you have to give it a hint.\r\nYou do this through a shard rule.\r\n\r\n```java\r\npublic interface ShardRule {\r\n int shard(String methodName, Object[] args, int numWorkers);\r\n}\r\n```\r\nWe worked on an app where the first argument to the services was the username, and then we used that to\r\nshard calls to a CPU intensive in-memory rules engine. This technique works. :)\r\n\r\nThe ServiceWorkers class has a method for creating a sharded worker pool.\r\n\r\n```java\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nTo use you just pass a shard key when you create the service workers.\r\n\r\n```java\r\n\r\n\r\n dispatcher = shardedWorkers((methodName, methodArgs, numWorkers) -> {\r\n String userName = methodArgs[0].toString();\r\n int shardKey = userName.hashCode() % numWorkers;\r\n return shardKey;\r\n });\r\n\r\n```\r\n\r\nThen add your services to the ServiceWorkers composition.\r\n```java\r\n int workerCount = Runtime.getRuntime().availableProcessors();\r\n\r\n for (int index = 0; index < workerCount; index++) {\r\n final Service service = serviceBuilder\r\n .setServiceObject(new ContentRulesEngine()).build();\r\n dispatcher.addServices(service);\r\n\r\n }\r\n```\r\n\r\nThen add it to the service bundle as before.\r\n```java\r\n\r\n dispatcher.start();\r\n\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nThen just use it:\r\n\r\n```java\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n for (int index = 0; index < 100; index++) {\r\n String userName = \"rickhigh\" + index;\r\n worker.pickSuggestions(userName);\r\n }\r\n\r\n```\r\n\r\n### Built in shard rules\r\n\r\n```java\r\n\r\n\r\npublic class ServiceWorkers {\r\n...\r\n public static ShardedMethodDispatcher shardOnFirstArgumentWorkers() {\r\n ...\r\n }\r\n\r\n...\r\n\r\n public static ShardedMethodDispatcher shardOnFifthArgumentWorkers() {\r\n ...\r\n }\r\n\r\n\r\n public static ShardedMethodDispatcher shardOnBeanPath(final String beanPath) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nThe shardOnBeanPath allows you to create a complex bean path navigation call and use its property to shard on.\r\n\r\n```java\r\n\r\n /* shard on 2nd arg which is an employee\r\n Use the employees department's id property. */\r\n dispatcher = shardOnBeanPath(\"[1].department.id\");\r\n\r\n /* Same as above. */\r\n dispatcher = shardOnBeanPath(\"1/department/id\");\r\n\r\n```\r\n\r\n[Read more about Service sharding and service workers here](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-QBit-Microservices-using-Service-Workers-and-sharded-service-workers)\r\n\r\n\r\nYou can find a lot more in the wiki. Also follow the commits.\r\nWe have been busy beavers.\r\n[QBit the microservice lib for Java - JSON, REST, WebSocket](https://github.com/advantageous/qbit/wiki).",
"note": "Don't delete this file! It's used internally to help with page regeneration."
}
\ No newline at end of file
From 9b0356121af3057e044a52b72c88f61b2617e15d Mon Sep 17 00:00:00 2001
From: Richard Hightower
Date: Fri, 15 Apr 2016 08:01:33 -0700
Subject: [PATCH 06/19] Create gh-pages branch via GitHub
---
index.html | 2 +-
params.json | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/index.html b/index.html
index fa620ac0..f1248264 100644
--- a/index.html
+++ b/index.html
@@ -20,7 +20,7 @@
The Java microservice lib. QBit is a reactive progra
QBit - The Microservice Lib for Java - JSON, REST, WebSocket, Speed!
diff --git a/params.json b/params.json
index 05e9efdc..719fcf7e 100644
--- a/params.json
+++ b/params.json
@@ -1,6 +1,6 @@
{
"name": "QBit - Microservices Lib",
"tagline": "The Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.",
- "body": "[QBit Java Micorservices lib tutorials](https://github.com/MammatusTech/qbit-microservices-examples/wiki)|\r\n[QBit Website](http://advantageous.github.io/qbit/)\r\n\r\n#QBit - The Microservice Lib for Java - JSON, REST, WebSocket, Speed! \r\n\r\n## Quick overview of QBit\r\n\r\nThe Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.\r\n\r\nGot a question? Ask here: [QBit Google Group](https://groups.google.com/forum/#!forum/qbit-microservice).\r\n\r\nEverything is a queue. You have a choice. You can embrace it and control it. You can optimize for it.\r\nOr you can hide behind abstractions. QBit opens you up to peeking into what is going on, and allows you\r\nto pull some levers without selling your soul.\r\n\r\nQBit is a library not a framework. You can mix and match QBit with Spring, Guice, etc.\r\n\r\nQBit is FAST!\r\n\r\n\r\n\r\n#### Using from maven\r\n```xml\r\n\r\n io.advantageous.qbit\r\n qbit-admin\r\n 1.0.0.RELEASE\r\n\r\n\r\n io.advantageous.qbit\r\n qbit-vertx\r\n 1.0.0.RELEASE\r\n\r\n```\r\n\r\n#### Using from gradle\r\n```java\r\ncompile 'io.advantageous.qbit:qbit-admin:1.0.0.RELEASE'\r\ncompile 'io.advantageous.qbit:qbit-vertx:1.0.0.RELEASE'\r\n```\r\n\r\nCore Features\r\n============\r\n\r\n* Write REST based async microservices\r\n* Write ***WebSocket*** based async microservices (fast async RPC over WebSocket)\r\n* Actor Service Queues using micro-batching for high-speed message passing\r\n* Strongly async typed event bus which can be distributed\r\n* Async low overhead metrics gathering which can be queried and distributed (for doing fast lane analytics)\r\n* Complex async call coordination (with the Reactor) for reactive programming\r\n* Built-in support for ***health checks*** (and integration with tools like Consul)\r\n* Built-in support for ***monitoring*** (and integration with wire protocols like StatsD)\r\n* Built-in support for ***Service Discovery*** (with integration with health system, DNS SRV records and Consul)\r\n* Integration with persistent queues\r\n* [12 factor app port bindings](http://12factor.net/), health checks, KPI gathering, Logging MDC\r\n* API Gateway support for client generation and consumption via [Swagger](http://swagger.io/).\r\n* Our services can generate Swagger files (like idl for JSON/REST).\r\n* Remote client proxies for WebSocket (your interface is your IDL)\r\n\r\n\r\nStatus\r\n=====\r\nDeployed at several large fortune 100 companies. \r\nQBit now works with Vertx (standalone or embedded).\r\nYou can also use QBit on non-QBit projects, it is just a lib.\r\n\r\nLicense\r\n=====\r\nApache 2\r\n\r\n\r\n## Java Microservice Lib\r\n\r\nQBit has inproc services, REST microservices and WebSocket microservices as well as an\r\nin-proc service event bus (which can be per module or per app). It supports workers and in-memory services.\r\n\r\nBefore we describe more, here are two sample services:\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {...\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {...\r\n```\r\n\r\n\r\n#### Adder Service using URI params\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {...\r\n }\r\n```\r\n\r\n\r\n\r\nQBit philosophy:\r\n====\r\nAt the end of the day QBit is a simple library not a framework.\r\nYour app is not a QBit app but a Java app that uses the QBit lib.\r\nQBit allows you to work with Java UTIL concurrent, and does not endeavor to hide it from you.\r\nJust trying to take the sting out of it.\r\n\r\nDoes it work\r\n=====\r\nWe have used techniques in Boon and QBit with great success in high-end, high-performance, high-scalable apps.\r\nWe helped clients handle 10x the load with 1/10th the servers of their competitors using techniques in QBit.\r\nQBit is us being sick of hand tuning queue access and threads.\r\n\r\n\r\nBoon and QBit humility policy\r\n=====\r\nIdeas for Boon and QBit often come from all over the web. We make mistakes. Point them out.\r\nAs a developer of Boon and QBit, we are fellow travelers.\r\nIf you have an idea or technique you want to share, we listen.\r\n\r\n\r\nInspiration\r\n====\r\n\r\nA big inspiration for Boon/QBit was Vertx, Akka, Go Channels, Active Objects, Apartment Model Threading, Actor,\r\nand the Mechanical Sympathy papers.\r\n\r\nQBit has ideas that are similar to many frameworks. We are all reading the same papers.\r\nQBit got inspiration from the LMAX disruptor papers and this blog post about\r\n[link transfer queue versus disruptor](http://php.sabscape.com/blog/?p=557). We had some theories about\r\nqueues that blog post inspired us to try them out. Some of these theories are deployed at some of the\r\nbiggest middleware backends and whose name brands are known around the world. And thus QBit was born.\r\n\r\nQBit also took an lot of inspiration by the great work done\r\nby Tim Fox on Vertx. The first project using something that could actually be called QBit (albeit early QBit)\r\n was using Vertx on an web/mobile microservice for an app that could potentially have 80 million users.\r\n It was this\r\nexperience with Vertx and early QBit that led to QBit development and evolution. QBit is built on the\r\nshoulders of giants (Netty/Vertx).\r\n\r\nDoes QBit compete with...\r\n====\r\nSpring Disruptor: No. You could use QBit to write plugins for Spring Disruptor I suppose, but QBit does\r\nnot compete with Spring Disruptor.\r\nSpring Boot/Spring MVC: No. We use the same annotations but QBit is geared for high-speed in-memory\r\nmicroservices. It is more like Akka than Spring Boot. QBit has a subset of the features of Spring MVC\r\ngeared only for microservices, i.e., WebSocket RPC, REST, JSON marshaling, etc.\r\nAkka: No. Well Maybe. Akka has similar concepts but they take a different approach. QBit is more focused\r\n on Java, and microservices (REST, JSON, WebSocket) than Akka.\r\nLMAX Disruptor: No. In fact, we can use disruptor as on of the queues that QBit uses underneath the covers.\r\n\r\n\r\n(Early benchmarks have been removed. They were here. QBit got a lot faster.\r\n Benchmarking QBit is a moving target at the moment.\r\n Links and reports will be created.)\r\n\r\n\r\nCode Examples\r\n\r\n\r\n## Basic Queue example (REST style services is further down)\r\n\r\n====\r\n\r\n```java\r\n\r\n BasicQueue queue = BasicQueue.create(Integer.class, 1000);\r\n\r\n //Sending threads\r\n\r\n SendQueue sendQueue = queue.sendQueue();\r\n for (int index = 0; index < amount; index++) {\r\n sendQueue.send(index);\r\n }\r\n sendQueue.flushSends();\r\n ...\r\n sendQueue.sendAndFlush(code);\r\n //other methods for sendQueue, writeBatch, writeMany\r\n\r\n\r\n //Receiving Threads\r\n ReceiveQueue receiveQueue = queue.receiveQueue();\r\n Integer item = receiveQueue.take();\r\n //other methods poll(), pollWait(), readBatch(), readBatch(count)\r\n```\r\n\r\n\r\n### What is QBit again?\r\n\r\nQBit is a queuing library for microservices. It is similar to many other projects like Akka, Spring Reactor,\r\netc. QBit is just a library not a platform. QBit has libraries to put a service behind a queue.\r\nYou can use QBit queues directly or you can create a service. QBit services can be exposed by WebSocket,\r\nHTTP, HTTP pipeline, and other types of remoting. A service in QBit is a Java class whose methods are\r\n executed behind service queues. QBit implements apartment model threading and is similar to the\r\n Actor model or a better description would be Active Objects. QBit does not use a disruptor (but could).\r\n It uses regular Java Queues. QBit can do north of 100 million ping pong calls per second which is\r\n an amazing speed (seen as high as 200M). QBit also supports calling services via REST, and WebSocket.\r\n QBit is microservices in the pure Web sense: JSON, HTTP, WebSocket, etc. QBit uses micro batching to\r\n push messages through the pipe (queue, IO, etc.) faster to reduce thread hand-off.\r\n\r\n### QBit lingo\r\n\r\nQBit is a Java microservice lib supporting REST, JSON and WebSocket. It is written in Java but we could\r\none day write a version in Rust or Go or C# (but that would require a large payday).\r\n\r\n**Service**\r\nPOJO (plain old Java object) behind a queue that can receive method calls via proxy calls or events\r\n(May have one thread managing events, method calls, and responses or two one for method calls and events\r\n 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.\r\n\r\n**ServiceBundle**\r\nMany POJOs behind one response queue and many receive queues. There may be one thread for all responses\r\nor not. They also can be one receive queue.\r\n\r\n**Queue**\r\nA thread managing a queue. It supports batching. It has events for empty, reachedLimit, startedBatch,\r\nidle. You can listen to these events from services that sit behind a queue. You don't have to use Services.\r\nYou can use Queue's direct. In QBit, you have sender queues and receivers queues. They are separated to\r\nsupport micro-batching.\r\n\r\n**ServiceEndpointServer**\r\nServiceBundle that is exposed to REST and WebSocket communication.\r\n\r\n**EventBus**\r\nEventBus is a way to send a lot of messages to services that may be loosely coupled.\r\n\r\n**ClientProxy**\r\nClientProxy is a way to invoke service through async interface, service can be inproc (same process) or\r\nremoted over WebSocket.\r\n\r\n**Non-blocking**\r\nQBit is a non-blocking lib. You use CallBacks via Java 8 Lambdas. You can also send event messages and get\r\nreplies. Messaging is built into the system so you can easily coordinate complex tasks.\r\nQBit takes an object-oriented approach to service development so services look like normal Java services\r\nthat you\r\nalready write, but the services live behind a queue/thread. This is not a new concept. Microsoft did this\r\nwith DCOM/COM and called it active objects. Akka does it with actors and called them strongly typed Actors.\r\nThe important concepts is that you get the speed of reactive and actor style messaging but you develop\r\nin a natural OOP approach. QBit is not the first. QBit is not the only.\r\n\r\n\r\n**Speed**\r\nQBit is VERY fast. There is a of course a lot of room for improvement. But already 200M+ TPS inproc ping pong, 10M-20M+ TPS event bus, 500K TPS RPC calls over WebSocket/JSON, etc.\r\nMore work needs to be done to improve speed, but now it is fast enough where we are focusing more on\r\nusability.\r\nThe JSON support uses Boon by default which is up to 4x faster than other JSON parsers for the\r\nREST/JSON, WebSocket/JSON use case.\r\n\r\n**Reactive Programming**\r\nQBit provides a **Reactor** to manage async calls. This allows callbacks to be handled on the same thread that called them and it provides for timeout and error handling. Read [Reactor tutorial for creating reactive micro service programming](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices)\r\n\r\n**Service Discovery**\r\nBuilt in support for service discovery. This includes integration with Consul.\r\n\r\n\r\n**StatService**\r\nBuilt in support for stats. The **StatService** can be integrated with **StatsD** (Graphite, Grafana, DataDog, etc.) to publish passive stats. Or you can query the stats engine and react to the stats (counts, timings and levels). The **StatsService** is a reactive stats system that can be clustered. The StatService is reactive in that your services can publish to it and query it and react based on the results. You can implement things like rate limiting and react to an increased rate of something. The ServiceDiscovery system integrates with the HealthSystem and Consul to roll up each of your internal services that make up you micro service and publish the composite availably of your micro service to a single HTTP endpoint or a dead mans switch in Consul (TTL). \r\n\r\n\r\n\r\n### CURLable REST services example\r\n\r\nTalk is cheap. Let's look at some code. You can get a detailed walk through in the Wiki.\r\nWe have a lot of documentation already.\r\n\r\nWe will create a service that is exposed through REST/JSON.\r\n\r\nTo query the size of the todo list:\r\n\r\n```bash\r\ncurl localhost:8080/services/todo-service/todo/count\r\n```\r\n\r\nTo add a new TODO item.\r\n\r\n```bash\r\ncurl -X POST -H \"Content-Type: application/json\" -d \\\r\n'{\"name\":\"xyz\",\"description\":\"xyz\"}' \\\r\nhttp://localhost:8080/services/todo-service/todo\r\n```\r\n\r\nTo get a list of TODO items\r\n```bash\r\ncurl http://localhost:8080/services/todo-service/todo/\r\n```\r\n\r\nThe TODO example will use and track Todo items.\r\n\r\n#### Todo item POJO sans getter\r\n\r\n```java\r\npackage io.advantageous.qbit.examples;\r\n\r\nimport java.util.Date;\r\n\r\n\r\npublic class TodoItem {\r\n\r\n\r\n private final String description;\r\n private final String name;\r\n private final Date due;\r\n\r\n```\r\n\r\nThe TodoService uses Spring MVC style annotations.\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n\r\n private List todoItemList = new ArrayList<>();\r\n\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {\r\n\r\n return todoItemList.size();\r\n }\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {\r\n\r\n return todoItemList;\r\n }\r\n\r\n @RequestMapping(value = \"/todo\", method = RequestMethod.POST)\r\n public void add(TodoItem item) {\r\n\r\n todoItemList.add(item);\r\n }\r\n\r\n}\r\n\r\n```\r\n\r\n\r\n#### Sending non-JSON\r\n\r\nYou can POST/PUT non-JSON and you can capture the body as a `String` or as a `byte[]`. \r\nIf the content-type is set to anything but `application/json` and your body is defined a String or byte[].\r\nThis works automatically. (The content-type has to be set.)\r\n\r\n```java\r\n @RequestMapping(value = \"/body/bytes\", method = RequestMethod.POST)\r\n public boolean bodyPostBytes( byte[] body) {\r\n String string = new String(body, StandardCharsets.UTF_8);\r\n return string.equals(\"foo\");\r\n }\r\n\r\n @RequestMapping(value = \"/body/string\", method = RequestMethod.POST)\r\n public boolean bodyPostString(String body) {\r\n return body.equals(\"foo\");\r\n }\r\n```\r\n\r\n\r\n#### Sending different response codes for success\r\n\r\nBy default QBit sends a `200` (OK) for a non-void call (a call that has a return or a Callback). If the REST operation has no return or no callback then QBit sends a `202` (Accepted). There may be times when you want to send a 201 (Created) or some other code that is not an Exception. You can do that by setting `code` on `@RequestMapping`. By default the code is -1 which means use the default behavior (200 for success, 202 for one-way message, and 500 for errors).\r\n\r\n\r\n#### Sending different response codes for success\r\n```java\r\n\r\n @RequestMapping(value = \"/helloj7\", code = 221)\r\n public void helloJSend7(Callback>> callback) {\r\n callback.returnThis(JSendResponseBuilder.jSendResponseBuilder(Lists.list(\r\n \"hello \" + System.currentTimeMillis())).build());\r\n }\r\n\r\n```\r\n\r\n`Callbacks` can be used for internal services as well. It is often the case that you use a [CallbackBuilder](https://github.com/advantageous/qbit/wiki/%5BDocument%5D-CallbackBuilder-and-generics-for-Reactive-Java-Microservices) or a QBit [Reactor](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices) to manage service calls. \r\n\r\n#### Working with non JSON responses\r\n\r\nYou do not have to return JSON form rest calls.\r\nYou can return any binary or any text by using `HttpBinaryResponse` and `HttpTextResponse`.\r\n\r\n#### Returning non JSON from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildTextResponse());\r\n }\r\n```\r\n\r\n\r\n#### Returning binary from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildBinaryResponse());\r\n }\r\n```\r\n\r\n#### Side note Why Spring style annotations?\r\nWhy did we pick Spring style annotations?\r\n1) Spring is not a standard and neither is QBit. 2) We found the Spring annotations to be less verbose.\r\n3) More people use Spring than Java EE. We wrote QBit for people to use.\r\nWe could easily support JAX-RS style annotations, and we probably will.\r\nSince QBit focuses on JSON, we do not need all of the complexity of JAX-RS or even all the features of\r\nthe Spring MVC annotations. Also we can literally use the actual Spring annotations. QBit and Boon\r\nuse a non-type safe mechanism for annotations which means they are not tied to a particular lib.\r\nYou can define your own. We hate vendor tie-in even if it is an open source vendor.\r\n(We also support @POST, @GET which is similar to JAX-RS).\r\n\r\nNow just start it up.\r\n\r\n```java\r\n\r\n public static void main(String... args) {\r\n\r\n ServiceEndpointServer server = new EndpointServerBuilder().build();\r\n server.initServices(new TodoService());\r\n server.start();\r\n }\r\n```\r\n\r\n\r\n\r\nThat is it. There is also out of the box WebSocket support with client side proxy generation so\r\nyou can call into services at the rate of millions of calls per second.\r\n\r\n## Using URI Params for QBit microservice\r\n\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {\r\n\r\n return a + b;\r\n }\r\n }\r\n\r\n```\r\n\r\n## WebSocket\r\nYou can always invoke QBit services via a WebSocket proxy.\r\nThe advantage of a WebSocket proxy is it allows you execute 1M RPC+ a second (1 million remote calls\r\nevery second).\r\n\r\n\r\n#### Using a microservice remotely with WebSocket\r\n```java\r\n /* Start QBit client for WebSocket calls. */\r\n final Client client = clientBuilder()\r\n .setPort(7000).setRequestBatchSize(1).build();\r\n\r\n\r\n /* Create a proxy to the service. */\r\n final AdderServiceClientInterface adderService =\r\n client.createProxy(AdderServiceClientInterface.class,\r\n \"adder-service\");\r\n\r\n client.start();\r\n\r\n\r\n\r\n /* Call the service */\r\n adderService.add(System.out::println, 1, 2);\r\n\r\n```\r\n\r\nThe output is 3.\r\n\r\n```output\r\n3\r\n```\r\n\r\n\r\nThe above uses a WebSocket proxy interface to call the service async.\r\n\r\n```java\r\n\r\n interface AdderServiceClientInterface {\r\n\r\n void add(Callback callback, int a, int b);\r\n }\r\n```\r\n\r\n#### ServiceDiscovery aware websocket builders\r\n\r\nCreate websocket service client that is ServiceDiscovery aware.\r\n\r\n\r\n```java\r\n final Client client = clientBuilder.setServiceDiscovery(serviceDiscovery, \"echo\")\r\n .setUri(\"/echo\").setProtocolBatchSize(20).build().startClient();\r\n\r\n\r\n final EchoAsync echoClient = client.createProxy(EchoAsync.class, \"echo\");\r\n```\r\n\r\nCurrently the `clientBuilder` will load all service endpoints that are registered under the service name,\r\nand randomly pick one. \r\n\r\nServiceDiscovery includes Consul based, watching JSON files on disk, and DNS. It is easy to write your own service discovery as well and plug it into QBit.\r\n\r\n\r\nIn the future we can RoundRobin calls or shard calls to websocket service and/or provide auto fail over if the connection is closed. We do this for the event bus that uses service discovery but it is not baked into WebSocket based client stubs yet.\r\n\r\n\r\n## REST call with URI params\r\n\r\nThe last client example uses WebSocket. You could also just use REST, and actually use the URI params\r\nthat we setup.\r\nREST is nice but it is going to be slower than WebSocket support.\r\n\r\nQBit ships with a nice little HTTP client. We can use it.\r\n\r\nYou can use it to send async calls and WebSocket messages with the HTTP client.\r\n\r\n\r\nHere we will use the http client to invoke our remote method:\r\n\r\n#### Using a microservice remotely with REST QBit microservice client\r\n```java\r\n\r\n\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\")\r\n .setPort(7000).build();\r\n\r\n httpClient.start();\r\n String results = httpClient\r\n .get(\"/services/adder-service/add/2/2\").body();\r\n System.out.println(results);\r\n\r\n```\r\n\r\n\r\nThe output is 4.\r\n\r\n```output\r\n4\r\n```\r\n\r\n## Accessing The URI Param example with CURL\r\n\r\nYou can also access the service from curl.\r\n\r\n```bash\r\n$ curl http://localhost:7000/services/adder-service/add/2/2\r\n```\r\n\r\nSee this full example here: [QBit microservice getting started tutorial](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-------------QBit-microservice-example).\r\n\r\n[QBit URI params and WebSocket proxy client](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Using-QBit-microservice-lib's-REST-support-with-URI-Params)\r\n\r\n## Working with WebSocket, HttpClient etc.\r\n\r\nQBit has a library for working with and writing async microservices that is lightweight and fun to use.\r\n\r\n#### WebSocket server and client.\r\n\r\n\r\n#### Create an HTTP server\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n```\r\n\r\n#### Setup server WebSocket support\r\n```java\r\n /* Setup WebSocket Server support. */\r\n httpServer.setWebSocketOnOpenConsumer(webSocket -> {\r\n webSocket.setTextMessageConsumer(message -> {\r\n webSocket.sendText(\"ECHO \" + message);\r\n });\r\n });\r\n\r\n```\r\n\r\n#### Start the server\r\n```java\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n```\r\n\r\n#### Setup the WebSocket client\r\n```java\r\n\r\n /** CLIENT. */\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\n#### Client WebSocket\r\n\r\n```java\r\n\r\n /* Setup the client websocket. */\r\n WebSocket webSocket = httpClient\r\n .createWebSocket(\"/websocket/rocket\");\r\n\r\n /* Setup the text consumer. */\r\n webSocket.setTextMessageConsumer(message -> {\r\n System.out.println(message);\r\n });\r\n webSocket.openAndWait();\r\n\r\n /* Send some messages. */\r\n webSocket.sendText(\"Hi mom\");\r\n webSocket.sendText(\"Hello World!\");\r\n\r\n```\r\n\r\n#### Output\r\n```output\r\n\r\nECHO Hi mom\r\nECHO Hello World!\r\n\r\n```\r\n\r\nNow stop the server and client. Pretty easy eh?\r\n\r\n## High-speed HTTP client and server done microservice style\r\n\r\n\r\n##### Starting up an HTTP server\r\n\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n /* Setting up a request Consumer with Java 8 Lambda expression. */\r\n httpServer.setHttpRequestConsumer(httpRequest -> {\r\n\r\n Map results = new HashMap<>();\r\n results.put(\"method\", httpRequest.getMethod());\r\n results.put(\"uri\", httpRequest.getUri());\r\n results.put(\"body\", httpRequest.getBodyAsString());\r\n results.put(\"headers\", httpRequest.getHeaders());\r\n results.put(\"params\", httpRequest.getParams());\r\n httpRequest.getReceiver()\r\n .response(200, \"application/json\", Boon.toJson(results));\r\n });\r\n\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n\r\n\r\n```\r\n\r\nThe focus is on ease of use and using Java 8 Lambdas for callbacks so the code is tight and small.\r\n\r\n[Find out more about QBit's microservice style WebSocket support here](https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-WebSocket-support)\r\n\r\n\r\n## Using HTTP Client lib\r\n\r\nNow, let's try out our HTTP client.\r\n\r\n##### Starting up an HTTP client\r\n\r\n```java\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\nYou just pass the URL, the port and then call start.\r\n\r\n## Synchronous HTTP calls\r\n\r\nNow you can start sending HTTP requests.\r\n\r\n##### No Param HTTP GET\r\n\r\n```java\r\n /* Send no param get. */\r\n HttpResponse httpResponse = httpClient.get( \"/hello/mom\" );\r\n puts( httpResponse );\r\n```\r\n\r\nAn HTTP response just contains the results from the server.\r\n\r\n\r\n##### No Param HTTP Response\r\n\r\n```java\r\npublic interface HttpResponse {\r\n\r\n MultiMap headers();\r\n\r\n int code();\r\n\r\n String contentType();\r\n\r\n String body();\r\n\r\n}\r\n\r\n```\r\n\r\nThere are helper methods for sync HTTP GET calls.\r\n\r\n\r\n\r\n##### Helper methods for GET\r\n```java\r\n\r\n\r\n /* Send one param get. */\r\n httpResponse = httpClient.getWith1Param(\"/hello/singleParam\",\r\n \"hi\", \"mom\");\r\n puts(\"single param\", httpResponse );\r\n\r\n\r\n /* Send two param get. */\r\n httpResponse = httpClient.getWith2Params(\"/hello/twoParams\",\r\n \"hi\", \"mom\", \"hello\", \"dad\");\r\n puts(\"two params\", httpResponse );\r\n\r\n...\r\n\r\n /* Send five param get. */\r\n httpResponse = httpClient.getWith5Params(\"/hello/5params\",\r\n \"hi\", \"mom\",\r\n \"hello\", \"dad\",\r\n \"greetings\", \"kids\",\r\n \"yo\", \"pets\",\r\n \"hola\", \"neighbors\");\r\n puts(\"5 params\", httpResponse );\r\n\r\n\r\n```\r\n\r\nThe puts method is a helper method it does System.out.println more or less by the way.\r\n\r\nThe first five params are covered. Beyond five, you have to use the HttpBuilder.\r\n\r\n```java\r\n\r\n\r\n /* Send six params with get. */\r\n\r\n final HttpRequest httpRequest = httpRequestBuilder()\r\n .addParam(\"hi\", \"mom\")\r\n .addParam(\"hello\", \"dad\")\r\n .addParam(\"greetings\", \"kids\")\r\n .addParam(\"yo\", \"pets\")\r\n .addParam(\"hola\", \"pets\")\r\n .addParam(\"salutations\", \"all\").build();\r\n\r\n httpResponse = httpClient.sendRequestAndWait(httpRequest);\r\n puts(\"6 params\", httpResponse );\r\n```\r\n\r\n## Http Async HTTP Client\r\n\r\nThere are async calls for GET as well.\r\n\r\n#### Async calls for HTTP GET using Java 8 lambda\r\n\r\n```java\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsync(\"/hi/async\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith1Param(\"/hi/async\", \"hi\", \"mom\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda 1 param\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith2Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 2 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n...\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith5Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n \"p3\", \"v3\",\r\n \"p4\", \"v4\",\r\n \"p5\", \"v5\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 5 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n```\r\n\r\n[Find more about the easy to use, fast microservice HTTP client here]\r\n(https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-HttpClient-GET,-POST,-et-al,-JSON,-Java-8-Lambda).\r\n\r\n## InProc QBit services\r\n\r\nQBit allows for services behind queues to be run in-proc as well.\r\n\r\n```java\r\n\r\n /* POJO service. */\r\n final TodoManager todoManagerImpl = new TodoManager();\r\n\r\n /*\r\n Create the service which manages async calls to todoManagerImpl.\r\n */\r\n final Service service = serviceBuilder()\r\n .setServiceObject(todoManagerImpl)\r\n .build().startServiceQueue();\r\n\r\n\r\n /* Create Asynchronous proxy over Synchronous service. */\r\n final TodoManagerClientInterface todoManager =\r\n service.createProxy(TodoManagerClientInterface.class);\r\n\r\n service.startCallBackHandler();\r\n\r\n\r\n System.out.println(\"This is an async call\");\r\n /* Asynchronous method call. */\r\n todoManager.add(new Todo(\"Call Mom\", \"Give Mom a call\"));\r\n\r\n\r\n AtomicInteger countTracker = new AtomicInteger();\r\n //Hold count from async call to service... for testing and showing it is an async callback\r\n\r\n System.out.println(\"This is an async call to count\");\r\n\r\n todoManager.count(count -> {\r\n System.out.println(\"This lambda expression is the callback \" + count);\r\n\r\n countTracker.set(count);\r\n });\r\n\r\n\r\n todoManager.clientProxyFlush(); //Flush all methods. It batches calls.\r\n\r\n Sys.sleep(100);\r\n\r\n System.out.printf(\"This is the count back from the server %d\\n\", countTracker.get());\r\n\r\n```\r\n\r\n[Detailed tutorial on in-proc services is being written.](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-Working-with-inproc-MicroServices-within-QBit.)\r\n\r\n\r\n## QBit Event Bus\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\nQBit also has a service event bus. This example is a an employee benefits services example.\r\n\r\nWe have two channels.\r\n\r\n```\r\npublic static final String NEW_HIRE_CHANNEL = \"com.mycompnay.employee.new\";\r\n\r\npublic static final String PAYROLL_ADJUSTMENT_CHANNEL = \"com.mycompnay.employee.payroll\";\r\n```\r\n\r\nAn employee object looks like this:\r\n\r\n```java\r\n\r\npublic static class Employee {\r\n final String firstName;\r\n final int employeeId;\r\n```\r\n\r\n\r\nThis example has three services: EmployeeHiringService, BenefitsService, and PayrollService.\r\n\r\nThese services are inproc services. QBit supports WebSocket, HTTP and REST remote services as well, but for now, let's focus on inproc services. If you understand inproc then you will understand remote.\r\n\r\nThe EmployeeHiringService actually fires off the events to other two services.\r\n\r\n```java\r\npublic class EmployeeHiringService {\r\n\r\n\r\n public void hireEmployee(final Employee employee) {\r\n\r\n int salary = 100;\r\n System.out.printf(\"Hired employee %s\\n\", employee);\r\n\r\n //Does stuff to hire employee\r\n\r\n //Sends events\r\n final EventManager eventManager =\r\n serviceContext().eventManager();\r\n eventManager.send(NEW_HIRE_CHANNEL, employee);\r\n\r\n eventManager.sendArray(PAYROLL_ADJUSTMENT_CHANNEL,\r\n employee, salary);\r\n\r\n\r\n }\r\n\r\n }\r\n```\r\n\r\n\r\nNotice that we call sendArray so we can send the employee and their salary.\r\nThe listener for PAYROLL_ADJUSTMENT_CHANNEL will have to handle both an employee and an int\r\nthat represents the new employees salary.\r\nYou can also use event bus proxies so you do not have to call into the event bus at all.\r\n\r\nThe BenefitsService listens for new employees being hired so it can enroll them into the benefits system.\r\n\r\n```java\r\npublic static class BenefitsService {\r\n\r\n @OnEvent(NEW_HIRE_CHANNEL)\r\n public void enroll(final Employee employee) {\r\n\r\n System.out.printf(\"Employee enrolled into benefits system employee %s %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId());\r\n\r\n }\r\n\r\n```\r\n\r\nDaddy needs to get paid.\r\n\r\n```java\r\n public static class PayrollService {\r\n\r\n @OnEvent(PAYROLL_ADJUSTMENT_CHANNEL)\r\n public void addEmployeeToPayroll(final Employee employee, int salary) {\r\n\r\n System.out.printf(\"Employee added to payroll %s %d %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId(), salary);\r\n\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nThe employee is the employee object from the EmployeeHiringService.\r\n\r\nso you can get your benefits, and paid!\r\n\r\nFind more details here:\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\n\r\n## Private event bus and event bus proxies\r\n\r\n You can define your own interface to the event bus and you can use your own event buses with QBit.\r\n Each module in your service can have its own internal event bus.\r\n\r\n To learn more read:\r\n [QBit Microservice working with a private event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-private-event-bus-for-inproc-microservices)\r\n and [QBit Java Microservice lib using your own interface to the event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-strongly-typed-event-bus-proxies-for-QBit-Java-Microservice-lib).\r\n\r\n\r\n\r\n## Queue Callbacks\r\n\r\n To really grasp QBit, one must grasp the concepts of a CallBack.\r\n\r\n A CallBack is a way to get an async response in QBit.\r\n\r\n You call a service method and it calls you back.\r\n\r\n Client proxies can have callbacks:\r\n\r\n\r\n#### Queue Callbacks - RecommendationService client interface\r\n```java\r\n\r\npublic interface RecommendationServiceClient {\r\n\r\n\r\n void recommend(final Callback> recommendationsCallback,\r\n final String userName);\r\n}\r\n\r\n```\r\n\r\nCallbacks are Java 8 Consumers with some optional extra error handling.\r\n\r\n\r\n#### Queue Callbacks - Callback\r\n\r\n```java\r\n\r\n\r\npublic interface Callback extends java.util.function.Consumer {\r\n default void onError(java.lang.Throwable error) { /* compiled code */ }\r\n}\r\n\r\n```\r\n\r\nServices that can block should use callbacks.\r\nThus if loadUser blocked in the following example, it should really use a callback instead of returning a value.\r\n\r\npublic class RecommendationService {\r\n\r\n#### Queue Callbacks - Simple minded implementation of RecommendationService\r\n```java\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n public List recommend(final String userName) {\r\n User user = users.get(userName);\r\n if (user == null) {\r\n user = loadUser(userName);\r\n }\r\n return runRulesEngineAgainstUser(user);\r\n }\r\n\r\n```\r\n\r\n\r\nLet's pretend `loadUser` has to look in a local cache, and if the user is not found, look in an off-heap cache\r\nand if not found it must ask for the user from the UserService which must check its caches and perhaps fallback\r\nto loading the user data from a database or from other services.\r\nIn other words, `loadUser` can potentially block on IO.\r\n\r\n\r\n\r\n### Queue Callbacks - The first rule of Queue Club - don't block\r\n\r\n\r\nOur client does not block, but our service does. Going back to our `RecommendationService`.\r\nIf we get a lot of cache hits for user loads, perhaps the\r\nblock will not be that long, but it will be there and every time we have to fault in a user, the whole system\r\nis gummed up. What we want to be able to do is if we can't handle the recommendation request,\r\nwe go ahead and make an async call to the `UserDataService`. When that async callback comes back, then we\r\nhandle that request. In the mean time, we handle recommendation lists requests as quickly as we can.\r\nWe never block.\r\n\r\n\r\nSo let's revisit the service. The first thing we are going to do is make the service method take\r\na callback. Before we do that, let's set down some rules.\r\n\r\n\r\n#### The first rule of queue club don't block.\r\n#### The second rule of queue club if you are not ready, use a callback and continue handling stuff you are ready for\r\n\r\n\r\n#### Queue Callbacks - Adding a CallBack to the RecommendationService inproc microservice\r\n\r\n```java\r\npublic class RecommendationService {\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n```\r\n\r\n\r\n\r\nNow we are taking a callback and we can decide when we want to handle this recommendation generation request.\r\nWe can do it right away if there user data we need is in-memory or we can delay it.\r\n\r\n\r\n#### If the user is found, call the callback right away for RecommendationService inproc microservice\r\n\r\n```java\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n /** Look for user in user cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n ...\r\n } else {\r\n /* Call the callback now because we can handle the callback now. */\r\n recommendationsCallback.accept(runRulesEngineAgainstUser(user));\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nNotice, if the user is found in the cache, we run our recommendation rules in-memory and call the callback right away\r\n`recommendationsCallback.accept(runRulesEngineAgainstUser(user))`.\r\n\r\nThe interesting part is what do we do if don't have the user loaded.\r\n\r\n\r\n#### If the user was not found, load him from the user microservice, but still don't block\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using Callback. */\r\n userDataService.loadUser(new Callback() {\r\n @Override\r\n public void accept(final User loadedUser) {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nHere we use a CallBack to load the user, and when the user is loaded, we call `handleLoadFromUserDataService`\r\nwhich adds some management about handling the callback so we can still handle this call, just not now.\r\n\r\n\r\n\r\n#### Lambda version of last example\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using lambda expression. */\r\n userDataService.loadUser(\r\n loadedUser -> {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nUsing lambdas like this makes the code more readable and terse, but remember don't deeply nest\r\nlambda expressions or you will create a code maintenance nightmare. Use them judiciously.\r\n\r\n\r\n### Queue Callbacks - Doing something later\r\n\r\nWhat we want is to handle the request for recommendations after the user service system loads\r\nthe user from its store.\r\n\r\n\r\n\r\n#### Handling UserServiceData callback methods once we get them.\r\n\r\n```java\r\n\r\npublic class RecommendationService {\r\n\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n private UserDataServiceClient userDataService;\r\n\r\n\r\n private BlockingQueue callbacks =\r\n new ArrayBlockingQueue(10_000);\r\n\r\n\r\n ...\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n ...\r\n\r\n }\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks queue. */\r\n callbacks.add(new Runnable() {\r\n @Override\r\n public void run() {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n }\r\n });\r\n }\r\n\r\n\r\n\r\n```\r\n\r\n\r\n\r\n\r\n#### handleLoadFromUserDataService rewritten using Lambda\r\n\r\n```java\r\n\r\n\r\npublic class RecommendationService {\r\n\r\n...\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks list. */\r\n callbacks.add(() -> {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n });\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nThe important part there is that every time we get a callback call from `UserDataService`, we then\r\nperform our CPU intensive recommendation rules and callback our caller. Well not exactly, what we\r\ndo is enqueue an runnable onto our callbacks queue, and later we will iterate through those but when?\r\n\r\n\r\n### Queue Callbacks Handling callbacks when our receive queue is empty, a new batch started or we hit a batch limit\r\n\r\nThe `RecommendationService` can be notified when its queue is empty, it has started a new batch and when\r\nit has reached a batch limit. These are all good times to handle callbacks from the `UserDataService`.\r\n\r\n#### Draining our callback queue\r\n```java\r\n\r\n @QueueCallback({\r\n QueueCallbackType.EMPTY,\r\n QueueCallbackType.START_BATCH,\r\n QueueCallbackType.LIMIT})\r\n private void handleCallbacks() {\r\n\r\n flushServiceProxy(userDataService);\r\n Runnable runnable = callbacks.poll();\r\n\r\n while (runnable != null) {\r\n runnable.run();\r\n runnable = callbacks.poll();\r\n }\r\n }\r\n\r\n```\r\n\r\nIt is important to remember when handling callbacks from another microservice that you want to handle\r\ncallbacks from the other service before you handle more incomming requests from you clients.\r\nEssentially you have clients that have been waiting (async waiting but still), and these clients\r\nmight represent an open TCP/IP connection like an HTTP call so it is best to close them out\r\nbefore handling more requests and like we said they were already waiting around with an open connection\r\nfor users to load form the user service.\r\n\r\nTo learn more about CallBacks, plesae read [QBit Java MicroService Lib CallBack fundamentals]([Rough Cut] QBit Microservice Lib Working With CallBacks).\r\n\r\n\r\n\r\n\r\n## Workers - pools and shards\r\n\r\n```java\r\npublic class ServiceWorkers {\r\n\r\n public static RoundRobinServiceDispatcher workers() {...\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {...\r\n```\r\n\r\nYou can compose sharded workers (for in-memory, thread safe, CPU intensive services), or workers for IO\r\nor talking to foreign services or foreign buses.\r\n\r\nHere is an example that uses a worker pool with three service workers in it:\r\n\r\nLet's say you have a service that does something:\r\n\r\n```java\r\n\r\n //Your POJO\r\n public class MultiWorker {\r\n\r\n void doSomeWork(...) {\r\n ...\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nNow this does some sort of IO and you want to have a bank of these running not just one so you can do\r\nIO in parallel. After some performance testing, you found out that three is the magic number.\r\n\r\nYou want to use your API for accessing this service:\r\n\r\n```java\r\n public interface MultiWorkerClient {\r\n void doSomeWork(...);\r\n }\r\n\r\n```\r\n\r\nNow let's create a bank of these and use it.\r\n\r\nFirst create the QBit services which add the thread/queue/microbatch.\r\n\r\n```java\r\n\r\n /* Create a service builder. */\r\n final ServiceBuilder serviceBuilder = serviceBuilder();\r\n\r\n /* Create some qbit services. */\r\n final Service service1 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service2 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service3 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n```\r\n\r\nNow add them to a ServiceWorkers object.\r\n\r\n```java\r\n\r\n ServiceWorkers dispatcher;\r\n dispatcher = workers(); //Create a round robin service dispatcher\r\n dispatcher.addServices(service1, service2, service3);\r\n dispatcher.start(); // start up the workers\r\n\r\n```\r\n\r\nYou can add services, POJOs and method consumers, method dispatchers to a service bundle.\r\nThe service bundle is an integration point into QBit.\r\n\r\nLet's add our new Service workers. ServiceWorkers is a ServiceMethodDispatcher.\r\n\r\n```Java\r\n /* Add the dispatcher to a service bundle. */\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nWe are probably going to add a helper method to the service bundle so most of this can happen in\r\na single call.\r\n\r\nNow you can start using your workers.\r\n\r\n```java\r\n\r\n /* Start using the workers. */\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n```\r\n\r\nNow you could use Spring or Guice to configure the builders and the service bundle.\r\nBut you can just do it like the above which is good for testing and understanding QBit internals.\r\n\r\nQBit also supports the concept of sharded services which is good for sharding resources like CPU\r\n(run a rules engine on each CPU core for a user recommendation engine).\r\n\r\nQBit does not know how to shard your services, you have to give it a hint.\r\nYou do this through a shard rule.\r\n\r\n```java\r\npublic interface ShardRule {\r\n int shard(String methodName, Object[] args, int numWorkers);\r\n}\r\n```\r\nWe worked on an app where the first argument to the services was the username, and then we used that to\r\nshard calls to a CPU intensive in-memory rules engine. This technique works. :)\r\n\r\nThe ServiceWorkers class has a method for creating a sharded worker pool.\r\n\r\n```java\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nTo use you just pass a shard key when you create the service workers.\r\n\r\n```java\r\n\r\n\r\n dispatcher = shardedWorkers((methodName, methodArgs, numWorkers) -> {\r\n String userName = methodArgs[0].toString();\r\n int shardKey = userName.hashCode() % numWorkers;\r\n return shardKey;\r\n });\r\n\r\n```\r\n\r\nThen add your services to the ServiceWorkers composition.\r\n```java\r\n int workerCount = Runtime.getRuntime().availableProcessors();\r\n\r\n for (int index = 0; index < workerCount; index++) {\r\n final Service service = serviceBuilder\r\n .setServiceObject(new ContentRulesEngine()).build();\r\n dispatcher.addServices(service);\r\n\r\n }\r\n```\r\n\r\nThen add it to the service bundle as before.\r\n```java\r\n\r\n dispatcher.start();\r\n\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nThen just use it:\r\n\r\n```java\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n for (int index = 0; index < 100; index++) {\r\n String userName = \"rickhigh\" + index;\r\n worker.pickSuggestions(userName);\r\n }\r\n\r\n```\r\n\r\n### Built in shard rules\r\n\r\n```java\r\n\r\n\r\npublic class ServiceWorkers {\r\n...\r\n public static ShardedMethodDispatcher shardOnFirstArgumentWorkers() {\r\n ...\r\n }\r\n\r\n...\r\n\r\n public static ShardedMethodDispatcher shardOnFifthArgumentWorkers() {\r\n ...\r\n }\r\n\r\n\r\n public static ShardedMethodDispatcher shardOnBeanPath(final String beanPath) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nThe shardOnBeanPath allows you to create a complex bean path navigation call and use its property to shard on.\r\n\r\n```java\r\n\r\n /* shard on 2nd arg which is an employee\r\n Use the employees department's id property. */\r\n dispatcher = shardOnBeanPath(\"[1].department.id\");\r\n\r\n /* Same as above. */\r\n dispatcher = shardOnBeanPath(\"1/department/id\");\r\n\r\n```\r\n\r\n[Read more about Service sharding and service workers here](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-QBit-Microservices-using-Service-Workers-and-sharded-service-workers)\r\n\r\n\r\nYou can find a lot more in the wiki. Also follow the commits.\r\nWe have been busy beavers.\r\n[QBit the microservice lib for Java - JSON, REST, WebSocket](https://github.com/advantageous/qbit/wiki).",
+ "body": "[QBit Java Micorservices lib tutorials](https://github.com/MammatusTech/qbit-microservices-examples/wiki)|\r\n[QBit Website](http://advantageous.github.io/qbit/) | [QBit uses Reakt](http://advantageous.github.io/reakt/) | [QBit works with Vert.x](http://vertx.io/) | [Reakt Vertx](http://advantageous.github.io/reakt-vertx/\r\n\r\n#QBit - The Microservice Lib for Java - JSON, REST, WebSocket, Speed! \r\n\r\n## Quick overview of QBit\r\n\r\nThe Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.\r\n\r\nGot a question? Ask here: [QBit Google Group](https://groups.google.com/forum/#!forum/qbit-microservice).\r\n\r\nEverything is a queue. You have a choice. You can embrace it and control it. You can optimize for it.\r\nOr you can hide behind abstractions. QBit opens you up to peeking into what is going on, and allows you\r\nto pull some levers without selling your soul.\r\n\r\nQBit is a library not a framework. You can mix and match QBit with Spring, Guice, etc.\r\n\r\nQBit is FAST!\r\n\r\n\r\n\r\n#### Using from maven\r\n```xml\r\n\r\n io.advantageous.qbit\r\n qbit-admin\r\n 1.0.0.RELEASE\r\n\r\n\r\n io.advantageous.qbit\r\n qbit-vertx\r\n 1.0.0.RELEASE\r\n\r\n```\r\n\r\n#### Using from gradle\r\n```java\r\ncompile 'io.advantageous.qbit:qbit-admin:1.0.0.RELEASE'\r\ncompile 'io.advantageous.qbit:qbit-vertx:1.0.0.RELEASE'\r\n```\r\n\r\nCore Features\r\n============\r\n\r\n* Write REST based async microservices\r\n* Write ***WebSocket*** based async microservices (fast async RPC over WebSocket)\r\n* Actor Service Queues using micro-batching for high-speed message passing\r\n* Strongly async typed event bus which can be distributed\r\n* Async low overhead metrics gathering which can be queried and distributed (for doing fast lane analytics)\r\n* Complex async call coordination (with the Reactor) for reactive programming\r\n* Built-in support for ***health checks*** (and integration with tools like Consul)\r\n* Built-in support for ***monitoring*** (and integration with wire protocols like StatsD)\r\n* Built-in support for ***Service Discovery*** (with integration with health system, DNS SRV records and Consul)\r\n* Integration with persistent queues\r\n* [12 factor app port bindings](http://12factor.net/), health checks, KPI gathering, Logging MDC\r\n* API Gateway support for client generation and consumption via [Swagger](http://swagger.io/).\r\n* Our services can generate Swagger files (like idl for JSON/REST).\r\n* Remote client proxies for WebSocket (your interface is your IDL)\r\n\r\n\r\nStatus\r\n=====\r\nDeployed at several large fortune 100 companies. \r\nQBit now works with Vertx (standalone or embedded).\r\nYou can also use QBit on non-QBit projects, it is just a lib.\r\n\r\nLicense\r\n=====\r\nApache 2\r\n\r\n\r\n## Java Microservice Lib\r\n\r\nQBit has inproc services, REST microservices and WebSocket microservices as well as an\r\nin-proc service event bus (which can be per module or per app). It supports workers and in-memory services.\r\n\r\nBefore we describe more, here are two sample services:\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {...\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {...\r\n```\r\n\r\n\r\n#### Adder Service using URI params\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {...\r\n }\r\n```\r\n\r\n\r\n\r\nQBit philosophy:\r\n====\r\nAt the end of the day QBit is a simple library not a framework.\r\nYour app is not a QBit app but a Java app that uses the QBit lib.\r\nQBit allows you to work with Java UTIL concurrent, and does not endeavor to hide it from you.\r\nJust trying to take the sting out of it.\r\n\r\nDoes it work\r\n=====\r\nWe have used techniques in Boon and QBit with great success in high-end, high-performance, high-scalable apps.\r\nWe helped clients handle 10x the load with 1/10th the servers of their competitors using techniques in QBit.\r\nQBit is us being sick of hand tuning queue access and threads.\r\n\r\n\r\nBoon and QBit humility policy\r\n=====\r\nIdeas for Boon and QBit often come from all over the web. We make mistakes. Point them out.\r\nAs a developer of Boon and QBit, we are fellow travelers.\r\nIf you have an idea or technique you want to share, we listen.\r\n\r\n\r\nInspiration\r\n====\r\n\r\nA big inspiration for Boon/QBit was Vertx, Akka, Go Channels, Active Objects, Apartment Model Threading, Actor,\r\nand the Mechanical Sympathy papers.\r\n\r\nQBit has ideas that are similar to many frameworks. We are all reading the same papers.\r\nQBit got inspiration from the LMAX disruptor papers and this blog post about\r\n[link transfer queue versus disruptor](http://php.sabscape.com/blog/?p=557). We had some theories about\r\nqueues that blog post inspired us to try them out. Some of these theories are deployed at some of the\r\nbiggest middleware backends and whose name brands are known around the world. And thus QBit was born.\r\n\r\nQBit also took an lot of inspiration by the great work done\r\nby Tim Fox on Vertx. The first project using something that could actually be called QBit (albeit early QBit)\r\n was using Vertx on an web/mobile microservice for an app that could potentially have 80 million users.\r\n It was this\r\nexperience with Vertx and early QBit that led to QBit development and evolution. QBit is built on the\r\nshoulders of giants (Netty/Vertx).\r\n\r\nDoes QBit compete with...\r\n====\r\nSpring Disruptor: No. You could use QBit to write plugins for Spring Disruptor I suppose, but QBit does\r\nnot compete with Spring Disruptor.\r\nSpring Boot/Spring MVC: No. We use the same annotations but QBit is geared for high-speed in-memory\r\nmicroservices. It is more like Akka than Spring Boot. QBit has a subset of the features of Spring MVC\r\ngeared only for microservices, i.e., WebSocket RPC, REST, JSON marshaling, etc.\r\nAkka: No. Well Maybe. Akka has similar concepts but they take a different approach. QBit is more focused\r\n on Java, and microservices (REST, JSON, WebSocket) than Akka.\r\nLMAX Disruptor: No. In fact, we can use disruptor as on of the queues that QBit uses underneath the covers.\r\n\r\n\r\n(Early benchmarks have been removed. They were here. QBit got a lot faster.\r\n Benchmarking QBit is a moving target at the moment.\r\n Links and reports will be created.)\r\n\r\n\r\nCode Examples\r\n\r\n\r\n## Basic Queue example (REST style services is further down)\r\n\r\n====\r\n\r\n```java\r\n\r\n BasicQueue queue = BasicQueue.create(Integer.class, 1000);\r\n\r\n //Sending threads\r\n\r\n SendQueue sendQueue = queue.sendQueue();\r\n for (int index = 0; index < amount; index++) {\r\n sendQueue.send(index);\r\n }\r\n sendQueue.flushSends();\r\n ...\r\n sendQueue.sendAndFlush(code);\r\n //other methods for sendQueue, writeBatch, writeMany\r\n\r\n\r\n //Receiving Threads\r\n ReceiveQueue receiveQueue = queue.receiveQueue();\r\n Integer item = receiveQueue.take();\r\n //other methods poll(), pollWait(), readBatch(), readBatch(count)\r\n```\r\n\r\n\r\n### What is QBit again?\r\n\r\nQBit is a queuing library for microservices. It is similar to many other projects like Akka, Spring Reactor,\r\netc. QBit is just a library not a platform. QBit has libraries to put a service behind a queue.\r\nYou can use QBit queues directly or you can create a service. QBit services can be exposed by WebSocket,\r\nHTTP, HTTP pipeline, and other types of remoting. A service in QBit is a Java class whose methods are\r\n executed behind service queues. QBit implements apartment model threading and is similar to the\r\n Actor model or a better description would be Active Objects. QBit does not use a disruptor (but could).\r\n It uses regular Java Queues. QBit can do north of 100 million ping pong calls per second which is\r\n an amazing speed (seen as high as 200M). QBit also supports calling services via REST, and WebSocket.\r\n QBit is microservices in the pure Web sense: JSON, HTTP, WebSocket, etc. QBit uses micro batching to\r\n push messages through the pipe (queue, IO, etc.) faster to reduce thread hand-off.\r\n\r\n### QBit lingo\r\n\r\nQBit is a Java microservice lib supporting REST, JSON and WebSocket. It is written in Java but we could\r\none day write a version in Rust or Go or C# (but that would require a large payday).\r\n\r\n**Service**\r\nPOJO (plain old Java object) behind a queue that can receive method calls via proxy calls or events\r\n(May have one thread managing events, method calls, and responses or two one for method calls and events\r\n 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.\r\n\r\n**ServiceBundle**\r\nMany POJOs behind one response queue and many receive queues. There may be one thread for all responses\r\nor not. They also can be one receive queue.\r\n\r\n**Queue**\r\nA thread managing a queue. It supports batching. It has events for empty, reachedLimit, startedBatch,\r\nidle. You can listen to these events from services that sit behind a queue. You don't have to use Services.\r\nYou can use Queue's direct. In QBit, you have sender queues and receivers queues. They are separated to\r\nsupport micro-batching.\r\n\r\n**ServiceEndpointServer**\r\nServiceBundle that is exposed to REST and WebSocket communication.\r\n\r\n**EventBus**\r\nEventBus is a way to send a lot of messages to services that may be loosely coupled.\r\n\r\n**ClientProxy**\r\nClientProxy is a way to invoke service through async interface, service can be inproc (same process) or\r\nremoted over WebSocket.\r\n\r\n**Non-blocking**\r\nQBit is a non-blocking lib. You use CallBacks via Java 8 Lambdas. You can also send event messages and get\r\nreplies. Messaging is built into the system so you can easily coordinate complex tasks.\r\nQBit takes an object-oriented approach to service development so services look like normal Java services\r\nthat you\r\nalready write, but the services live behind a queue/thread. This is not a new concept. Microsoft did this\r\nwith DCOM/COM and called it active objects. Akka does it with actors and called them strongly typed Actors.\r\nThe important concepts is that you get the speed of reactive and actor style messaging but you develop\r\nin a natural OOP approach. QBit is not the first. QBit is not the only.\r\n\r\n\r\n**Speed**\r\nQBit is VERY fast. There is a of course a lot of room for improvement. But already 200M+ TPS inproc ping pong, 10M-20M+ TPS event bus, 500K TPS RPC calls over WebSocket/JSON, etc.\r\nMore work needs to be done to improve speed, but now it is fast enough where we are focusing more on\r\nusability.\r\nThe JSON support uses Boon by default which is up to 4x faster than other JSON parsers for the\r\nREST/JSON, WebSocket/JSON use case.\r\n\r\n**Reactive Programming**\r\nQBit provides a **Reactor** to manage async calls. This allows callbacks to be handled on the same thread that called them and it provides for timeout and error handling. Read [Reactor tutorial for creating reactive micro service programming](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices)\r\n\r\n**Service Discovery**\r\nBuilt in support for service discovery. This includes integration with Consul.\r\n\r\n\r\n**StatService**\r\nBuilt in support for stats. The **StatService** can be integrated with **StatsD** (Graphite, Grafana, DataDog, etc.) to publish passive stats. Or you can query the stats engine and react to the stats (counts, timings and levels). The **StatsService** is a reactive stats system that can be clustered. The StatService is reactive in that your services can publish to it and query it and react based on the results. You can implement things like rate limiting and react to an increased rate of something. The ServiceDiscovery system integrates with the HealthSystem and Consul to roll up each of your internal services that make up you micro service and publish the composite availably of your micro service to a single HTTP endpoint or a dead mans switch in Consul (TTL). \r\n\r\n\r\n\r\n### CURLable REST services example\r\n\r\nTalk is cheap. Let's look at some code. You can get a detailed walk through in the Wiki.\r\nWe have a lot of documentation already.\r\n\r\nWe will create a service that is exposed through REST/JSON.\r\n\r\nTo query the size of the todo list:\r\n\r\n```bash\r\ncurl localhost:8080/services/todo-service/todo/count\r\n```\r\n\r\nTo add a new TODO item.\r\n\r\n```bash\r\ncurl -X POST -H \"Content-Type: application/json\" -d \\\r\n'{\"name\":\"xyz\",\"description\":\"xyz\"}' \\\r\nhttp://localhost:8080/services/todo-service/todo\r\n```\r\n\r\nTo get a list of TODO items\r\n```bash\r\ncurl http://localhost:8080/services/todo-service/todo/\r\n```\r\n\r\nThe TODO example will use and track Todo items.\r\n\r\n#### Todo item POJO sans getter\r\n\r\n```java\r\npackage io.advantageous.qbit.examples;\r\n\r\nimport java.util.Date;\r\n\r\n\r\npublic class TodoItem {\r\n\r\n\r\n private final String description;\r\n private final String name;\r\n private final Date due;\r\n\r\n```\r\n\r\nThe TodoService uses Spring MVC style annotations.\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n\r\n private List todoItemList = new ArrayList<>();\r\n\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {\r\n\r\n return todoItemList.size();\r\n }\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {\r\n\r\n return todoItemList;\r\n }\r\n\r\n @RequestMapping(value = \"/todo\", method = RequestMethod.POST)\r\n public void add(TodoItem item) {\r\n\r\n todoItemList.add(item);\r\n }\r\n\r\n}\r\n\r\n```\r\n\r\n\r\n#### Sending non-JSON\r\n\r\nYou can POST/PUT non-JSON and you can capture the body as a `String` or as a `byte[]`. \r\nIf the content-type is set to anything but `application/json` and your body is defined a String or byte[].\r\nThis works automatically. (The content-type has to be set.)\r\n\r\n```java\r\n @RequestMapping(value = \"/body/bytes\", method = RequestMethod.POST)\r\n public boolean bodyPostBytes( byte[] body) {\r\n String string = new String(body, StandardCharsets.UTF_8);\r\n return string.equals(\"foo\");\r\n }\r\n\r\n @RequestMapping(value = \"/body/string\", method = RequestMethod.POST)\r\n public boolean bodyPostString(String body) {\r\n return body.equals(\"foo\");\r\n }\r\n```\r\n\r\n\r\n#### Sending different response codes for success\r\n\r\nBy default QBit sends a `200` (OK) for a non-void call (a call that has a return or a Callback). If the REST operation has no return or no callback then QBit sends a `202` (Accepted). There may be times when you want to send a 201 (Created) or some other code that is not an Exception. You can do that by setting `code` on `@RequestMapping`. By default the code is -1 which means use the default behavior (200 for success, 202 for one-way message, and 500 for errors).\r\n\r\n\r\n#### Sending different response codes for success\r\n```java\r\n\r\n @RequestMapping(value = \"/helloj7\", code = 221)\r\n public void helloJSend7(Callback>> callback) {\r\n callback.returnThis(JSendResponseBuilder.jSendResponseBuilder(Lists.list(\r\n \"hello \" + System.currentTimeMillis())).build());\r\n }\r\n\r\n```\r\n\r\n`Callbacks` can be used for internal services as well. It is often the case that you use a [CallbackBuilder](https://github.com/advantageous/qbit/wiki/%5BDocument%5D-CallbackBuilder-and-generics-for-Reactive-Java-Microservices) or a QBit [Reactor](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices) to manage service calls. \r\n\r\n#### Working with non JSON responses\r\n\r\nYou do not have to return JSON form rest calls.\r\nYou can return any binary or any text by using `HttpBinaryResponse` and `HttpTextResponse`.\r\n\r\n#### Returning non JSON from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildTextResponse());\r\n }\r\n```\r\n\r\n\r\n#### Returning binary from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildBinaryResponse());\r\n }\r\n```\r\n\r\n#### Side note Why Spring style annotations?\r\nWhy did we pick Spring style annotations?\r\n1) Spring is not a standard and neither is QBit. 2) We found the Spring annotations to be less verbose.\r\n3) More people use Spring than Java EE. We wrote QBit for people to use.\r\nWe could easily support JAX-RS style annotations, and we probably will.\r\nSince QBit focuses on JSON, we do not need all of the complexity of JAX-RS or even all the features of\r\nthe Spring MVC annotations. Also we can literally use the actual Spring annotations. QBit and Boon\r\nuse a non-type safe mechanism for annotations which means they are not tied to a particular lib.\r\nYou can define your own. We hate vendor tie-in even if it is an open source vendor.\r\n(We also support @POST, @GET which is similar to JAX-RS).\r\n\r\nNow just start it up.\r\n\r\n```java\r\n\r\n public static void main(String... args) {\r\n\r\n ServiceEndpointServer server = new EndpointServerBuilder().build();\r\n server.initServices(new TodoService());\r\n server.start();\r\n }\r\n```\r\n\r\n\r\n\r\nThat is it. There is also out of the box WebSocket support with client side proxy generation so\r\nyou can call into services at the rate of millions of calls per second.\r\n\r\n## Using URI Params for QBit microservice\r\n\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {\r\n\r\n return a + b;\r\n }\r\n }\r\n\r\n```\r\n\r\n## WebSocket\r\nYou can always invoke QBit services via a WebSocket proxy.\r\nThe advantage of a WebSocket proxy is it allows you execute 1M RPC+ a second (1 million remote calls\r\nevery second).\r\n\r\n\r\n#### Using a microservice remotely with WebSocket\r\n```java\r\n /* Start QBit client for WebSocket calls. */\r\n final Client client = clientBuilder()\r\n .setPort(7000).setRequestBatchSize(1).build();\r\n\r\n\r\n /* Create a proxy to the service. */\r\n final AdderServiceClientInterface adderService =\r\n client.createProxy(AdderServiceClientInterface.class,\r\n \"adder-service\");\r\n\r\n client.start();\r\n\r\n\r\n\r\n /* Call the service */\r\n adderService.add(System.out::println, 1, 2);\r\n\r\n```\r\n\r\nThe output is 3.\r\n\r\n```output\r\n3\r\n```\r\n\r\n\r\nThe above uses a WebSocket proxy interface to call the service async.\r\n\r\n```java\r\n\r\n interface AdderServiceClientInterface {\r\n\r\n void add(Callback callback, int a, int b);\r\n }\r\n```\r\n\r\n#### ServiceDiscovery aware websocket builders\r\n\r\nCreate websocket service client that is ServiceDiscovery aware.\r\n\r\n\r\n```java\r\n final Client client = clientBuilder.setServiceDiscovery(serviceDiscovery, \"echo\")\r\n .setUri(\"/echo\").setProtocolBatchSize(20).build().startClient();\r\n\r\n\r\n final EchoAsync echoClient = client.createProxy(EchoAsync.class, \"echo\");\r\n```\r\n\r\nCurrently the `clientBuilder` will load all service endpoints that are registered under the service name,\r\nand randomly pick one. \r\n\r\nServiceDiscovery includes Consul based, watching JSON files on disk, and DNS. It is easy to write your own service discovery as well and plug it into QBit.\r\n\r\n\r\nIn the future we can RoundRobin calls or shard calls to websocket service and/or provide auto fail over if the connection is closed. We do this for the event bus that uses service discovery but it is not baked into WebSocket based client stubs yet.\r\n\r\n\r\n## REST call with URI params\r\n\r\nThe last client example uses WebSocket. You could also just use REST, and actually use the URI params\r\nthat we setup.\r\nREST is nice but it is going to be slower than WebSocket support.\r\n\r\nQBit ships with a nice little HTTP client. We can use it.\r\n\r\nYou can use it to send async calls and WebSocket messages with the HTTP client.\r\n\r\n\r\nHere we will use the http client to invoke our remote method:\r\n\r\n#### Using a microservice remotely with REST QBit microservice client\r\n```java\r\n\r\n\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\")\r\n .setPort(7000).build();\r\n\r\n httpClient.start();\r\n String results = httpClient\r\n .get(\"/services/adder-service/add/2/2\").body();\r\n System.out.println(results);\r\n\r\n```\r\n\r\n\r\nThe output is 4.\r\n\r\n```output\r\n4\r\n```\r\n\r\n## Accessing The URI Param example with CURL\r\n\r\nYou can also access the service from curl.\r\n\r\n```bash\r\n$ curl http://localhost:7000/services/adder-service/add/2/2\r\n```\r\n\r\nSee this full example here: [QBit microservice getting started tutorial](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-------------QBit-microservice-example).\r\n\r\n[QBit URI params and WebSocket proxy client](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Using-QBit-microservice-lib's-REST-support-with-URI-Params)\r\n\r\n## Working with WebSocket, HttpClient etc.\r\n\r\nQBit has a library for working with and writing async microservices that is lightweight and fun to use.\r\n\r\n#### WebSocket server and client.\r\n\r\n\r\n#### Create an HTTP server\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n```\r\n\r\n#### Setup server WebSocket support\r\n```java\r\n /* Setup WebSocket Server support. */\r\n httpServer.setWebSocketOnOpenConsumer(webSocket -> {\r\n webSocket.setTextMessageConsumer(message -> {\r\n webSocket.sendText(\"ECHO \" + message);\r\n });\r\n });\r\n\r\n```\r\n\r\n#### Start the server\r\n```java\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n```\r\n\r\n#### Setup the WebSocket client\r\n```java\r\n\r\n /** CLIENT. */\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\n#### Client WebSocket\r\n\r\n```java\r\n\r\n /* Setup the client websocket. */\r\n WebSocket webSocket = httpClient\r\n .createWebSocket(\"/websocket/rocket\");\r\n\r\n /* Setup the text consumer. */\r\n webSocket.setTextMessageConsumer(message -> {\r\n System.out.println(message);\r\n });\r\n webSocket.openAndWait();\r\n\r\n /* Send some messages. */\r\n webSocket.sendText(\"Hi mom\");\r\n webSocket.sendText(\"Hello World!\");\r\n\r\n```\r\n\r\n#### Output\r\n```output\r\n\r\nECHO Hi mom\r\nECHO Hello World!\r\n\r\n```\r\n\r\nNow stop the server and client. Pretty easy eh?\r\n\r\n## High-speed HTTP client and server done microservice style\r\n\r\n\r\n##### Starting up an HTTP server\r\n\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n /* Setting up a request Consumer with Java 8 Lambda expression. */\r\n httpServer.setHttpRequestConsumer(httpRequest -> {\r\n\r\n Map results = new HashMap<>();\r\n results.put(\"method\", httpRequest.getMethod());\r\n results.put(\"uri\", httpRequest.getUri());\r\n results.put(\"body\", httpRequest.getBodyAsString());\r\n results.put(\"headers\", httpRequest.getHeaders());\r\n results.put(\"params\", httpRequest.getParams());\r\n httpRequest.getReceiver()\r\n .response(200, \"application/json\", Boon.toJson(results));\r\n });\r\n\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n\r\n\r\n```\r\n\r\nThe focus is on ease of use and using Java 8 Lambdas for callbacks so the code is tight and small.\r\n\r\n[Find out more about QBit's microservice style WebSocket support here](https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-WebSocket-support)\r\n\r\n\r\n## Using HTTP Client lib\r\n\r\nNow, let's try out our HTTP client.\r\n\r\n##### Starting up an HTTP client\r\n\r\n```java\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\nYou just pass the URL, the port and then call start.\r\n\r\n## Synchronous HTTP calls\r\n\r\nNow you can start sending HTTP requests.\r\n\r\n##### No Param HTTP GET\r\n\r\n```java\r\n /* Send no param get. */\r\n HttpResponse httpResponse = httpClient.get( \"/hello/mom\" );\r\n puts( httpResponse );\r\n```\r\n\r\nAn HTTP response just contains the results from the server.\r\n\r\n\r\n##### No Param HTTP Response\r\n\r\n```java\r\npublic interface HttpResponse {\r\n\r\n MultiMap headers();\r\n\r\n int code();\r\n\r\n String contentType();\r\n\r\n String body();\r\n\r\n}\r\n\r\n```\r\n\r\nThere are helper methods for sync HTTP GET calls.\r\n\r\n\r\n\r\n##### Helper methods for GET\r\n```java\r\n\r\n\r\n /* Send one param get. */\r\n httpResponse = httpClient.getWith1Param(\"/hello/singleParam\",\r\n \"hi\", \"mom\");\r\n puts(\"single param\", httpResponse );\r\n\r\n\r\n /* Send two param get. */\r\n httpResponse = httpClient.getWith2Params(\"/hello/twoParams\",\r\n \"hi\", \"mom\", \"hello\", \"dad\");\r\n puts(\"two params\", httpResponse );\r\n\r\n...\r\n\r\n /* Send five param get. */\r\n httpResponse = httpClient.getWith5Params(\"/hello/5params\",\r\n \"hi\", \"mom\",\r\n \"hello\", \"dad\",\r\n \"greetings\", \"kids\",\r\n \"yo\", \"pets\",\r\n \"hola\", \"neighbors\");\r\n puts(\"5 params\", httpResponse );\r\n\r\n\r\n```\r\n\r\nThe puts method is a helper method it does System.out.println more or less by the way.\r\n\r\nThe first five params are covered. Beyond five, you have to use the HttpBuilder.\r\n\r\n```java\r\n\r\n\r\n /* Send six params with get. */\r\n\r\n final HttpRequest httpRequest = httpRequestBuilder()\r\n .addParam(\"hi\", \"mom\")\r\n .addParam(\"hello\", \"dad\")\r\n .addParam(\"greetings\", \"kids\")\r\n .addParam(\"yo\", \"pets\")\r\n .addParam(\"hola\", \"pets\")\r\n .addParam(\"salutations\", \"all\").build();\r\n\r\n httpResponse = httpClient.sendRequestAndWait(httpRequest);\r\n puts(\"6 params\", httpResponse );\r\n```\r\n\r\n## Http Async HTTP Client\r\n\r\nThere are async calls for GET as well.\r\n\r\n#### Async calls for HTTP GET using Java 8 lambda\r\n\r\n```java\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsync(\"/hi/async\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith1Param(\"/hi/async\", \"hi\", \"mom\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda 1 param\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith2Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 2 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n...\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith5Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n \"p3\", \"v3\",\r\n \"p4\", \"v4\",\r\n \"p5\", \"v5\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 5 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n```\r\n\r\n[Find more about the easy to use, fast microservice HTTP client here]\r\n(https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-HttpClient-GET,-POST,-et-al,-JSON,-Java-8-Lambda).\r\n\r\n## InProc QBit services\r\n\r\nQBit allows for services behind queues to be run in-proc as well.\r\n\r\n```java\r\n\r\n /* POJO service. */\r\n final TodoManager todoManagerImpl = new TodoManager();\r\n\r\n /*\r\n Create the service which manages async calls to todoManagerImpl.\r\n */\r\n final Service service = serviceBuilder()\r\n .setServiceObject(todoManagerImpl)\r\n .build().startServiceQueue();\r\n\r\n\r\n /* Create Asynchronous proxy over Synchronous service. */\r\n final TodoManagerClientInterface todoManager =\r\n service.createProxy(TodoManagerClientInterface.class);\r\n\r\n service.startCallBackHandler();\r\n\r\n\r\n System.out.println(\"This is an async call\");\r\n /* Asynchronous method call. */\r\n todoManager.add(new Todo(\"Call Mom\", \"Give Mom a call\"));\r\n\r\n\r\n AtomicInteger countTracker = new AtomicInteger();\r\n //Hold count from async call to service... for testing and showing it is an async callback\r\n\r\n System.out.println(\"This is an async call to count\");\r\n\r\n todoManager.count(count -> {\r\n System.out.println(\"This lambda expression is the callback \" + count);\r\n\r\n countTracker.set(count);\r\n });\r\n\r\n\r\n todoManager.clientProxyFlush(); //Flush all methods. It batches calls.\r\n\r\n Sys.sleep(100);\r\n\r\n System.out.printf(\"This is the count back from the server %d\\n\", countTracker.get());\r\n\r\n```\r\n\r\n[Detailed tutorial on in-proc services is being written.](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-Working-with-inproc-MicroServices-within-QBit.)\r\n\r\n\r\n## QBit Event Bus\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\nQBit also has a service event bus. This example is a an employee benefits services example.\r\n\r\nWe have two channels.\r\n\r\n```\r\npublic static final String NEW_HIRE_CHANNEL = \"com.mycompnay.employee.new\";\r\n\r\npublic static final String PAYROLL_ADJUSTMENT_CHANNEL = \"com.mycompnay.employee.payroll\";\r\n```\r\n\r\nAn employee object looks like this:\r\n\r\n```java\r\n\r\npublic static class Employee {\r\n final String firstName;\r\n final int employeeId;\r\n```\r\n\r\n\r\nThis example has three services: EmployeeHiringService, BenefitsService, and PayrollService.\r\n\r\nThese services are inproc services. QBit supports WebSocket, HTTP and REST remote services as well, but for now, let's focus on inproc services. If you understand inproc then you will understand remote.\r\n\r\nThe EmployeeHiringService actually fires off the events to other two services.\r\n\r\n```java\r\npublic class EmployeeHiringService {\r\n\r\n\r\n public void hireEmployee(final Employee employee) {\r\n\r\n int salary = 100;\r\n System.out.printf(\"Hired employee %s\\n\", employee);\r\n\r\n //Does stuff to hire employee\r\n\r\n //Sends events\r\n final EventManager eventManager =\r\n serviceContext().eventManager();\r\n eventManager.send(NEW_HIRE_CHANNEL, employee);\r\n\r\n eventManager.sendArray(PAYROLL_ADJUSTMENT_CHANNEL,\r\n employee, salary);\r\n\r\n\r\n }\r\n\r\n }\r\n```\r\n\r\n\r\nNotice that we call sendArray so we can send the employee and their salary.\r\nThe listener for PAYROLL_ADJUSTMENT_CHANNEL will have to handle both an employee and an int\r\nthat represents the new employees salary.\r\nYou can also use event bus proxies so you do not have to call into the event bus at all.\r\n\r\nThe BenefitsService listens for new employees being hired so it can enroll them into the benefits system.\r\n\r\n```java\r\npublic static class BenefitsService {\r\n\r\n @OnEvent(NEW_HIRE_CHANNEL)\r\n public void enroll(final Employee employee) {\r\n\r\n System.out.printf(\"Employee enrolled into benefits system employee %s %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId());\r\n\r\n }\r\n\r\n```\r\n\r\nDaddy needs to get paid.\r\n\r\n```java\r\n public static class PayrollService {\r\n\r\n @OnEvent(PAYROLL_ADJUSTMENT_CHANNEL)\r\n public void addEmployeeToPayroll(final Employee employee, int salary) {\r\n\r\n System.out.printf(\"Employee added to payroll %s %d %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId(), salary);\r\n\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nThe employee is the employee object from the EmployeeHiringService.\r\n\r\nso you can get your benefits, and paid!\r\n\r\nFind more details here:\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\n\r\n## Private event bus and event bus proxies\r\n\r\n You can define your own interface to the event bus and you can use your own event buses with QBit.\r\n Each module in your service can have its own internal event bus.\r\n\r\n To learn more read:\r\n [QBit Microservice working with a private event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-private-event-bus-for-inproc-microservices)\r\n and [QBit Java Microservice lib using your own interface to the event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-strongly-typed-event-bus-proxies-for-QBit-Java-Microservice-lib).\r\n\r\n\r\n\r\n## Queue Callbacks\r\n\r\n To really grasp QBit, one must grasp the concepts of a CallBack.\r\n\r\n A CallBack is a way to get an async response in QBit.\r\n\r\n You call a service method and it calls you back.\r\n\r\n Client proxies can have callbacks:\r\n\r\n\r\n#### Queue Callbacks - RecommendationService client interface\r\n```java\r\n\r\npublic interface RecommendationServiceClient {\r\n\r\n\r\n void recommend(final Callback> recommendationsCallback,\r\n final String userName);\r\n}\r\n\r\n```\r\n\r\nCallbacks are Java 8 Consumers with some optional extra error handling.\r\n\r\n\r\n#### Queue Callbacks - Callback\r\n\r\n```java\r\n\r\n\r\npublic interface Callback extends java.util.function.Consumer {\r\n default void onError(java.lang.Throwable error) { /* compiled code */ }\r\n}\r\n\r\n```\r\n\r\nServices that can block should use callbacks.\r\nThus if loadUser blocked in the following example, it should really use a callback instead of returning a value.\r\n\r\npublic class RecommendationService {\r\n\r\n#### Queue Callbacks - Simple minded implementation of RecommendationService\r\n```java\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n public List recommend(final String userName) {\r\n User user = users.get(userName);\r\n if (user == null) {\r\n user = loadUser(userName);\r\n }\r\n return runRulesEngineAgainstUser(user);\r\n }\r\n\r\n```\r\n\r\n\r\nLet's pretend `loadUser` has to look in a local cache, and if the user is not found, look in an off-heap cache\r\nand if not found it must ask for the user from the UserService which must check its caches and perhaps fallback\r\nto loading the user data from a database or from other services.\r\nIn other words, `loadUser` can potentially block on IO.\r\n\r\n\r\n\r\n### Queue Callbacks - The first rule of Queue Club - don't block\r\n\r\n\r\nOur client does not block, but our service does. Going back to our `RecommendationService`.\r\nIf we get a lot of cache hits for user loads, perhaps the\r\nblock will not be that long, but it will be there and every time we have to fault in a user, the whole system\r\nis gummed up. What we want to be able to do is if we can't handle the recommendation request,\r\nwe go ahead and make an async call to the `UserDataService`. When that async callback comes back, then we\r\nhandle that request. In the mean time, we handle recommendation lists requests as quickly as we can.\r\nWe never block.\r\n\r\n\r\nSo let's revisit the service. The first thing we are going to do is make the service method take\r\na callback. Before we do that, let's set down some rules.\r\n\r\n\r\n#### The first rule of queue club don't block.\r\n#### The second rule of queue club if you are not ready, use a callback and continue handling stuff you are ready for\r\n\r\n\r\n#### Queue Callbacks - Adding a CallBack to the RecommendationService inproc microservice\r\n\r\n```java\r\npublic class RecommendationService {\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n```\r\n\r\n\r\n\r\nNow we are taking a callback and we can decide when we want to handle this recommendation generation request.\r\nWe can do it right away if there user data we need is in-memory or we can delay it.\r\n\r\n\r\n#### If the user is found, call the callback right away for RecommendationService inproc microservice\r\n\r\n```java\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n /** Look for user in user cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n ...\r\n } else {\r\n /* Call the callback now because we can handle the callback now. */\r\n recommendationsCallback.accept(runRulesEngineAgainstUser(user));\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nNotice, if the user is found in the cache, we run our recommendation rules in-memory and call the callback right away\r\n`recommendationsCallback.accept(runRulesEngineAgainstUser(user))`.\r\n\r\nThe interesting part is what do we do if don't have the user loaded.\r\n\r\n\r\n#### If the user was not found, load him from the user microservice, but still don't block\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using Callback. */\r\n userDataService.loadUser(new Callback() {\r\n @Override\r\n public void accept(final User loadedUser) {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nHere we use a CallBack to load the user, and when the user is loaded, we call `handleLoadFromUserDataService`\r\nwhich adds some management about handling the callback so we can still handle this call, just not now.\r\n\r\n\r\n\r\n#### Lambda version of last example\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using lambda expression. */\r\n userDataService.loadUser(\r\n loadedUser -> {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nUsing lambdas like this makes the code more readable and terse, but remember don't deeply nest\r\nlambda expressions or you will create a code maintenance nightmare. Use them judiciously.\r\n\r\n\r\n### Queue Callbacks - Doing something later\r\n\r\nWhat we want is to handle the request for recommendations after the user service system loads\r\nthe user from its store.\r\n\r\n\r\n\r\n#### Handling UserServiceData callback methods once we get them.\r\n\r\n```java\r\n\r\npublic class RecommendationService {\r\n\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n private UserDataServiceClient userDataService;\r\n\r\n\r\n private BlockingQueue callbacks =\r\n new ArrayBlockingQueue(10_000);\r\n\r\n\r\n ...\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n ...\r\n\r\n }\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks queue. */\r\n callbacks.add(new Runnable() {\r\n @Override\r\n public void run() {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n }\r\n });\r\n }\r\n\r\n\r\n\r\n```\r\n\r\n\r\n\r\n\r\n#### handleLoadFromUserDataService rewritten using Lambda\r\n\r\n```java\r\n\r\n\r\npublic class RecommendationService {\r\n\r\n...\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks list. */\r\n callbacks.add(() -> {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n });\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nThe important part there is that every time we get a callback call from `UserDataService`, we then\r\nperform our CPU intensive recommendation rules and callback our caller. Well not exactly, what we\r\ndo is enqueue an runnable onto our callbacks queue, and later we will iterate through those but when?\r\n\r\n\r\n### Queue Callbacks Handling callbacks when our receive queue is empty, a new batch started or we hit a batch limit\r\n\r\nThe `RecommendationService` can be notified when its queue is empty, it has started a new batch and when\r\nit has reached a batch limit. These are all good times to handle callbacks from the `UserDataService`.\r\n\r\n#### Draining our callback queue\r\n```java\r\n\r\n @QueueCallback({\r\n QueueCallbackType.EMPTY,\r\n QueueCallbackType.START_BATCH,\r\n QueueCallbackType.LIMIT})\r\n private void handleCallbacks() {\r\n\r\n flushServiceProxy(userDataService);\r\n Runnable runnable = callbacks.poll();\r\n\r\n while (runnable != null) {\r\n runnable.run();\r\n runnable = callbacks.poll();\r\n }\r\n }\r\n\r\n```\r\n\r\nIt is important to remember when handling callbacks from another microservice that you want to handle\r\ncallbacks from the other service before you handle more incomming requests from you clients.\r\nEssentially you have clients that have been waiting (async waiting but still), and these clients\r\nmight represent an open TCP/IP connection like an HTTP call so it is best to close them out\r\nbefore handling more requests and like we said they were already waiting around with an open connection\r\nfor users to load form the user service.\r\n\r\nTo learn more about CallBacks, plesae read [QBit Java MicroService Lib CallBack fundamentals]([Rough Cut] QBit Microservice Lib Working With CallBacks).\r\n\r\n\r\n\r\n\r\n## Workers - pools and shards\r\n\r\n```java\r\npublic class ServiceWorkers {\r\n\r\n public static RoundRobinServiceDispatcher workers() {...\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {...\r\n```\r\n\r\nYou can compose sharded workers (for in-memory, thread safe, CPU intensive services), or workers for IO\r\nor talking to foreign services or foreign buses.\r\n\r\nHere is an example that uses a worker pool with three service workers in it:\r\n\r\nLet's say you have a service that does something:\r\n\r\n```java\r\n\r\n //Your POJO\r\n public class MultiWorker {\r\n\r\n void doSomeWork(...) {\r\n ...\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nNow this does some sort of IO and you want to have a bank of these running not just one so you can do\r\nIO in parallel. After some performance testing, you found out that three is the magic number.\r\n\r\nYou want to use your API for accessing this service:\r\n\r\n```java\r\n public interface MultiWorkerClient {\r\n void doSomeWork(...);\r\n }\r\n\r\n```\r\n\r\nNow let's create a bank of these and use it.\r\n\r\nFirst create the QBit services which add the thread/queue/microbatch.\r\n\r\n```java\r\n\r\n /* Create a service builder. */\r\n final ServiceBuilder serviceBuilder = serviceBuilder();\r\n\r\n /* Create some qbit services. */\r\n final Service service1 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service2 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service3 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n```\r\n\r\nNow add them to a ServiceWorkers object.\r\n\r\n```java\r\n\r\n ServiceWorkers dispatcher;\r\n dispatcher = workers(); //Create a round robin service dispatcher\r\n dispatcher.addServices(service1, service2, service3);\r\n dispatcher.start(); // start up the workers\r\n\r\n```\r\n\r\nYou can add services, POJOs and method consumers, method dispatchers to a service bundle.\r\nThe service bundle is an integration point into QBit.\r\n\r\nLet's add our new Service workers. ServiceWorkers is a ServiceMethodDispatcher.\r\n\r\n```Java\r\n /* Add the dispatcher to a service bundle. */\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nWe are probably going to add a helper method to the service bundle so most of this can happen in\r\na single call.\r\n\r\nNow you can start using your workers.\r\n\r\n```java\r\n\r\n /* Start using the workers. */\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n```\r\n\r\nNow you could use Spring or Guice to configure the builders and the service bundle.\r\nBut you can just do it like the above which is good for testing and understanding QBit internals.\r\n\r\nQBit also supports the concept of sharded services which is good for sharding resources like CPU\r\n(run a rules engine on each CPU core for a user recommendation engine).\r\n\r\nQBit does not know how to shard your services, you have to give it a hint.\r\nYou do this through a shard rule.\r\n\r\n```java\r\npublic interface ShardRule {\r\n int shard(String methodName, Object[] args, int numWorkers);\r\n}\r\n```\r\nWe worked on an app where the first argument to the services was the username, and then we used that to\r\nshard calls to a CPU intensive in-memory rules engine. This technique works. :)\r\n\r\nThe ServiceWorkers class has a method for creating a sharded worker pool.\r\n\r\n```java\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nTo use you just pass a shard key when you create the service workers.\r\n\r\n```java\r\n\r\n\r\n dispatcher = shardedWorkers((methodName, methodArgs, numWorkers) -> {\r\n String userName = methodArgs[0].toString();\r\n int shardKey = userName.hashCode() % numWorkers;\r\n return shardKey;\r\n });\r\n\r\n```\r\n\r\nThen add your services to the ServiceWorkers composition.\r\n```java\r\n int workerCount = Runtime.getRuntime().availableProcessors();\r\n\r\n for (int index = 0; index < workerCount; index++) {\r\n final Service service = serviceBuilder\r\n .setServiceObject(new ContentRulesEngine()).build();\r\n dispatcher.addServices(service);\r\n\r\n }\r\n```\r\n\r\nThen add it to the service bundle as before.\r\n```java\r\n\r\n dispatcher.start();\r\n\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nThen just use it:\r\n\r\n```java\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n for (int index = 0; index < 100; index++) {\r\n String userName = \"rickhigh\" + index;\r\n worker.pickSuggestions(userName);\r\n }\r\n\r\n```\r\n\r\n### Built in shard rules\r\n\r\n```java\r\n\r\n\r\npublic class ServiceWorkers {\r\n...\r\n public static ShardedMethodDispatcher shardOnFirstArgumentWorkers() {\r\n ...\r\n }\r\n\r\n...\r\n\r\n public static ShardedMethodDispatcher shardOnFifthArgumentWorkers() {\r\n ...\r\n }\r\n\r\n\r\n public static ShardedMethodDispatcher shardOnBeanPath(final String beanPath) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nThe shardOnBeanPath allows you to create a complex bean path navigation call and use its property to shard on.\r\n\r\n```java\r\n\r\n /* shard on 2nd arg which is an employee\r\n Use the employees department's id property. */\r\n dispatcher = shardOnBeanPath(\"[1].department.id\");\r\n\r\n /* Same as above. */\r\n dispatcher = shardOnBeanPath(\"1/department/id\");\r\n\r\n```\r\n\r\n[Read more about Service sharding and service workers here](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-QBit-Microservices-using-Service-Workers-and-sharded-service-workers)\r\n\r\n\r\nYou can find a lot more in the wiki. Also follow the commits.\r\nWe have been busy beavers.\r\n[QBit the microservice lib for Java - JSON, REST, WebSocket](https://github.com/advantageous/qbit/wiki).",
"note": "Don't delete this file! It's used internally to help with page regeneration."
}
\ No newline at end of file
From 7aa26d96ff743162301d21e0959d42139ecedd5e Mon Sep 17 00:00:00 2001
From: Richard Hightower
Date: Fri, 15 Apr 2016 08:02:25 -0700
Subject: [PATCH 07/19] Create gh-pages branch via GitHub
---
index.html | 2 +-
params.json | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/index.html b/index.html
index f1248264..7d864771 100644
--- a/index.html
+++ b/index.html
@@ -20,7 +20,7 @@
The Java microservice lib. QBit is a reactive progra
QBit - The Microservice Lib for Java - JSON, REST, WebSocket, Speed!
diff --git a/params.json b/params.json
index 719fcf7e..afb867d9 100644
--- a/params.json
+++ b/params.json
@@ -1,6 +1,6 @@
{
"name": "QBit - Microservices Lib",
"tagline": "The Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.",
- "body": "[QBit Java Micorservices lib tutorials](https://github.com/MammatusTech/qbit-microservices-examples/wiki)|\r\n[QBit Website](http://advantageous.github.io/qbit/) | [QBit uses Reakt](http://advantageous.github.io/reakt/) | [QBit works with Vert.x](http://vertx.io/) | [Reakt Vertx](http://advantageous.github.io/reakt-vertx/\r\n\r\n#QBit - The Microservice Lib for Java - JSON, REST, WebSocket, Speed! \r\n\r\n## Quick overview of QBit\r\n\r\nThe Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.\r\n\r\nGot a question? Ask here: [QBit Google Group](https://groups.google.com/forum/#!forum/qbit-microservice).\r\n\r\nEverything is a queue. You have a choice. You can embrace it and control it. You can optimize for it.\r\nOr you can hide behind abstractions. QBit opens you up to peeking into what is going on, and allows you\r\nto pull some levers without selling your soul.\r\n\r\nQBit is a library not a framework. You can mix and match QBit with Spring, Guice, etc.\r\n\r\nQBit is FAST!\r\n\r\n\r\n\r\n#### Using from maven\r\n```xml\r\n\r\n io.advantageous.qbit\r\n qbit-admin\r\n 1.0.0.RELEASE\r\n\r\n\r\n io.advantageous.qbit\r\n qbit-vertx\r\n 1.0.0.RELEASE\r\n\r\n```\r\n\r\n#### Using from gradle\r\n```java\r\ncompile 'io.advantageous.qbit:qbit-admin:1.0.0.RELEASE'\r\ncompile 'io.advantageous.qbit:qbit-vertx:1.0.0.RELEASE'\r\n```\r\n\r\nCore Features\r\n============\r\n\r\n* Write REST based async microservices\r\n* Write ***WebSocket*** based async microservices (fast async RPC over WebSocket)\r\n* Actor Service Queues using micro-batching for high-speed message passing\r\n* Strongly async typed event bus which can be distributed\r\n* Async low overhead metrics gathering which can be queried and distributed (for doing fast lane analytics)\r\n* Complex async call coordination (with the Reactor) for reactive programming\r\n* Built-in support for ***health checks*** (and integration with tools like Consul)\r\n* Built-in support for ***monitoring*** (and integration with wire protocols like StatsD)\r\n* Built-in support for ***Service Discovery*** (with integration with health system, DNS SRV records and Consul)\r\n* Integration with persistent queues\r\n* [12 factor app port bindings](http://12factor.net/), health checks, KPI gathering, Logging MDC\r\n* API Gateway support for client generation and consumption via [Swagger](http://swagger.io/).\r\n* Our services can generate Swagger files (like idl for JSON/REST).\r\n* Remote client proxies for WebSocket (your interface is your IDL)\r\n\r\n\r\nStatus\r\n=====\r\nDeployed at several large fortune 100 companies. \r\nQBit now works with Vertx (standalone or embedded).\r\nYou can also use QBit on non-QBit projects, it is just a lib.\r\n\r\nLicense\r\n=====\r\nApache 2\r\n\r\n\r\n## Java Microservice Lib\r\n\r\nQBit has inproc services, REST microservices and WebSocket microservices as well as an\r\nin-proc service event bus (which can be per module or per app). It supports workers and in-memory services.\r\n\r\nBefore we describe more, here are two sample services:\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {...\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {...\r\n```\r\n\r\n\r\n#### Adder Service using URI params\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {...\r\n }\r\n```\r\n\r\n\r\n\r\nQBit philosophy:\r\n====\r\nAt the end of the day QBit is a simple library not a framework.\r\nYour app is not a QBit app but a Java app that uses the QBit lib.\r\nQBit allows you to work with Java UTIL concurrent, and does not endeavor to hide it from you.\r\nJust trying to take the sting out of it.\r\n\r\nDoes it work\r\n=====\r\nWe have used techniques in Boon and QBit with great success in high-end, high-performance, high-scalable apps.\r\nWe helped clients handle 10x the load with 1/10th the servers of their competitors using techniques in QBit.\r\nQBit is us being sick of hand tuning queue access and threads.\r\n\r\n\r\nBoon and QBit humility policy\r\n=====\r\nIdeas for Boon and QBit often come from all over the web. We make mistakes. Point them out.\r\nAs a developer of Boon and QBit, we are fellow travelers.\r\nIf you have an idea or technique you want to share, we listen.\r\n\r\n\r\nInspiration\r\n====\r\n\r\nA big inspiration for Boon/QBit was Vertx, Akka, Go Channels, Active Objects, Apartment Model Threading, Actor,\r\nand the Mechanical Sympathy papers.\r\n\r\nQBit has ideas that are similar to many frameworks. We are all reading the same papers.\r\nQBit got inspiration from the LMAX disruptor papers and this blog post about\r\n[link transfer queue versus disruptor](http://php.sabscape.com/blog/?p=557). We had some theories about\r\nqueues that blog post inspired us to try them out. Some of these theories are deployed at some of the\r\nbiggest middleware backends and whose name brands are known around the world. And thus QBit was born.\r\n\r\nQBit also took an lot of inspiration by the great work done\r\nby Tim Fox on Vertx. The first project using something that could actually be called QBit (albeit early QBit)\r\n was using Vertx on an web/mobile microservice for an app that could potentially have 80 million users.\r\n It was this\r\nexperience with Vertx and early QBit that led to QBit development and evolution. QBit is built on the\r\nshoulders of giants (Netty/Vertx).\r\n\r\nDoes QBit compete with...\r\n====\r\nSpring Disruptor: No. You could use QBit to write plugins for Spring Disruptor I suppose, but QBit does\r\nnot compete with Spring Disruptor.\r\nSpring Boot/Spring MVC: No. We use the same annotations but QBit is geared for high-speed in-memory\r\nmicroservices. It is more like Akka than Spring Boot. QBit has a subset of the features of Spring MVC\r\ngeared only for microservices, i.e., WebSocket RPC, REST, JSON marshaling, etc.\r\nAkka: No. Well Maybe. Akka has similar concepts but they take a different approach. QBit is more focused\r\n on Java, and microservices (REST, JSON, WebSocket) than Akka.\r\nLMAX Disruptor: No. In fact, we can use disruptor as on of the queues that QBit uses underneath the covers.\r\n\r\n\r\n(Early benchmarks have been removed. They were here. QBit got a lot faster.\r\n Benchmarking QBit is a moving target at the moment.\r\n Links and reports will be created.)\r\n\r\n\r\nCode Examples\r\n\r\n\r\n## Basic Queue example (REST style services is further down)\r\n\r\n====\r\n\r\n```java\r\n\r\n BasicQueue queue = BasicQueue.create(Integer.class, 1000);\r\n\r\n //Sending threads\r\n\r\n SendQueue sendQueue = queue.sendQueue();\r\n for (int index = 0; index < amount; index++) {\r\n sendQueue.send(index);\r\n }\r\n sendQueue.flushSends();\r\n ...\r\n sendQueue.sendAndFlush(code);\r\n //other methods for sendQueue, writeBatch, writeMany\r\n\r\n\r\n //Receiving Threads\r\n ReceiveQueue receiveQueue = queue.receiveQueue();\r\n Integer item = receiveQueue.take();\r\n //other methods poll(), pollWait(), readBatch(), readBatch(count)\r\n```\r\n\r\n\r\n### What is QBit again?\r\n\r\nQBit is a queuing library for microservices. It is similar to many other projects like Akka, Spring Reactor,\r\netc. QBit is just a library not a platform. QBit has libraries to put a service behind a queue.\r\nYou can use QBit queues directly or you can create a service. QBit services can be exposed by WebSocket,\r\nHTTP, HTTP pipeline, and other types of remoting. A service in QBit is a Java class whose methods are\r\n executed behind service queues. QBit implements apartment model threading and is similar to the\r\n Actor model or a better description would be Active Objects. QBit does not use a disruptor (but could).\r\n It uses regular Java Queues. QBit can do north of 100 million ping pong calls per second which is\r\n an amazing speed (seen as high as 200M). QBit also supports calling services via REST, and WebSocket.\r\n QBit is microservices in the pure Web sense: JSON, HTTP, WebSocket, etc. QBit uses micro batching to\r\n push messages through the pipe (queue, IO, etc.) faster to reduce thread hand-off.\r\n\r\n### QBit lingo\r\n\r\nQBit is a Java microservice lib supporting REST, JSON and WebSocket. It is written in Java but we could\r\none day write a version in Rust or Go or C# (but that would require a large payday).\r\n\r\n**Service**\r\nPOJO (plain old Java object) behind a queue that can receive method calls via proxy calls or events\r\n(May have one thread managing events, method calls, and responses or two one for method calls and events\r\n 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.\r\n\r\n**ServiceBundle**\r\nMany POJOs behind one response queue and many receive queues. There may be one thread for all responses\r\nor not. They also can be one receive queue.\r\n\r\n**Queue**\r\nA thread managing a queue. It supports batching. It has events for empty, reachedLimit, startedBatch,\r\nidle. You can listen to these events from services that sit behind a queue. You don't have to use Services.\r\nYou can use Queue's direct. In QBit, you have sender queues and receivers queues. They are separated to\r\nsupport micro-batching.\r\n\r\n**ServiceEndpointServer**\r\nServiceBundle that is exposed to REST and WebSocket communication.\r\n\r\n**EventBus**\r\nEventBus is a way to send a lot of messages to services that may be loosely coupled.\r\n\r\n**ClientProxy**\r\nClientProxy is a way to invoke service through async interface, service can be inproc (same process) or\r\nremoted over WebSocket.\r\n\r\n**Non-blocking**\r\nQBit is a non-blocking lib. You use CallBacks via Java 8 Lambdas. You can also send event messages and get\r\nreplies. Messaging is built into the system so you can easily coordinate complex tasks.\r\nQBit takes an object-oriented approach to service development so services look like normal Java services\r\nthat you\r\nalready write, but the services live behind a queue/thread. This is not a new concept. Microsoft did this\r\nwith DCOM/COM and called it active objects. Akka does it with actors and called them strongly typed Actors.\r\nThe important concepts is that you get the speed of reactive and actor style messaging but you develop\r\nin a natural OOP approach. QBit is not the first. QBit is not the only.\r\n\r\n\r\n**Speed**\r\nQBit is VERY fast. There is a of course a lot of room for improvement. But already 200M+ TPS inproc ping pong, 10M-20M+ TPS event bus, 500K TPS RPC calls over WebSocket/JSON, etc.\r\nMore work needs to be done to improve speed, but now it is fast enough where we are focusing more on\r\nusability.\r\nThe JSON support uses Boon by default which is up to 4x faster than other JSON parsers for the\r\nREST/JSON, WebSocket/JSON use case.\r\n\r\n**Reactive Programming**\r\nQBit provides a **Reactor** to manage async calls. This allows callbacks to be handled on the same thread that called them and it provides for timeout and error handling. Read [Reactor tutorial for creating reactive micro service programming](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices)\r\n\r\n**Service Discovery**\r\nBuilt in support for service discovery. This includes integration with Consul.\r\n\r\n\r\n**StatService**\r\nBuilt in support for stats. The **StatService** can be integrated with **StatsD** (Graphite, Grafana, DataDog, etc.) to publish passive stats. Or you can query the stats engine and react to the stats (counts, timings and levels). The **StatsService** is a reactive stats system that can be clustered. The StatService is reactive in that your services can publish to it and query it and react based on the results. You can implement things like rate limiting and react to an increased rate of something. The ServiceDiscovery system integrates with the HealthSystem and Consul to roll up each of your internal services that make up you micro service and publish the composite availably of your micro service to a single HTTP endpoint or a dead mans switch in Consul (TTL). \r\n\r\n\r\n\r\n### CURLable REST services example\r\n\r\nTalk is cheap. Let's look at some code. You can get a detailed walk through in the Wiki.\r\nWe have a lot of documentation already.\r\n\r\nWe will create a service that is exposed through REST/JSON.\r\n\r\nTo query the size of the todo list:\r\n\r\n```bash\r\ncurl localhost:8080/services/todo-service/todo/count\r\n```\r\n\r\nTo add a new TODO item.\r\n\r\n```bash\r\ncurl -X POST -H \"Content-Type: application/json\" -d \\\r\n'{\"name\":\"xyz\",\"description\":\"xyz\"}' \\\r\nhttp://localhost:8080/services/todo-service/todo\r\n```\r\n\r\nTo get a list of TODO items\r\n```bash\r\ncurl http://localhost:8080/services/todo-service/todo/\r\n```\r\n\r\nThe TODO example will use and track Todo items.\r\n\r\n#### Todo item POJO sans getter\r\n\r\n```java\r\npackage io.advantageous.qbit.examples;\r\n\r\nimport java.util.Date;\r\n\r\n\r\npublic class TodoItem {\r\n\r\n\r\n private final String description;\r\n private final String name;\r\n private final Date due;\r\n\r\n```\r\n\r\nThe TodoService uses Spring MVC style annotations.\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n\r\n private List todoItemList = new ArrayList<>();\r\n\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {\r\n\r\n return todoItemList.size();\r\n }\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {\r\n\r\n return todoItemList;\r\n }\r\n\r\n @RequestMapping(value = \"/todo\", method = RequestMethod.POST)\r\n public void add(TodoItem item) {\r\n\r\n todoItemList.add(item);\r\n }\r\n\r\n}\r\n\r\n```\r\n\r\n\r\n#### Sending non-JSON\r\n\r\nYou can POST/PUT non-JSON and you can capture the body as a `String` or as a `byte[]`. \r\nIf the content-type is set to anything but `application/json` and your body is defined a String or byte[].\r\nThis works automatically. (The content-type has to be set.)\r\n\r\n```java\r\n @RequestMapping(value = \"/body/bytes\", method = RequestMethod.POST)\r\n public boolean bodyPostBytes( byte[] body) {\r\n String string = new String(body, StandardCharsets.UTF_8);\r\n return string.equals(\"foo\");\r\n }\r\n\r\n @RequestMapping(value = \"/body/string\", method = RequestMethod.POST)\r\n public boolean bodyPostString(String body) {\r\n return body.equals(\"foo\");\r\n }\r\n```\r\n\r\n\r\n#### Sending different response codes for success\r\n\r\nBy default QBit sends a `200` (OK) for a non-void call (a call that has a return or a Callback). If the REST operation has no return or no callback then QBit sends a `202` (Accepted). There may be times when you want to send a 201 (Created) or some other code that is not an Exception. You can do that by setting `code` on `@RequestMapping`. By default the code is -1 which means use the default behavior (200 for success, 202 for one-way message, and 500 for errors).\r\n\r\n\r\n#### Sending different response codes for success\r\n```java\r\n\r\n @RequestMapping(value = \"/helloj7\", code = 221)\r\n public void helloJSend7(Callback>> callback) {\r\n callback.returnThis(JSendResponseBuilder.jSendResponseBuilder(Lists.list(\r\n \"hello \" + System.currentTimeMillis())).build());\r\n }\r\n\r\n```\r\n\r\n`Callbacks` can be used for internal services as well. It is often the case that you use a [CallbackBuilder](https://github.com/advantageous/qbit/wiki/%5BDocument%5D-CallbackBuilder-and-generics-for-Reactive-Java-Microservices) or a QBit [Reactor](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices) to manage service calls. \r\n\r\n#### Working with non JSON responses\r\n\r\nYou do not have to return JSON form rest calls.\r\nYou can return any binary or any text by using `HttpBinaryResponse` and `HttpTextResponse`.\r\n\r\n#### Returning non JSON from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildTextResponse());\r\n }\r\n```\r\n\r\n\r\n#### Returning binary from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildBinaryResponse());\r\n }\r\n```\r\n\r\n#### Side note Why Spring style annotations?\r\nWhy did we pick Spring style annotations?\r\n1) Spring is not a standard and neither is QBit. 2) We found the Spring annotations to be less verbose.\r\n3) More people use Spring than Java EE. We wrote QBit for people to use.\r\nWe could easily support JAX-RS style annotations, and we probably will.\r\nSince QBit focuses on JSON, we do not need all of the complexity of JAX-RS or even all the features of\r\nthe Spring MVC annotations. Also we can literally use the actual Spring annotations. QBit and Boon\r\nuse a non-type safe mechanism for annotations which means they are not tied to a particular lib.\r\nYou can define your own. We hate vendor tie-in even if it is an open source vendor.\r\n(We also support @POST, @GET which is similar to JAX-RS).\r\n\r\nNow just start it up.\r\n\r\n```java\r\n\r\n public static void main(String... args) {\r\n\r\n ServiceEndpointServer server = new EndpointServerBuilder().build();\r\n server.initServices(new TodoService());\r\n server.start();\r\n }\r\n```\r\n\r\n\r\n\r\nThat is it. There is also out of the box WebSocket support with client side proxy generation so\r\nyou can call into services at the rate of millions of calls per second.\r\n\r\n## Using URI Params for QBit microservice\r\n\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {\r\n\r\n return a + b;\r\n }\r\n }\r\n\r\n```\r\n\r\n## WebSocket\r\nYou can always invoke QBit services via a WebSocket proxy.\r\nThe advantage of a WebSocket proxy is it allows you execute 1M RPC+ a second (1 million remote calls\r\nevery second).\r\n\r\n\r\n#### Using a microservice remotely with WebSocket\r\n```java\r\n /* Start QBit client for WebSocket calls. */\r\n final Client client = clientBuilder()\r\n .setPort(7000).setRequestBatchSize(1).build();\r\n\r\n\r\n /* Create a proxy to the service. */\r\n final AdderServiceClientInterface adderService =\r\n client.createProxy(AdderServiceClientInterface.class,\r\n \"adder-service\");\r\n\r\n client.start();\r\n\r\n\r\n\r\n /* Call the service */\r\n adderService.add(System.out::println, 1, 2);\r\n\r\n```\r\n\r\nThe output is 3.\r\n\r\n```output\r\n3\r\n```\r\n\r\n\r\nThe above uses a WebSocket proxy interface to call the service async.\r\n\r\n```java\r\n\r\n interface AdderServiceClientInterface {\r\n\r\n void add(Callback callback, int a, int b);\r\n }\r\n```\r\n\r\n#### ServiceDiscovery aware websocket builders\r\n\r\nCreate websocket service client that is ServiceDiscovery aware.\r\n\r\n\r\n```java\r\n final Client client = clientBuilder.setServiceDiscovery(serviceDiscovery, \"echo\")\r\n .setUri(\"/echo\").setProtocolBatchSize(20).build().startClient();\r\n\r\n\r\n final EchoAsync echoClient = client.createProxy(EchoAsync.class, \"echo\");\r\n```\r\n\r\nCurrently the `clientBuilder` will load all service endpoints that are registered under the service name,\r\nand randomly pick one. \r\n\r\nServiceDiscovery includes Consul based, watching JSON files on disk, and DNS. It is easy to write your own service discovery as well and plug it into QBit.\r\n\r\n\r\nIn the future we can RoundRobin calls or shard calls to websocket service and/or provide auto fail over if the connection is closed. We do this for the event bus that uses service discovery but it is not baked into WebSocket based client stubs yet.\r\n\r\n\r\n## REST call with URI params\r\n\r\nThe last client example uses WebSocket. You could also just use REST, and actually use the URI params\r\nthat we setup.\r\nREST is nice but it is going to be slower than WebSocket support.\r\n\r\nQBit ships with a nice little HTTP client. We can use it.\r\n\r\nYou can use it to send async calls and WebSocket messages with the HTTP client.\r\n\r\n\r\nHere we will use the http client to invoke our remote method:\r\n\r\n#### Using a microservice remotely with REST QBit microservice client\r\n```java\r\n\r\n\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\")\r\n .setPort(7000).build();\r\n\r\n httpClient.start();\r\n String results = httpClient\r\n .get(\"/services/adder-service/add/2/2\").body();\r\n System.out.println(results);\r\n\r\n```\r\n\r\n\r\nThe output is 4.\r\n\r\n```output\r\n4\r\n```\r\n\r\n## Accessing The URI Param example with CURL\r\n\r\nYou can also access the service from curl.\r\n\r\n```bash\r\n$ curl http://localhost:7000/services/adder-service/add/2/2\r\n```\r\n\r\nSee this full example here: [QBit microservice getting started tutorial](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-------------QBit-microservice-example).\r\n\r\n[QBit URI params and WebSocket proxy client](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Using-QBit-microservice-lib's-REST-support-with-URI-Params)\r\n\r\n## Working with WebSocket, HttpClient etc.\r\n\r\nQBit has a library for working with and writing async microservices that is lightweight and fun to use.\r\n\r\n#### WebSocket server and client.\r\n\r\n\r\n#### Create an HTTP server\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n```\r\n\r\n#### Setup server WebSocket support\r\n```java\r\n /* Setup WebSocket Server support. */\r\n httpServer.setWebSocketOnOpenConsumer(webSocket -> {\r\n webSocket.setTextMessageConsumer(message -> {\r\n webSocket.sendText(\"ECHO \" + message);\r\n });\r\n });\r\n\r\n```\r\n\r\n#### Start the server\r\n```java\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n```\r\n\r\n#### Setup the WebSocket client\r\n```java\r\n\r\n /** CLIENT. */\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\n#### Client WebSocket\r\n\r\n```java\r\n\r\n /* Setup the client websocket. */\r\n WebSocket webSocket = httpClient\r\n .createWebSocket(\"/websocket/rocket\");\r\n\r\n /* Setup the text consumer. */\r\n webSocket.setTextMessageConsumer(message -> {\r\n System.out.println(message);\r\n });\r\n webSocket.openAndWait();\r\n\r\n /* Send some messages. */\r\n webSocket.sendText(\"Hi mom\");\r\n webSocket.sendText(\"Hello World!\");\r\n\r\n```\r\n\r\n#### Output\r\n```output\r\n\r\nECHO Hi mom\r\nECHO Hello World!\r\n\r\n```\r\n\r\nNow stop the server and client. Pretty easy eh?\r\n\r\n## High-speed HTTP client and server done microservice style\r\n\r\n\r\n##### Starting up an HTTP server\r\n\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n /* Setting up a request Consumer with Java 8 Lambda expression. */\r\n httpServer.setHttpRequestConsumer(httpRequest -> {\r\n\r\n Map results = new HashMap<>();\r\n results.put(\"method\", httpRequest.getMethod());\r\n results.put(\"uri\", httpRequest.getUri());\r\n results.put(\"body\", httpRequest.getBodyAsString());\r\n results.put(\"headers\", httpRequest.getHeaders());\r\n results.put(\"params\", httpRequest.getParams());\r\n httpRequest.getReceiver()\r\n .response(200, \"application/json\", Boon.toJson(results));\r\n });\r\n\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n\r\n\r\n```\r\n\r\nThe focus is on ease of use and using Java 8 Lambdas for callbacks so the code is tight and small.\r\n\r\n[Find out more about QBit's microservice style WebSocket support here](https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-WebSocket-support)\r\n\r\n\r\n## Using HTTP Client lib\r\n\r\nNow, let's try out our HTTP client.\r\n\r\n##### Starting up an HTTP client\r\n\r\n```java\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\nYou just pass the URL, the port and then call start.\r\n\r\n## Synchronous HTTP calls\r\n\r\nNow you can start sending HTTP requests.\r\n\r\n##### No Param HTTP GET\r\n\r\n```java\r\n /* Send no param get. */\r\n HttpResponse httpResponse = httpClient.get( \"/hello/mom\" );\r\n puts( httpResponse );\r\n```\r\n\r\nAn HTTP response just contains the results from the server.\r\n\r\n\r\n##### No Param HTTP Response\r\n\r\n```java\r\npublic interface HttpResponse {\r\n\r\n MultiMap headers();\r\n\r\n int code();\r\n\r\n String contentType();\r\n\r\n String body();\r\n\r\n}\r\n\r\n```\r\n\r\nThere are helper methods for sync HTTP GET calls.\r\n\r\n\r\n\r\n##### Helper methods for GET\r\n```java\r\n\r\n\r\n /* Send one param get. */\r\n httpResponse = httpClient.getWith1Param(\"/hello/singleParam\",\r\n \"hi\", \"mom\");\r\n puts(\"single param\", httpResponse );\r\n\r\n\r\n /* Send two param get. */\r\n httpResponse = httpClient.getWith2Params(\"/hello/twoParams\",\r\n \"hi\", \"mom\", \"hello\", \"dad\");\r\n puts(\"two params\", httpResponse );\r\n\r\n...\r\n\r\n /* Send five param get. */\r\n httpResponse = httpClient.getWith5Params(\"/hello/5params\",\r\n \"hi\", \"mom\",\r\n \"hello\", \"dad\",\r\n \"greetings\", \"kids\",\r\n \"yo\", \"pets\",\r\n \"hola\", \"neighbors\");\r\n puts(\"5 params\", httpResponse );\r\n\r\n\r\n```\r\n\r\nThe puts method is a helper method it does System.out.println more or less by the way.\r\n\r\nThe first five params are covered. Beyond five, you have to use the HttpBuilder.\r\n\r\n```java\r\n\r\n\r\n /* Send six params with get. */\r\n\r\n final HttpRequest httpRequest = httpRequestBuilder()\r\n .addParam(\"hi\", \"mom\")\r\n .addParam(\"hello\", \"dad\")\r\n .addParam(\"greetings\", \"kids\")\r\n .addParam(\"yo\", \"pets\")\r\n .addParam(\"hola\", \"pets\")\r\n .addParam(\"salutations\", \"all\").build();\r\n\r\n httpResponse = httpClient.sendRequestAndWait(httpRequest);\r\n puts(\"6 params\", httpResponse );\r\n```\r\n\r\n## Http Async HTTP Client\r\n\r\nThere are async calls for GET as well.\r\n\r\n#### Async calls for HTTP GET using Java 8 lambda\r\n\r\n```java\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsync(\"/hi/async\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith1Param(\"/hi/async\", \"hi\", \"mom\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda 1 param\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith2Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 2 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n...\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith5Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n \"p3\", \"v3\",\r\n \"p4\", \"v4\",\r\n \"p5\", \"v5\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 5 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n```\r\n\r\n[Find more about the easy to use, fast microservice HTTP client here]\r\n(https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-HttpClient-GET,-POST,-et-al,-JSON,-Java-8-Lambda).\r\n\r\n## InProc QBit services\r\n\r\nQBit allows for services behind queues to be run in-proc as well.\r\n\r\n```java\r\n\r\n /* POJO service. */\r\n final TodoManager todoManagerImpl = new TodoManager();\r\n\r\n /*\r\n Create the service which manages async calls to todoManagerImpl.\r\n */\r\n final Service service = serviceBuilder()\r\n .setServiceObject(todoManagerImpl)\r\n .build().startServiceQueue();\r\n\r\n\r\n /* Create Asynchronous proxy over Synchronous service. */\r\n final TodoManagerClientInterface todoManager =\r\n service.createProxy(TodoManagerClientInterface.class);\r\n\r\n service.startCallBackHandler();\r\n\r\n\r\n System.out.println(\"This is an async call\");\r\n /* Asynchronous method call. */\r\n todoManager.add(new Todo(\"Call Mom\", \"Give Mom a call\"));\r\n\r\n\r\n AtomicInteger countTracker = new AtomicInteger();\r\n //Hold count from async call to service... for testing and showing it is an async callback\r\n\r\n System.out.println(\"This is an async call to count\");\r\n\r\n todoManager.count(count -> {\r\n System.out.println(\"This lambda expression is the callback \" + count);\r\n\r\n countTracker.set(count);\r\n });\r\n\r\n\r\n todoManager.clientProxyFlush(); //Flush all methods. It batches calls.\r\n\r\n Sys.sleep(100);\r\n\r\n System.out.printf(\"This is the count back from the server %d\\n\", countTracker.get());\r\n\r\n```\r\n\r\n[Detailed tutorial on in-proc services is being written.](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-Working-with-inproc-MicroServices-within-QBit.)\r\n\r\n\r\n## QBit Event Bus\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\nQBit also has a service event bus. This example is a an employee benefits services example.\r\n\r\nWe have two channels.\r\n\r\n```\r\npublic static final String NEW_HIRE_CHANNEL = \"com.mycompnay.employee.new\";\r\n\r\npublic static final String PAYROLL_ADJUSTMENT_CHANNEL = \"com.mycompnay.employee.payroll\";\r\n```\r\n\r\nAn employee object looks like this:\r\n\r\n```java\r\n\r\npublic static class Employee {\r\n final String firstName;\r\n final int employeeId;\r\n```\r\n\r\n\r\nThis example has three services: EmployeeHiringService, BenefitsService, and PayrollService.\r\n\r\nThese services are inproc services. QBit supports WebSocket, HTTP and REST remote services as well, but for now, let's focus on inproc services. If you understand inproc then you will understand remote.\r\n\r\nThe EmployeeHiringService actually fires off the events to other two services.\r\n\r\n```java\r\npublic class EmployeeHiringService {\r\n\r\n\r\n public void hireEmployee(final Employee employee) {\r\n\r\n int salary = 100;\r\n System.out.printf(\"Hired employee %s\\n\", employee);\r\n\r\n //Does stuff to hire employee\r\n\r\n //Sends events\r\n final EventManager eventManager =\r\n serviceContext().eventManager();\r\n eventManager.send(NEW_HIRE_CHANNEL, employee);\r\n\r\n eventManager.sendArray(PAYROLL_ADJUSTMENT_CHANNEL,\r\n employee, salary);\r\n\r\n\r\n }\r\n\r\n }\r\n```\r\n\r\n\r\nNotice that we call sendArray so we can send the employee and their salary.\r\nThe listener for PAYROLL_ADJUSTMENT_CHANNEL will have to handle both an employee and an int\r\nthat represents the new employees salary.\r\nYou can also use event bus proxies so you do not have to call into the event bus at all.\r\n\r\nThe BenefitsService listens for new employees being hired so it can enroll them into the benefits system.\r\n\r\n```java\r\npublic static class BenefitsService {\r\n\r\n @OnEvent(NEW_HIRE_CHANNEL)\r\n public void enroll(final Employee employee) {\r\n\r\n System.out.printf(\"Employee enrolled into benefits system employee %s %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId());\r\n\r\n }\r\n\r\n```\r\n\r\nDaddy needs to get paid.\r\n\r\n```java\r\n public static class PayrollService {\r\n\r\n @OnEvent(PAYROLL_ADJUSTMENT_CHANNEL)\r\n public void addEmployeeToPayroll(final Employee employee, int salary) {\r\n\r\n System.out.printf(\"Employee added to payroll %s %d %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId(), salary);\r\n\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nThe employee is the employee object from the EmployeeHiringService.\r\n\r\nso you can get your benefits, and paid!\r\n\r\nFind more details here:\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\n\r\n## Private event bus and event bus proxies\r\n\r\n You can define your own interface to the event bus and you can use your own event buses with QBit.\r\n Each module in your service can have its own internal event bus.\r\n\r\n To learn more read:\r\n [QBit Microservice working with a private event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-private-event-bus-for-inproc-microservices)\r\n and [QBit Java Microservice lib using your own interface to the event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-strongly-typed-event-bus-proxies-for-QBit-Java-Microservice-lib).\r\n\r\n\r\n\r\n## Queue Callbacks\r\n\r\n To really grasp QBit, one must grasp the concepts of a CallBack.\r\n\r\n A CallBack is a way to get an async response in QBit.\r\n\r\n You call a service method and it calls you back.\r\n\r\n Client proxies can have callbacks:\r\n\r\n\r\n#### Queue Callbacks - RecommendationService client interface\r\n```java\r\n\r\npublic interface RecommendationServiceClient {\r\n\r\n\r\n void recommend(final Callback> recommendationsCallback,\r\n final String userName);\r\n}\r\n\r\n```\r\n\r\nCallbacks are Java 8 Consumers with some optional extra error handling.\r\n\r\n\r\n#### Queue Callbacks - Callback\r\n\r\n```java\r\n\r\n\r\npublic interface Callback extends java.util.function.Consumer {\r\n default void onError(java.lang.Throwable error) { /* compiled code */ }\r\n}\r\n\r\n```\r\n\r\nServices that can block should use callbacks.\r\nThus if loadUser blocked in the following example, it should really use a callback instead of returning a value.\r\n\r\npublic class RecommendationService {\r\n\r\n#### Queue Callbacks - Simple minded implementation of RecommendationService\r\n```java\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n public List recommend(final String userName) {\r\n User user = users.get(userName);\r\n if (user == null) {\r\n user = loadUser(userName);\r\n }\r\n return runRulesEngineAgainstUser(user);\r\n }\r\n\r\n```\r\n\r\n\r\nLet's pretend `loadUser` has to look in a local cache, and if the user is not found, look in an off-heap cache\r\nand if not found it must ask for the user from the UserService which must check its caches and perhaps fallback\r\nto loading the user data from a database or from other services.\r\nIn other words, `loadUser` can potentially block on IO.\r\n\r\n\r\n\r\n### Queue Callbacks - The first rule of Queue Club - don't block\r\n\r\n\r\nOur client does not block, but our service does. Going back to our `RecommendationService`.\r\nIf we get a lot of cache hits for user loads, perhaps the\r\nblock will not be that long, but it will be there and every time we have to fault in a user, the whole system\r\nis gummed up. What we want to be able to do is if we can't handle the recommendation request,\r\nwe go ahead and make an async call to the `UserDataService`. When that async callback comes back, then we\r\nhandle that request. In the mean time, we handle recommendation lists requests as quickly as we can.\r\nWe never block.\r\n\r\n\r\nSo let's revisit the service. The first thing we are going to do is make the service method take\r\na callback. Before we do that, let's set down some rules.\r\n\r\n\r\n#### The first rule of queue club don't block.\r\n#### The second rule of queue club if you are not ready, use a callback and continue handling stuff you are ready for\r\n\r\n\r\n#### Queue Callbacks - Adding a CallBack to the RecommendationService inproc microservice\r\n\r\n```java\r\npublic class RecommendationService {\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n```\r\n\r\n\r\n\r\nNow we are taking a callback and we can decide when we want to handle this recommendation generation request.\r\nWe can do it right away if there user data we need is in-memory or we can delay it.\r\n\r\n\r\n#### If the user is found, call the callback right away for RecommendationService inproc microservice\r\n\r\n```java\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n /** Look for user in user cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n ...\r\n } else {\r\n /* Call the callback now because we can handle the callback now. */\r\n recommendationsCallback.accept(runRulesEngineAgainstUser(user));\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nNotice, if the user is found in the cache, we run our recommendation rules in-memory and call the callback right away\r\n`recommendationsCallback.accept(runRulesEngineAgainstUser(user))`.\r\n\r\nThe interesting part is what do we do if don't have the user loaded.\r\n\r\n\r\n#### If the user was not found, load him from the user microservice, but still don't block\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using Callback. */\r\n userDataService.loadUser(new Callback() {\r\n @Override\r\n public void accept(final User loadedUser) {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nHere we use a CallBack to load the user, and when the user is loaded, we call `handleLoadFromUserDataService`\r\nwhich adds some management about handling the callback so we can still handle this call, just not now.\r\n\r\n\r\n\r\n#### Lambda version of last example\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using lambda expression. */\r\n userDataService.loadUser(\r\n loadedUser -> {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nUsing lambdas like this makes the code more readable and terse, but remember don't deeply nest\r\nlambda expressions or you will create a code maintenance nightmare. Use them judiciously.\r\n\r\n\r\n### Queue Callbacks - Doing something later\r\n\r\nWhat we want is to handle the request for recommendations after the user service system loads\r\nthe user from its store.\r\n\r\n\r\n\r\n#### Handling UserServiceData callback methods once we get them.\r\n\r\n```java\r\n\r\npublic class RecommendationService {\r\n\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n private UserDataServiceClient userDataService;\r\n\r\n\r\n private BlockingQueue callbacks =\r\n new ArrayBlockingQueue(10_000);\r\n\r\n\r\n ...\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n ...\r\n\r\n }\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks queue. */\r\n callbacks.add(new Runnable() {\r\n @Override\r\n public void run() {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n }\r\n });\r\n }\r\n\r\n\r\n\r\n```\r\n\r\n\r\n\r\n\r\n#### handleLoadFromUserDataService rewritten using Lambda\r\n\r\n```java\r\n\r\n\r\npublic class RecommendationService {\r\n\r\n...\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks list. */\r\n callbacks.add(() -> {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n });\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nThe important part there is that every time we get a callback call from `UserDataService`, we then\r\nperform our CPU intensive recommendation rules and callback our caller. Well not exactly, what we\r\ndo is enqueue an runnable onto our callbacks queue, and later we will iterate through those but when?\r\n\r\n\r\n### Queue Callbacks Handling callbacks when our receive queue is empty, a new batch started or we hit a batch limit\r\n\r\nThe `RecommendationService` can be notified when its queue is empty, it has started a new batch and when\r\nit has reached a batch limit. These are all good times to handle callbacks from the `UserDataService`.\r\n\r\n#### Draining our callback queue\r\n```java\r\n\r\n @QueueCallback({\r\n QueueCallbackType.EMPTY,\r\n QueueCallbackType.START_BATCH,\r\n QueueCallbackType.LIMIT})\r\n private void handleCallbacks() {\r\n\r\n flushServiceProxy(userDataService);\r\n Runnable runnable = callbacks.poll();\r\n\r\n while (runnable != null) {\r\n runnable.run();\r\n runnable = callbacks.poll();\r\n }\r\n }\r\n\r\n```\r\n\r\nIt is important to remember when handling callbacks from another microservice that you want to handle\r\ncallbacks from the other service before you handle more incomming requests from you clients.\r\nEssentially you have clients that have been waiting (async waiting but still), and these clients\r\nmight represent an open TCP/IP connection like an HTTP call so it is best to close them out\r\nbefore handling more requests and like we said they were already waiting around with an open connection\r\nfor users to load form the user service.\r\n\r\nTo learn more about CallBacks, plesae read [QBit Java MicroService Lib CallBack fundamentals]([Rough Cut] QBit Microservice Lib Working With CallBacks).\r\n\r\n\r\n\r\n\r\n## Workers - pools and shards\r\n\r\n```java\r\npublic class ServiceWorkers {\r\n\r\n public static RoundRobinServiceDispatcher workers() {...\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {...\r\n```\r\n\r\nYou can compose sharded workers (for in-memory, thread safe, CPU intensive services), or workers for IO\r\nor talking to foreign services or foreign buses.\r\n\r\nHere is an example that uses a worker pool with three service workers in it:\r\n\r\nLet's say you have a service that does something:\r\n\r\n```java\r\n\r\n //Your POJO\r\n public class MultiWorker {\r\n\r\n void doSomeWork(...) {\r\n ...\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nNow this does some sort of IO and you want to have a bank of these running not just one so you can do\r\nIO in parallel. After some performance testing, you found out that three is the magic number.\r\n\r\nYou want to use your API for accessing this service:\r\n\r\n```java\r\n public interface MultiWorkerClient {\r\n void doSomeWork(...);\r\n }\r\n\r\n```\r\n\r\nNow let's create a bank of these and use it.\r\n\r\nFirst create the QBit services which add the thread/queue/microbatch.\r\n\r\n```java\r\n\r\n /* Create a service builder. */\r\n final ServiceBuilder serviceBuilder = serviceBuilder();\r\n\r\n /* Create some qbit services. */\r\n final Service service1 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service2 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service3 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n```\r\n\r\nNow add them to a ServiceWorkers object.\r\n\r\n```java\r\n\r\n ServiceWorkers dispatcher;\r\n dispatcher = workers(); //Create a round robin service dispatcher\r\n dispatcher.addServices(service1, service2, service3);\r\n dispatcher.start(); // start up the workers\r\n\r\n```\r\n\r\nYou can add services, POJOs and method consumers, method dispatchers to a service bundle.\r\nThe service bundle is an integration point into QBit.\r\n\r\nLet's add our new Service workers. ServiceWorkers is a ServiceMethodDispatcher.\r\n\r\n```Java\r\n /* Add the dispatcher to a service bundle. */\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nWe are probably going to add a helper method to the service bundle so most of this can happen in\r\na single call.\r\n\r\nNow you can start using your workers.\r\n\r\n```java\r\n\r\n /* Start using the workers. */\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n```\r\n\r\nNow you could use Spring or Guice to configure the builders and the service bundle.\r\nBut you can just do it like the above which is good for testing and understanding QBit internals.\r\n\r\nQBit also supports the concept of sharded services which is good for sharding resources like CPU\r\n(run a rules engine on each CPU core for a user recommendation engine).\r\n\r\nQBit does not know how to shard your services, you have to give it a hint.\r\nYou do this through a shard rule.\r\n\r\n```java\r\npublic interface ShardRule {\r\n int shard(String methodName, Object[] args, int numWorkers);\r\n}\r\n```\r\nWe worked on an app where the first argument to the services was the username, and then we used that to\r\nshard calls to a CPU intensive in-memory rules engine. This technique works. :)\r\n\r\nThe ServiceWorkers class has a method for creating a sharded worker pool.\r\n\r\n```java\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nTo use you just pass a shard key when you create the service workers.\r\n\r\n```java\r\n\r\n\r\n dispatcher = shardedWorkers((methodName, methodArgs, numWorkers) -> {\r\n String userName = methodArgs[0].toString();\r\n int shardKey = userName.hashCode() % numWorkers;\r\n return shardKey;\r\n });\r\n\r\n```\r\n\r\nThen add your services to the ServiceWorkers composition.\r\n```java\r\n int workerCount = Runtime.getRuntime().availableProcessors();\r\n\r\n for (int index = 0; index < workerCount; index++) {\r\n final Service service = serviceBuilder\r\n .setServiceObject(new ContentRulesEngine()).build();\r\n dispatcher.addServices(service);\r\n\r\n }\r\n```\r\n\r\nThen add it to the service bundle as before.\r\n```java\r\n\r\n dispatcher.start();\r\n\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nThen just use it:\r\n\r\n```java\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n for (int index = 0; index < 100; index++) {\r\n String userName = \"rickhigh\" + index;\r\n worker.pickSuggestions(userName);\r\n }\r\n\r\n```\r\n\r\n### Built in shard rules\r\n\r\n```java\r\n\r\n\r\npublic class ServiceWorkers {\r\n...\r\n public static ShardedMethodDispatcher shardOnFirstArgumentWorkers() {\r\n ...\r\n }\r\n\r\n...\r\n\r\n public static ShardedMethodDispatcher shardOnFifthArgumentWorkers() {\r\n ...\r\n }\r\n\r\n\r\n public static ShardedMethodDispatcher shardOnBeanPath(final String beanPath) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nThe shardOnBeanPath allows you to create a complex bean path navigation call and use its property to shard on.\r\n\r\n```java\r\n\r\n /* shard on 2nd arg which is an employee\r\n Use the employees department's id property. */\r\n dispatcher = shardOnBeanPath(\"[1].department.id\");\r\n\r\n /* Same as above. */\r\n dispatcher = shardOnBeanPath(\"1/department/id\");\r\n\r\n```\r\n\r\n[Read more about Service sharding and service workers here](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-QBit-Microservices-using-Service-Workers-and-sharded-service-workers)\r\n\r\n\r\nYou can find a lot more in the wiki. Also follow the commits.\r\nWe have been busy beavers.\r\n[QBit the microservice lib for Java - JSON, REST, WebSocket](https://github.com/advantageous/qbit/wiki).",
+ "body": "[QBit Java Micorservices lib tutorials](https://github.com/MammatusTech/qbit-microservices-examples/wiki)|\r\n[QBit Website](http://advantageous.github.io/qbit/) | [QBit uses Reakt](http://advantageous.github.io/reakt/) | [QBit works with Vert.x](http://vertx.io/) | [Reakt Vertx](http://advantageous.github.io/reakt-vertx/)\r\n\r\n#QBit - The Microservice Lib for Java - JSON, REST, WebSocket, Speed! \r\n\r\n## Quick overview of QBit\r\n\r\nThe Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.\r\n\r\nGot a question? Ask here: [QBit Google Group](https://groups.google.com/forum/#!forum/qbit-microservice).\r\n\r\nEverything is a queue. You have a choice. You can embrace it and control it. You can optimize for it.\r\nOr you can hide behind abstractions. QBit opens you up to peeking into what is going on, and allows you\r\nto pull some levers without selling your soul.\r\n\r\nQBit is a library not a framework. You can mix and match QBit with Spring, Guice, etc.\r\n\r\nQBit is FAST!\r\n\r\n\r\n\r\n#### Using from maven\r\n```xml\r\n\r\n io.advantageous.qbit\r\n qbit-admin\r\n 1.0.0.RELEASE\r\n\r\n\r\n io.advantageous.qbit\r\n qbit-vertx\r\n 1.0.0.RELEASE\r\n\r\n```\r\n\r\n#### Using from gradle\r\n```java\r\ncompile 'io.advantageous.qbit:qbit-admin:1.0.0.RELEASE'\r\ncompile 'io.advantageous.qbit:qbit-vertx:1.0.0.RELEASE'\r\n```\r\n\r\nCore Features\r\n============\r\n\r\n* Write REST based async microservices\r\n* Write ***WebSocket*** based async microservices (fast async RPC over WebSocket)\r\n* Actor Service Queues using micro-batching for high-speed message passing\r\n* Strongly async typed event bus which can be distributed\r\n* Async low overhead metrics gathering which can be queried and distributed (for doing fast lane analytics)\r\n* Complex async call coordination (with the Reactor) for reactive programming\r\n* Built-in support for ***health checks*** (and integration with tools like Consul)\r\n* Built-in support for ***monitoring*** (and integration with wire protocols like StatsD)\r\n* Built-in support for ***Service Discovery*** (with integration with health system, DNS SRV records and Consul)\r\n* Integration with persistent queues\r\n* [12 factor app port bindings](http://12factor.net/), health checks, KPI gathering, Logging MDC\r\n* API Gateway support for client generation and consumption via [Swagger](http://swagger.io/).\r\n* Our services can generate Swagger files (like idl for JSON/REST).\r\n* Remote client proxies for WebSocket (your interface is your IDL)\r\n\r\n\r\nStatus\r\n=====\r\nDeployed at several large fortune 100 companies. \r\nQBit now works with Vertx (standalone or embedded).\r\nYou can also use QBit on non-QBit projects, it is just a lib.\r\n\r\nLicense\r\n=====\r\nApache 2\r\n\r\n\r\n## Java Microservice Lib\r\n\r\nQBit has inproc services, REST microservices and WebSocket microservices as well as an\r\nin-proc service event bus (which can be per module or per app). It supports workers and in-memory services.\r\n\r\nBefore we describe more, here are two sample services:\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {...\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {...\r\n```\r\n\r\n\r\n#### Adder Service using URI params\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {...\r\n }\r\n```\r\n\r\n\r\n\r\nQBit philosophy:\r\n====\r\nAt the end of the day QBit is a simple library not a framework.\r\nYour app is not a QBit app but a Java app that uses the QBit lib.\r\nQBit allows you to work with Java UTIL concurrent, and does not endeavor to hide it from you.\r\nJust trying to take the sting out of it.\r\n\r\nDoes it work\r\n=====\r\nWe have used techniques in Boon and QBit with great success in high-end, high-performance, high-scalable apps.\r\nWe helped clients handle 10x the load with 1/10th the servers of their competitors using techniques in QBit.\r\nQBit is us being sick of hand tuning queue access and threads.\r\n\r\n\r\nBoon and QBit humility policy\r\n=====\r\nIdeas for Boon and QBit often come from all over the web. We make mistakes. Point them out.\r\nAs a developer of Boon and QBit, we are fellow travelers.\r\nIf you have an idea or technique you want to share, we listen.\r\n\r\n\r\nInspiration\r\n====\r\n\r\nA big inspiration for Boon/QBit was Vertx, Akka, Go Channels, Active Objects, Apartment Model Threading, Actor,\r\nand the Mechanical Sympathy papers.\r\n\r\nQBit has ideas that are similar to many frameworks. We are all reading the same papers.\r\nQBit got inspiration from the LMAX disruptor papers and this blog post about\r\n[link transfer queue versus disruptor](http://php.sabscape.com/blog/?p=557). We had some theories about\r\nqueues that blog post inspired us to try them out. Some of these theories are deployed at some of the\r\nbiggest middleware backends and whose name brands are known around the world. And thus QBit was born.\r\n\r\nQBit also took an lot of inspiration by the great work done\r\nby Tim Fox on Vertx. The first project using something that could actually be called QBit (albeit early QBit)\r\n was using Vertx on an web/mobile microservice for an app that could potentially have 80 million users.\r\n It was this\r\nexperience with Vertx and early QBit that led to QBit development and evolution. QBit is built on the\r\nshoulders of giants (Netty/Vertx).\r\n\r\nDoes QBit compete with...\r\n====\r\nSpring Disruptor: No. You could use QBit to write plugins for Spring Disruptor I suppose, but QBit does\r\nnot compete with Spring Disruptor.\r\nSpring Boot/Spring MVC: No. We use the same annotations but QBit is geared for high-speed in-memory\r\nmicroservices. It is more like Akka than Spring Boot. QBit has a subset of the features of Spring MVC\r\ngeared only for microservices, i.e., WebSocket RPC, REST, JSON marshaling, etc.\r\nAkka: No. Well Maybe. Akka has similar concepts but they take a different approach. QBit is more focused\r\n on Java, and microservices (REST, JSON, WebSocket) than Akka.\r\nLMAX Disruptor: No. In fact, we can use disruptor as on of the queues that QBit uses underneath the covers.\r\n\r\n\r\n(Early benchmarks have been removed. They were here. QBit got a lot faster.\r\n Benchmarking QBit is a moving target at the moment.\r\n Links and reports will be created.)\r\n\r\n\r\nCode Examples\r\n\r\n\r\n## Basic Queue example (REST style services is further down)\r\n\r\n====\r\n\r\n```java\r\n\r\n BasicQueue queue = BasicQueue.create(Integer.class, 1000);\r\n\r\n //Sending threads\r\n\r\n SendQueue sendQueue = queue.sendQueue();\r\n for (int index = 0; index < amount; index++) {\r\n sendQueue.send(index);\r\n }\r\n sendQueue.flushSends();\r\n ...\r\n sendQueue.sendAndFlush(code);\r\n //other methods for sendQueue, writeBatch, writeMany\r\n\r\n\r\n //Receiving Threads\r\n ReceiveQueue receiveQueue = queue.receiveQueue();\r\n Integer item = receiveQueue.take();\r\n //other methods poll(), pollWait(), readBatch(), readBatch(count)\r\n```\r\n\r\n\r\n### What is QBit again?\r\n\r\nQBit is a queuing library for microservices. It is similar to many other projects like Akka, Spring Reactor,\r\netc. QBit is just a library not a platform. QBit has libraries to put a service behind a queue.\r\nYou can use QBit queues directly or you can create a service. QBit services can be exposed by WebSocket,\r\nHTTP, HTTP pipeline, and other types of remoting. A service in QBit is a Java class whose methods are\r\n executed behind service queues. QBit implements apartment model threading and is similar to the\r\n Actor model or a better description would be Active Objects. QBit does not use a disruptor (but could).\r\n It uses regular Java Queues. QBit can do north of 100 million ping pong calls per second which is\r\n an amazing speed (seen as high as 200M). QBit also supports calling services via REST, and WebSocket.\r\n QBit is microservices in the pure Web sense: JSON, HTTP, WebSocket, etc. QBit uses micro batching to\r\n push messages through the pipe (queue, IO, etc.) faster to reduce thread hand-off.\r\n\r\n### QBit lingo\r\n\r\nQBit is a Java microservice lib supporting REST, JSON and WebSocket. It is written in Java but we could\r\none day write a version in Rust or Go or C# (but that would require a large payday).\r\n\r\n**Service**\r\nPOJO (plain old Java object) behind a queue that can receive method calls via proxy calls or events\r\n(May have one thread managing events, method calls, and responses or two one for method calls and events\r\n 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.\r\n\r\n**ServiceBundle**\r\nMany POJOs behind one response queue and many receive queues. There may be one thread for all responses\r\nor not. They also can be one receive queue.\r\n\r\n**Queue**\r\nA thread managing a queue. It supports batching. It has events for empty, reachedLimit, startedBatch,\r\nidle. You can listen to these events from services that sit behind a queue. You don't have to use Services.\r\nYou can use Queue's direct. In QBit, you have sender queues and receivers queues. They are separated to\r\nsupport micro-batching.\r\n\r\n**ServiceEndpointServer**\r\nServiceBundle that is exposed to REST and WebSocket communication.\r\n\r\n**EventBus**\r\nEventBus is a way to send a lot of messages to services that may be loosely coupled.\r\n\r\n**ClientProxy**\r\nClientProxy is a way to invoke service through async interface, service can be inproc (same process) or\r\nremoted over WebSocket.\r\n\r\n**Non-blocking**\r\nQBit is a non-blocking lib. You use CallBacks via Java 8 Lambdas. You can also send event messages and get\r\nreplies. Messaging is built into the system so you can easily coordinate complex tasks.\r\nQBit takes an object-oriented approach to service development so services look like normal Java services\r\nthat you\r\nalready write, but the services live behind a queue/thread. This is not a new concept. Microsoft did this\r\nwith DCOM/COM and called it active objects. Akka does it with actors and called them strongly typed Actors.\r\nThe important concepts is that you get the speed of reactive and actor style messaging but you develop\r\nin a natural OOP approach. QBit is not the first. QBit is not the only.\r\n\r\n\r\n**Speed**\r\nQBit is VERY fast. There is a of course a lot of room for improvement. But already 200M+ TPS inproc ping pong, 10M-20M+ TPS event bus, 500K TPS RPC calls over WebSocket/JSON, etc.\r\nMore work needs to be done to improve speed, but now it is fast enough where we are focusing more on\r\nusability.\r\nThe JSON support uses Boon by default which is up to 4x faster than other JSON parsers for the\r\nREST/JSON, WebSocket/JSON use case.\r\n\r\n**Reactive Programming**\r\nQBit provides a **Reactor** to manage async calls. This allows callbacks to be handled on the same thread that called them and it provides for timeout and error handling. Read [Reactor tutorial for creating reactive micro service programming](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices)\r\n\r\n**Service Discovery**\r\nBuilt in support for service discovery. This includes integration with Consul.\r\n\r\n\r\n**StatService**\r\nBuilt in support for stats. The **StatService** can be integrated with **StatsD** (Graphite, Grafana, DataDog, etc.) to publish passive stats. Or you can query the stats engine and react to the stats (counts, timings and levels). The **StatsService** is a reactive stats system that can be clustered. The StatService is reactive in that your services can publish to it and query it and react based on the results. You can implement things like rate limiting and react to an increased rate of something. The ServiceDiscovery system integrates with the HealthSystem and Consul to roll up each of your internal services that make up you micro service and publish the composite availably of your micro service to a single HTTP endpoint or a dead mans switch in Consul (TTL). \r\n\r\n\r\n\r\n### CURLable REST services example\r\n\r\nTalk is cheap. Let's look at some code. You can get a detailed walk through in the Wiki.\r\nWe have a lot of documentation already.\r\n\r\nWe will create a service that is exposed through REST/JSON.\r\n\r\nTo query the size of the todo list:\r\n\r\n```bash\r\ncurl localhost:8080/services/todo-service/todo/count\r\n```\r\n\r\nTo add a new TODO item.\r\n\r\n```bash\r\ncurl -X POST -H \"Content-Type: application/json\" -d \\\r\n'{\"name\":\"xyz\",\"description\":\"xyz\"}' \\\r\nhttp://localhost:8080/services/todo-service/todo\r\n```\r\n\r\nTo get a list of TODO items\r\n```bash\r\ncurl http://localhost:8080/services/todo-service/todo/\r\n```\r\n\r\nThe TODO example will use and track Todo items.\r\n\r\n#### Todo item POJO sans getter\r\n\r\n```java\r\npackage io.advantageous.qbit.examples;\r\n\r\nimport java.util.Date;\r\n\r\n\r\npublic class TodoItem {\r\n\r\n\r\n private final String description;\r\n private final String name;\r\n private final Date due;\r\n\r\n```\r\n\r\nThe TodoService uses Spring MVC style annotations.\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n\r\n private List todoItemList = new ArrayList<>();\r\n\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {\r\n\r\n return todoItemList.size();\r\n }\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {\r\n\r\n return todoItemList;\r\n }\r\n\r\n @RequestMapping(value = \"/todo\", method = RequestMethod.POST)\r\n public void add(TodoItem item) {\r\n\r\n todoItemList.add(item);\r\n }\r\n\r\n}\r\n\r\n```\r\n\r\n\r\n#### Sending non-JSON\r\n\r\nYou can POST/PUT non-JSON and you can capture the body as a `String` or as a `byte[]`. \r\nIf the content-type is set to anything but `application/json` and your body is defined a String or byte[].\r\nThis works automatically. (The content-type has to be set.)\r\n\r\n```java\r\n @RequestMapping(value = \"/body/bytes\", method = RequestMethod.POST)\r\n public boolean bodyPostBytes( byte[] body) {\r\n String string = new String(body, StandardCharsets.UTF_8);\r\n return string.equals(\"foo\");\r\n }\r\n\r\n @RequestMapping(value = \"/body/string\", method = RequestMethod.POST)\r\n public boolean bodyPostString(String body) {\r\n return body.equals(\"foo\");\r\n }\r\n```\r\n\r\n\r\n#### Sending different response codes for success\r\n\r\nBy default QBit sends a `200` (OK) for a non-void call (a call that has a return or a Callback). If the REST operation has no return or no callback then QBit sends a `202` (Accepted). There may be times when you want to send a 201 (Created) or some other code that is not an Exception. You can do that by setting `code` on `@RequestMapping`. By default the code is -1 which means use the default behavior (200 for success, 202 for one-way message, and 500 for errors).\r\n\r\n\r\n#### Sending different response codes for success\r\n```java\r\n\r\n @RequestMapping(value = \"/helloj7\", code = 221)\r\n public void helloJSend7(Callback>> callback) {\r\n callback.returnThis(JSendResponseBuilder.jSendResponseBuilder(Lists.list(\r\n \"hello \" + System.currentTimeMillis())).build());\r\n }\r\n\r\n```\r\n\r\n`Callbacks` can be used for internal services as well. It is often the case that you use a [CallbackBuilder](https://github.com/advantageous/qbit/wiki/%5BDocument%5D-CallbackBuilder-and-generics-for-Reactive-Java-Microservices) or a QBit [Reactor](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices) to manage service calls. \r\n\r\n#### Working with non JSON responses\r\n\r\nYou do not have to return JSON form rest calls.\r\nYou can return any binary or any text by using `HttpBinaryResponse` and `HttpTextResponse`.\r\n\r\n#### Returning non JSON from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildTextResponse());\r\n }\r\n```\r\n\r\n\r\n#### Returning binary from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildBinaryResponse());\r\n }\r\n```\r\n\r\n#### Side note Why Spring style annotations?\r\nWhy did we pick Spring style annotations?\r\n1) Spring is not a standard and neither is QBit. 2) We found the Spring annotations to be less verbose.\r\n3) More people use Spring than Java EE. We wrote QBit for people to use.\r\nWe could easily support JAX-RS style annotations, and we probably will.\r\nSince QBit focuses on JSON, we do not need all of the complexity of JAX-RS or even all the features of\r\nthe Spring MVC annotations. Also we can literally use the actual Spring annotations. QBit and Boon\r\nuse a non-type safe mechanism for annotations which means they are not tied to a particular lib.\r\nYou can define your own. We hate vendor tie-in even if it is an open source vendor.\r\n(We also support @POST, @GET which is similar to JAX-RS).\r\n\r\nNow just start it up.\r\n\r\n```java\r\n\r\n public static void main(String... args) {\r\n\r\n ServiceEndpointServer server = new EndpointServerBuilder().build();\r\n server.initServices(new TodoService());\r\n server.start();\r\n }\r\n```\r\n\r\n\r\n\r\nThat is it. There is also out of the box WebSocket support with client side proxy generation so\r\nyou can call into services at the rate of millions of calls per second.\r\n\r\n## Using URI Params for QBit microservice\r\n\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {\r\n\r\n return a + b;\r\n }\r\n }\r\n\r\n```\r\n\r\n## WebSocket\r\nYou can always invoke QBit services via a WebSocket proxy.\r\nThe advantage of a WebSocket proxy is it allows you execute 1M RPC+ a second (1 million remote calls\r\nevery second).\r\n\r\n\r\n#### Using a microservice remotely with WebSocket\r\n```java\r\n /* Start QBit client for WebSocket calls. */\r\n final Client client = clientBuilder()\r\n .setPort(7000).setRequestBatchSize(1).build();\r\n\r\n\r\n /* Create a proxy to the service. */\r\n final AdderServiceClientInterface adderService =\r\n client.createProxy(AdderServiceClientInterface.class,\r\n \"adder-service\");\r\n\r\n client.start();\r\n\r\n\r\n\r\n /* Call the service */\r\n adderService.add(System.out::println, 1, 2);\r\n\r\n```\r\n\r\nThe output is 3.\r\n\r\n```output\r\n3\r\n```\r\n\r\n\r\nThe above uses a WebSocket proxy interface to call the service async.\r\n\r\n```java\r\n\r\n interface AdderServiceClientInterface {\r\n\r\n void add(Callback callback, int a, int b);\r\n }\r\n```\r\n\r\n#### ServiceDiscovery aware websocket builders\r\n\r\nCreate websocket service client that is ServiceDiscovery aware.\r\n\r\n\r\n```java\r\n final Client client = clientBuilder.setServiceDiscovery(serviceDiscovery, \"echo\")\r\n .setUri(\"/echo\").setProtocolBatchSize(20).build().startClient();\r\n\r\n\r\n final EchoAsync echoClient = client.createProxy(EchoAsync.class, \"echo\");\r\n```\r\n\r\nCurrently the `clientBuilder` will load all service endpoints that are registered under the service name,\r\nand randomly pick one. \r\n\r\nServiceDiscovery includes Consul based, watching JSON files on disk, and DNS. It is easy to write your own service discovery as well and plug it into QBit.\r\n\r\n\r\nIn the future we can RoundRobin calls or shard calls to websocket service and/or provide auto fail over if the connection is closed. We do this for the event bus that uses service discovery but it is not baked into WebSocket based client stubs yet.\r\n\r\n\r\n## REST call with URI params\r\n\r\nThe last client example uses WebSocket. You could also just use REST, and actually use the URI params\r\nthat we setup.\r\nREST is nice but it is going to be slower than WebSocket support.\r\n\r\nQBit ships with a nice little HTTP client. We can use it.\r\n\r\nYou can use it to send async calls and WebSocket messages with the HTTP client.\r\n\r\n\r\nHere we will use the http client to invoke our remote method:\r\n\r\n#### Using a microservice remotely with REST QBit microservice client\r\n```java\r\n\r\n\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\")\r\n .setPort(7000).build();\r\n\r\n httpClient.start();\r\n String results = httpClient\r\n .get(\"/services/adder-service/add/2/2\").body();\r\n System.out.println(results);\r\n\r\n```\r\n\r\n\r\nThe output is 4.\r\n\r\n```output\r\n4\r\n```\r\n\r\n## Accessing The URI Param example with CURL\r\n\r\nYou can also access the service from curl.\r\n\r\n```bash\r\n$ curl http://localhost:7000/services/adder-service/add/2/2\r\n```\r\n\r\nSee this full example here: [QBit microservice getting started tutorial](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-------------QBit-microservice-example).\r\n\r\n[QBit URI params and WebSocket proxy client](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Using-QBit-microservice-lib's-REST-support-with-URI-Params)\r\n\r\n## Working with WebSocket, HttpClient etc.\r\n\r\nQBit has a library for working with and writing async microservices that is lightweight and fun to use.\r\n\r\n#### WebSocket server and client.\r\n\r\n\r\n#### Create an HTTP server\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n```\r\n\r\n#### Setup server WebSocket support\r\n```java\r\n /* Setup WebSocket Server support. */\r\n httpServer.setWebSocketOnOpenConsumer(webSocket -> {\r\n webSocket.setTextMessageConsumer(message -> {\r\n webSocket.sendText(\"ECHO \" + message);\r\n });\r\n });\r\n\r\n```\r\n\r\n#### Start the server\r\n```java\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n```\r\n\r\n#### Setup the WebSocket client\r\n```java\r\n\r\n /** CLIENT. */\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\n#### Client WebSocket\r\n\r\n```java\r\n\r\n /* Setup the client websocket. */\r\n WebSocket webSocket = httpClient\r\n .createWebSocket(\"/websocket/rocket\");\r\n\r\n /* Setup the text consumer. */\r\n webSocket.setTextMessageConsumer(message -> {\r\n System.out.println(message);\r\n });\r\n webSocket.openAndWait();\r\n\r\n /* Send some messages. */\r\n webSocket.sendText(\"Hi mom\");\r\n webSocket.sendText(\"Hello World!\");\r\n\r\n```\r\n\r\n#### Output\r\n```output\r\n\r\nECHO Hi mom\r\nECHO Hello World!\r\n\r\n```\r\n\r\nNow stop the server and client. Pretty easy eh?\r\n\r\n## High-speed HTTP client and server done microservice style\r\n\r\n\r\n##### Starting up an HTTP server\r\n\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n /* Setting up a request Consumer with Java 8 Lambda expression. */\r\n httpServer.setHttpRequestConsumer(httpRequest -> {\r\n\r\n Map results = new HashMap<>();\r\n results.put(\"method\", httpRequest.getMethod());\r\n results.put(\"uri\", httpRequest.getUri());\r\n results.put(\"body\", httpRequest.getBodyAsString());\r\n results.put(\"headers\", httpRequest.getHeaders());\r\n results.put(\"params\", httpRequest.getParams());\r\n httpRequest.getReceiver()\r\n .response(200, \"application/json\", Boon.toJson(results));\r\n });\r\n\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n\r\n\r\n```\r\n\r\nThe focus is on ease of use and using Java 8 Lambdas for callbacks so the code is tight and small.\r\n\r\n[Find out more about QBit's microservice style WebSocket support here](https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-WebSocket-support)\r\n\r\n\r\n## Using HTTP Client lib\r\n\r\nNow, let's try out our HTTP client.\r\n\r\n##### Starting up an HTTP client\r\n\r\n```java\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\nYou just pass the URL, the port and then call start.\r\n\r\n## Synchronous HTTP calls\r\n\r\nNow you can start sending HTTP requests.\r\n\r\n##### No Param HTTP GET\r\n\r\n```java\r\n /* Send no param get. */\r\n HttpResponse httpResponse = httpClient.get( \"/hello/mom\" );\r\n puts( httpResponse );\r\n```\r\n\r\nAn HTTP response just contains the results from the server.\r\n\r\n\r\n##### No Param HTTP Response\r\n\r\n```java\r\npublic interface HttpResponse {\r\n\r\n MultiMap headers();\r\n\r\n int code();\r\n\r\n String contentType();\r\n\r\n String body();\r\n\r\n}\r\n\r\n```\r\n\r\nThere are helper methods for sync HTTP GET calls.\r\n\r\n\r\n\r\n##### Helper methods for GET\r\n```java\r\n\r\n\r\n /* Send one param get. */\r\n httpResponse = httpClient.getWith1Param(\"/hello/singleParam\",\r\n \"hi\", \"mom\");\r\n puts(\"single param\", httpResponse );\r\n\r\n\r\n /* Send two param get. */\r\n httpResponse = httpClient.getWith2Params(\"/hello/twoParams\",\r\n \"hi\", \"mom\", \"hello\", \"dad\");\r\n puts(\"two params\", httpResponse );\r\n\r\n...\r\n\r\n /* Send five param get. */\r\n httpResponse = httpClient.getWith5Params(\"/hello/5params\",\r\n \"hi\", \"mom\",\r\n \"hello\", \"dad\",\r\n \"greetings\", \"kids\",\r\n \"yo\", \"pets\",\r\n \"hola\", \"neighbors\");\r\n puts(\"5 params\", httpResponse );\r\n\r\n\r\n```\r\n\r\nThe puts method is a helper method it does System.out.println more or less by the way.\r\n\r\nThe first five params are covered. Beyond five, you have to use the HttpBuilder.\r\n\r\n```java\r\n\r\n\r\n /* Send six params with get. */\r\n\r\n final HttpRequest httpRequest = httpRequestBuilder()\r\n .addParam(\"hi\", \"mom\")\r\n .addParam(\"hello\", \"dad\")\r\n .addParam(\"greetings\", \"kids\")\r\n .addParam(\"yo\", \"pets\")\r\n .addParam(\"hola\", \"pets\")\r\n .addParam(\"salutations\", \"all\").build();\r\n\r\n httpResponse = httpClient.sendRequestAndWait(httpRequest);\r\n puts(\"6 params\", httpResponse );\r\n```\r\n\r\n## Http Async HTTP Client\r\n\r\nThere are async calls for GET as well.\r\n\r\n#### Async calls for HTTP GET using Java 8 lambda\r\n\r\n```java\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsync(\"/hi/async\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith1Param(\"/hi/async\", \"hi\", \"mom\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda 1 param\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith2Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 2 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n...\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith5Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n \"p3\", \"v3\",\r\n \"p4\", \"v4\",\r\n \"p5\", \"v5\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 5 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n```\r\n\r\n[Find more about the easy to use, fast microservice HTTP client here]\r\n(https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-HttpClient-GET,-POST,-et-al,-JSON,-Java-8-Lambda).\r\n\r\n## InProc QBit services\r\n\r\nQBit allows for services behind queues to be run in-proc as well.\r\n\r\n```java\r\n\r\n /* POJO service. */\r\n final TodoManager todoManagerImpl = new TodoManager();\r\n\r\n /*\r\n Create the service which manages async calls to todoManagerImpl.\r\n */\r\n final Service service = serviceBuilder()\r\n .setServiceObject(todoManagerImpl)\r\n .build().startServiceQueue();\r\n\r\n\r\n /* Create Asynchronous proxy over Synchronous service. */\r\n final TodoManagerClientInterface todoManager =\r\n service.createProxy(TodoManagerClientInterface.class);\r\n\r\n service.startCallBackHandler();\r\n\r\n\r\n System.out.println(\"This is an async call\");\r\n /* Asynchronous method call. */\r\n todoManager.add(new Todo(\"Call Mom\", \"Give Mom a call\"));\r\n\r\n\r\n AtomicInteger countTracker = new AtomicInteger();\r\n //Hold count from async call to service... for testing and showing it is an async callback\r\n\r\n System.out.println(\"This is an async call to count\");\r\n\r\n todoManager.count(count -> {\r\n System.out.println(\"This lambda expression is the callback \" + count);\r\n\r\n countTracker.set(count);\r\n });\r\n\r\n\r\n todoManager.clientProxyFlush(); //Flush all methods. It batches calls.\r\n\r\n Sys.sleep(100);\r\n\r\n System.out.printf(\"This is the count back from the server %d\\n\", countTracker.get());\r\n\r\n```\r\n\r\n[Detailed tutorial on in-proc services is being written.](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-Working-with-inproc-MicroServices-within-QBit.)\r\n\r\n\r\n## QBit Event Bus\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\nQBit also has a service event bus. This example is a an employee benefits services example.\r\n\r\nWe have two channels.\r\n\r\n```\r\npublic static final String NEW_HIRE_CHANNEL = \"com.mycompnay.employee.new\";\r\n\r\npublic static final String PAYROLL_ADJUSTMENT_CHANNEL = \"com.mycompnay.employee.payroll\";\r\n```\r\n\r\nAn employee object looks like this:\r\n\r\n```java\r\n\r\npublic static class Employee {\r\n final String firstName;\r\n final int employeeId;\r\n```\r\n\r\n\r\nThis example has three services: EmployeeHiringService, BenefitsService, and PayrollService.\r\n\r\nThese services are inproc services. QBit supports WebSocket, HTTP and REST remote services as well, but for now, let's focus on inproc services. If you understand inproc then you will understand remote.\r\n\r\nThe EmployeeHiringService actually fires off the events to other two services.\r\n\r\n```java\r\npublic class EmployeeHiringService {\r\n\r\n\r\n public void hireEmployee(final Employee employee) {\r\n\r\n int salary = 100;\r\n System.out.printf(\"Hired employee %s\\n\", employee);\r\n\r\n //Does stuff to hire employee\r\n\r\n //Sends events\r\n final EventManager eventManager =\r\n serviceContext().eventManager();\r\n eventManager.send(NEW_HIRE_CHANNEL, employee);\r\n\r\n eventManager.sendArray(PAYROLL_ADJUSTMENT_CHANNEL,\r\n employee, salary);\r\n\r\n\r\n }\r\n\r\n }\r\n```\r\n\r\n\r\nNotice that we call sendArray so we can send the employee and their salary.\r\nThe listener for PAYROLL_ADJUSTMENT_CHANNEL will have to handle both an employee and an int\r\nthat represents the new employees salary.\r\nYou can also use event bus proxies so you do not have to call into the event bus at all.\r\n\r\nThe BenefitsService listens for new employees being hired so it can enroll them into the benefits system.\r\n\r\n```java\r\npublic static class BenefitsService {\r\n\r\n @OnEvent(NEW_HIRE_CHANNEL)\r\n public void enroll(final Employee employee) {\r\n\r\n System.out.printf(\"Employee enrolled into benefits system employee %s %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId());\r\n\r\n }\r\n\r\n```\r\n\r\nDaddy needs to get paid.\r\n\r\n```java\r\n public static class PayrollService {\r\n\r\n @OnEvent(PAYROLL_ADJUSTMENT_CHANNEL)\r\n public void addEmployeeToPayroll(final Employee employee, int salary) {\r\n\r\n System.out.printf(\"Employee added to payroll %s %d %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId(), salary);\r\n\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nThe employee is the employee object from the EmployeeHiringService.\r\n\r\nso you can get your benefits, and paid!\r\n\r\nFind more details here:\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\n\r\n## Private event bus and event bus proxies\r\n\r\n You can define your own interface to the event bus and you can use your own event buses with QBit.\r\n Each module in your service can have its own internal event bus.\r\n\r\n To learn more read:\r\n [QBit Microservice working with a private event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-private-event-bus-for-inproc-microservices)\r\n and [QBit Java Microservice lib using your own interface to the event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-strongly-typed-event-bus-proxies-for-QBit-Java-Microservice-lib).\r\n\r\n\r\n\r\n## Queue Callbacks\r\n\r\n To really grasp QBit, one must grasp the concepts of a CallBack.\r\n\r\n A CallBack is a way to get an async response in QBit.\r\n\r\n You call a service method and it calls you back.\r\n\r\n Client proxies can have callbacks:\r\n\r\n\r\n#### Queue Callbacks - RecommendationService client interface\r\n```java\r\n\r\npublic interface RecommendationServiceClient {\r\n\r\n\r\n void recommend(final Callback> recommendationsCallback,\r\n final String userName);\r\n}\r\n\r\n```\r\n\r\nCallbacks are Java 8 Consumers with some optional extra error handling.\r\n\r\n\r\n#### Queue Callbacks - Callback\r\n\r\n```java\r\n\r\n\r\npublic interface Callback extends java.util.function.Consumer {\r\n default void onError(java.lang.Throwable error) { /* compiled code */ }\r\n}\r\n\r\n```\r\n\r\nServices that can block should use callbacks.\r\nThus if loadUser blocked in the following example, it should really use a callback instead of returning a value.\r\n\r\npublic class RecommendationService {\r\n\r\n#### Queue Callbacks - Simple minded implementation of RecommendationService\r\n```java\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n public List recommend(final String userName) {\r\n User user = users.get(userName);\r\n if (user == null) {\r\n user = loadUser(userName);\r\n }\r\n return runRulesEngineAgainstUser(user);\r\n }\r\n\r\n```\r\n\r\n\r\nLet's pretend `loadUser` has to look in a local cache, and if the user is not found, look in an off-heap cache\r\nand if not found it must ask for the user from the UserService which must check its caches and perhaps fallback\r\nto loading the user data from a database or from other services.\r\nIn other words, `loadUser` can potentially block on IO.\r\n\r\n\r\n\r\n### Queue Callbacks - The first rule of Queue Club - don't block\r\n\r\n\r\nOur client does not block, but our service does. Going back to our `RecommendationService`.\r\nIf we get a lot of cache hits for user loads, perhaps the\r\nblock will not be that long, but it will be there and every time we have to fault in a user, the whole system\r\nis gummed up. What we want to be able to do is if we can't handle the recommendation request,\r\nwe go ahead and make an async call to the `UserDataService`. When that async callback comes back, then we\r\nhandle that request. In the mean time, we handle recommendation lists requests as quickly as we can.\r\nWe never block.\r\n\r\n\r\nSo let's revisit the service. The first thing we are going to do is make the service method take\r\na callback. Before we do that, let's set down some rules.\r\n\r\n\r\n#### The first rule of queue club don't block.\r\n#### The second rule of queue club if you are not ready, use a callback and continue handling stuff you are ready for\r\n\r\n\r\n#### Queue Callbacks - Adding a CallBack to the RecommendationService inproc microservice\r\n\r\n```java\r\npublic class RecommendationService {\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n```\r\n\r\n\r\n\r\nNow we are taking a callback and we can decide when we want to handle this recommendation generation request.\r\nWe can do it right away if there user data we need is in-memory or we can delay it.\r\n\r\n\r\n#### If the user is found, call the callback right away for RecommendationService inproc microservice\r\n\r\n```java\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n /** Look for user in user cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n ...\r\n } else {\r\n /* Call the callback now because we can handle the callback now. */\r\n recommendationsCallback.accept(runRulesEngineAgainstUser(user));\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nNotice, if the user is found in the cache, we run our recommendation rules in-memory and call the callback right away\r\n`recommendationsCallback.accept(runRulesEngineAgainstUser(user))`.\r\n\r\nThe interesting part is what do we do if don't have the user loaded.\r\n\r\n\r\n#### If the user was not found, load him from the user microservice, but still don't block\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using Callback. */\r\n userDataService.loadUser(new Callback() {\r\n @Override\r\n public void accept(final User loadedUser) {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nHere we use a CallBack to load the user, and when the user is loaded, we call `handleLoadFromUserDataService`\r\nwhich adds some management about handling the callback so we can still handle this call, just not now.\r\n\r\n\r\n\r\n#### Lambda version of last example\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using lambda expression. */\r\n userDataService.loadUser(\r\n loadedUser -> {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nUsing lambdas like this makes the code more readable and terse, but remember don't deeply nest\r\nlambda expressions or you will create a code maintenance nightmare. Use them judiciously.\r\n\r\n\r\n### Queue Callbacks - Doing something later\r\n\r\nWhat we want is to handle the request for recommendations after the user service system loads\r\nthe user from its store.\r\n\r\n\r\n\r\n#### Handling UserServiceData callback methods once we get them.\r\n\r\n```java\r\n\r\npublic class RecommendationService {\r\n\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n private UserDataServiceClient userDataService;\r\n\r\n\r\n private BlockingQueue callbacks =\r\n new ArrayBlockingQueue(10_000);\r\n\r\n\r\n ...\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n ...\r\n\r\n }\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks queue. */\r\n callbacks.add(new Runnable() {\r\n @Override\r\n public void run() {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n }\r\n });\r\n }\r\n\r\n\r\n\r\n```\r\n\r\n\r\n\r\n\r\n#### handleLoadFromUserDataService rewritten using Lambda\r\n\r\n```java\r\n\r\n\r\npublic class RecommendationService {\r\n\r\n...\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks list. */\r\n callbacks.add(() -> {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n });\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nThe important part there is that every time we get a callback call from `UserDataService`, we then\r\nperform our CPU intensive recommendation rules and callback our caller. Well not exactly, what we\r\ndo is enqueue an runnable onto our callbacks queue, and later we will iterate through those but when?\r\n\r\n\r\n### Queue Callbacks Handling callbacks when our receive queue is empty, a new batch started or we hit a batch limit\r\n\r\nThe `RecommendationService` can be notified when its queue is empty, it has started a new batch and when\r\nit has reached a batch limit. These are all good times to handle callbacks from the `UserDataService`.\r\n\r\n#### Draining our callback queue\r\n```java\r\n\r\n @QueueCallback({\r\n QueueCallbackType.EMPTY,\r\n QueueCallbackType.START_BATCH,\r\n QueueCallbackType.LIMIT})\r\n private void handleCallbacks() {\r\n\r\n flushServiceProxy(userDataService);\r\n Runnable runnable = callbacks.poll();\r\n\r\n while (runnable != null) {\r\n runnable.run();\r\n runnable = callbacks.poll();\r\n }\r\n }\r\n\r\n```\r\n\r\nIt is important to remember when handling callbacks from another microservice that you want to handle\r\ncallbacks from the other service before you handle more incomming requests from you clients.\r\nEssentially you have clients that have been waiting (async waiting but still), and these clients\r\nmight represent an open TCP/IP connection like an HTTP call so it is best to close them out\r\nbefore handling more requests and like we said they were already waiting around with an open connection\r\nfor users to load form the user service.\r\n\r\nTo learn more about CallBacks, plesae read [QBit Java MicroService Lib CallBack fundamentals]([Rough Cut] QBit Microservice Lib Working With CallBacks).\r\n\r\n\r\n\r\n\r\n## Workers - pools and shards\r\n\r\n```java\r\npublic class ServiceWorkers {\r\n\r\n public static RoundRobinServiceDispatcher workers() {...\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {...\r\n```\r\n\r\nYou can compose sharded workers (for in-memory, thread safe, CPU intensive services), or workers for IO\r\nor talking to foreign services or foreign buses.\r\n\r\nHere is an example that uses a worker pool with three service workers in it:\r\n\r\nLet's say you have a service that does something:\r\n\r\n```java\r\n\r\n //Your POJO\r\n public class MultiWorker {\r\n\r\n void doSomeWork(...) {\r\n ...\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nNow this does some sort of IO and you want to have a bank of these running not just one so you can do\r\nIO in parallel. After some performance testing, you found out that three is the magic number.\r\n\r\nYou want to use your API for accessing this service:\r\n\r\n```java\r\n public interface MultiWorkerClient {\r\n void doSomeWork(...);\r\n }\r\n\r\n```\r\n\r\nNow let's create a bank of these and use it.\r\n\r\nFirst create the QBit services which add the thread/queue/microbatch.\r\n\r\n```java\r\n\r\n /* Create a service builder. */\r\n final ServiceBuilder serviceBuilder = serviceBuilder();\r\n\r\n /* Create some qbit services. */\r\n final Service service1 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service2 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service3 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n```\r\n\r\nNow add them to a ServiceWorkers object.\r\n\r\n```java\r\n\r\n ServiceWorkers dispatcher;\r\n dispatcher = workers(); //Create a round robin service dispatcher\r\n dispatcher.addServices(service1, service2, service3);\r\n dispatcher.start(); // start up the workers\r\n\r\n```\r\n\r\nYou can add services, POJOs and method consumers, method dispatchers to a service bundle.\r\nThe service bundle is an integration point into QBit.\r\n\r\nLet's add our new Service workers. ServiceWorkers is a ServiceMethodDispatcher.\r\n\r\n```Java\r\n /* Add the dispatcher to a service bundle. */\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nWe are probably going to add a helper method to the service bundle so most of this can happen in\r\na single call.\r\n\r\nNow you can start using your workers.\r\n\r\n```java\r\n\r\n /* Start using the workers. */\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n```\r\n\r\nNow you could use Spring or Guice to configure the builders and the service bundle.\r\nBut you can just do it like the above which is good for testing and understanding QBit internals.\r\n\r\nQBit also supports the concept of sharded services which is good for sharding resources like CPU\r\n(run a rules engine on each CPU core for a user recommendation engine).\r\n\r\nQBit does not know how to shard your services, you have to give it a hint.\r\nYou do this through a shard rule.\r\n\r\n```java\r\npublic interface ShardRule {\r\n int shard(String methodName, Object[] args, int numWorkers);\r\n}\r\n```\r\nWe worked on an app where the first argument to the services was the username, and then we used that to\r\nshard calls to a CPU intensive in-memory rules engine. This technique works. :)\r\n\r\nThe ServiceWorkers class has a method for creating a sharded worker pool.\r\n\r\n```java\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nTo use you just pass a shard key when you create the service workers.\r\n\r\n```java\r\n\r\n\r\n dispatcher = shardedWorkers((methodName, methodArgs, numWorkers) -> {\r\n String userName = methodArgs[0].toString();\r\n int shardKey = userName.hashCode() % numWorkers;\r\n return shardKey;\r\n });\r\n\r\n```\r\n\r\nThen add your services to the ServiceWorkers composition.\r\n```java\r\n int workerCount = Runtime.getRuntime().availableProcessors();\r\n\r\n for (int index = 0; index < workerCount; index++) {\r\n final Service service = serviceBuilder\r\n .setServiceObject(new ContentRulesEngine()).build();\r\n dispatcher.addServices(service);\r\n\r\n }\r\n```\r\n\r\nThen add it to the service bundle as before.\r\n```java\r\n\r\n dispatcher.start();\r\n\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nThen just use it:\r\n\r\n```java\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n for (int index = 0; index < 100; index++) {\r\n String userName = \"rickhigh\" + index;\r\n worker.pickSuggestions(userName);\r\n }\r\n\r\n```\r\n\r\n### Built in shard rules\r\n\r\n```java\r\n\r\n\r\npublic class ServiceWorkers {\r\n...\r\n public static ShardedMethodDispatcher shardOnFirstArgumentWorkers() {\r\n ...\r\n }\r\n\r\n...\r\n\r\n public static ShardedMethodDispatcher shardOnFifthArgumentWorkers() {\r\n ...\r\n }\r\n\r\n\r\n public static ShardedMethodDispatcher shardOnBeanPath(final String beanPath) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nThe shardOnBeanPath allows you to create a complex bean path navigation call and use its property to shard on.\r\n\r\n```java\r\n\r\n /* shard on 2nd arg which is an employee\r\n Use the employees department's id property. */\r\n dispatcher = shardOnBeanPath(\"[1].department.id\");\r\n\r\n /* Same as above. */\r\n dispatcher = shardOnBeanPath(\"1/department/id\");\r\n\r\n```\r\n\r\n[Read more about Service sharding and service workers here](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-QBit-Microservices-using-Service-Workers-and-sharded-service-workers)\r\n\r\n\r\nYou can find a lot more in the wiki. Also follow the commits.\r\nWe have been busy beavers.\r\n[QBit the microservice lib for Java - JSON, REST, WebSocket](https://github.com/advantageous/qbit/wiki).",
"note": "Don't delete this file! It's used internally to help with page regeneration."
}
\ No newline at end of file
From f7938e463ebe3450ff8a5f17ade59a2596eaaf03 Mon Sep 17 00:00:00 2001
From: Richard Hightower
Date: Fri, 15 Apr 2016 08:24:33 -0700
Subject: [PATCH 08/19] Create gh-pages branch via GitHub
---
index.html | 2 +-
params.json | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/index.html b/index.html
index 7d864771..ae53d139 100644
--- a/index.html
+++ b/index.html
@@ -19,7 +19,7 @@
The Java microservice lib. QBit is a reactive progra
diff --git a/params.json b/params.json
index afb867d9..1bf15f38 100644
--- a/params.json
+++ b/params.json
@@ -1,6 +1,6 @@
{
"name": "QBit - Microservices Lib",
"tagline": "The Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.",
- "body": "[QBit Java Micorservices lib tutorials](https://github.com/MammatusTech/qbit-microservices-examples/wiki)|\r\n[QBit Website](http://advantageous.github.io/qbit/) | [QBit uses Reakt](http://advantageous.github.io/reakt/) | [QBit works with Vert.x](http://vertx.io/) | [Reakt Vertx](http://advantageous.github.io/reakt-vertx/)\r\n\r\n#QBit - The Microservice Lib for Java - JSON, REST, WebSocket, Speed! \r\n\r\n## Quick overview of QBit\r\n\r\nThe Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.\r\n\r\nGot a question? Ask here: [QBit Google Group](https://groups.google.com/forum/#!forum/qbit-microservice).\r\n\r\nEverything is a queue. You have a choice. You can embrace it and control it. You can optimize for it.\r\nOr you can hide behind abstractions. QBit opens you up to peeking into what is going on, and allows you\r\nto pull some levers without selling your soul.\r\n\r\nQBit is a library not a framework. You can mix and match QBit with Spring, Guice, etc.\r\n\r\nQBit is FAST!\r\n\r\n\r\n\r\n#### Using from maven\r\n```xml\r\n\r\n io.advantageous.qbit\r\n qbit-admin\r\n 1.0.0.RELEASE\r\n\r\n\r\n io.advantageous.qbit\r\n qbit-vertx\r\n 1.0.0.RELEASE\r\n\r\n```\r\n\r\n#### Using from gradle\r\n```java\r\ncompile 'io.advantageous.qbit:qbit-admin:1.0.0.RELEASE'\r\ncompile 'io.advantageous.qbit:qbit-vertx:1.0.0.RELEASE'\r\n```\r\n\r\nCore Features\r\n============\r\n\r\n* Write REST based async microservices\r\n* Write ***WebSocket*** based async microservices (fast async RPC over WebSocket)\r\n* Actor Service Queues using micro-batching for high-speed message passing\r\n* Strongly async typed event bus which can be distributed\r\n* Async low overhead metrics gathering which can be queried and distributed (for doing fast lane analytics)\r\n* Complex async call coordination (with the Reactor) for reactive programming\r\n* Built-in support for ***health checks*** (and integration with tools like Consul)\r\n* Built-in support for ***monitoring*** (and integration with wire protocols like StatsD)\r\n* Built-in support for ***Service Discovery*** (with integration with health system, DNS SRV records and Consul)\r\n* Integration with persistent queues\r\n* [12 factor app port bindings](http://12factor.net/), health checks, KPI gathering, Logging MDC\r\n* API Gateway support for client generation and consumption via [Swagger](http://swagger.io/).\r\n* Our services can generate Swagger files (like idl for JSON/REST).\r\n* Remote client proxies for WebSocket (your interface is your IDL)\r\n\r\n\r\nStatus\r\n=====\r\nDeployed at several large fortune 100 companies. \r\nQBit now works with Vertx (standalone or embedded).\r\nYou can also use QBit on non-QBit projects, it is just a lib.\r\n\r\nLicense\r\n=====\r\nApache 2\r\n\r\n\r\n## Java Microservice Lib\r\n\r\nQBit has inproc services, REST microservices and WebSocket microservices as well as an\r\nin-proc service event bus (which can be per module or per app). It supports workers and in-memory services.\r\n\r\nBefore we describe more, here are two sample services:\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {...\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {...\r\n```\r\n\r\n\r\n#### Adder Service using URI params\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {...\r\n }\r\n```\r\n\r\n\r\n\r\nQBit philosophy:\r\n====\r\nAt the end of the day QBit is a simple library not a framework.\r\nYour app is not a QBit app but a Java app that uses the QBit lib.\r\nQBit allows you to work with Java UTIL concurrent, and does not endeavor to hide it from you.\r\nJust trying to take the sting out of it.\r\n\r\nDoes it work\r\n=====\r\nWe have used techniques in Boon and QBit with great success in high-end, high-performance, high-scalable apps.\r\nWe helped clients handle 10x the load with 1/10th the servers of their competitors using techniques in QBit.\r\nQBit is us being sick of hand tuning queue access and threads.\r\n\r\n\r\nBoon and QBit humility policy\r\n=====\r\nIdeas for Boon and QBit often come from all over the web. We make mistakes. Point them out.\r\nAs a developer of Boon and QBit, we are fellow travelers.\r\nIf you have an idea or technique you want to share, we listen.\r\n\r\n\r\nInspiration\r\n====\r\n\r\nA big inspiration for Boon/QBit was Vertx, Akka, Go Channels, Active Objects, Apartment Model Threading, Actor,\r\nand the Mechanical Sympathy papers.\r\n\r\nQBit has ideas that are similar to many frameworks. We are all reading the same papers.\r\nQBit got inspiration from the LMAX disruptor papers and this blog post about\r\n[link transfer queue versus disruptor](http://php.sabscape.com/blog/?p=557). We had some theories about\r\nqueues that blog post inspired us to try them out. Some of these theories are deployed at some of the\r\nbiggest middleware backends and whose name brands are known around the world. And thus QBit was born.\r\n\r\nQBit also took an lot of inspiration by the great work done\r\nby Tim Fox on Vertx. The first project using something that could actually be called QBit (albeit early QBit)\r\n was using Vertx on an web/mobile microservice for an app that could potentially have 80 million users.\r\n It was this\r\nexperience with Vertx and early QBit that led to QBit development and evolution. QBit is built on the\r\nshoulders of giants (Netty/Vertx).\r\n\r\nDoes QBit compete with...\r\n====\r\nSpring Disruptor: No. You could use QBit to write plugins for Spring Disruptor I suppose, but QBit does\r\nnot compete with Spring Disruptor.\r\nSpring Boot/Spring MVC: No. We use the same annotations but QBit is geared for high-speed in-memory\r\nmicroservices. It is more like Akka than Spring Boot. QBit has a subset of the features of Spring MVC\r\ngeared only for microservices, i.e., WebSocket RPC, REST, JSON marshaling, etc.\r\nAkka: No. Well Maybe. Akka has similar concepts but they take a different approach. QBit is more focused\r\n on Java, and microservices (REST, JSON, WebSocket) than Akka.\r\nLMAX Disruptor: No. In fact, we can use disruptor as on of the queues that QBit uses underneath the covers.\r\n\r\n\r\n(Early benchmarks have been removed. They were here. QBit got a lot faster.\r\n Benchmarking QBit is a moving target at the moment.\r\n Links and reports will be created.)\r\n\r\n\r\nCode Examples\r\n\r\n\r\n## Basic Queue example (REST style services is further down)\r\n\r\n====\r\n\r\n```java\r\n\r\n BasicQueue queue = BasicQueue.create(Integer.class, 1000);\r\n\r\n //Sending threads\r\n\r\n SendQueue sendQueue = queue.sendQueue();\r\n for (int index = 0; index < amount; index++) {\r\n sendQueue.send(index);\r\n }\r\n sendQueue.flushSends();\r\n ...\r\n sendQueue.sendAndFlush(code);\r\n //other methods for sendQueue, writeBatch, writeMany\r\n\r\n\r\n //Receiving Threads\r\n ReceiveQueue receiveQueue = queue.receiveQueue();\r\n Integer item = receiveQueue.take();\r\n //other methods poll(), pollWait(), readBatch(), readBatch(count)\r\n```\r\n\r\n\r\n### What is QBit again?\r\n\r\nQBit is a queuing library for microservices. It is similar to many other projects like Akka, Spring Reactor,\r\netc. QBit is just a library not a platform. QBit has libraries to put a service behind a queue.\r\nYou can use QBit queues directly or you can create a service. QBit services can be exposed by WebSocket,\r\nHTTP, HTTP pipeline, and other types of remoting. A service in QBit is a Java class whose methods are\r\n executed behind service queues. QBit implements apartment model threading and is similar to the\r\n Actor model or a better description would be Active Objects. QBit does not use a disruptor (but could).\r\n It uses regular Java Queues. QBit can do north of 100 million ping pong calls per second which is\r\n an amazing speed (seen as high as 200M). QBit also supports calling services via REST, and WebSocket.\r\n QBit is microservices in the pure Web sense: JSON, HTTP, WebSocket, etc. QBit uses micro batching to\r\n push messages through the pipe (queue, IO, etc.) faster to reduce thread hand-off.\r\n\r\n### QBit lingo\r\n\r\nQBit is a Java microservice lib supporting REST, JSON and WebSocket. It is written in Java but we could\r\none day write a version in Rust or Go or C# (but that would require a large payday).\r\n\r\n**Service**\r\nPOJO (plain old Java object) behind a queue that can receive method calls via proxy calls or events\r\n(May have one thread managing events, method calls, and responses or two one for method calls and events\r\n 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.\r\n\r\n**ServiceBundle**\r\nMany POJOs behind one response queue and many receive queues. There may be one thread for all responses\r\nor not. They also can be one receive queue.\r\n\r\n**Queue**\r\nA thread managing a queue. It supports batching. It has events for empty, reachedLimit, startedBatch,\r\nidle. You can listen to these events from services that sit behind a queue. You don't have to use Services.\r\nYou can use Queue's direct. In QBit, you have sender queues and receivers queues. They are separated to\r\nsupport micro-batching.\r\n\r\n**ServiceEndpointServer**\r\nServiceBundle that is exposed to REST and WebSocket communication.\r\n\r\n**EventBus**\r\nEventBus is a way to send a lot of messages to services that may be loosely coupled.\r\n\r\n**ClientProxy**\r\nClientProxy is a way to invoke service through async interface, service can be inproc (same process) or\r\nremoted over WebSocket.\r\n\r\n**Non-blocking**\r\nQBit is a non-blocking lib. You use CallBacks via Java 8 Lambdas. You can also send event messages and get\r\nreplies. Messaging is built into the system so you can easily coordinate complex tasks.\r\nQBit takes an object-oriented approach to service development so services look like normal Java services\r\nthat you\r\nalready write, but the services live behind a queue/thread. This is not a new concept. Microsoft did this\r\nwith DCOM/COM and called it active objects. Akka does it with actors and called them strongly typed Actors.\r\nThe important concepts is that you get the speed of reactive and actor style messaging but you develop\r\nin a natural OOP approach. QBit is not the first. QBit is not the only.\r\n\r\n\r\n**Speed**\r\nQBit is VERY fast. There is a of course a lot of room for improvement. But already 200M+ TPS inproc ping pong, 10M-20M+ TPS event bus, 500K TPS RPC calls over WebSocket/JSON, etc.\r\nMore work needs to be done to improve speed, but now it is fast enough where we are focusing more on\r\nusability.\r\nThe JSON support uses Boon by default which is up to 4x faster than other JSON parsers for the\r\nREST/JSON, WebSocket/JSON use case.\r\n\r\n**Reactive Programming**\r\nQBit provides a **Reactor** to manage async calls. This allows callbacks to be handled on the same thread that called them and it provides for timeout and error handling. Read [Reactor tutorial for creating reactive micro service programming](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices)\r\n\r\n**Service Discovery**\r\nBuilt in support for service discovery. This includes integration with Consul.\r\n\r\n\r\n**StatService**\r\nBuilt in support for stats. The **StatService** can be integrated with **StatsD** (Graphite, Grafana, DataDog, etc.) to publish passive stats. Or you can query the stats engine and react to the stats (counts, timings and levels). The **StatsService** is a reactive stats system that can be clustered. The StatService is reactive in that your services can publish to it and query it and react based on the results. You can implement things like rate limiting and react to an increased rate of something. The ServiceDiscovery system integrates with the HealthSystem and Consul to roll up each of your internal services that make up you micro service and publish the composite availably of your micro service to a single HTTP endpoint or a dead mans switch in Consul (TTL). \r\n\r\n\r\n\r\n### CURLable REST services example\r\n\r\nTalk is cheap. Let's look at some code. You can get a detailed walk through in the Wiki.\r\nWe have a lot of documentation already.\r\n\r\nWe will create a service that is exposed through REST/JSON.\r\n\r\nTo query the size of the todo list:\r\n\r\n```bash\r\ncurl localhost:8080/services/todo-service/todo/count\r\n```\r\n\r\nTo add a new TODO item.\r\n\r\n```bash\r\ncurl -X POST -H \"Content-Type: application/json\" -d \\\r\n'{\"name\":\"xyz\",\"description\":\"xyz\"}' \\\r\nhttp://localhost:8080/services/todo-service/todo\r\n```\r\n\r\nTo get a list of TODO items\r\n```bash\r\ncurl http://localhost:8080/services/todo-service/todo/\r\n```\r\n\r\nThe TODO example will use and track Todo items.\r\n\r\n#### Todo item POJO sans getter\r\n\r\n```java\r\npackage io.advantageous.qbit.examples;\r\n\r\nimport java.util.Date;\r\n\r\n\r\npublic class TodoItem {\r\n\r\n\r\n private final String description;\r\n private final String name;\r\n private final Date due;\r\n\r\n```\r\n\r\nThe TodoService uses Spring MVC style annotations.\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n\r\n private List todoItemList = new ArrayList<>();\r\n\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {\r\n\r\n return todoItemList.size();\r\n }\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {\r\n\r\n return todoItemList;\r\n }\r\n\r\n @RequestMapping(value = \"/todo\", method = RequestMethod.POST)\r\n public void add(TodoItem item) {\r\n\r\n todoItemList.add(item);\r\n }\r\n\r\n}\r\n\r\n```\r\n\r\n\r\n#### Sending non-JSON\r\n\r\nYou can POST/PUT non-JSON and you can capture the body as a `String` or as a `byte[]`. \r\nIf the content-type is set to anything but `application/json` and your body is defined a String or byte[].\r\nThis works automatically. (The content-type has to be set.)\r\n\r\n```java\r\n @RequestMapping(value = \"/body/bytes\", method = RequestMethod.POST)\r\n public boolean bodyPostBytes( byte[] body) {\r\n String string = new String(body, StandardCharsets.UTF_8);\r\n return string.equals(\"foo\");\r\n }\r\n\r\n @RequestMapping(value = \"/body/string\", method = RequestMethod.POST)\r\n public boolean bodyPostString(String body) {\r\n return body.equals(\"foo\");\r\n }\r\n```\r\n\r\n\r\n#### Sending different response codes for success\r\n\r\nBy default QBit sends a `200` (OK) for a non-void call (a call that has a return or a Callback). If the REST operation has no return or no callback then QBit sends a `202` (Accepted). There may be times when you want to send a 201 (Created) or some other code that is not an Exception. You can do that by setting `code` on `@RequestMapping`. By default the code is -1 which means use the default behavior (200 for success, 202 for one-way message, and 500 for errors).\r\n\r\n\r\n#### Sending different response codes for success\r\n```java\r\n\r\n @RequestMapping(value = \"/helloj7\", code = 221)\r\n public void helloJSend7(Callback>> callback) {\r\n callback.returnThis(JSendResponseBuilder.jSendResponseBuilder(Lists.list(\r\n \"hello \" + System.currentTimeMillis())).build());\r\n }\r\n\r\n```\r\n\r\n`Callbacks` can be used for internal services as well. It is often the case that you use a [CallbackBuilder](https://github.com/advantageous/qbit/wiki/%5BDocument%5D-CallbackBuilder-and-generics-for-Reactive-Java-Microservices) or a QBit [Reactor](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices) to manage service calls. \r\n\r\n#### Working with non JSON responses\r\n\r\nYou do not have to return JSON form rest calls.\r\nYou can return any binary or any text by using `HttpBinaryResponse` and `HttpTextResponse`.\r\n\r\n#### Returning non JSON from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildTextResponse());\r\n }\r\n```\r\n\r\n\r\n#### Returning binary from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildBinaryResponse());\r\n }\r\n```\r\n\r\n#### Side note Why Spring style annotations?\r\nWhy did we pick Spring style annotations?\r\n1) Spring is not a standard and neither is QBit. 2) We found the Spring annotations to be less verbose.\r\n3) More people use Spring than Java EE. We wrote QBit for people to use.\r\nWe could easily support JAX-RS style annotations, and we probably will.\r\nSince QBit focuses on JSON, we do not need all of the complexity of JAX-RS or even all the features of\r\nthe Spring MVC annotations. Also we can literally use the actual Spring annotations. QBit and Boon\r\nuse a non-type safe mechanism for annotations which means they are not tied to a particular lib.\r\nYou can define your own. We hate vendor tie-in even if it is an open source vendor.\r\n(We also support @POST, @GET which is similar to JAX-RS).\r\n\r\nNow just start it up.\r\n\r\n```java\r\n\r\n public static void main(String... args) {\r\n\r\n ServiceEndpointServer server = new EndpointServerBuilder().build();\r\n server.initServices(new TodoService());\r\n server.start();\r\n }\r\n```\r\n\r\n\r\n\r\nThat is it. There is also out of the box WebSocket support with client side proxy generation so\r\nyou can call into services at the rate of millions of calls per second.\r\n\r\n## Using URI Params for QBit microservice\r\n\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {\r\n\r\n return a + b;\r\n }\r\n }\r\n\r\n```\r\n\r\n## WebSocket\r\nYou can always invoke QBit services via a WebSocket proxy.\r\nThe advantage of a WebSocket proxy is it allows you execute 1M RPC+ a second (1 million remote calls\r\nevery second).\r\n\r\n\r\n#### Using a microservice remotely with WebSocket\r\n```java\r\n /* Start QBit client for WebSocket calls. */\r\n final Client client = clientBuilder()\r\n .setPort(7000).setRequestBatchSize(1).build();\r\n\r\n\r\n /* Create a proxy to the service. */\r\n final AdderServiceClientInterface adderService =\r\n client.createProxy(AdderServiceClientInterface.class,\r\n \"adder-service\");\r\n\r\n client.start();\r\n\r\n\r\n\r\n /* Call the service */\r\n adderService.add(System.out::println, 1, 2);\r\n\r\n```\r\n\r\nThe output is 3.\r\n\r\n```output\r\n3\r\n```\r\n\r\n\r\nThe above uses a WebSocket proxy interface to call the service async.\r\n\r\n```java\r\n\r\n interface AdderServiceClientInterface {\r\n\r\n void add(Callback callback, int a, int b);\r\n }\r\n```\r\n\r\n#### ServiceDiscovery aware websocket builders\r\n\r\nCreate websocket service client that is ServiceDiscovery aware.\r\n\r\n\r\n```java\r\n final Client client = clientBuilder.setServiceDiscovery(serviceDiscovery, \"echo\")\r\n .setUri(\"/echo\").setProtocolBatchSize(20).build().startClient();\r\n\r\n\r\n final EchoAsync echoClient = client.createProxy(EchoAsync.class, \"echo\");\r\n```\r\n\r\nCurrently the `clientBuilder` will load all service endpoints that are registered under the service name,\r\nand randomly pick one. \r\n\r\nServiceDiscovery includes Consul based, watching JSON files on disk, and DNS. It is easy to write your own service discovery as well and plug it into QBit.\r\n\r\n\r\nIn the future we can RoundRobin calls or shard calls to websocket service and/or provide auto fail over if the connection is closed. We do this for the event bus that uses service discovery but it is not baked into WebSocket based client stubs yet.\r\n\r\n\r\n## REST call with URI params\r\n\r\nThe last client example uses WebSocket. You could also just use REST, and actually use the URI params\r\nthat we setup.\r\nREST is nice but it is going to be slower than WebSocket support.\r\n\r\nQBit ships with a nice little HTTP client. We can use it.\r\n\r\nYou can use it to send async calls and WebSocket messages with the HTTP client.\r\n\r\n\r\nHere we will use the http client to invoke our remote method:\r\n\r\n#### Using a microservice remotely with REST QBit microservice client\r\n```java\r\n\r\n\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\")\r\n .setPort(7000).build();\r\n\r\n httpClient.start();\r\n String results = httpClient\r\n .get(\"/services/adder-service/add/2/2\").body();\r\n System.out.println(results);\r\n\r\n```\r\n\r\n\r\nThe output is 4.\r\n\r\n```output\r\n4\r\n```\r\n\r\n## Accessing The URI Param example with CURL\r\n\r\nYou can also access the service from curl.\r\n\r\n```bash\r\n$ curl http://localhost:7000/services/adder-service/add/2/2\r\n```\r\n\r\nSee this full example here: [QBit microservice getting started tutorial](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-------------QBit-microservice-example).\r\n\r\n[QBit URI params and WebSocket proxy client](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Using-QBit-microservice-lib's-REST-support-with-URI-Params)\r\n\r\n## Working with WebSocket, HttpClient etc.\r\n\r\nQBit has a library for working with and writing async microservices that is lightweight and fun to use.\r\n\r\n#### WebSocket server and client.\r\n\r\n\r\n#### Create an HTTP server\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n```\r\n\r\n#### Setup server WebSocket support\r\n```java\r\n /* Setup WebSocket Server support. */\r\n httpServer.setWebSocketOnOpenConsumer(webSocket -> {\r\n webSocket.setTextMessageConsumer(message -> {\r\n webSocket.sendText(\"ECHO \" + message);\r\n });\r\n });\r\n\r\n```\r\n\r\n#### Start the server\r\n```java\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n```\r\n\r\n#### Setup the WebSocket client\r\n```java\r\n\r\n /** CLIENT. */\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\n#### Client WebSocket\r\n\r\n```java\r\n\r\n /* Setup the client websocket. */\r\n WebSocket webSocket = httpClient\r\n .createWebSocket(\"/websocket/rocket\");\r\n\r\n /* Setup the text consumer. */\r\n webSocket.setTextMessageConsumer(message -> {\r\n System.out.println(message);\r\n });\r\n webSocket.openAndWait();\r\n\r\n /* Send some messages. */\r\n webSocket.sendText(\"Hi mom\");\r\n webSocket.sendText(\"Hello World!\");\r\n\r\n```\r\n\r\n#### Output\r\n```output\r\n\r\nECHO Hi mom\r\nECHO Hello World!\r\n\r\n```\r\n\r\nNow stop the server and client. Pretty easy eh?\r\n\r\n## High-speed HTTP client and server done microservice style\r\n\r\n\r\n##### Starting up an HTTP server\r\n\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n /* Setting up a request Consumer with Java 8 Lambda expression. */\r\n httpServer.setHttpRequestConsumer(httpRequest -> {\r\n\r\n Map results = new HashMap<>();\r\n results.put(\"method\", httpRequest.getMethod());\r\n results.put(\"uri\", httpRequest.getUri());\r\n results.put(\"body\", httpRequest.getBodyAsString());\r\n results.put(\"headers\", httpRequest.getHeaders());\r\n results.put(\"params\", httpRequest.getParams());\r\n httpRequest.getReceiver()\r\n .response(200, \"application/json\", Boon.toJson(results));\r\n });\r\n\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n\r\n\r\n```\r\n\r\nThe focus is on ease of use and using Java 8 Lambdas for callbacks so the code is tight and small.\r\n\r\n[Find out more about QBit's microservice style WebSocket support here](https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-WebSocket-support)\r\n\r\n\r\n## Using HTTP Client lib\r\n\r\nNow, let's try out our HTTP client.\r\n\r\n##### Starting up an HTTP client\r\n\r\n```java\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\nYou just pass the URL, the port and then call start.\r\n\r\n## Synchronous HTTP calls\r\n\r\nNow you can start sending HTTP requests.\r\n\r\n##### No Param HTTP GET\r\n\r\n```java\r\n /* Send no param get. */\r\n HttpResponse httpResponse = httpClient.get( \"/hello/mom\" );\r\n puts( httpResponse );\r\n```\r\n\r\nAn HTTP response just contains the results from the server.\r\n\r\n\r\n##### No Param HTTP Response\r\n\r\n```java\r\npublic interface HttpResponse {\r\n\r\n MultiMap headers();\r\n\r\n int code();\r\n\r\n String contentType();\r\n\r\n String body();\r\n\r\n}\r\n\r\n```\r\n\r\nThere are helper methods for sync HTTP GET calls.\r\n\r\n\r\n\r\n##### Helper methods for GET\r\n```java\r\n\r\n\r\n /* Send one param get. */\r\n httpResponse = httpClient.getWith1Param(\"/hello/singleParam\",\r\n \"hi\", \"mom\");\r\n puts(\"single param\", httpResponse );\r\n\r\n\r\n /* Send two param get. */\r\n httpResponse = httpClient.getWith2Params(\"/hello/twoParams\",\r\n \"hi\", \"mom\", \"hello\", \"dad\");\r\n puts(\"two params\", httpResponse );\r\n\r\n...\r\n\r\n /* Send five param get. */\r\n httpResponse = httpClient.getWith5Params(\"/hello/5params\",\r\n \"hi\", \"mom\",\r\n \"hello\", \"dad\",\r\n \"greetings\", \"kids\",\r\n \"yo\", \"pets\",\r\n \"hola\", \"neighbors\");\r\n puts(\"5 params\", httpResponse );\r\n\r\n\r\n```\r\n\r\nThe puts method is a helper method it does System.out.println more or less by the way.\r\n\r\nThe first five params are covered. Beyond five, you have to use the HttpBuilder.\r\n\r\n```java\r\n\r\n\r\n /* Send six params with get. */\r\n\r\n final HttpRequest httpRequest = httpRequestBuilder()\r\n .addParam(\"hi\", \"mom\")\r\n .addParam(\"hello\", \"dad\")\r\n .addParam(\"greetings\", \"kids\")\r\n .addParam(\"yo\", \"pets\")\r\n .addParam(\"hola\", \"pets\")\r\n .addParam(\"salutations\", \"all\").build();\r\n\r\n httpResponse = httpClient.sendRequestAndWait(httpRequest);\r\n puts(\"6 params\", httpResponse );\r\n```\r\n\r\n## Http Async HTTP Client\r\n\r\nThere are async calls for GET as well.\r\n\r\n#### Async calls for HTTP GET using Java 8 lambda\r\n\r\n```java\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsync(\"/hi/async\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith1Param(\"/hi/async\", \"hi\", \"mom\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda 1 param\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith2Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 2 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n...\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith5Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n \"p3\", \"v3\",\r\n \"p4\", \"v4\",\r\n \"p5\", \"v5\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 5 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n```\r\n\r\n[Find more about the easy to use, fast microservice HTTP client here]\r\n(https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-HttpClient-GET,-POST,-et-al,-JSON,-Java-8-Lambda).\r\n\r\n## InProc QBit services\r\n\r\nQBit allows for services behind queues to be run in-proc as well.\r\n\r\n```java\r\n\r\n /* POJO service. */\r\n final TodoManager todoManagerImpl = new TodoManager();\r\n\r\n /*\r\n Create the service which manages async calls to todoManagerImpl.\r\n */\r\n final Service service = serviceBuilder()\r\n .setServiceObject(todoManagerImpl)\r\n .build().startServiceQueue();\r\n\r\n\r\n /* Create Asynchronous proxy over Synchronous service. */\r\n final TodoManagerClientInterface todoManager =\r\n service.createProxy(TodoManagerClientInterface.class);\r\n\r\n service.startCallBackHandler();\r\n\r\n\r\n System.out.println(\"This is an async call\");\r\n /* Asynchronous method call. */\r\n todoManager.add(new Todo(\"Call Mom\", \"Give Mom a call\"));\r\n\r\n\r\n AtomicInteger countTracker = new AtomicInteger();\r\n //Hold count from async call to service... for testing and showing it is an async callback\r\n\r\n System.out.println(\"This is an async call to count\");\r\n\r\n todoManager.count(count -> {\r\n System.out.println(\"This lambda expression is the callback \" + count);\r\n\r\n countTracker.set(count);\r\n });\r\n\r\n\r\n todoManager.clientProxyFlush(); //Flush all methods. It batches calls.\r\n\r\n Sys.sleep(100);\r\n\r\n System.out.printf(\"This is the count back from the server %d\\n\", countTracker.get());\r\n\r\n```\r\n\r\n[Detailed tutorial on in-proc services is being written.](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-Working-with-inproc-MicroServices-within-QBit.)\r\n\r\n\r\n## QBit Event Bus\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\nQBit also has a service event bus. This example is a an employee benefits services example.\r\n\r\nWe have two channels.\r\n\r\n```\r\npublic static final String NEW_HIRE_CHANNEL = \"com.mycompnay.employee.new\";\r\n\r\npublic static final String PAYROLL_ADJUSTMENT_CHANNEL = \"com.mycompnay.employee.payroll\";\r\n```\r\n\r\nAn employee object looks like this:\r\n\r\n```java\r\n\r\npublic static class Employee {\r\n final String firstName;\r\n final int employeeId;\r\n```\r\n\r\n\r\nThis example has three services: EmployeeHiringService, BenefitsService, and PayrollService.\r\n\r\nThese services are inproc services. QBit supports WebSocket, HTTP and REST remote services as well, but for now, let's focus on inproc services. If you understand inproc then you will understand remote.\r\n\r\nThe EmployeeHiringService actually fires off the events to other two services.\r\n\r\n```java\r\npublic class EmployeeHiringService {\r\n\r\n\r\n public void hireEmployee(final Employee employee) {\r\n\r\n int salary = 100;\r\n System.out.printf(\"Hired employee %s\\n\", employee);\r\n\r\n //Does stuff to hire employee\r\n\r\n //Sends events\r\n final EventManager eventManager =\r\n serviceContext().eventManager();\r\n eventManager.send(NEW_HIRE_CHANNEL, employee);\r\n\r\n eventManager.sendArray(PAYROLL_ADJUSTMENT_CHANNEL,\r\n employee, salary);\r\n\r\n\r\n }\r\n\r\n }\r\n```\r\n\r\n\r\nNotice that we call sendArray so we can send the employee and their salary.\r\nThe listener for PAYROLL_ADJUSTMENT_CHANNEL will have to handle both an employee and an int\r\nthat represents the new employees salary.\r\nYou can also use event bus proxies so you do not have to call into the event bus at all.\r\n\r\nThe BenefitsService listens for new employees being hired so it can enroll them into the benefits system.\r\n\r\n```java\r\npublic static class BenefitsService {\r\n\r\n @OnEvent(NEW_HIRE_CHANNEL)\r\n public void enroll(final Employee employee) {\r\n\r\n System.out.printf(\"Employee enrolled into benefits system employee %s %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId());\r\n\r\n }\r\n\r\n```\r\n\r\nDaddy needs to get paid.\r\n\r\n```java\r\n public static class PayrollService {\r\n\r\n @OnEvent(PAYROLL_ADJUSTMENT_CHANNEL)\r\n public void addEmployeeToPayroll(final Employee employee, int salary) {\r\n\r\n System.out.printf(\"Employee added to payroll %s %d %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId(), salary);\r\n\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nThe employee is the employee object from the EmployeeHiringService.\r\n\r\nso you can get your benefits, and paid!\r\n\r\nFind more details here:\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\n\r\n## Private event bus and event bus proxies\r\n\r\n You can define your own interface to the event bus and you can use your own event buses with QBit.\r\n Each module in your service can have its own internal event bus.\r\n\r\n To learn more read:\r\n [QBit Microservice working with a private event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-private-event-bus-for-inproc-microservices)\r\n and [QBit Java Microservice lib using your own interface to the event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-strongly-typed-event-bus-proxies-for-QBit-Java-Microservice-lib).\r\n\r\n\r\n\r\n## Queue Callbacks\r\n\r\n To really grasp QBit, one must grasp the concepts of a CallBack.\r\n\r\n A CallBack is a way to get an async response in QBit.\r\n\r\n You call a service method and it calls you back.\r\n\r\n Client proxies can have callbacks:\r\n\r\n\r\n#### Queue Callbacks - RecommendationService client interface\r\n```java\r\n\r\npublic interface RecommendationServiceClient {\r\n\r\n\r\n void recommend(final Callback> recommendationsCallback,\r\n final String userName);\r\n}\r\n\r\n```\r\n\r\nCallbacks are Java 8 Consumers with some optional extra error handling.\r\n\r\n\r\n#### Queue Callbacks - Callback\r\n\r\n```java\r\n\r\n\r\npublic interface Callback extends java.util.function.Consumer {\r\n default void onError(java.lang.Throwable error) { /* compiled code */ }\r\n}\r\n\r\n```\r\n\r\nServices that can block should use callbacks.\r\nThus if loadUser blocked in the following example, it should really use a callback instead of returning a value.\r\n\r\npublic class RecommendationService {\r\n\r\n#### Queue Callbacks - Simple minded implementation of RecommendationService\r\n```java\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n public List recommend(final String userName) {\r\n User user = users.get(userName);\r\n if (user == null) {\r\n user = loadUser(userName);\r\n }\r\n return runRulesEngineAgainstUser(user);\r\n }\r\n\r\n```\r\n\r\n\r\nLet's pretend `loadUser` has to look in a local cache, and if the user is not found, look in an off-heap cache\r\nand if not found it must ask for the user from the UserService which must check its caches and perhaps fallback\r\nto loading the user data from a database or from other services.\r\nIn other words, `loadUser` can potentially block on IO.\r\n\r\n\r\n\r\n### Queue Callbacks - The first rule of Queue Club - don't block\r\n\r\n\r\nOur client does not block, but our service does. Going back to our `RecommendationService`.\r\nIf we get a lot of cache hits for user loads, perhaps the\r\nblock will not be that long, but it will be there and every time we have to fault in a user, the whole system\r\nis gummed up. What we want to be able to do is if we can't handle the recommendation request,\r\nwe go ahead and make an async call to the `UserDataService`. When that async callback comes back, then we\r\nhandle that request. In the mean time, we handle recommendation lists requests as quickly as we can.\r\nWe never block.\r\n\r\n\r\nSo let's revisit the service. The first thing we are going to do is make the service method take\r\na callback. Before we do that, let's set down some rules.\r\n\r\n\r\n#### The first rule of queue club don't block.\r\n#### The second rule of queue club if you are not ready, use a callback and continue handling stuff you are ready for\r\n\r\n\r\n#### Queue Callbacks - Adding a CallBack to the RecommendationService inproc microservice\r\n\r\n```java\r\npublic class RecommendationService {\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n```\r\n\r\n\r\n\r\nNow we are taking a callback and we can decide when we want to handle this recommendation generation request.\r\nWe can do it right away if there user data we need is in-memory or we can delay it.\r\n\r\n\r\n#### If the user is found, call the callback right away for RecommendationService inproc microservice\r\n\r\n```java\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n /** Look for user in user cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n ...\r\n } else {\r\n /* Call the callback now because we can handle the callback now. */\r\n recommendationsCallback.accept(runRulesEngineAgainstUser(user));\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nNotice, if the user is found in the cache, we run our recommendation rules in-memory and call the callback right away\r\n`recommendationsCallback.accept(runRulesEngineAgainstUser(user))`.\r\n\r\nThe interesting part is what do we do if don't have the user loaded.\r\n\r\n\r\n#### If the user was not found, load him from the user microservice, but still don't block\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using Callback. */\r\n userDataService.loadUser(new Callback() {\r\n @Override\r\n public void accept(final User loadedUser) {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nHere we use a CallBack to load the user, and when the user is loaded, we call `handleLoadFromUserDataService`\r\nwhich adds some management about handling the callback so we can still handle this call, just not now.\r\n\r\n\r\n\r\n#### Lambda version of last example\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using lambda expression. */\r\n userDataService.loadUser(\r\n loadedUser -> {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nUsing lambdas like this makes the code more readable and terse, but remember don't deeply nest\r\nlambda expressions or you will create a code maintenance nightmare. Use them judiciously.\r\n\r\n\r\n### Queue Callbacks - Doing something later\r\n\r\nWhat we want is to handle the request for recommendations after the user service system loads\r\nthe user from its store.\r\n\r\n\r\n\r\n#### Handling UserServiceData callback methods once we get them.\r\n\r\n```java\r\n\r\npublic class RecommendationService {\r\n\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n private UserDataServiceClient userDataService;\r\n\r\n\r\n private BlockingQueue callbacks =\r\n new ArrayBlockingQueue(10_000);\r\n\r\n\r\n ...\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n ...\r\n\r\n }\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks queue. */\r\n callbacks.add(new Runnable() {\r\n @Override\r\n public void run() {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n }\r\n });\r\n }\r\n\r\n\r\n\r\n```\r\n\r\n\r\n\r\n\r\n#### handleLoadFromUserDataService rewritten using Lambda\r\n\r\n```java\r\n\r\n\r\npublic class RecommendationService {\r\n\r\n...\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks list. */\r\n callbacks.add(() -> {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n });\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nThe important part there is that every time we get a callback call from `UserDataService`, we then\r\nperform our CPU intensive recommendation rules and callback our caller. Well not exactly, what we\r\ndo is enqueue an runnable onto our callbacks queue, and later we will iterate through those but when?\r\n\r\n\r\n### Queue Callbacks Handling callbacks when our receive queue is empty, a new batch started or we hit a batch limit\r\n\r\nThe `RecommendationService` can be notified when its queue is empty, it has started a new batch and when\r\nit has reached a batch limit. These are all good times to handle callbacks from the `UserDataService`.\r\n\r\n#### Draining our callback queue\r\n```java\r\n\r\n @QueueCallback({\r\n QueueCallbackType.EMPTY,\r\n QueueCallbackType.START_BATCH,\r\n QueueCallbackType.LIMIT})\r\n private void handleCallbacks() {\r\n\r\n flushServiceProxy(userDataService);\r\n Runnable runnable = callbacks.poll();\r\n\r\n while (runnable != null) {\r\n runnable.run();\r\n runnable = callbacks.poll();\r\n }\r\n }\r\n\r\n```\r\n\r\nIt is important to remember when handling callbacks from another microservice that you want to handle\r\ncallbacks from the other service before you handle more incomming requests from you clients.\r\nEssentially you have clients that have been waiting (async waiting but still), and these clients\r\nmight represent an open TCP/IP connection like an HTTP call so it is best to close them out\r\nbefore handling more requests and like we said they were already waiting around with an open connection\r\nfor users to load form the user service.\r\n\r\nTo learn more about CallBacks, plesae read [QBit Java MicroService Lib CallBack fundamentals]([Rough Cut] QBit Microservice Lib Working With CallBacks).\r\n\r\n\r\n\r\n\r\n## Workers - pools and shards\r\n\r\n```java\r\npublic class ServiceWorkers {\r\n\r\n public static RoundRobinServiceDispatcher workers() {...\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {...\r\n```\r\n\r\nYou can compose sharded workers (for in-memory, thread safe, CPU intensive services), or workers for IO\r\nor talking to foreign services or foreign buses.\r\n\r\nHere is an example that uses a worker pool with three service workers in it:\r\n\r\nLet's say you have a service that does something:\r\n\r\n```java\r\n\r\n //Your POJO\r\n public class MultiWorker {\r\n\r\n void doSomeWork(...) {\r\n ...\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nNow this does some sort of IO and you want to have a bank of these running not just one so you can do\r\nIO in parallel. After some performance testing, you found out that three is the magic number.\r\n\r\nYou want to use your API for accessing this service:\r\n\r\n```java\r\n public interface MultiWorkerClient {\r\n void doSomeWork(...);\r\n }\r\n\r\n```\r\n\r\nNow let's create a bank of these and use it.\r\n\r\nFirst create the QBit services which add the thread/queue/microbatch.\r\n\r\n```java\r\n\r\n /* Create a service builder. */\r\n final ServiceBuilder serviceBuilder = serviceBuilder();\r\n\r\n /* Create some qbit services. */\r\n final Service service1 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service2 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service3 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n```\r\n\r\nNow add them to a ServiceWorkers object.\r\n\r\n```java\r\n\r\n ServiceWorkers dispatcher;\r\n dispatcher = workers(); //Create a round robin service dispatcher\r\n dispatcher.addServices(service1, service2, service3);\r\n dispatcher.start(); // start up the workers\r\n\r\n```\r\n\r\nYou can add services, POJOs and method consumers, method dispatchers to a service bundle.\r\nThe service bundle is an integration point into QBit.\r\n\r\nLet's add our new Service workers. ServiceWorkers is a ServiceMethodDispatcher.\r\n\r\n```Java\r\n /* Add the dispatcher to a service bundle. */\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nWe are probably going to add a helper method to the service bundle so most of this can happen in\r\na single call.\r\n\r\nNow you can start using your workers.\r\n\r\n```java\r\n\r\n /* Start using the workers. */\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n```\r\n\r\nNow you could use Spring or Guice to configure the builders and the service bundle.\r\nBut you can just do it like the above which is good for testing and understanding QBit internals.\r\n\r\nQBit also supports the concept of sharded services which is good for sharding resources like CPU\r\n(run a rules engine on each CPU core for a user recommendation engine).\r\n\r\nQBit does not know how to shard your services, you have to give it a hint.\r\nYou do this through a shard rule.\r\n\r\n```java\r\npublic interface ShardRule {\r\n int shard(String methodName, Object[] args, int numWorkers);\r\n}\r\n```\r\nWe worked on an app where the first argument to the services was the username, and then we used that to\r\nshard calls to a CPU intensive in-memory rules engine. This technique works. :)\r\n\r\nThe ServiceWorkers class has a method for creating a sharded worker pool.\r\n\r\n```java\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nTo use you just pass a shard key when you create the service workers.\r\n\r\n```java\r\n\r\n\r\n dispatcher = shardedWorkers((methodName, methodArgs, numWorkers) -> {\r\n String userName = methodArgs[0].toString();\r\n int shardKey = userName.hashCode() % numWorkers;\r\n return shardKey;\r\n });\r\n\r\n```\r\n\r\nThen add your services to the ServiceWorkers composition.\r\n```java\r\n int workerCount = Runtime.getRuntime().availableProcessors();\r\n\r\n for (int index = 0; index < workerCount; index++) {\r\n final Service service = serviceBuilder\r\n .setServiceObject(new ContentRulesEngine()).build();\r\n dispatcher.addServices(service);\r\n\r\n }\r\n```\r\n\r\nThen add it to the service bundle as before.\r\n```java\r\n\r\n dispatcher.start();\r\n\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nThen just use it:\r\n\r\n```java\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n for (int index = 0; index < 100; index++) {\r\n String userName = \"rickhigh\" + index;\r\n worker.pickSuggestions(userName);\r\n }\r\n\r\n```\r\n\r\n### Built in shard rules\r\n\r\n```java\r\n\r\n\r\npublic class ServiceWorkers {\r\n...\r\n public static ShardedMethodDispatcher shardOnFirstArgumentWorkers() {\r\n ...\r\n }\r\n\r\n...\r\n\r\n public static ShardedMethodDispatcher shardOnFifthArgumentWorkers() {\r\n ...\r\n }\r\n\r\n\r\n public static ShardedMethodDispatcher shardOnBeanPath(final String beanPath) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nThe shardOnBeanPath allows you to create a complex bean path navigation call and use its property to shard on.\r\n\r\n```java\r\n\r\n /* shard on 2nd arg which is an employee\r\n Use the employees department's id property. */\r\n dispatcher = shardOnBeanPath(\"[1].department.id\");\r\n\r\n /* Same as above. */\r\n dispatcher = shardOnBeanPath(\"1/department/id\");\r\n\r\n```\r\n\r\n[Read more about Service sharding and service workers here](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-QBit-Microservices-using-Service-Workers-and-sharded-service-workers)\r\n\r\n\r\nYou can find a lot more in the wiki. Also follow the commits.\r\nWe have been busy beavers.\r\n[QBit the microservice lib for Java - JSON, REST, WebSocket](https://github.com/advantageous/qbit/wiki).",
+ "body": "[QBit Micorservices tutorials](https://github.com/MammatusTech/qbit-microservices-examples/wiki)|\r\n[QBit Website](http://advantageous.github.io/qbit/) | [QBit uses Reakt](http://advantageous.github.io/reakt/) | [QBit works with Vert.x](http://vertx.io/) | [Reakt Vertx](http://advantageous.github.io/reakt-vertx/)\r\n\r\n#QBit - The Microservice Lib for Java - JSON, REST, WebSocket, Speed! \r\n\r\n## Quick overview of QBit\r\n\r\nThe Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.\r\n\r\nGot a question? Ask here: [QBit Google Group](https://groups.google.com/forum/#!forum/qbit-microservice).\r\n\r\nEverything is a queue. You have a choice. You can embrace it and control it. You can optimize for it.\r\nOr you can hide behind abstractions. QBit opens you up to peeking into what is going on, and allows you\r\nto pull some levers without selling your soul.\r\n\r\nQBit is a library not a framework. You can mix and match QBit with Spring, Guice, etc.\r\n\r\nQBit is FAST!\r\n\r\n\r\n\r\n#### Using from maven\r\n```xml\r\n\r\n io.advantageous.qbit\r\n qbit-admin\r\n 1.0.0.RELEASE\r\n\r\n\r\n io.advantageous.qbit\r\n qbit-vertx\r\n 1.0.0.RELEASE\r\n\r\n```\r\n\r\n#### Using from gradle\r\n```java\r\ncompile 'io.advantageous.qbit:qbit-admin:1.0.0.RELEASE'\r\ncompile 'io.advantageous.qbit:qbit-vertx:1.0.0.RELEASE'\r\n```\r\n\r\nCore Features\r\n============\r\n\r\n* Write REST based async microservices\r\n* Write ***WebSocket*** based async microservices (fast async RPC over WebSocket)\r\n* Actor Service Queues using micro-batching for high-speed message passing\r\n* Strongly async typed event bus which can be distributed\r\n* Async low overhead metrics gathering which can be queried and distributed (for doing fast lane analytics)\r\n* Complex async call coordination (with the Reactor) for reactive programming\r\n* Built-in support for ***health checks*** (and integration with tools like Consul)\r\n* Built-in support for ***monitoring*** (and integration with wire protocols like StatsD)\r\n* Built-in support for ***Service Discovery*** (with integration with health system, DNS SRV records and Consul)\r\n* Integration with persistent queues\r\n* [12 factor app port bindings](http://12factor.net/), health checks, KPI gathering, Logging MDC\r\n* API Gateway support for client generation and consumption via [Swagger](http://swagger.io/).\r\n* Our services can generate Swagger files (like idl for JSON/REST).\r\n* Remote client proxies for WebSocket (your interface is your IDL)\r\n\r\n\r\nStatus\r\n=====\r\nDeployed at several large fortune 100 companies. \r\nQBit now works with Vertx (standalone or embedded).\r\nYou can also use QBit on non-QBit projects, it is just a lib.\r\n\r\nLicense\r\n=====\r\nApache 2\r\n\r\n\r\n## Java Microservice Lib\r\n\r\nQBit has inproc services, REST microservices and WebSocket microservices as well as an\r\nin-proc service event bus (which can be per module or per app). It supports workers and in-memory services.\r\n\r\nBefore we describe more, here are two sample services:\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {...\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {...\r\n```\r\n\r\n\r\n#### Adder Service using URI params\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {...\r\n }\r\n```\r\n\r\n\r\n\r\nQBit philosophy:\r\n====\r\nAt the end of the day QBit is a simple library not a framework.\r\nYour app is not a QBit app but a Java app that uses the QBit lib.\r\nQBit allows you to work with Java UTIL concurrent, and does not endeavor to hide it from you.\r\nJust trying to take the sting out of it.\r\n\r\nDoes it work\r\n=====\r\nWe have used techniques in Boon and QBit with great success in high-end, high-performance, high-scalable apps.\r\nWe helped clients handle 10x the load with 1/10th the servers of their competitors using techniques in QBit.\r\nQBit is us being sick of hand tuning queue access and threads.\r\n\r\n\r\nBoon and QBit humility policy\r\n=====\r\nIdeas for Boon and QBit often come from all over the web. We make mistakes. Point them out.\r\nAs a developer of Boon and QBit, we are fellow travelers.\r\nIf you have an idea or technique you want to share, we listen.\r\n\r\n\r\nInspiration\r\n====\r\n\r\nA big inspiration for Boon/QBit was Vertx, Akka, Go Channels, Active Objects, Apartment Model Threading, Actor,\r\nand the Mechanical Sympathy papers.\r\n\r\nQBit has ideas that are similar to many frameworks. We are all reading the same papers.\r\nQBit got inspiration from the LMAX disruptor papers and this blog post about\r\n[link transfer queue versus disruptor](http://php.sabscape.com/blog/?p=557). We had some theories about\r\nqueues that blog post inspired us to try them out. Some of these theories are deployed at some of the\r\nbiggest middleware backends and whose name brands are known around the world. And thus QBit was born.\r\n\r\nQBit also took an lot of inspiration by the great work done\r\nby Tim Fox on Vertx. The first project using something that could actually be called QBit (albeit early QBit)\r\n was using Vertx on an web/mobile microservice for an app that could potentially have 80 million users.\r\n It was this\r\nexperience with Vertx and early QBit that led to QBit development and evolution. QBit is built on the\r\nshoulders of giants (Netty/Vertx).\r\n\r\nDoes QBit compete with...\r\n====\r\nSpring Disruptor: No. You could use QBit to write plugins for Spring Disruptor I suppose, but QBit does\r\nnot compete with Spring Disruptor.\r\nSpring Boot/Spring MVC: No. We use the same annotations but QBit is geared for high-speed in-memory\r\nmicroservices. It is more like Akka than Spring Boot. QBit has a subset of the features of Spring MVC\r\ngeared only for microservices, i.e., WebSocket RPC, REST, JSON marshaling, etc.\r\nAkka: No. Well Maybe. Akka has similar concepts but they take a different approach. QBit is more focused\r\n on Java, and microservices (REST, JSON, WebSocket) than Akka.\r\nLMAX Disruptor: No. In fact, we can use disruptor as on of the queues that QBit uses underneath the covers.\r\n\r\n\r\n(Early benchmarks have been removed. They were here. QBit got a lot faster.\r\n Benchmarking QBit is a moving target at the moment.\r\n Links and reports will be created.)\r\n\r\n\r\nCode Examples\r\n\r\n\r\n## Basic Queue example (REST style services is further down)\r\n\r\n====\r\n\r\n```java\r\n\r\n BasicQueue queue = BasicQueue.create(Integer.class, 1000);\r\n\r\n //Sending threads\r\n\r\n SendQueue sendQueue = queue.sendQueue();\r\n for (int index = 0; index < amount; index++) {\r\n sendQueue.send(index);\r\n }\r\n sendQueue.flushSends();\r\n ...\r\n sendQueue.sendAndFlush(code);\r\n //other methods for sendQueue, writeBatch, writeMany\r\n\r\n\r\n //Receiving Threads\r\n ReceiveQueue receiveQueue = queue.receiveQueue();\r\n Integer item = receiveQueue.take();\r\n //other methods poll(), pollWait(), readBatch(), readBatch(count)\r\n```\r\n\r\n\r\n### What is QBit again?\r\n\r\nQBit is a queuing library for microservices. It is similar to many other projects like Akka, Spring Reactor,\r\netc. QBit is just a library not a platform. QBit has libraries to put a service behind a queue.\r\nYou can use QBit queues directly or you can create a service. QBit services can be exposed by WebSocket,\r\nHTTP, HTTP pipeline, and other types of remoting. A service in QBit is a Java class whose methods are\r\n executed behind service queues. QBit implements apartment model threading and is similar to the\r\n Actor model or a better description would be Active Objects. QBit does not use a disruptor (but could).\r\n It uses regular Java Queues. QBit can do north of 100 million ping pong calls per second which is\r\n an amazing speed (seen as high as 200M). QBit also supports calling services via REST, and WebSocket.\r\n QBit is microservices in the pure Web sense: JSON, HTTP, WebSocket, etc. QBit uses micro batching to\r\n push messages through the pipe (queue, IO, etc.) faster to reduce thread hand-off.\r\n\r\n### QBit lingo\r\n\r\nQBit is a Java microservice lib supporting REST, JSON and WebSocket. It is written in Java but we could\r\none day write a version in Rust or Go or C# (but that would require a large payday).\r\n\r\n**Service**\r\nPOJO (plain old Java object) behind a queue that can receive method calls via proxy calls or events\r\n(May have one thread managing events, method calls, and responses or two one for method calls and events\r\n 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.\r\n\r\n**ServiceBundle**\r\nMany POJOs behind one response queue and many receive queues. There may be one thread for all responses\r\nor not. They also can be one receive queue.\r\n\r\n**Queue**\r\nA thread managing a queue. It supports batching. It has events for empty, reachedLimit, startedBatch,\r\nidle. You can listen to these events from services that sit behind a queue. You don't have to use Services.\r\nYou can use Queue's direct. In QBit, you have sender queues and receivers queues. They are separated to\r\nsupport micro-batching.\r\n\r\n**ServiceEndpointServer**\r\nServiceBundle that is exposed to REST and WebSocket communication.\r\n\r\n**EventBus**\r\nEventBus is a way to send a lot of messages to services that may be loosely coupled.\r\n\r\n**ClientProxy**\r\nClientProxy is a way to invoke service through async interface, service can be inproc (same process) or\r\nremoted over WebSocket.\r\n\r\n**Non-blocking**\r\nQBit is a non-blocking lib. You use CallBacks via Java 8 Lambdas. You can also send event messages and get\r\nreplies. Messaging is built into the system so you can easily coordinate complex tasks.\r\nQBit takes an object-oriented approach to service development so services look like normal Java services\r\nthat you\r\nalready write, but the services live behind a queue/thread. This is not a new concept. Microsoft did this\r\nwith DCOM/COM and called it active objects. Akka does it with actors and called them strongly typed Actors.\r\nThe important concepts is that you get the speed of reactive and actor style messaging but you develop\r\nin a natural OOP approach. QBit is not the first. QBit is not the only.\r\n\r\n\r\n**Speed**\r\nQBit is VERY fast. There is a of course a lot of room for improvement. But already 200M+ TPS inproc ping pong, 10M-20M+ TPS event bus, 500K TPS RPC calls over WebSocket/JSON, etc.\r\nMore work needs to be done to improve speed, but now it is fast enough where we are focusing more on\r\nusability.\r\nThe JSON support uses Boon by default which is up to 4x faster than other JSON parsers for the\r\nREST/JSON, WebSocket/JSON use case.\r\n\r\n**Reactive Programming**\r\nQBit provides a **Reactor** to manage async calls. This allows callbacks to be handled on the same thread that called them and it provides for timeout and error handling. Read [Reactor tutorial for creating reactive micro service programming](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices)\r\n\r\n**Service Discovery**\r\nBuilt in support for service discovery. This includes integration with Consul.\r\n\r\n\r\n**StatService**\r\nBuilt in support for stats. The **StatService** can be integrated with **StatsD** (Graphite, Grafana, DataDog, etc.) to publish passive stats. Or you can query the stats engine and react to the stats (counts, timings and levels). The **StatsService** is a reactive stats system that can be clustered. The StatService is reactive in that your services can publish to it and query it and react based on the results. You can implement things like rate limiting and react to an increased rate of something. The ServiceDiscovery system integrates with the HealthSystem and Consul to roll up each of your internal services that make up you micro service and publish the composite availably of your micro service to a single HTTP endpoint or a dead mans switch in Consul (TTL). \r\n\r\n\r\n\r\n### CURLable REST services example\r\n\r\nTalk is cheap. Let's look at some code. You can get a detailed walk through in the Wiki.\r\nWe have a lot of documentation already.\r\n\r\nWe will create a service that is exposed through REST/JSON.\r\n\r\nTo query the size of the todo list:\r\n\r\n```bash\r\ncurl localhost:8080/services/todo-service/todo/count\r\n```\r\n\r\nTo add a new TODO item.\r\n\r\n```bash\r\ncurl -X POST -H \"Content-Type: application/json\" -d \\\r\n'{\"name\":\"xyz\",\"description\":\"xyz\"}' \\\r\nhttp://localhost:8080/services/todo-service/todo\r\n```\r\n\r\nTo get a list of TODO items\r\n```bash\r\ncurl http://localhost:8080/services/todo-service/todo/\r\n```\r\n\r\nThe TODO example will use and track Todo items.\r\n\r\n#### Todo item POJO sans getter\r\n\r\n```java\r\npackage io.advantageous.qbit.examples;\r\n\r\nimport java.util.Date;\r\n\r\n\r\npublic class TodoItem {\r\n\r\n\r\n private final String description;\r\n private final String name;\r\n private final Date due;\r\n\r\n```\r\n\r\nThe TodoService uses Spring MVC style annotations.\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n\r\n private List todoItemList = new ArrayList<>();\r\n\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {\r\n\r\n return todoItemList.size();\r\n }\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {\r\n\r\n return todoItemList;\r\n }\r\n\r\n @RequestMapping(value = \"/todo\", method = RequestMethod.POST)\r\n public void add(TodoItem item) {\r\n\r\n todoItemList.add(item);\r\n }\r\n\r\n}\r\n\r\n```\r\n\r\n\r\n#### Sending non-JSON\r\n\r\nYou can POST/PUT non-JSON and you can capture the body as a `String` or as a `byte[]`. \r\nIf the content-type is set to anything but `application/json` and your body is defined a String or byte[].\r\nThis works automatically. (The content-type has to be set.)\r\n\r\n```java\r\n @RequestMapping(value = \"/body/bytes\", method = RequestMethod.POST)\r\n public boolean bodyPostBytes( byte[] body) {\r\n String string = new String(body, StandardCharsets.UTF_8);\r\n return string.equals(\"foo\");\r\n }\r\n\r\n @RequestMapping(value = \"/body/string\", method = RequestMethod.POST)\r\n public boolean bodyPostString(String body) {\r\n return body.equals(\"foo\");\r\n }\r\n```\r\n\r\n\r\n#### Sending different response codes for success\r\n\r\nBy default QBit sends a `200` (OK) for a non-void call (a call that has a return or a Callback). If the REST operation has no return or no callback then QBit sends a `202` (Accepted). There may be times when you want to send a 201 (Created) or some other code that is not an Exception. You can do that by setting `code` on `@RequestMapping`. By default the code is -1 which means use the default behavior (200 for success, 202 for one-way message, and 500 for errors).\r\n\r\n\r\n#### Sending different response codes for success\r\n```java\r\n\r\n @RequestMapping(value = \"/helloj7\", code = 221)\r\n public void helloJSend7(Callback>> callback) {\r\n callback.returnThis(JSendResponseBuilder.jSendResponseBuilder(Lists.list(\r\n \"hello \" + System.currentTimeMillis())).build());\r\n }\r\n\r\n```\r\n\r\n`Callbacks` can be used for internal services as well. It is often the case that you use a [CallbackBuilder](https://github.com/advantageous/qbit/wiki/%5BDocument%5D-CallbackBuilder-and-generics-for-Reactive-Java-Microservices) or a QBit [Reactor](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices) to manage service calls. \r\n\r\n#### Working with non JSON responses\r\n\r\nYou do not have to return JSON form rest calls.\r\nYou can return any binary or any text by using `HttpBinaryResponse` and `HttpTextResponse`.\r\n\r\n#### Returning non JSON from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildTextResponse());\r\n }\r\n```\r\n\r\n\r\n#### Returning binary from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildBinaryResponse());\r\n }\r\n```\r\n\r\n#### Side note Why Spring style annotations?\r\nWhy did we pick Spring style annotations?\r\n1) Spring is not a standard and neither is QBit. 2) We found the Spring annotations to be less verbose.\r\n3) More people use Spring than Java EE. We wrote QBit for people to use.\r\nWe could easily support JAX-RS style annotations, and we probably will.\r\nSince QBit focuses on JSON, we do not need all of the complexity of JAX-RS or even all the features of\r\nthe Spring MVC annotations. Also we can literally use the actual Spring annotations. QBit and Boon\r\nuse a non-type safe mechanism for annotations which means they are not tied to a particular lib.\r\nYou can define your own. We hate vendor tie-in even if it is an open source vendor.\r\n(We also support @POST, @GET which is similar to JAX-RS).\r\n\r\nNow just start it up.\r\n\r\n```java\r\n\r\n public static void main(String... args) {\r\n\r\n ServiceEndpointServer server = new EndpointServerBuilder().build();\r\n server.initServices(new TodoService());\r\n server.start();\r\n }\r\n```\r\n\r\n\r\n\r\nThat is it. There is also out of the box WebSocket support with client side proxy generation so\r\nyou can call into services at the rate of millions of calls per second.\r\n\r\n## Using URI Params for QBit microservice\r\n\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {\r\n\r\n return a + b;\r\n }\r\n }\r\n\r\n```\r\n\r\n## WebSocket\r\nYou can always invoke QBit services via a WebSocket proxy.\r\nThe advantage of a WebSocket proxy is it allows you execute 1M RPC+ a second (1 million remote calls\r\nevery second).\r\n\r\n\r\n#### Using a microservice remotely with WebSocket\r\n```java\r\n /* Start QBit client for WebSocket calls. */\r\n final Client client = clientBuilder()\r\n .setPort(7000).setRequestBatchSize(1).build();\r\n\r\n\r\n /* Create a proxy to the service. */\r\n final AdderServiceClientInterface adderService =\r\n client.createProxy(AdderServiceClientInterface.class,\r\n \"adder-service\");\r\n\r\n client.start();\r\n\r\n\r\n\r\n /* Call the service */\r\n adderService.add(System.out::println, 1, 2);\r\n\r\n```\r\n\r\nThe output is 3.\r\n\r\n```output\r\n3\r\n```\r\n\r\n\r\nThe above uses a WebSocket proxy interface to call the service async.\r\n\r\n```java\r\n\r\n interface AdderServiceClientInterface {\r\n\r\n void add(Callback callback, int a, int b);\r\n }\r\n```\r\n\r\n#### ServiceDiscovery aware websocket builders\r\n\r\nCreate websocket service client that is ServiceDiscovery aware.\r\n\r\n\r\n```java\r\n final Client client = clientBuilder.setServiceDiscovery(serviceDiscovery, \"echo\")\r\n .setUri(\"/echo\").setProtocolBatchSize(20).build().startClient();\r\n\r\n\r\n final EchoAsync echoClient = client.createProxy(EchoAsync.class, \"echo\");\r\n```\r\n\r\nCurrently the `clientBuilder` will load all service endpoints that are registered under the service name,\r\nand randomly pick one. \r\n\r\nServiceDiscovery includes Consul based, watching JSON files on disk, and DNS. It is easy to write your own service discovery as well and plug it into QBit.\r\n\r\n\r\nIn the future we can RoundRobin calls or shard calls to websocket service and/or provide auto fail over if the connection is closed. We do this for the event bus that uses service discovery but it is not baked into WebSocket based client stubs yet.\r\n\r\n\r\n## REST call with URI params\r\n\r\nThe last client example uses WebSocket. You could also just use REST, and actually use the URI params\r\nthat we setup.\r\nREST is nice but it is going to be slower than WebSocket support.\r\n\r\nQBit ships with a nice little HTTP client. We can use it.\r\n\r\nYou can use it to send async calls and WebSocket messages with the HTTP client.\r\n\r\n\r\nHere we will use the http client to invoke our remote method:\r\n\r\n#### Using a microservice remotely with REST QBit microservice client\r\n```java\r\n\r\n\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\")\r\n .setPort(7000).build();\r\n\r\n httpClient.start();\r\n String results = httpClient\r\n .get(\"/services/adder-service/add/2/2\").body();\r\n System.out.println(results);\r\n\r\n```\r\n\r\n\r\nThe output is 4.\r\n\r\n```output\r\n4\r\n```\r\n\r\n## Accessing The URI Param example with CURL\r\n\r\nYou can also access the service from curl.\r\n\r\n```bash\r\n$ curl http://localhost:7000/services/adder-service/add/2/2\r\n```\r\n\r\nSee this full example here: [QBit microservice getting started tutorial](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-------------QBit-microservice-example).\r\n\r\n[QBit URI params and WebSocket proxy client](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Using-QBit-microservice-lib's-REST-support-with-URI-Params)\r\n\r\n## Working with WebSocket, HttpClient etc.\r\n\r\nQBit has a library for working with and writing async microservices that is lightweight and fun to use.\r\n\r\n#### WebSocket server and client.\r\n\r\n\r\n#### Create an HTTP server\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n```\r\n\r\n#### Setup server WebSocket support\r\n```java\r\n /* Setup WebSocket Server support. */\r\n httpServer.setWebSocketOnOpenConsumer(webSocket -> {\r\n webSocket.setTextMessageConsumer(message -> {\r\n webSocket.sendText(\"ECHO \" + message);\r\n });\r\n });\r\n\r\n```\r\n\r\n#### Start the server\r\n```java\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n```\r\n\r\n#### Setup the WebSocket client\r\n```java\r\n\r\n /** CLIENT. */\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\n#### Client WebSocket\r\n\r\n```java\r\n\r\n /* Setup the client websocket. */\r\n WebSocket webSocket = httpClient\r\n .createWebSocket(\"/websocket/rocket\");\r\n\r\n /* Setup the text consumer. */\r\n webSocket.setTextMessageConsumer(message -> {\r\n System.out.println(message);\r\n });\r\n webSocket.openAndWait();\r\n\r\n /* Send some messages. */\r\n webSocket.sendText(\"Hi mom\");\r\n webSocket.sendText(\"Hello World!\");\r\n\r\n```\r\n\r\n#### Output\r\n```output\r\n\r\nECHO Hi mom\r\nECHO Hello World!\r\n\r\n```\r\n\r\nNow stop the server and client. Pretty easy eh?\r\n\r\n## High-speed HTTP client and server done microservice style\r\n\r\n\r\n##### Starting up an HTTP server\r\n\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n /* Setting up a request Consumer with Java 8 Lambda expression. */\r\n httpServer.setHttpRequestConsumer(httpRequest -> {\r\n\r\n Map results = new HashMap<>();\r\n results.put(\"method\", httpRequest.getMethod());\r\n results.put(\"uri\", httpRequest.getUri());\r\n results.put(\"body\", httpRequest.getBodyAsString());\r\n results.put(\"headers\", httpRequest.getHeaders());\r\n results.put(\"params\", httpRequest.getParams());\r\n httpRequest.getReceiver()\r\n .response(200, \"application/json\", Boon.toJson(results));\r\n });\r\n\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n\r\n\r\n```\r\n\r\nThe focus is on ease of use and using Java 8 Lambdas for callbacks so the code is tight and small.\r\n\r\n[Find out more about QBit's microservice style WebSocket support here](https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-WebSocket-support)\r\n\r\n\r\n## Using HTTP Client lib\r\n\r\nNow, let's try out our HTTP client.\r\n\r\n##### Starting up an HTTP client\r\n\r\n```java\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\nYou just pass the URL, the port and then call start.\r\n\r\n## Synchronous HTTP calls\r\n\r\nNow you can start sending HTTP requests.\r\n\r\n##### No Param HTTP GET\r\n\r\n```java\r\n /* Send no param get. */\r\n HttpResponse httpResponse = httpClient.get( \"/hello/mom\" );\r\n puts( httpResponse );\r\n```\r\n\r\nAn HTTP response just contains the results from the server.\r\n\r\n\r\n##### No Param HTTP Response\r\n\r\n```java\r\npublic interface HttpResponse {\r\n\r\n MultiMap headers();\r\n\r\n int code();\r\n\r\n String contentType();\r\n\r\n String body();\r\n\r\n}\r\n\r\n```\r\n\r\nThere are helper methods for sync HTTP GET calls.\r\n\r\n\r\n\r\n##### Helper methods for GET\r\n```java\r\n\r\n\r\n /* Send one param get. */\r\n httpResponse = httpClient.getWith1Param(\"/hello/singleParam\",\r\n \"hi\", \"mom\");\r\n puts(\"single param\", httpResponse );\r\n\r\n\r\n /* Send two param get. */\r\n httpResponse = httpClient.getWith2Params(\"/hello/twoParams\",\r\n \"hi\", \"mom\", \"hello\", \"dad\");\r\n puts(\"two params\", httpResponse );\r\n\r\n...\r\n\r\n /* Send five param get. */\r\n httpResponse = httpClient.getWith5Params(\"/hello/5params\",\r\n \"hi\", \"mom\",\r\n \"hello\", \"dad\",\r\n \"greetings\", \"kids\",\r\n \"yo\", \"pets\",\r\n \"hola\", \"neighbors\");\r\n puts(\"5 params\", httpResponse );\r\n\r\n\r\n```\r\n\r\nThe puts method is a helper method it does System.out.println more or less by the way.\r\n\r\nThe first five params are covered. Beyond five, you have to use the HttpBuilder.\r\n\r\n```java\r\n\r\n\r\n /* Send six params with get. */\r\n\r\n final HttpRequest httpRequest = httpRequestBuilder()\r\n .addParam(\"hi\", \"mom\")\r\n .addParam(\"hello\", \"dad\")\r\n .addParam(\"greetings\", \"kids\")\r\n .addParam(\"yo\", \"pets\")\r\n .addParam(\"hola\", \"pets\")\r\n .addParam(\"salutations\", \"all\").build();\r\n\r\n httpResponse = httpClient.sendRequestAndWait(httpRequest);\r\n puts(\"6 params\", httpResponse );\r\n```\r\n\r\n## Http Async HTTP Client\r\n\r\nThere are async calls for GET as well.\r\n\r\n#### Async calls for HTTP GET using Java 8 lambda\r\n\r\n```java\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsync(\"/hi/async\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith1Param(\"/hi/async\", \"hi\", \"mom\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda 1 param\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith2Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 2 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n...\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith5Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n \"p3\", \"v3\",\r\n \"p4\", \"v4\",\r\n \"p5\", \"v5\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 5 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n```\r\n\r\n[Find more about the easy to use, fast microservice HTTP client here]\r\n(https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-HttpClient-GET,-POST,-et-al,-JSON,-Java-8-Lambda).\r\n\r\n## InProc QBit services\r\n\r\nQBit allows for services behind queues to be run in-proc as well.\r\n\r\n```java\r\n\r\n /* POJO service. */\r\n final TodoManager todoManagerImpl = new TodoManager();\r\n\r\n /*\r\n Create the service which manages async calls to todoManagerImpl.\r\n */\r\n final Service service = serviceBuilder()\r\n .setServiceObject(todoManagerImpl)\r\n .build().startServiceQueue();\r\n\r\n\r\n /* Create Asynchronous proxy over Synchronous service. */\r\n final TodoManagerClientInterface todoManager =\r\n service.createProxy(TodoManagerClientInterface.class);\r\n\r\n service.startCallBackHandler();\r\n\r\n\r\n System.out.println(\"This is an async call\");\r\n /* Asynchronous method call. */\r\n todoManager.add(new Todo(\"Call Mom\", \"Give Mom a call\"));\r\n\r\n\r\n AtomicInteger countTracker = new AtomicInteger();\r\n //Hold count from async call to service... for testing and showing it is an async callback\r\n\r\n System.out.println(\"This is an async call to count\");\r\n\r\n todoManager.count(count -> {\r\n System.out.println(\"This lambda expression is the callback \" + count);\r\n\r\n countTracker.set(count);\r\n });\r\n\r\n\r\n todoManager.clientProxyFlush(); //Flush all methods. It batches calls.\r\n\r\n Sys.sleep(100);\r\n\r\n System.out.printf(\"This is the count back from the server %d\\n\", countTracker.get());\r\n\r\n```\r\n\r\n[Detailed tutorial on in-proc services is being written.](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-Working-with-inproc-MicroServices-within-QBit.)\r\n\r\n\r\n## QBit Event Bus\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\nQBit also has a service event bus. This example is a an employee benefits services example.\r\n\r\nWe have two channels.\r\n\r\n```\r\npublic static final String NEW_HIRE_CHANNEL = \"com.mycompnay.employee.new\";\r\n\r\npublic static final String PAYROLL_ADJUSTMENT_CHANNEL = \"com.mycompnay.employee.payroll\";\r\n```\r\n\r\nAn employee object looks like this:\r\n\r\n```java\r\n\r\npublic static class Employee {\r\n final String firstName;\r\n final int employeeId;\r\n```\r\n\r\n\r\nThis example has three services: EmployeeHiringService, BenefitsService, and PayrollService.\r\n\r\nThese services are inproc services. QBit supports WebSocket, HTTP and REST remote services as well, but for now, let's focus on inproc services. If you understand inproc then you will understand remote.\r\n\r\nThe EmployeeHiringService actually fires off the events to other two services.\r\n\r\n```java\r\npublic class EmployeeHiringService {\r\n\r\n\r\n public void hireEmployee(final Employee employee) {\r\n\r\n int salary = 100;\r\n System.out.printf(\"Hired employee %s\\n\", employee);\r\n\r\n //Does stuff to hire employee\r\n\r\n //Sends events\r\n final EventManager eventManager =\r\n serviceContext().eventManager();\r\n eventManager.send(NEW_HIRE_CHANNEL, employee);\r\n\r\n eventManager.sendArray(PAYROLL_ADJUSTMENT_CHANNEL,\r\n employee, salary);\r\n\r\n\r\n }\r\n\r\n }\r\n```\r\n\r\n\r\nNotice that we call sendArray so we can send the employee and their salary.\r\nThe listener for PAYROLL_ADJUSTMENT_CHANNEL will have to handle both an employee and an int\r\nthat represents the new employees salary.\r\nYou can also use event bus proxies so you do not have to call into the event bus at all.\r\n\r\nThe BenefitsService listens for new employees being hired so it can enroll them into the benefits system.\r\n\r\n```java\r\npublic static class BenefitsService {\r\n\r\n @OnEvent(NEW_HIRE_CHANNEL)\r\n public void enroll(final Employee employee) {\r\n\r\n System.out.printf(\"Employee enrolled into benefits system employee %s %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId());\r\n\r\n }\r\n\r\n```\r\n\r\nDaddy needs to get paid.\r\n\r\n```java\r\n public static class PayrollService {\r\n\r\n @OnEvent(PAYROLL_ADJUSTMENT_CHANNEL)\r\n public void addEmployeeToPayroll(final Employee employee, int salary) {\r\n\r\n System.out.printf(\"Employee added to payroll %s %d %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId(), salary);\r\n\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nThe employee is the employee object from the EmployeeHiringService.\r\n\r\nso you can get your benefits, and paid!\r\n\r\nFind more details here:\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\n\r\n## Private event bus and event bus proxies\r\n\r\n You can define your own interface to the event bus and you can use your own event buses with QBit.\r\n Each module in your service can have its own internal event bus.\r\n\r\n To learn more read:\r\n [QBit Microservice working with a private event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-private-event-bus-for-inproc-microservices)\r\n and [QBit Java Microservice lib using your own interface to the event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-strongly-typed-event-bus-proxies-for-QBit-Java-Microservice-lib).\r\n\r\n\r\n\r\n## Queue Callbacks\r\n\r\n To really grasp QBit, one must grasp the concepts of a CallBack.\r\n\r\n A CallBack is a way to get an async response in QBit.\r\n\r\n You call a service method and it calls you back.\r\n\r\n Client proxies can have callbacks:\r\n\r\n\r\n#### Queue Callbacks - RecommendationService client interface\r\n```java\r\n\r\npublic interface RecommendationServiceClient {\r\n\r\n\r\n void recommend(final Callback> recommendationsCallback,\r\n final String userName);\r\n}\r\n\r\n```\r\n\r\nCallbacks are Java 8 Consumers with some optional extra error handling.\r\n\r\n\r\n#### Queue Callbacks - Callback\r\n\r\n```java\r\n\r\n\r\npublic interface Callback extends java.util.function.Consumer {\r\n default void onError(java.lang.Throwable error) { /* compiled code */ }\r\n}\r\n\r\n```\r\n\r\nServices that can block should use callbacks.\r\nThus if loadUser blocked in the following example, it should really use a callback instead of returning a value.\r\n\r\npublic class RecommendationService {\r\n\r\n#### Queue Callbacks - Simple minded implementation of RecommendationService\r\n```java\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n public List recommend(final String userName) {\r\n User user = users.get(userName);\r\n if (user == null) {\r\n user = loadUser(userName);\r\n }\r\n return runRulesEngineAgainstUser(user);\r\n }\r\n\r\n```\r\n\r\n\r\nLet's pretend `loadUser` has to look in a local cache, and if the user is not found, look in an off-heap cache\r\nand if not found it must ask for the user from the UserService which must check its caches and perhaps fallback\r\nto loading the user data from a database or from other services.\r\nIn other words, `loadUser` can potentially block on IO.\r\n\r\n\r\n\r\n### Queue Callbacks - The first rule of Queue Club - don't block\r\n\r\n\r\nOur client does not block, but our service does. Going back to our `RecommendationService`.\r\nIf we get a lot of cache hits for user loads, perhaps the\r\nblock will not be that long, but it will be there and every time we have to fault in a user, the whole system\r\nis gummed up. What we want to be able to do is if we can't handle the recommendation request,\r\nwe go ahead and make an async call to the `UserDataService`. When that async callback comes back, then we\r\nhandle that request. In the mean time, we handle recommendation lists requests as quickly as we can.\r\nWe never block.\r\n\r\n\r\nSo let's revisit the service. The first thing we are going to do is make the service method take\r\na callback. Before we do that, let's set down some rules.\r\n\r\n\r\n#### The first rule of queue club don't block.\r\n#### The second rule of queue club if you are not ready, use a callback and continue handling stuff you are ready for\r\n\r\n\r\n#### Queue Callbacks - Adding a CallBack to the RecommendationService inproc microservice\r\n\r\n```java\r\npublic class RecommendationService {\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n```\r\n\r\n\r\n\r\nNow we are taking a callback and we can decide when we want to handle this recommendation generation request.\r\nWe can do it right away if there user data we need is in-memory or we can delay it.\r\n\r\n\r\n#### If the user is found, call the callback right away for RecommendationService inproc microservice\r\n\r\n```java\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n /** Look for user in user cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n ...\r\n } else {\r\n /* Call the callback now because we can handle the callback now. */\r\n recommendationsCallback.accept(runRulesEngineAgainstUser(user));\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nNotice, if the user is found in the cache, we run our recommendation rules in-memory and call the callback right away\r\n`recommendationsCallback.accept(runRulesEngineAgainstUser(user))`.\r\n\r\nThe interesting part is what do we do if don't have the user loaded.\r\n\r\n\r\n#### If the user was not found, load him from the user microservice, but still don't block\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using Callback. */\r\n userDataService.loadUser(new Callback() {\r\n @Override\r\n public void accept(final User loadedUser) {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nHere we use a CallBack to load the user, and when the user is loaded, we call `handleLoadFromUserDataService`\r\nwhich adds some management about handling the callback so we can still handle this call, just not now.\r\n\r\n\r\n\r\n#### Lambda version of last example\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using lambda expression. */\r\n userDataService.loadUser(\r\n loadedUser -> {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nUsing lambdas like this makes the code more readable and terse, but remember don't deeply nest\r\nlambda expressions or you will create a code maintenance nightmare. Use them judiciously.\r\n\r\n\r\n### Queue Callbacks - Doing something later\r\n\r\nWhat we want is to handle the request for recommendations after the user service system loads\r\nthe user from its store.\r\n\r\n\r\n\r\n#### Handling UserServiceData callback methods once we get them.\r\n\r\n```java\r\n\r\npublic class RecommendationService {\r\n\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n private UserDataServiceClient userDataService;\r\n\r\n\r\n private BlockingQueue callbacks =\r\n new ArrayBlockingQueue(10_000);\r\n\r\n\r\n ...\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n ...\r\n\r\n }\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks queue. */\r\n callbacks.add(new Runnable() {\r\n @Override\r\n public void run() {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n }\r\n });\r\n }\r\n\r\n\r\n\r\n```\r\n\r\n\r\n\r\n\r\n#### handleLoadFromUserDataService rewritten using Lambda\r\n\r\n```java\r\n\r\n\r\npublic class RecommendationService {\r\n\r\n...\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks list. */\r\n callbacks.add(() -> {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n });\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nThe important part there is that every time we get a callback call from `UserDataService`, we then\r\nperform our CPU intensive recommendation rules and callback our caller. Well not exactly, what we\r\ndo is enqueue an runnable onto our callbacks queue, and later we will iterate through those but when?\r\n\r\n\r\n### Queue Callbacks Handling callbacks when our receive queue is empty, a new batch started or we hit a batch limit\r\n\r\nThe `RecommendationService` can be notified when its queue is empty, it has started a new batch and when\r\nit has reached a batch limit. These are all good times to handle callbacks from the `UserDataService`.\r\n\r\n#### Draining our callback queue\r\n```java\r\n\r\n @QueueCallback({\r\n QueueCallbackType.EMPTY,\r\n QueueCallbackType.START_BATCH,\r\n QueueCallbackType.LIMIT})\r\n private void handleCallbacks() {\r\n\r\n flushServiceProxy(userDataService);\r\n Runnable runnable = callbacks.poll();\r\n\r\n while (runnable != null) {\r\n runnable.run();\r\n runnable = callbacks.poll();\r\n }\r\n }\r\n\r\n```\r\n\r\nIt is important to remember when handling callbacks from another microservice that you want to handle\r\ncallbacks from the other service before you handle more incomming requests from you clients.\r\nEssentially you have clients that have been waiting (async waiting but still), and these clients\r\nmight represent an open TCP/IP connection like an HTTP call so it is best to close them out\r\nbefore handling more requests and like we said they were already waiting around with an open connection\r\nfor users to load form the user service.\r\n\r\nTo learn more about CallBacks, plesae read [QBit Java MicroService Lib CallBack fundamentals]([Rough Cut] QBit Microservice Lib Working With CallBacks).\r\n\r\n\r\n\r\n\r\n## Workers - pools and shards\r\n\r\n```java\r\npublic class ServiceWorkers {\r\n\r\n public static RoundRobinServiceDispatcher workers() {...\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {...\r\n```\r\n\r\nYou can compose sharded workers (for in-memory, thread safe, CPU intensive services), or workers for IO\r\nor talking to foreign services or foreign buses.\r\n\r\nHere is an example that uses a worker pool with three service workers in it:\r\n\r\nLet's say you have a service that does something:\r\n\r\n```java\r\n\r\n //Your POJO\r\n public class MultiWorker {\r\n\r\n void doSomeWork(...) {\r\n ...\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nNow this does some sort of IO and you want to have a bank of these running not just one so you can do\r\nIO in parallel. After some performance testing, you found out that three is the magic number.\r\n\r\nYou want to use your API for accessing this service:\r\n\r\n```java\r\n public interface MultiWorkerClient {\r\n void doSomeWork(...);\r\n }\r\n\r\n```\r\n\r\nNow let's create a bank of these and use it.\r\n\r\nFirst create the QBit services which add the thread/queue/microbatch.\r\n\r\n```java\r\n\r\n /* Create a service builder. */\r\n final ServiceBuilder serviceBuilder = serviceBuilder();\r\n\r\n /* Create some qbit services. */\r\n final Service service1 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service2 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service3 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n```\r\n\r\nNow add them to a ServiceWorkers object.\r\n\r\n```java\r\n\r\n ServiceWorkers dispatcher;\r\n dispatcher = workers(); //Create a round robin service dispatcher\r\n dispatcher.addServices(service1, service2, service3);\r\n dispatcher.start(); // start up the workers\r\n\r\n```\r\n\r\nYou can add services, POJOs and method consumers, method dispatchers to a service bundle.\r\nThe service bundle is an integration point into QBit.\r\n\r\nLet's add our new Service workers. ServiceWorkers is a ServiceMethodDispatcher.\r\n\r\n```Java\r\n /* Add the dispatcher to a service bundle. */\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nWe are probably going to add a helper method to the service bundle so most of this can happen in\r\na single call.\r\n\r\nNow you can start using your workers.\r\n\r\n```java\r\n\r\n /* Start using the workers. */\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n```\r\n\r\nNow you could use Spring or Guice to configure the builders and the service bundle.\r\nBut you can just do it like the above which is good for testing and understanding QBit internals.\r\n\r\nQBit also supports the concept of sharded services which is good for sharding resources like CPU\r\n(run a rules engine on each CPU core for a user recommendation engine).\r\n\r\nQBit does not know how to shard your services, you have to give it a hint.\r\nYou do this through a shard rule.\r\n\r\n```java\r\npublic interface ShardRule {\r\n int shard(String methodName, Object[] args, int numWorkers);\r\n}\r\n```\r\nWe worked on an app where the first argument to the services was the username, and then we used that to\r\nshard calls to a CPU intensive in-memory rules engine. This technique works. :)\r\n\r\nThe ServiceWorkers class has a method for creating a sharded worker pool.\r\n\r\n```java\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nTo use you just pass a shard key when you create the service workers.\r\n\r\n```java\r\n\r\n\r\n dispatcher = shardedWorkers((methodName, methodArgs, numWorkers) -> {\r\n String userName = methodArgs[0].toString();\r\n int shardKey = userName.hashCode() % numWorkers;\r\n return shardKey;\r\n });\r\n\r\n```\r\n\r\nThen add your services to the ServiceWorkers composition.\r\n```java\r\n int workerCount = Runtime.getRuntime().availableProcessors();\r\n\r\n for (int index = 0; index < workerCount; index++) {\r\n final Service service = serviceBuilder\r\n .setServiceObject(new ContentRulesEngine()).build();\r\n dispatcher.addServices(service);\r\n\r\n }\r\n```\r\n\r\nThen add it to the service bundle as before.\r\n```java\r\n\r\n dispatcher.start();\r\n\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nThen just use it:\r\n\r\n```java\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n for (int index = 0; index < 100; index++) {\r\n String userName = \"rickhigh\" + index;\r\n worker.pickSuggestions(userName);\r\n }\r\n\r\n```\r\n\r\n### Built in shard rules\r\n\r\n```java\r\n\r\n\r\npublic class ServiceWorkers {\r\n...\r\n public static ShardedMethodDispatcher shardOnFirstArgumentWorkers() {\r\n ...\r\n }\r\n\r\n...\r\n\r\n public static ShardedMethodDispatcher shardOnFifthArgumentWorkers() {\r\n ...\r\n }\r\n\r\n\r\n public static ShardedMethodDispatcher shardOnBeanPath(final String beanPath) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nThe shardOnBeanPath allows you to create a complex bean path navigation call and use its property to shard on.\r\n\r\n```java\r\n\r\n /* shard on 2nd arg which is an employee\r\n Use the employees department's id property. */\r\n dispatcher = shardOnBeanPath(\"[1].department.id\");\r\n\r\n /* Same as above. */\r\n dispatcher = shardOnBeanPath(\"1/department/id\");\r\n\r\n```\r\n\r\n[Read more about Service sharding and service workers here](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-QBit-Microservices-using-Service-Workers-and-sharded-service-workers)\r\n\r\n\r\nYou can find a lot more in the wiki. Also follow the commits.\r\nWe have been busy beavers.\r\n[QBit the microservice lib for Java - JSON, REST, WebSocket](https://github.com/advantageous/qbit/wiki).",
"note": "Don't delete this file! It's used internally to help with page regeneration."
}
\ No newline at end of file
From 60a9478c2139c833c7660596dbd32a868e5e71a5 Mon Sep 17 00:00:00 2001
From: Richard Hightower
Date: Fri, 15 Apr 2016 08:27:10 -0700
Subject: [PATCH 09/19] Create gh-pages branch via GitHub
---
index.html | 3 +--
params.json | 2 +-
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/index.html b/index.html
index ae53d139..3339de78 100644
--- a/index.html
+++ b/index.html
@@ -19,8 +19,7 @@
The Java microservice lib. QBit is a reactive progra
QBit - The Microservice Lib for Java - JSON, REST, WebSocket, Speed!
diff --git a/params.json b/params.json
index 1bf15f38..3efdd85d 100644
--- a/params.json
+++ b/params.json
@@ -1,6 +1,6 @@
{
"name": "QBit - Microservices Lib",
"tagline": "The Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.",
- "body": "[QBit Micorservices tutorials](https://github.com/MammatusTech/qbit-microservices-examples/wiki)|\r\n[QBit Website](http://advantageous.github.io/qbit/) | [QBit uses Reakt](http://advantageous.github.io/reakt/) | [QBit works with Vert.x](http://vertx.io/) | [Reakt Vertx](http://advantageous.github.io/reakt-vertx/)\r\n\r\n#QBit - The Microservice Lib for Java - JSON, REST, WebSocket, Speed! \r\n\r\n## Quick overview of QBit\r\n\r\nThe Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.\r\n\r\nGot a question? Ask here: [QBit Google Group](https://groups.google.com/forum/#!forum/qbit-microservice).\r\n\r\nEverything is a queue. You have a choice. You can embrace it and control it. You can optimize for it.\r\nOr you can hide behind abstractions. QBit opens you up to peeking into what is going on, and allows you\r\nto pull some levers without selling your soul.\r\n\r\nQBit is a library not a framework. You can mix and match QBit with Spring, Guice, etc.\r\n\r\nQBit is FAST!\r\n\r\n\r\n\r\n#### Using from maven\r\n```xml\r\n\r\n io.advantageous.qbit\r\n qbit-admin\r\n 1.0.0.RELEASE\r\n\r\n\r\n io.advantageous.qbit\r\n qbit-vertx\r\n 1.0.0.RELEASE\r\n\r\n```\r\n\r\n#### Using from gradle\r\n```java\r\ncompile 'io.advantageous.qbit:qbit-admin:1.0.0.RELEASE'\r\ncompile 'io.advantageous.qbit:qbit-vertx:1.0.0.RELEASE'\r\n```\r\n\r\nCore Features\r\n============\r\n\r\n* Write REST based async microservices\r\n* Write ***WebSocket*** based async microservices (fast async RPC over WebSocket)\r\n* Actor Service Queues using micro-batching for high-speed message passing\r\n* Strongly async typed event bus which can be distributed\r\n* Async low overhead metrics gathering which can be queried and distributed (for doing fast lane analytics)\r\n* Complex async call coordination (with the Reactor) for reactive programming\r\n* Built-in support for ***health checks*** (and integration with tools like Consul)\r\n* Built-in support for ***monitoring*** (and integration with wire protocols like StatsD)\r\n* Built-in support for ***Service Discovery*** (with integration with health system, DNS SRV records and Consul)\r\n* Integration with persistent queues\r\n* [12 factor app port bindings](http://12factor.net/), health checks, KPI gathering, Logging MDC\r\n* API Gateway support for client generation and consumption via [Swagger](http://swagger.io/).\r\n* Our services can generate Swagger files (like idl for JSON/REST).\r\n* Remote client proxies for WebSocket (your interface is your IDL)\r\n\r\n\r\nStatus\r\n=====\r\nDeployed at several large fortune 100 companies. \r\nQBit now works with Vertx (standalone or embedded).\r\nYou can also use QBit on non-QBit projects, it is just a lib.\r\n\r\nLicense\r\n=====\r\nApache 2\r\n\r\n\r\n## Java Microservice Lib\r\n\r\nQBit has inproc services, REST microservices and WebSocket microservices as well as an\r\nin-proc service event bus (which can be per module or per app). It supports workers and in-memory services.\r\n\r\nBefore we describe more, here are two sample services:\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {...\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {...\r\n```\r\n\r\n\r\n#### Adder Service using URI params\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {...\r\n }\r\n```\r\n\r\n\r\n\r\nQBit philosophy:\r\n====\r\nAt the end of the day QBit is a simple library not a framework.\r\nYour app is not a QBit app but a Java app that uses the QBit lib.\r\nQBit allows you to work with Java UTIL concurrent, and does not endeavor to hide it from you.\r\nJust trying to take the sting out of it.\r\n\r\nDoes it work\r\n=====\r\nWe have used techniques in Boon and QBit with great success in high-end, high-performance, high-scalable apps.\r\nWe helped clients handle 10x the load with 1/10th the servers of their competitors using techniques in QBit.\r\nQBit is us being sick of hand tuning queue access and threads.\r\n\r\n\r\nBoon and QBit humility policy\r\n=====\r\nIdeas for Boon and QBit often come from all over the web. We make mistakes. Point them out.\r\nAs a developer of Boon and QBit, we are fellow travelers.\r\nIf you have an idea or technique you want to share, we listen.\r\n\r\n\r\nInspiration\r\n====\r\n\r\nA big inspiration for Boon/QBit was Vertx, Akka, Go Channels, Active Objects, Apartment Model Threading, Actor,\r\nand the Mechanical Sympathy papers.\r\n\r\nQBit has ideas that are similar to many frameworks. We are all reading the same papers.\r\nQBit got inspiration from the LMAX disruptor papers and this blog post about\r\n[link transfer queue versus disruptor](http://php.sabscape.com/blog/?p=557). We had some theories about\r\nqueues that blog post inspired us to try them out. Some of these theories are deployed at some of the\r\nbiggest middleware backends and whose name brands are known around the world. And thus QBit was born.\r\n\r\nQBit also took an lot of inspiration by the great work done\r\nby Tim Fox on Vertx. The first project using something that could actually be called QBit (albeit early QBit)\r\n was using Vertx on an web/mobile microservice for an app that could potentially have 80 million users.\r\n It was this\r\nexperience with Vertx and early QBit that led to QBit development and evolution. QBit is built on the\r\nshoulders of giants (Netty/Vertx).\r\n\r\nDoes QBit compete with...\r\n====\r\nSpring Disruptor: No. You could use QBit to write plugins for Spring Disruptor I suppose, but QBit does\r\nnot compete with Spring Disruptor.\r\nSpring Boot/Spring MVC: No. We use the same annotations but QBit is geared for high-speed in-memory\r\nmicroservices. It is more like Akka than Spring Boot. QBit has a subset of the features of Spring MVC\r\ngeared only for microservices, i.e., WebSocket RPC, REST, JSON marshaling, etc.\r\nAkka: No. Well Maybe. Akka has similar concepts but they take a different approach. QBit is more focused\r\n on Java, and microservices (REST, JSON, WebSocket) than Akka.\r\nLMAX Disruptor: No. In fact, we can use disruptor as on of the queues that QBit uses underneath the covers.\r\n\r\n\r\n(Early benchmarks have been removed. They were here. QBit got a lot faster.\r\n Benchmarking QBit is a moving target at the moment.\r\n Links and reports will be created.)\r\n\r\n\r\nCode Examples\r\n\r\n\r\n## Basic Queue example (REST style services is further down)\r\n\r\n====\r\n\r\n```java\r\n\r\n BasicQueue queue = BasicQueue.create(Integer.class, 1000);\r\n\r\n //Sending threads\r\n\r\n SendQueue sendQueue = queue.sendQueue();\r\n for (int index = 0; index < amount; index++) {\r\n sendQueue.send(index);\r\n }\r\n sendQueue.flushSends();\r\n ...\r\n sendQueue.sendAndFlush(code);\r\n //other methods for sendQueue, writeBatch, writeMany\r\n\r\n\r\n //Receiving Threads\r\n ReceiveQueue receiveQueue = queue.receiveQueue();\r\n Integer item = receiveQueue.take();\r\n //other methods poll(), pollWait(), readBatch(), readBatch(count)\r\n```\r\n\r\n\r\n### What is QBit again?\r\n\r\nQBit is a queuing library for microservices. It is similar to many other projects like Akka, Spring Reactor,\r\netc. QBit is just a library not a platform. QBit has libraries to put a service behind a queue.\r\nYou can use QBit queues directly or you can create a service. QBit services can be exposed by WebSocket,\r\nHTTP, HTTP pipeline, and other types of remoting. A service in QBit is a Java class whose methods are\r\n executed behind service queues. QBit implements apartment model threading and is similar to the\r\n Actor model or a better description would be Active Objects. QBit does not use a disruptor (but could).\r\n It uses regular Java Queues. QBit can do north of 100 million ping pong calls per second which is\r\n an amazing speed (seen as high as 200M). QBit also supports calling services via REST, and WebSocket.\r\n QBit is microservices in the pure Web sense: JSON, HTTP, WebSocket, etc. QBit uses micro batching to\r\n push messages through the pipe (queue, IO, etc.) faster to reduce thread hand-off.\r\n\r\n### QBit lingo\r\n\r\nQBit is a Java microservice lib supporting REST, JSON and WebSocket. It is written in Java but we could\r\none day write a version in Rust or Go or C# (but that would require a large payday).\r\n\r\n**Service**\r\nPOJO (plain old Java object) behind a queue that can receive method calls via proxy calls or events\r\n(May have one thread managing events, method calls, and responses or two one for method calls and events\r\n 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.\r\n\r\n**ServiceBundle**\r\nMany POJOs behind one response queue and many receive queues. There may be one thread for all responses\r\nor not. They also can be one receive queue.\r\n\r\n**Queue**\r\nA thread managing a queue. It supports batching. It has events for empty, reachedLimit, startedBatch,\r\nidle. You can listen to these events from services that sit behind a queue. You don't have to use Services.\r\nYou can use Queue's direct. In QBit, you have sender queues and receivers queues. They are separated to\r\nsupport micro-batching.\r\n\r\n**ServiceEndpointServer**\r\nServiceBundle that is exposed to REST and WebSocket communication.\r\n\r\n**EventBus**\r\nEventBus is a way to send a lot of messages to services that may be loosely coupled.\r\n\r\n**ClientProxy**\r\nClientProxy is a way to invoke service through async interface, service can be inproc (same process) or\r\nremoted over WebSocket.\r\n\r\n**Non-blocking**\r\nQBit is a non-blocking lib. You use CallBacks via Java 8 Lambdas. You can also send event messages and get\r\nreplies. Messaging is built into the system so you can easily coordinate complex tasks.\r\nQBit takes an object-oriented approach to service development so services look like normal Java services\r\nthat you\r\nalready write, but the services live behind a queue/thread. This is not a new concept. Microsoft did this\r\nwith DCOM/COM and called it active objects. Akka does it with actors and called them strongly typed Actors.\r\nThe important concepts is that you get the speed of reactive and actor style messaging but you develop\r\nin a natural OOP approach. QBit is not the first. QBit is not the only.\r\n\r\n\r\n**Speed**\r\nQBit is VERY fast. There is a of course a lot of room for improvement. But already 200M+ TPS inproc ping pong, 10M-20M+ TPS event bus, 500K TPS RPC calls over WebSocket/JSON, etc.\r\nMore work needs to be done to improve speed, but now it is fast enough where we are focusing more on\r\nusability.\r\nThe JSON support uses Boon by default which is up to 4x faster than other JSON parsers for the\r\nREST/JSON, WebSocket/JSON use case.\r\n\r\n**Reactive Programming**\r\nQBit provides a **Reactor** to manage async calls. This allows callbacks to be handled on the same thread that called them and it provides for timeout and error handling. Read [Reactor tutorial for creating reactive micro service programming](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices)\r\n\r\n**Service Discovery**\r\nBuilt in support for service discovery. This includes integration with Consul.\r\n\r\n\r\n**StatService**\r\nBuilt in support for stats. The **StatService** can be integrated with **StatsD** (Graphite, Grafana, DataDog, etc.) to publish passive stats. Or you can query the stats engine and react to the stats (counts, timings and levels). The **StatsService** is a reactive stats system that can be clustered. The StatService is reactive in that your services can publish to it and query it and react based on the results. You can implement things like rate limiting and react to an increased rate of something. The ServiceDiscovery system integrates with the HealthSystem and Consul to roll up each of your internal services that make up you micro service and publish the composite availably of your micro service to a single HTTP endpoint or a dead mans switch in Consul (TTL). \r\n\r\n\r\n\r\n### CURLable REST services example\r\n\r\nTalk is cheap. Let's look at some code. You can get a detailed walk through in the Wiki.\r\nWe have a lot of documentation already.\r\n\r\nWe will create a service that is exposed through REST/JSON.\r\n\r\nTo query the size of the todo list:\r\n\r\n```bash\r\ncurl localhost:8080/services/todo-service/todo/count\r\n```\r\n\r\nTo add a new TODO item.\r\n\r\n```bash\r\ncurl -X POST -H \"Content-Type: application/json\" -d \\\r\n'{\"name\":\"xyz\",\"description\":\"xyz\"}' \\\r\nhttp://localhost:8080/services/todo-service/todo\r\n```\r\n\r\nTo get a list of TODO items\r\n```bash\r\ncurl http://localhost:8080/services/todo-service/todo/\r\n```\r\n\r\nThe TODO example will use and track Todo items.\r\n\r\n#### Todo item POJO sans getter\r\n\r\n```java\r\npackage io.advantageous.qbit.examples;\r\n\r\nimport java.util.Date;\r\n\r\n\r\npublic class TodoItem {\r\n\r\n\r\n private final String description;\r\n private final String name;\r\n private final Date due;\r\n\r\n```\r\n\r\nThe TodoService uses Spring MVC style annotations.\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n\r\n private List todoItemList = new ArrayList<>();\r\n\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {\r\n\r\n return todoItemList.size();\r\n }\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {\r\n\r\n return todoItemList;\r\n }\r\n\r\n @RequestMapping(value = \"/todo\", method = RequestMethod.POST)\r\n public void add(TodoItem item) {\r\n\r\n todoItemList.add(item);\r\n }\r\n\r\n}\r\n\r\n```\r\n\r\n\r\n#### Sending non-JSON\r\n\r\nYou can POST/PUT non-JSON and you can capture the body as a `String` or as a `byte[]`. \r\nIf the content-type is set to anything but `application/json` and your body is defined a String or byte[].\r\nThis works automatically. (The content-type has to be set.)\r\n\r\n```java\r\n @RequestMapping(value = \"/body/bytes\", method = RequestMethod.POST)\r\n public boolean bodyPostBytes( byte[] body) {\r\n String string = new String(body, StandardCharsets.UTF_8);\r\n return string.equals(\"foo\");\r\n }\r\n\r\n @RequestMapping(value = \"/body/string\", method = RequestMethod.POST)\r\n public boolean bodyPostString(String body) {\r\n return body.equals(\"foo\");\r\n }\r\n```\r\n\r\n\r\n#### Sending different response codes for success\r\n\r\nBy default QBit sends a `200` (OK) for a non-void call (a call that has a return or a Callback). If the REST operation has no return or no callback then QBit sends a `202` (Accepted). There may be times when you want to send a 201 (Created) or some other code that is not an Exception. You can do that by setting `code` on `@RequestMapping`. By default the code is -1 which means use the default behavior (200 for success, 202 for one-way message, and 500 for errors).\r\n\r\n\r\n#### Sending different response codes for success\r\n```java\r\n\r\n @RequestMapping(value = \"/helloj7\", code = 221)\r\n public void helloJSend7(Callback>> callback) {\r\n callback.returnThis(JSendResponseBuilder.jSendResponseBuilder(Lists.list(\r\n \"hello \" + System.currentTimeMillis())).build());\r\n }\r\n\r\n```\r\n\r\n`Callbacks` can be used for internal services as well. It is often the case that you use a [CallbackBuilder](https://github.com/advantageous/qbit/wiki/%5BDocument%5D-CallbackBuilder-and-generics-for-Reactive-Java-Microservices) or a QBit [Reactor](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices) to manage service calls. \r\n\r\n#### Working with non JSON responses\r\n\r\nYou do not have to return JSON form rest calls.\r\nYou can return any binary or any text by using `HttpBinaryResponse` and `HttpTextResponse`.\r\n\r\n#### Returning non JSON from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildTextResponse());\r\n }\r\n```\r\n\r\n\r\n#### Returning binary from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildBinaryResponse());\r\n }\r\n```\r\n\r\n#### Side note Why Spring style annotations?\r\nWhy did we pick Spring style annotations?\r\n1) Spring is not a standard and neither is QBit. 2) We found the Spring annotations to be less verbose.\r\n3) More people use Spring than Java EE. We wrote QBit for people to use.\r\nWe could easily support JAX-RS style annotations, and we probably will.\r\nSince QBit focuses on JSON, we do not need all of the complexity of JAX-RS or even all the features of\r\nthe Spring MVC annotations. Also we can literally use the actual Spring annotations. QBit and Boon\r\nuse a non-type safe mechanism for annotations which means they are not tied to a particular lib.\r\nYou can define your own. We hate vendor tie-in even if it is an open source vendor.\r\n(We also support @POST, @GET which is similar to JAX-RS).\r\n\r\nNow just start it up.\r\n\r\n```java\r\n\r\n public static void main(String... args) {\r\n\r\n ServiceEndpointServer server = new EndpointServerBuilder().build();\r\n server.initServices(new TodoService());\r\n server.start();\r\n }\r\n```\r\n\r\n\r\n\r\nThat is it. There is also out of the box WebSocket support with client side proxy generation so\r\nyou can call into services at the rate of millions of calls per second.\r\n\r\n## Using URI Params for QBit microservice\r\n\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {\r\n\r\n return a + b;\r\n }\r\n }\r\n\r\n```\r\n\r\n## WebSocket\r\nYou can always invoke QBit services via a WebSocket proxy.\r\nThe advantage of a WebSocket proxy is it allows you execute 1M RPC+ a second (1 million remote calls\r\nevery second).\r\n\r\n\r\n#### Using a microservice remotely with WebSocket\r\n```java\r\n /* Start QBit client for WebSocket calls. */\r\n final Client client = clientBuilder()\r\n .setPort(7000).setRequestBatchSize(1).build();\r\n\r\n\r\n /* Create a proxy to the service. */\r\n final AdderServiceClientInterface adderService =\r\n client.createProxy(AdderServiceClientInterface.class,\r\n \"adder-service\");\r\n\r\n client.start();\r\n\r\n\r\n\r\n /* Call the service */\r\n adderService.add(System.out::println, 1, 2);\r\n\r\n```\r\n\r\nThe output is 3.\r\n\r\n```output\r\n3\r\n```\r\n\r\n\r\nThe above uses a WebSocket proxy interface to call the service async.\r\n\r\n```java\r\n\r\n interface AdderServiceClientInterface {\r\n\r\n void add(Callback callback, int a, int b);\r\n }\r\n```\r\n\r\n#### ServiceDiscovery aware websocket builders\r\n\r\nCreate websocket service client that is ServiceDiscovery aware.\r\n\r\n\r\n```java\r\n final Client client = clientBuilder.setServiceDiscovery(serviceDiscovery, \"echo\")\r\n .setUri(\"/echo\").setProtocolBatchSize(20).build().startClient();\r\n\r\n\r\n final EchoAsync echoClient = client.createProxy(EchoAsync.class, \"echo\");\r\n```\r\n\r\nCurrently the `clientBuilder` will load all service endpoints that are registered under the service name,\r\nand randomly pick one. \r\n\r\nServiceDiscovery includes Consul based, watching JSON files on disk, and DNS. It is easy to write your own service discovery as well and plug it into QBit.\r\n\r\n\r\nIn the future we can RoundRobin calls or shard calls to websocket service and/or provide auto fail over if the connection is closed. We do this for the event bus that uses service discovery but it is not baked into WebSocket based client stubs yet.\r\n\r\n\r\n## REST call with URI params\r\n\r\nThe last client example uses WebSocket. You could also just use REST, and actually use the URI params\r\nthat we setup.\r\nREST is nice but it is going to be slower than WebSocket support.\r\n\r\nQBit ships with a nice little HTTP client. We can use it.\r\n\r\nYou can use it to send async calls and WebSocket messages with the HTTP client.\r\n\r\n\r\nHere we will use the http client to invoke our remote method:\r\n\r\n#### Using a microservice remotely with REST QBit microservice client\r\n```java\r\n\r\n\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\")\r\n .setPort(7000).build();\r\n\r\n httpClient.start();\r\n String results = httpClient\r\n .get(\"/services/adder-service/add/2/2\").body();\r\n System.out.println(results);\r\n\r\n```\r\n\r\n\r\nThe output is 4.\r\n\r\n```output\r\n4\r\n```\r\n\r\n## Accessing The URI Param example with CURL\r\n\r\nYou can also access the service from curl.\r\n\r\n```bash\r\n$ curl http://localhost:7000/services/adder-service/add/2/2\r\n```\r\n\r\nSee this full example here: [QBit microservice getting started tutorial](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-------------QBit-microservice-example).\r\n\r\n[QBit URI params and WebSocket proxy client](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Using-QBit-microservice-lib's-REST-support-with-URI-Params)\r\n\r\n## Working with WebSocket, HttpClient etc.\r\n\r\nQBit has a library for working with and writing async microservices that is lightweight and fun to use.\r\n\r\n#### WebSocket server and client.\r\n\r\n\r\n#### Create an HTTP server\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n```\r\n\r\n#### Setup server WebSocket support\r\n```java\r\n /* Setup WebSocket Server support. */\r\n httpServer.setWebSocketOnOpenConsumer(webSocket -> {\r\n webSocket.setTextMessageConsumer(message -> {\r\n webSocket.sendText(\"ECHO \" + message);\r\n });\r\n });\r\n\r\n```\r\n\r\n#### Start the server\r\n```java\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n```\r\n\r\n#### Setup the WebSocket client\r\n```java\r\n\r\n /** CLIENT. */\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\n#### Client WebSocket\r\n\r\n```java\r\n\r\n /* Setup the client websocket. */\r\n WebSocket webSocket = httpClient\r\n .createWebSocket(\"/websocket/rocket\");\r\n\r\n /* Setup the text consumer. */\r\n webSocket.setTextMessageConsumer(message -> {\r\n System.out.println(message);\r\n });\r\n webSocket.openAndWait();\r\n\r\n /* Send some messages. */\r\n webSocket.sendText(\"Hi mom\");\r\n webSocket.sendText(\"Hello World!\");\r\n\r\n```\r\n\r\n#### Output\r\n```output\r\n\r\nECHO Hi mom\r\nECHO Hello World!\r\n\r\n```\r\n\r\nNow stop the server and client. Pretty easy eh?\r\n\r\n## High-speed HTTP client and server done microservice style\r\n\r\n\r\n##### Starting up an HTTP server\r\n\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n /* Setting up a request Consumer with Java 8 Lambda expression. */\r\n httpServer.setHttpRequestConsumer(httpRequest -> {\r\n\r\n Map results = new HashMap<>();\r\n results.put(\"method\", httpRequest.getMethod());\r\n results.put(\"uri\", httpRequest.getUri());\r\n results.put(\"body\", httpRequest.getBodyAsString());\r\n results.put(\"headers\", httpRequest.getHeaders());\r\n results.put(\"params\", httpRequest.getParams());\r\n httpRequest.getReceiver()\r\n .response(200, \"application/json\", Boon.toJson(results));\r\n });\r\n\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n\r\n\r\n```\r\n\r\nThe focus is on ease of use and using Java 8 Lambdas for callbacks so the code is tight and small.\r\n\r\n[Find out more about QBit's microservice style WebSocket support here](https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-WebSocket-support)\r\n\r\n\r\n## Using HTTP Client lib\r\n\r\nNow, let's try out our HTTP client.\r\n\r\n##### Starting up an HTTP client\r\n\r\n```java\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\nYou just pass the URL, the port and then call start.\r\n\r\n## Synchronous HTTP calls\r\n\r\nNow you can start sending HTTP requests.\r\n\r\n##### No Param HTTP GET\r\n\r\n```java\r\n /* Send no param get. */\r\n HttpResponse httpResponse = httpClient.get( \"/hello/mom\" );\r\n puts( httpResponse );\r\n```\r\n\r\nAn HTTP response just contains the results from the server.\r\n\r\n\r\n##### No Param HTTP Response\r\n\r\n```java\r\npublic interface HttpResponse {\r\n\r\n MultiMap headers();\r\n\r\n int code();\r\n\r\n String contentType();\r\n\r\n String body();\r\n\r\n}\r\n\r\n```\r\n\r\nThere are helper methods for sync HTTP GET calls.\r\n\r\n\r\n\r\n##### Helper methods for GET\r\n```java\r\n\r\n\r\n /* Send one param get. */\r\n httpResponse = httpClient.getWith1Param(\"/hello/singleParam\",\r\n \"hi\", \"mom\");\r\n puts(\"single param\", httpResponse );\r\n\r\n\r\n /* Send two param get. */\r\n httpResponse = httpClient.getWith2Params(\"/hello/twoParams\",\r\n \"hi\", \"mom\", \"hello\", \"dad\");\r\n puts(\"two params\", httpResponse );\r\n\r\n...\r\n\r\n /* Send five param get. */\r\n httpResponse = httpClient.getWith5Params(\"/hello/5params\",\r\n \"hi\", \"mom\",\r\n \"hello\", \"dad\",\r\n \"greetings\", \"kids\",\r\n \"yo\", \"pets\",\r\n \"hola\", \"neighbors\");\r\n puts(\"5 params\", httpResponse );\r\n\r\n\r\n```\r\n\r\nThe puts method is a helper method it does System.out.println more or less by the way.\r\n\r\nThe first five params are covered. Beyond five, you have to use the HttpBuilder.\r\n\r\n```java\r\n\r\n\r\n /* Send six params with get. */\r\n\r\n final HttpRequest httpRequest = httpRequestBuilder()\r\n .addParam(\"hi\", \"mom\")\r\n .addParam(\"hello\", \"dad\")\r\n .addParam(\"greetings\", \"kids\")\r\n .addParam(\"yo\", \"pets\")\r\n .addParam(\"hola\", \"pets\")\r\n .addParam(\"salutations\", \"all\").build();\r\n\r\n httpResponse = httpClient.sendRequestAndWait(httpRequest);\r\n puts(\"6 params\", httpResponse );\r\n```\r\n\r\n## Http Async HTTP Client\r\n\r\nThere are async calls for GET as well.\r\n\r\n#### Async calls for HTTP GET using Java 8 lambda\r\n\r\n```java\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsync(\"/hi/async\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith1Param(\"/hi/async\", \"hi\", \"mom\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda 1 param\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith2Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 2 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n...\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith5Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n \"p3\", \"v3\",\r\n \"p4\", \"v4\",\r\n \"p5\", \"v5\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 5 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n```\r\n\r\n[Find more about the easy to use, fast microservice HTTP client here]\r\n(https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-HttpClient-GET,-POST,-et-al,-JSON,-Java-8-Lambda).\r\n\r\n## InProc QBit services\r\n\r\nQBit allows for services behind queues to be run in-proc as well.\r\n\r\n```java\r\n\r\n /* POJO service. */\r\n final TodoManager todoManagerImpl = new TodoManager();\r\n\r\n /*\r\n Create the service which manages async calls to todoManagerImpl.\r\n */\r\n final Service service = serviceBuilder()\r\n .setServiceObject(todoManagerImpl)\r\n .build().startServiceQueue();\r\n\r\n\r\n /* Create Asynchronous proxy over Synchronous service. */\r\n final TodoManagerClientInterface todoManager =\r\n service.createProxy(TodoManagerClientInterface.class);\r\n\r\n service.startCallBackHandler();\r\n\r\n\r\n System.out.println(\"This is an async call\");\r\n /* Asynchronous method call. */\r\n todoManager.add(new Todo(\"Call Mom\", \"Give Mom a call\"));\r\n\r\n\r\n AtomicInteger countTracker = new AtomicInteger();\r\n //Hold count from async call to service... for testing and showing it is an async callback\r\n\r\n System.out.println(\"This is an async call to count\");\r\n\r\n todoManager.count(count -> {\r\n System.out.println(\"This lambda expression is the callback \" + count);\r\n\r\n countTracker.set(count);\r\n });\r\n\r\n\r\n todoManager.clientProxyFlush(); //Flush all methods. It batches calls.\r\n\r\n Sys.sleep(100);\r\n\r\n System.out.printf(\"This is the count back from the server %d\\n\", countTracker.get());\r\n\r\n```\r\n\r\n[Detailed tutorial on in-proc services is being written.](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-Working-with-inproc-MicroServices-within-QBit.)\r\n\r\n\r\n## QBit Event Bus\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\nQBit also has a service event bus. This example is a an employee benefits services example.\r\n\r\nWe have two channels.\r\n\r\n```\r\npublic static final String NEW_HIRE_CHANNEL = \"com.mycompnay.employee.new\";\r\n\r\npublic static final String PAYROLL_ADJUSTMENT_CHANNEL = \"com.mycompnay.employee.payroll\";\r\n```\r\n\r\nAn employee object looks like this:\r\n\r\n```java\r\n\r\npublic static class Employee {\r\n final String firstName;\r\n final int employeeId;\r\n```\r\n\r\n\r\nThis example has three services: EmployeeHiringService, BenefitsService, and PayrollService.\r\n\r\nThese services are inproc services. QBit supports WebSocket, HTTP and REST remote services as well, but for now, let's focus on inproc services. If you understand inproc then you will understand remote.\r\n\r\nThe EmployeeHiringService actually fires off the events to other two services.\r\n\r\n```java\r\npublic class EmployeeHiringService {\r\n\r\n\r\n public void hireEmployee(final Employee employee) {\r\n\r\n int salary = 100;\r\n System.out.printf(\"Hired employee %s\\n\", employee);\r\n\r\n //Does stuff to hire employee\r\n\r\n //Sends events\r\n final EventManager eventManager =\r\n serviceContext().eventManager();\r\n eventManager.send(NEW_HIRE_CHANNEL, employee);\r\n\r\n eventManager.sendArray(PAYROLL_ADJUSTMENT_CHANNEL,\r\n employee, salary);\r\n\r\n\r\n }\r\n\r\n }\r\n```\r\n\r\n\r\nNotice that we call sendArray so we can send the employee and their salary.\r\nThe listener for PAYROLL_ADJUSTMENT_CHANNEL will have to handle both an employee and an int\r\nthat represents the new employees salary.\r\nYou can also use event bus proxies so you do not have to call into the event bus at all.\r\n\r\nThe BenefitsService listens for new employees being hired so it can enroll them into the benefits system.\r\n\r\n```java\r\npublic static class BenefitsService {\r\n\r\n @OnEvent(NEW_HIRE_CHANNEL)\r\n public void enroll(final Employee employee) {\r\n\r\n System.out.printf(\"Employee enrolled into benefits system employee %s %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId());\r\n\r\n }\r\n\r\n```\r\n\r\nDaddy needs to get paid.\r\n\r\n```java\r\n public static class PayrollService {\r\n\r\n @OnEvent(PAYROLL_ADJUSTMENT_CHANNEL)\r\n public void addEmployeeToPayroll(final Employee employee, int salary) {\r\n\r\n System.out.printf(\"Employee added to payroll %s %d %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId(), salary);\r\n\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nThe employee is the employee object from the EmployeeHiringService.\r\n\r\nso you can get your benefits, and paid!\r\n\r\nFind more details here:\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\n\r\n## Private event bus and event bus proxies\r\n\r\n You can define your own interface to the event bus and you can use your own event buses with QBit.\r\n Each module in your service can have its own internal event bus.\r\n\r\n To learn more read:\r\n [QBit Microservice working with a private event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-private-event-bus-for-inproc-microservices)\r\n and [QBit Java Microservice lib using your own interface to the event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-strongly-typed-event-bus-proxies-for-QBit-Java-Microservice-lib).\r\n\r\n\r\n\r\n## Queue Callbacks\r\n\r\n To really grasp QBit, one must grasp the concepts of a CallBack.\r\n\r\n A CallBack is a way to get an async response in QBit.\r\n\r\n You call a service method and it calls you back.\r\n\r\n Client proxies can have callbacks:\r\n\r\n\r\n#### Queue Callbacks - RecommendationService client interface\r\n```java\r\n\r\npublic interface RecommendationServiceClient {\r\n\r\n\r\n void recommend(final Callback> recommendationsCallback,\r\n final String userName);\r\n}\r\n\r\n```\r\n\r\nCallbacks are Java 8 Consumers with some optional extra error handling.\r\n\r\n\r\n#### Queue Callbacks - Callback\r\n\r\n```java\r\n\r\n\r\npublic interface Callback extends java.util.function.Consumer {\r\n default void onError(java.lang.Throwable error) { /* compiled code */ }\r\n}\r\n\r\n```\r\n\r\nServices that can block should use callbacks.\r\nThus if loadUser blocked in the following example, it should really use a callback instead of returning a value.\r\n\r\npublic class RecommendationService {\r\n\r\n#### Queue Callbacks - Simple minded implementation of RecommendationService\r\n```java\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n public List recommend(final String userName) {\r\n User user = users.get(userName);\r\n if (user == null) {\r\n user = loadUser(userName);\r\n }\r\n return runRulesEngineAgainstUser(user);\r\n }\r\n\r\n```\r\n\r\n\r\nLet's pretend `loadUser` has to look in a local cache, and if the user is not found, look in an off-heap cache\r\nand if not found it must ask for the user from the UserService which must check its caches and perhaps fallback\r\nto loading the user data from a database or from other services.\r\nIn other words, `loadUser` can potentially block on IO.\r\n\r\n\r\n\r\n### Queue Callbacks - The first rule of Queue Club - don't block\r\n\r\n\r\nOur client does not block, but our service does. Going back to our `RecommendationService`.\r\nIf we get a lot of cache hits for user loads, perhaps the\r\nblock will not be that long, but it will be there and every time we have to fault in a user, the whole system\r\nis gummed up. What we want to be able to do is if we can't handle the recommendation request,\r\nwe go ahead and make an async call to the `UserDataService`. When that async callback comes back, then we\r\nhandle that request. In the mean time, we handle recommendation lists requests as quickly as we can.\r\nWe never block.\r\n\r\n\r\nSo let's revisit the service. The first thing we are going to do is make the service method take\r\na callback. Before we do that, let's set down some rules.\r\n\r\n\r\n#### The first rule of queue club don't block.\r\n#### The second rule of queue club if you are not ready, use a callback and continue handling stuff you are ready for\r\n\r\n\r\n#### Queue Callbacks - Adding a CallBack to the RecommendationService inproc microservice\r\n\r\n```java\r\npublic class RecommendationService {\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n```\r\n\r\n\r\n\r\nNow we are taking a callback and we can decide when we want to handle this recommendation generation request.\r\nWe can do it right away if there user data we need is in-memory or we can delay it.\r\n\r\n\r\n#### If the user is found, call the callback right away for RecommendationService inproc microservice\r\n\r\n```java\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n /** Look for user in user cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n ...\r\n } else {\r\n /* Call the callback now because we can handle the callback now. */\r\n recommendationsCallback.accept(runRulesEngineAgainstUser(user));\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nNotice, if the user is found in the cache, we run our recommendation rules in-memory and call the callback right away\r\n`recommendationsCallback.accept(runRulesEngineAgainstUser(user))`.\r\n\r\nThe interesting part is what do we do if don't have the user loaded.\r\n\r\n\r\n#### If the user was not found, load him from the user microservice, but still don't block\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using Callback. */\r\n userDataService.loadUser(new Callback() {\r\n @Override\r\n public void accept(final User loadedUser) {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nHere we use a CallBack to load the user, and when the user is loaded, we call `handleLoadFromUserDataService`\r\nwhich adds some management about handling the callback so we can still handle this call, just not now.\r\n\r\n\r\n\r\n#### Lambda version of last example\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using lambda expression. */\r\n userDataService.loadUser(\r\n loadedUser -> {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nUsing lambdas like this makes the code more readable and terse, but remember don't deeply nest\r\nlambda expressions or you will create a code maintenance nightmare. Use them judiciously.\r\n\r\n\r\n### Queue Callbacks - Doing something later\r\n\r\nWhat we want is to handle the request for recommendations after the user service system loads\r\nthe user from its store.\r\n\r\n\r\n\r\n#### Handling UserServiceData callback methods once we get them.\r\n\r\n```java\r\n\r\npublic class RecommendationService {\r\n\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n private UserDataServiceClient userDataService;\r\n\r\n\r\n private BlockingQueue callbacks =\r\n new ArrayBlockingQueue(10_000);\r\n\r\n\r\n ...\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n ...\r\n\r\n }\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks queue. */\r\n callbacks.add(new Runnable() {\r\n @Override\r\n public void run() {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n }\r\n });\r\n }\r\n\r\n\r\n\r\n```\r\n\r\n\r\n\r\n\r\n#### handleLoadFromUserDataService rewritten using Lambda\r\n\r\n```java\r\n\r\n\r\npublic class RecommendationService {\r\n\r\n...\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks list. */\r\n callbacks.add(() -> {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n });\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nThe important part there is that every time we get a callback call from `UserDataService`, we then\r\nperform our CPU intensive recommendation rules and callback our caller. Well not exactly, what we\r\ndo is enqueue an runnable onto our callbacks queue, and later we will iterate through those but when?\r\n\r\n\r\n### Queue Callbacks Handling callbacks when our receive queue is empty, a new batch started or we hit a batch limit\r\n\r\nThe `RecommendationService` can be notified when its queue is empty, it has started a new batch and when\r\nit has reached a batch limit. These are all good times to handle callbacks from the `UserDataService`.\r\n\r\n#### Draining our callback queue\r\n```java\r\n\r\n @QueueCallback({\r\n QueueCallbackType.EMPTY,\r\n QueueCallbackType.START_BATCH,\r\n QueueCallbackType.LIMIT})\r\n private void handleCallbacks() {\r\n\r\n flushServiceProxy(userDataService);\r\n Runnable runnable = callbacks.poll();\r\n\r\n while (runnable != null) {\r\n runnable.run();\r\n runnable = callbacks.poll();\r\n }\r\n }\r\n\r\n```\r\n\r\nIt is important to remember when handling callbacks from another microservice that you want to handle\r\ncallbacks from the other service before you handle more incomming requests from you clients.\r\nEssentially you have clients that have been waiting (async waiting but still), and these clients\r\nmight represent an open TCP/IP connection like an HTTP call so it is best to close them out\r\nbefore handling more requests and like we said they were already waiting around with an open connection\r\nfor users to load form the user service.\r\n\r\nTo learn more about CallBacks, plesae read [QBit Java MicroService Lib CallBack fundamentals]([Rough Cut] QBit Microservice Lib Working With CallBacks).\r\n\r\n\r\n\r\n\r\n## Workers - pools and shards\r\n\r\n```java\r\npublic class ServiceWorkers {\r\n\r\n public static RoundRobinServiceDispatcher workers() {...\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {...\r\n```\r\n\r\nYou can compose sharded workers (for in-memory, thread safe, CPU intensive services), or workers for IO\r\nor talking to foreign services or foreign buses.\r\n\r\nHere is an example that uses a worker pool with three service workers in it:\r\n\r\nLet's say you have a service that does something:\r\n\r\n```java\r\n\r\n //Your POJO\r\n public class MultiWorker {\r\n\r\n void doSomeWork(...) {\r\n ...\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nNow this does some sort of IO and you want to have a bank of these running not just one so you can do\r\nIO in parallel. After some performance testing, you found out that three is the magic number.\r\n\r\nYou want to use your API for accessing this service:\r\n\r\n```java\r\n public interface MultiWorkerClient {\r\n void doSomeWork(...);\r\n }\r\n\r\n```\r\n\r\nNow let's create a bank of these and use it.\r\n\r\nFirst create the QBit services which add the thread/queue/microbatch.\r\n\r\n```java\r\n\r\n /* Create a service builder. */\r\n final ServiceBuilder serviceBuilder = serviceBuilder();\r\n\r\n /* Create some qbit services. */\r\n final Service service1 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service2 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service3 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n```\r\n\r\nNow add them to a ServiceWorkers object.\r\n\r\n```java\r\n\r\n ServiceWorkers dispatcher;\r\n dispatcher = workers(); //Create a round robin service dispatcher\r\n dispatcher.addServices(service1, service2, service3);\r\n dispatcher.start(); // start up the workers\r\n\r\n```\r\n\r\nYou can add services, POJOs and method consumers, method dispatchers to a service bundle.\r\nThe service bundle is an integration point into QBit.\r\n\r\nLet's add our new Service workers. ServiceWorkers is a ServiceMethodDispatcher.\r\n\r\n```Java\r\n /* Add the dispatcher to a service bundle. */\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nWe are probably going to add a helper method to the service bundle so most of this can happen in\r\na single call.\r\n\r\nNow you can start using your workers.\r\n\r\n```java\r\n\r\n /* Start using the workers. */\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n```\r\n\r\nNow you could use Spring or Guice to configure the builders and the service bundle.\r\nBut you can just do it like the above which is good for testing and understanding QBit internals.\r\n\r\nQBit also supports the concept of sharded services which is good for sharding resources like CPU\r\n(run a rules engine on each CPU core for a user recommendation engine).\r\n\r\nQBit does not know how to shard your services, you have to give it a hint.\r\nYou do this through a shard rule.\r\n\r\n```java\r\npublic interface ShardRule {\r\n int shard(String methodName, Object[] args, int numWorkers);\r\n}\r\n```\r\nWe worked on an app where the first argument to the services was the username, and then we used that to\r\nshard calls to a CPU intensive in-memory rules engine. This technique works. :)\r\n\r\nThe ServiceWorkers class has a method for creating a sharded worker pool.\r\n\r\n```java\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nTo use you just pass a shard key when you create the service workers.\r\n\r\n```java\r\n\r\n\r\n dispatcher = shardedWorkers((methodName, methodArgs, numWorkers) -> {\r\n String userName = methodArgs[0].toString();\r\n int shardKey = userName.hashCode() % numWorkers;\r\n return shardKey;\r\n });\r\n\r\n```\r\n\r\nThen add your services to the ServiceWorkers composition.\r\n```java\r\n int workerCount = Runtime.getRuntime().availableProcessors();\r\n\r\n for (int index = 0; index < workerCount; index++) {\r\n final Service service = serviceBuilder\r\n .setServiceObject(new ContentRulesEngine()).build();\r\n dispatcher.addServices(service);\r\n\r\n }\r\n```\r\n\r\nThen add it to the service bundle as before.\r\n```java\r\n\r\n dispatcher.start();\r\n\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nThen just use it:\r\n\r\n```java\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n for (int index = 0; index < 100; index++) {\r\n String userName = \"rickhigh\" + index;\r\n worker.pickSuggestions(userName);\r\n }\r\n\r\n```\r\n\r\n### Built in shard rules\r\n\r\n```java\r\n\r\n\r\npublic class ServiceWorkers {\r\n...\r\n public static ShardedMethodDispatcher shardOnFirstArgumentWorkers() {\r\n ...\r\n }\r\n\r\n...\r\n\r\n public static ShardedMethodDispatcher shardOnFifthArgumentWorkers() {\r\n ...\r\n }\r\n\r\n\r\n public static ShardedMethodDispatcher shardOnBeanPath(final String beanPath) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nThe shardOnBeanPath allows you to create a complex bean path navigation call and use its property to shard on.\r\n\r\n```java\r\n\r\n /* shard on 2nd arg which is an employee\r\n Use the employees department's id property. */\r\n dispatcher = shardOnBeanPath(\"[1].department.id\");\r\n\r\n /* Same as above. */\r\n dispatcher = shardOnBeanPath(\"1/department/id\");\r\n\r\n```\r\n\r\n[Read more about Service sharding and service workers here](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-QBit-Microservices-using-Service-Workers-and-sharded-service-workers)\r\n\r\n\r\nYou can find a lot more in the wiki. Also follow the commits.\r\nWe have been busy beavers.\r\n[QBit the microservice lib for Java - JSON, REST, WebSocket](https://github.com/advantageous/qbit/wiki).",
+ "body": "[QBit Micorservices tutorials](https://github.com/MammatusTech/qbit-microservices-examples/wiki) .. | .. [QBit uses Reakt](http://advantageous.github.io/reakt/) .. | .. [QBit works with Vert.x](http://vertx.io/) .. | .. [Reakt Vertx](http://advantageous.github.io/reakt-vertx/)\r\n\r\n#QBit - The Microservice Lib for Java - JSON, REST, WebSocket, Speed! \r\n\r\n## Quick overview of QBit\r\n\r\nThe Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.\r\n\r\nGot a question? Ask here: [QBit Google Group](https://groups.google.com/forum/#!forum/qbit-microservice).\r\n\r\nEverything is a queue. You have a choice. You can embrace it and control it. You can optimize for it.\r\nOr you can hide behind abstractions. QBit opens you up to peeking into what is going on, and allows you\r\nto pull some levers without selling your soul.\r\n\r\nQBit is a library not a framework. You can mix and match QBit with Spring, Guice, etc.\r\n\r\nQBit is FAST!\r\n\r\n\r\n\r\n#### Using from maven\r\n```xml\r\n\r\n io.advantageous.qbit\r\n qbit-admin\r\n 1.0.0.RELEASE\r\n\r\n\r\n io.advantageous.qbit\r\n qbit-vertx\r\n 1.0.0.RELEASE\r\n\r\n```\r\n\r\n#### Using from gradle\r\n```java\r\ncompile 'io.advantageous.qbit:qbit-admin:1.0.0.RELEASE'\r\ncompile 'io.advantageous.qbit:qbit-vertx:1.0.0.RELEASE'\r\n```\r\n\r\nCore Features\r\n============\r\n\r\n* Write REST based async microservices\r\n* Write ***WebSocket*** based async microservices (fast async RPC over WebSocket)\r\n* Actor Service Queues using micro-batching for high-speed message passing\r\n* Strongly async typed event bus which can be distributed\r\n* Async low overhead metrics gathering which can be queried and distributed (for doing fast lane analytics)\r\n* Complex async call coordination (with the Reactor) for reactive programming\r\n* Built-in support for ***health checks*** (and integration with tools like Consul)\r\n* Built-in support for ***monitoring*** (and integration with wire protocols like StatsD)\r\n* Built-in support for ***Service Discovery*** (with integration with health system, DNS SRV records and Consul)\r\n* Integration with persistent queues\r\n* [12 factor app port bindings](http://12factor.net/), health checks, KPI gathering, Logging MDC\r\n* API Gateway support for client generation and consumption via [Swagger](http://swagger.io/).\r\n* Our services can generate Swagger files (like idl for JSON/REST).\r\n* Remote client proxies for WebSocket (your interface is your IDL)\r\n\r\n\r\nStatus\r\n=====\r\nDeployed at several large fortune 100 companies. \r\nQBit now works with Vertx (standalone or embedded).\r\nYou can also use QBit on non-QBit projects, it is just a lib.\r\n\r\nLicense\r\n=====\r\nApache 2\r\n\r\n\r\n## Java Microservice Lib\r\n\r\nQBit has inproc services, REST microservices and WebSocket microservices as well as an\r\nin-proc service event bus (which can be per module or per app). It supports workers and in-memory services.\r\n\r\nBefore we describe more, here are two sample services:\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {...\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {...\r\n```\r\n\r\n\r\n#### Adder Service using URI params\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {...\r\n }\r\n```\r\n\r\n\r\n\r\nQBit philosophy:\r\n====\r\nAt the end of the day QBit is a simple library not a framework.\r\nYour app is not a QBit app but a Java app that uses the QBit lib.\r\nQBit allows you to work with Java UTIL concurrent, and does not endeavor to hide it from you.\r\nJust trying to take the sting out of it.\r\n\r\nDoes it work\r\n=====\r\nWe have used techniques in Boon and QBit with great success in high-end, high-performance, high-scalable apps.\r\nWe helped clients handle 10x the load with 1/10th the servers of their competitors using techniques in QBit.\r\nQBit is us being sick of hand tuning queue access and threads.\r\n\r\n\r\nBoon and QBit humility policy\r\n=====\r\nIdeas for Boon and QBit often come from all over the web. We make mistakes. Point them out.\r\nAs a developer of Boon and QBit, we are fellow travelers.\r\nIf you have an idea or technique you want to share, we listen.\r\n\r\n\r\nInspiration\r\n====\r\n\r\nA big inspiration for Boon/QBit was Vertx, Akka, Go Channels, Active Objects, Apartment Model Threading, Actor,\r\nand the Mechanical Sympathy papers.\r\n\r\nQBit has ideas that are similar to many frameworks. We are all reading the same papers.\r\nQBit got inspiration from the LMAX disruptor papers and this blog post about\r\n[link transfer queue versus disruptor](http://php.sabscape.com/blog/?p=557). We had some theories about\r\nqueues that blog post inspired us to try them out. Some of these theories are deployed at some of the\r\nbiggest middleware backends and whose name brands are known around the world. And thus QBit was born.\r\n\r\nQBit also took an lot of inspiration by the great work done\r\nby Tim Fox on Vertx. The first project using something that could actually be called QBit (albeit early QBit)\r\n was using Vertx on an web/mobile microservice for an app that could potentially have 80 million users.\r\n It was this\r\nexperience with Vertx and early QBit that led to QBit development and evolution. QBit is built on the\r\nshoulders of giants (Netty/Vertx).\r\n\r\nDoes QBit compete with...\r\n====\r\nSpring Disruptor: No. You could use QBit to write plugins for Spring Disruptor I suppose, but QBit does\r\nnot compete with Spring Disruptor.\r\nSpring Boot/Spring MVC: No. We use the same annotations but QBit is geared for high-speed in-memory\r\nmicroservices. It is more like Akka than Spring Boot. QBit has a subset of the features of Spring MVC\r\ngeared only for microservices, i.e., WebSocket RPC, REST, JSON marshaling, etc.\r\nAkka: No. Well Maybe. Akka has similar concepts but they take a different approach. QBit is more focused\r\n on Java, and microservices (REST, JSON, WebSocket) than Akka.\r\nLMAX Disruptor: No. In fact, we can use disruptor as on of the queues that QBit uses underneath the covers.\r\n\r\n\r\n(Early benchmarks have been removed. They were here. QBit got a lot faster.\r\n Benchmarking QBit is a moving target at the moment.\r\n Links and reports will be created.)\r\n\r\n\r\nCode Examples\r\n\r\n\r\n## Basic Queue example (REST style services is further down)\r\n\r\n====\r\n\r\n```java\r\n\r\n BasicQueue queue = BasicQueue.create(Integer.class, 1000);\r\n\r\n //Sending threads\r\n\r\n SendQueue sendQueue = queue.sendQueue();\r\n for (int index = 0; index < amount; index++) {\r\n sendQueue.send(index);\r\n }\r\n sendQueue.flushSends();\r\n ...\r\n sendQueue.sendAndFlush(code);\r\n //other methods for sendQueue, writeBatch, writeMany\r\n\r\n\r\n //Receiving Threads\r\n ReceiveQueue receiveQueue = queue.receiveQueue();\r\n Integer item = receiveQueue.take();\r\n //other methods poll(), pollWait(), readBatch(), readBatch(count)\r\n```\r\n\r\n\r\n### What is QBit again?\r\n\r\nQBit is a queuing library for microservices. It is similar to many other projects like Akka, Spring Reactor,\r\netc. QBit is just a library not a platform. QBit has libraries to put a service behind a queue.\r\nYou can use QBit queues directly or you can create a service. QBit services can be exposed by WebSocket,\r\nHTTP, HTTP pipeline, and other types of remoting. A service in QBit is a Java class whose methods are\r\n executed behind service queues. QBit implements apartment model threading and is similar to the\r\n Actor model or a better description would be Active Objects. QBit does not use a disruptor (but could).\r\n It uses regular Java Queues. QBit can do north of 100 million ping pong calls per second which is\r\n an amazing speed (seen as high as 200M). QBit also supports calling services via REST, and WebSocket.\r\n QBit is microservices in the pure Web sense: JSON, HTTP, WebSocket, etc. QBit uses micro batching to\r\n push messages through the pipe (queue, IO, etc.) faster to reduce thread hand-off.\r\n\r\n### QBit lingo\r\n\r\nQBit is a Java microservice lib supporting REST, JSON and WebSocket. It is written in Java but we could\r\none day write a version in Rust or Go or C# (but that would require a large payday).\r\n\r\n**Service**\r\nPOJO (plain old Java object) behind a queue that can receive method calls via proxy calls or events\r\n(May have one thread managing events, method calls, and responses or two one for method calls and events\r\n 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.\r\n\r\n**ServiceBundle**\r\nMany POJOs behind one response queue and many receive queues. There may be one thread for all responses\r\nor not. They also can be one receive queue.\r\n\r\n**Queue**\r\nA thread managing a queue. It supports batching. It has events for empty, reachedLimit, startedBatch,\r\nidle. You can listen to these events from services that sit behind a queue. You don't have to use Services.\r\nYou can use Queue's direct. In QBit, you have sender queues and receivers queues. They are separated to\r\nsupport micro-batching.\r\n\r\n**ServiceEndpointServer**\r\nServiceBundle that is exposed to REST and WebSocket communication.\r\n\r\n**EventBus**\r\nEventBus is a way to send a lot of messages to services that may be loosely coupled.\r\n\r\n**ClientProxy**\r\nClientProxy is a way to invoke service through async interface, service can be inproc (same process) or\r\nremoted over WebSocket.\r\n\r\n**Non-blocking**\r\nQBit is a non-blocking lib. You use CallBacks via Java 8 Lambdas. You can also send event messages and get\r\nreplies. Messaging is built into the system so you can easily coordinate complex tasks.\r\nQBit takes an object-oriented approach to service development so services look like normal Java services\r\nthat you\r\nalready write, but the services live behind a queue/thread. This is not a new concept. Microsoft did this\r\nwith DCOM/COM and called it active objects. Akka does it with actors and called them strongly typed Actors.\r\nThe important concepts is that you get the speed of reactive and actor style messaging but you develop\r\nin a natural OOP approach. QBit is not the first. QBit is not the only.\r\n\r\n\r\n**Speed**\r\nQBit is VERY fast. There is a of course a lot of room for improvement. But already 200M+ TPS inproc ping pong, 10M-20M+ TPS event bus, 500K TPS RPC calls over WebSocket/JSON, etc.\r\nMore work needs to be done to improve speed, but now it is fast enough where we are focusing more on\r\nusability.\r\nThe JSON support uses Boon by default which is up to 4x faster than other JSON parsers for the\r\nREST/JSON, WebSocket/JSON use case.\r\n\r\n**Reactive Programming**\r\nQBit provides a **Reactor** to manage async calls. This allows callbacks to be handled on the same thread that called them and it provides for timeout and error handling. Read [Reactor tutorial for creating reactive micro service programming](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices)\r\n\r\n**Service Discovery**\r\nBuilt in support for service discovery. This includes integration with Consul.\r\n\r\n\r\n**StatService**\r\nBuilt in support for stats. The **StatService** can be integrated with **StatsD** (Graphite, Grafana, DataDog, etc.) to publish passive stats. Or you can query the stats engine and react to the stats (counts, timings and levels). The **StatsService** is a reactive stats system that can be clustered. The StatService is reactive in that your services can publish to it and query it and react based on the results. You can implement things like rate limiting and react to an increased rate of something. The ServiceDiscovery system integrates with the HealthSystem and Consul to roll up each of your internal services that make up you micro service and publish the composite availably of your micro service to a single HTTP endpoint or a dead mans switch in Consul (TTL). \r\n\r\n\r\n\r\n### CURLable REST services example\r\n\r\nTalk is cheap. Let's look at some code. You can get a detailed walk through in the Wiki.\r\nWe have a lot of documentation already.\r\n\r\nWe will create a service that is exposed through REST/JSON.\r\n\r\nTo query the size of the todo list:\r\n\r\n```bash\r\ncurl localhost:8080/services/todo-service/todo/count\r\n```\r\n\r\nTo add a new TODO item.\r\n\r\n```bash\r\ncurl -X POST -H \"Content-Type: application/json\" -d \\\r\n'{\"name\":\"xyz\",\"description\":\"xyz\"}' \\\r\nhttp://localhost:8080/services/todo-service/todo\r\n```\r\n\r\nTo get a list of TODO items\r\n```bash\r\ncurl http://localhost:8080/services/todo-service/todo/\r\n```\r\n\r\nThe TODO example will use and track Todo items.\r\n\r\n#### Todo item POJO sans getter\r\n\r\n```java\r\npackage io.advantageous.qbit.examples;\r\n\r\nimport java.util.Date;\r\n\r\n\r\npublic class TodoItem {\r\n\r\n\r\n private final String description;\r\n private final String name;\r\n private final Date due;\r\n\r\n```\r\n\r\nThe TodoService uses Spring MVC style annotations.\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n\r\n private List todoItemList = new ArrayList<>();\r\n\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {\r\n\r\n return todoItemList.size();\r\n }\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {\r\n\r\n return todoItemList;\r\n }\r\n\r\n @RequestMapping(value = \"/todo\", method = RequestMethod.POST)\r\n public void add(TodoItem item) {\r\n\r\n todoItemList.add(item);\r\n }\r\n\r\n}\r\n\r\n```\r\n\r\n\r\n#### Sending non-JSON\r\n\r\nYou can POST/PUT non-JSON and you can capture the body as a `String` or as a `byte[]`. \r\nIf the content-type is set to anything but `application/json` and your body is defined a String or byte[].\r\nThis works automatically. (The content-type has to be set.)\r\n\r\n```java\r\n @RequestMapping(value = \"/body/bytes\", method = RequestMethod.POST)\r\n public boolean bodyPostBytes( byte[] body) {\r\n String string = new String(body, StandardCharsets.UTF_8);\r\n return string.equals(\"foo\");\r\n }\r\n\r\n @RequestMapping(value = \"/body/string\", method = RequestMethod.POST)\r\n public boolean bodyPostString(String body) {\r\n return body.equals(\"foo\");\r\n }\r\n```\r\n\r\n\r\n#### Sending different response codes for success\r\n\r\nBy default QBit sends a `200` (OK) for a non-void call (a call that has a return or a Callback). If the REST operation has no return or no callback then QBit sends a `202` (Accepted). There may be times when you want to send a 201 (Created) or some other code that is not an Exception. You can do that by setting `code` on `@RequestMapping`. By default the code is -1 which means use the default behavior (200 for success, 202 for one-way message, and 500 for errors).\r\n\r\n\r\n#### Sending different response codes for success\r\n```java\r\n\r\n @RequestMapping(value = \"/helloj7\", code = 221)\r\n public void helloJSend7(Callback>> callback) {\r\n callback.returnThis(JSendResponseBuilder.jSendResponseBuilder(Lists.list(\r\n \"hello \" + System.currentTimeMillis())).build());\r\n }\r\n\r\n```\r\n\r\n`Callbacks` can be used for internal services as well. It is often the case that you use a [CallbackBuilder](https://github.com/advantageous/qbit/wiki/%5BDocument%5D-CallbackBuilder-and-generics-for-Reactive-Java-Microservices) or a QBit [Reactor](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices) to manage service calls. \r\n\r\n#### Working with non JSON responses\r\n\r\nYou do not have to return JSON form rest calls.\r\nYou can return any binary or any text by using `HttpBinaryResponse` and `HttpTextResponse`.\r\n\r\n#### Returning non JSON from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildTextResponse());\r\n }\r\n```\r\n\r\n\r\n#### Returning binary from REST call\r\n```java\r\n @RequestMapping(method = RequestMethod.GET)\r\n public void ping2(Callback callback) {\r\n\r\n callback.returnThis(HttpResponseBuilder.httpResponseBuilder()\r\n .setBody(\"hello mom\").setContentType(\"mom\")\r\n .setCode(777)\r\n .buildBinaryResponse());\r\n }\r\n```\r\n\r\n#### Side note Why Spring style annotations?\r\nWhy did we pick Spring style annotations?\r\n1) Spring is not a standard and neither is QBit. 2) We found the Spring annotations to be less verbose.\r\n3) More people use Spring than Java EE. We wrote QBit for people to use.\r\nWe could easily support JAX-RS style annotations, and we probably will.\r\nSince QBit focuses on JSON, we do not need all of the complexity of JAX-RS or even all the features of\r\nthe Spring MVC annotations. Also we can literally use the actual Spring annotations. QBit and Boon\r\nuse a non-type safe mechanism for annotations which means they are not tied to a particular lib.\r\nYou can define your own. We hate vendor tie-in even if it is an open source vendor.\r\n(We also support @POST, @GET which is similar to JAX-RS).\r\n\r\nNow just start it up.\r\n\r\n```java\r\n\r\n public static void main(String... args) {\r\n\r\n ServiceEndpointServer server = new EndpointServerBuilder().build();\r\n server.initServices(new TodoService());\r\n server.start();\r\n }\r\n```\r\n\r\n\r\n\r\nThat is it. There is also out of the box WebSocket support with client side proxy generation so\r\nyou can call into services at the rate of millions of calls per second.\r\n\r\n## Using URI Params for QBit microservice\r\n\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {\r\n\r\n return a + b;\r\n }\r\n }\r\n\r\n```\r\n\r\n## WebSocket\r\nYou can always invoke QBit services via a WebSocket proxy.\r\nThe advantage of a WebSocket proxy is it allows you execute 1M RPC+ a second (1 million remote calls\r\nevery second).\r\n\r\n\r\n#### Using a microservice remotely with WebSocket\r\n```java\r\n /* Start QBit client for WebSocket calls. */\r\n final Client client = clientBuilder()\r\n .setPort(7000).setRequestBatchSize(1).build();\r\n\r\n\r\n /* Create a proxy to the service. */\r\n final AdderServiceClientInterface adderService =\r\n client.createProxy(AdderServiceClientInterface.class,\r\n \"adder-service\");\r\n\r\n client.start();\r\n\r\n\r\n\r\n /* Call the service */\r\n adderService.add(System.out::println, 1, 2);\r\n\r\n```\r\n\r\nThe output is 3.\r\n\r\n```output\r\n3\r\n```\r\n\r\n\r\nThe above uses a WebSocket proxy interface to call the service async.\r\n\r\n```java\r\n\r\n interface AdderServiceClientInterface {\r\n\r\n void add(Callback callback, int a, int b);\r\n }\r\n```\r\n\r\n#### ServiceDiscovery aware websocket builders\r\n\r\nCreate websocket service client that is ServiceDiscovery aware.\r\n\r\n\r\n```java\r\n final Client client = clientBuilder.setServiceDiscovery(serviceDiscovery, \"echo\")\r\n .setUri(\"/echo\").setProtocolBatchSize(20).build().startClient();\r\n\r\n\r\n final EchoAsync echoClient = client.createProxy(EchoAsync.class, \"echo\");\r\n```\r\n\r\nCurrently the `clientBuilder` will load all service endpoints that are registered under the service name,\r\nand randomly pick one. \r\n\r\nServiceDiscovery includes Consul based, watching JSON files on disk, and DNS. It is easy to write your own service discovery as well and plug it into QBit.\r\n\r\n\r\nIn the future we can RoundRobin calls or shard calls to websocket service and/or provide auto fail over if the connection is closed. We do this for the event bus that uses service discovery but it is not baked into WebSocket based client stubs yet.\r\n\r\n\r\n## REST call with URI params\r\n\r\nThe last client example uses WebSocket. You could also just use REST, and actually use the URI params\r\nthat we setup.\r\nREST is nice but it is going to be slower than WebSocket support.\r\n\r\nQBit ships with a nice little HTTP client. We can use it.\r\n\r\nYou can use it to send async calls and WebSocket messages with the HTTP client.\r\n\r\n\r\nHere we will use the http client to invoke our remote method:\r\n\r\n#### Using a microservice remotely with REST QBit microservice client\r\n```java\r\n\r\n\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\")\r\n .setPort(7000).build();\r\n\r\n httpClient.start();\r\n String results = httpClient\r\n .get(\"/services/adder-service/add/2/2\").body();\r\n System.out.println(results);\r\n\r\n```\r\n\r\n\r\nThe output is 4.\r\n\r\n```output\r\n4\r\n```\r\n\r\n## Accessing The URI Param example with CURL\r\n\r\nYou can also access the service from curl.\r\n\r\n```bash\r\n$ curl http://localhost:7000/services/adder-service/add/2/2\r\n```\r\n\r\nSee this full example here: [QBit microservice getting started tutorial](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-------------QBit-microservice-example).\r\n\r\n[QBit URI params and WebSocket proxy client](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Using-QBit-microservice-lib's-REST-support-with-URI-Params)\r\n\r\n## Working with WebSocket, HttpClient etc.\r\n\r\nQBit has a library for working with and writing async microservices that is lightweight and fun to use.\r\n\r\n#### WebSocket server and client.\r\n\r\n\r\n#### Create an HTTP server\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n```\r\n\r\n#### Setup server WebSocket support\r\n```java\r\n /* Setup WebSocket Server support. */\r\n httpServer.setWebSocketOnOpenConsumer(webSocket -> {\r\n webSocket.setTextMessageConsumer(message -> {\r\n webSocket.sendText(\"ECHO \" + message);\r\n });\r\n });\r\n\r\n```\r\n\r\n#### Start the server\r\n```java\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n```\r\n\r\n#### Setup the WebSocket client\r\n```java\r\n\r\n /** CLIENT. */\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\n#### Client WebSocket\r\n\r\n```java\r\n\r\n /* Setup the client websocket. */\r\n WebSocket webSocket = httpClient\r\n .createWebSocket(\"/websocket/rocket\");\r\n\r\n /* Setup the text consumer. */\r\n webSocket.setTextMessageConsumer(message -> {\r\n System.out.println(message);\r\n });\r\n webSocket.openAndWait();\r\n\r\n /* Send some messages. */\r\n webSocket.sendText(\"Hi mom\");\r\n webSocket.sendText(\"Hello World!\");\r\n\r\n```\r\n\r\n#### Output\r\n```output\r\n\r\nECHO Hi mom\r\nECHO Hello World!\r\n\r\n```\r\n\r\nNow stop the server and client. Pretty easy eh?\r\n\r\n## High-speed HTTP client and server done microservice style\r\n\r\n\r\n##### Starting up an HTTP server\r\n\r\n```java\r\n\r\n /* Create an HTTP server. */\r\n HttpServer httpServer = httpServerBuilder()\r\n .setPort(8080).build();\r\n\r\n /* Setting up a request Consumer with Java 8 Lambda expression. */\r\n httpServer.setHttpRequestConsumer(httpRequest -> {\r\n\r\n Map results = new HashMap<>();\r\n results.put(\"method\", httpRequest.getMethod());\r\n results.put(\"uri\", httpRequest.getUri());\r\n results.put(\"body\", httpRequest.getBodyAsString());\r\n results.put(\"headers\", httpRequest.getHeaders());\r\n results.put(\"params\", httpRequest.getParams());\r\n httpRequest.getReceiver()\r\n .response(200, \"application/json\", Boon.toJson(results));\r\n });\r\n\r\n\r\n /* Start the server. */\r\n httpServer.start();\r\n\r\n\r\n```\r\n\r\nThe focus is on ease of use and using Java 8 Lambdas for callbacks so the code is tight and small.\r\n\r\n[Find out more about QBit's microservice style WebSocket support here](https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-WebSocket-support)\r\n\r\n\r\n## Using HTTP Client lib\r\n\r\nNow, let's try out our HTTP client.\r\n\r\n##### Starting up an HTTP client\r\n\r\n```java\r\n\r\n /* Setup an httpClient. */\r\n HttpClient httpClient = httpClientBuilder()\r\n .setHost(\"localhost\").setPort(8080).build();\r\n httpClient.start();\r\n```\r\n\r\nYou just pass the URL, the port and then call start.\r\n\r\n## Synchronous HTTP calls\r\n\r\nNow you can start sending HTTP requests.\r\n\r\n##### No Param HTTP GET\r\n\r\n```java\r\n /* Send no param get. */\r\n HttpResponse httpResponse = httpClient.get( \"/hello/mom\" );\r\n puts( httpResponse );\r\n```\r\n\r\nAn HTTP response just contains the results from the server.\r\n\r\n\r\n##### No Param HTTP Response\r\n\r\n```java\r\npublic interface HttpResponse {\r\n\r\n MultiMap headers();\r\n\r\n int code();\r\n\r\n String contentType();\r\n\r\n String body();\r\n\r\n}\r\n\r\n```\r\n\r\nThere are helper methods for sync HTTP GET calls.\r\n\r\n\r\n\r\n##### Helper methods for GET\r\n```java\r\n\r\n\r\n /* Send one param get. */\r\n httpResponse = httpClient.getWith1Param(\"/hello/singleParam\",\r\n \"hi\", \"mom\");\r\n puts(\"single param\", httpResponse );\r\n\r\n\r\n /* Send two param get. */\r\n httpResponse = httpClient.getWith2Params(\"/hello/twoParams\",\r\n \"hi\", \"mom\", \"hello\", \"dad\");\r\n puts(\"two params\", httpResponse );\r\n\r\n...\r\n\r\n /* Send five param get. */\r\n httpResponse = httpClient.getWith5Params(\"/hello/5params\",\r\n \"hi\", \"mom\",\r\n \"hello\", \"dad\",\r\n \"greetings\", \"kids\",\r\n \"yo\", \"pets\",\r\n \"hola\", \"neighbors\");\r\n puts(\"5 params\", httpResponse );\r\n\r\n\r\n```\r\n\r\nThe puts method is a helper method it does System.out.println more or less by the way.\r\n\r\nThe first five params are covered. Beyond five, you have to use the HttpBuilder.\r\n\r\n```java\r\n\r\n\r\n /* Send six params with get. */\r\n\r\n final HttpRequest httpRequest = httpRequestBuilder()\r\n .addParam(\"hi\", \"mom\")\r\n .addParam(\"hello\", \"dad\")\r\n .addParam(\"greetings\", \"kids\")\r\n .addParam(\"yo\", \"pets\")\r\n .addParam(\"hola\", \"pets\")\r\n .addParam(\"salutations\", \"all\").build();\r\n\r\n httpResponse = httpClient.sendRequestAndWait(httpRequest);\r\n puts(\"6 params\", httpResponse );\r\n```\r\n\r\n## Http Async HTTP Client\r\n\r\nThere are async calls for GET as well.\r\n\r\n#### Async calls for HTTP GET using Java 8 lambda\r\n\r\n```java\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsync(\"/hi/async\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith1Param(\"/hi/async\", \"hi\", \"mom\", (code, contentType, body) -> {\r\n puts(\"Async text with lambda 1 param\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith2Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 2 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n\r\n...\r\n /* Using Async support with lambda. */\r\n httpClient.getAsyncWith5Params(\"/hi/async\",\r\n \"p1\", \"v1\",\r\n \"p2\", \"v2\",\r\n \"p3\", \"v3\",\r\n \"p4\", \"v4\",\r\n \"p5\", \"v5\",\r\n (code, contentType, body) -> {\r\n puts(\"Async text with lambda 5 params\\n\", body);\r\n });\r\n\r\n Sys.sleep(100);\r\n\r\n```\r\n\r\n[Find more about the easy to use, fast microservice HTTP client here]\r\n(https://github.com/advantageous/qbit/wiki/%5BDoc%5D-Using-QBit-microservice-lib's-HttpClient-GET,-POST,-et-al,-JSON,-Java-8-Lambda).\r\n\r\n## InProc QBit services\r\n\r\nQBit allows for services behind queues to be run in-proc as well.\r\n\r\n```java\r\n\r\n /* POJO service. */\r\n final TodoManager todoManagerImpl = new TodoManager();\r\n\r\n /*\r\n Create the service which manages async calls to todoManagerImpl.\r\n */\r\n final Service service = serviceBuilder()\r\n .setServiceObject(todoManagerImpl)\r\n .build().startServiceQueue();\r\n\r\n\r\n /* Create Asynchronous proxy over Synchronous service. */\r\n final TodoManagerClientInterface todoManager =\r\n service.createProxy(TodoManagerClientInterface.class);\r\n\r\n service.startCallBackHandler();\r\n\r\n\r\n System.out.println(\"This is an async call\");\r\n /* Asynchronous method call. */\r\n todoManager.add(new Todo(\"Call Mom\", \"Give Mom a call\"));\r\n\r\n\r\n AtomicInteger countTracker = new AtomicInteger();\r\n //Hold count from async call to service... for testing and showing it is an async callback\r\n\r\n System.out.println(\"This is an async call to count\");\r\n\r\n todoManager.count(count -> {\r\n System.out.println(\"This lambda expression is the callback \" + count);\r\n\r\n countTracker.set(count);\r\n });\r\n\r\n\r\n todoManager.clientProxyFlush(); //Flush all methods. It batches calls.\r\n\r\n Sys.sleep(100);\r\n\r\n System.out.printf(\"This is the count back from the server %d\\n\", countTracker.get());\r\n\r\n```\r\n\r\n[Detailed tutorial on in-proc services is being written.](https://github.com/advantageous/qbit/wiki/%5BDetailed-Tutorial%5D-Working-with-inproc-MicroServices-within-QBit.)\r\n\r\n\r\n## QBit Event Bus\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\nQBit also has a service event bus. This example is a an employee benefits services example.\r\n\r\nWe have two channels.\r\n\r\n```\r\npublic static final String NEW_HIRE_CHANNEL = \"com.mycompnay.employee.new\";\r\n\r\npublic static final String PAYROLL_ADJUSTMENT_CHANNEL = \"com.mycompnay.employee.payroll\";\r\n```\r\n\r\nAn employee object looks like this:\r\n\r\n```java\r\n\r\npublic static class Employee {\r\n final String firstName;\r\n final int employeeId;\r\n```\r\n\r\n\r\nThis example has three services: EmployeeHiringService, BenefitsService, and PayrollService.\r\n\r\nThese services are inproc services. QBit supports WebSocket, HTTP and REST remote services as well, but for now, let's focus on inproc services. If you understand inproc then you will understand remote.\r\n\r\nThe EmployeeHiringService actually fires off the events to other two services.\r\n\r\n```java\r\npublic class EmployeeHiringService {\r\n\r\n\r\n public void hireEmployee(final Employee employee) {\r\n\r\n int salary = 100;\r\n System.out.printf(\"Hired employee %s\\n\", employee);\r\n\r\n //Does stuff to hire employee\r\n\r\n //Sends events\r\n final EventManager eventManager =\r\n serviceContext().eventManager();\r\n eventManager.send(NEW_HIRE_CHANNEL, employee);\r\n\r\n eventManager.sendArray(PAYROLL_ADJUSTMENT_CHANNEL,\r\n employee, salary);\r\n\r\n\r\n }\r\n\r\n }\r\n```\r\n\r\n\r\nNotice that we call sendArray so we can send the employee and their salary.\r\nThe listener for PAYROLL_ADJUSTMENT_CHANNEL will have to handle both an employee and an int\r\nthat represents the new employees salary.\r\nYou can also use event bus proxies so you do not have to call into the event bus at all.\r\n\r\nThe BenefitsService listens for new employees being hired so it can enroll them into the benefits system.\r\n\r\n```java\r\npublic static class BenefitsService {\r\n\r\n @OnEvent(NEW_HIRE_CHANNEL)\r\n public void enroll(final Employee employee) {\r\n\r\n System.out.printf(\"Employee enrolled into benefits system employee %s %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId());\r\n\r\n }\r\n\r\n```\r\n\r\nDaddy needs to get paid.\r\n\r\n```java\r\n public static class PayrollService {\r\n\r\n @OnEvent(PAYROLL_ADJUSTMENT_CHANNEL)\r\n public void addEmployeeToPayroll(final Employee employee, int salary) {\r\n\r\n System.out.printf(\"Employee added to payroll %s %d %d\\n\",\r\n employee.getFirstName(), employee.getEmployeeId(), salary);\r\n\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nThe employee is the employee object from the EmployeeHiringService.\r\n\r\nso you can get your benefits, and paid!\r\n\r\nFind more details here:\r\n\r\n[QBit Event Bus more detailed example](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-event-bus-for-QBit-the-microservice-engine)\r\n\r\n\r\n## Private event bus and event bus proxies\r\n\r\n You can define your own interface to the event bus and you can use your own event buses with QBit.\r\n Each module in your service can have its own internal event bus.\r\n\r\n To learn more read:\r\n [QBit Microservice working with a private event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-private-event-bus-for-inproc-microservices)\r\n and [QBit Java Microservice lib using your own interface to the event bus](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-Working-with-strongly-typed-event-bus-proxies-for-QBit-Java-Microservice-lib).\r\n\r\n\r\n\r\n## Queue Callbacks\r\n\r\n To really grasp QBit, one must grasp the concepts of a CallBack.\r\n\r\n A CallBack is a way to get an async response in QBit.\r\n\r\n You call a service method and it calls you back.\r\n\r\n Client proxies can have callbacks:\r\n\r\n\r\n#### Queue Callbacks - RecommendationService client interface\r\n```java\r\n\r\npublic interface RecommendationServiceClient {\r\n\r\n\r\n void recommend(final Callback> recommendationsCallback,\r\n final String userName);\r\n}\r\n\r\n```\r\n\r\nCallbacks are Java 8 Consumers with some optional extra error handling.\r\n\r\n\r\n#### Queue Callbacks - Callback\r\n\r\n```java\r\n\r\n\r\npublic interface Callback extends java.util.function.Consumer {\r\n default void onError(java.lang.Throwable error) { /* compiled code */ }\r\n}\r\n\r\n```\r\n\r\nServices that can block should use callbacks.\r\nThus if loadUser blocked in the following example, it should really use a callback instead of returning a value.\r\n\r\npublic class RecommendationService {\r\n\r\n#### Queue Callbacks - Simple minded implementation of RecommendationService\r\n```java\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n public List recommend(final String userName) {\r\n User user = users.get(userName);\r\n if (user == null) {\r\n user = loadUser(userName);\r\n }\r\n return runRulesEngineAgainstUser(user);\r\n }\r\n\r\n```\r\n\r\n\r\nLet's pretend `loadUser` has to look in a local cache, and if the user is not found, look in an off-heap cache\r\nand if not found it must ask for the user from the UserService which must check its caches and perhaps fallback\r\nto loading the user data from a database or from other services.\r\nIn other words, `loadUser` can potentially block on IO.\r\n\r\n\r\n\r\n### Queue Callbacks - The first rule of Queue Club - don't block\r\n\r\n\r\nOur client does not block, but our service does. Going back to our `RecommendationService`.\r\nIf we get a lot of cache hits for user loads, perhaps the\r\nblock will not be that long, but it will be there and every time we have to fault in a user, the whole system\r\nis gummed up. What we want to be able to do is if we can't handle the recommendation request,\r\nwe go ahead and make an async call to the `UserDataService`. When that async callback comes back, then we\r\nhandle that request. In the mean time, we handle recommendation lists requests as quickly as we can.\r\nWe never block.\r\n\r\n\r\nSo let's revisit the service. The first thing we are going to do is make the service method take\r\na callback. Before we do that, let's set down some rules.\r\n\r\n\r\n#### The first rule of queue club don't block.\r\n#### The second rule of queue club if you are not ready, use a callback and continue handling stuff you are ready for\r\n\r\n\r\n#### Queue Callbacks - Adding a CallBack to the RecommendationService inproc microservice\r\n\r\n```java\r\npublic class RecommendationService {\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n```\r\n\r\n\r\n\r\nNow we are taking a callback and we can decide when we want to handle this recommendation generation request.\r\nWe can do it right away if there user data we need is in-memory or we can delay it.\r\n\r\n\r\n#### If the user is found, call the callback right away for RecommendationService inproc microservice\r\n\r\n```java\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n /** Look for user in user cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n ...\r\n } else {\r\n /* Call the callback now because we can handle the callback now. */\r\n recommendationsCallback.accept(runRulesEngineAgainstUser(user));\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nNotice, if the user is found in the cache, we run our recommendation rules in-memory and call the callback right away\r\n`recommendationsCallback.accept(runRulesEngineAgainstUser(user))`.\r\n\r\nThe interesting part is what do we do if don't have the user loaded.\r\n\r\n\r\n#### If the user was not found, load him from the user microservice, but still don't block\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using Callback. */\r\n userDataService.loadUser(new Callback() {\r\n @Override\r\n public void accept(final User loadedUser) {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nHere we use a CallBack to load the user, and when the user is loaded, we call `handleLoadFromUserDataService`\r\nwhich adds some management about handling the callback so we can still handle this call, just not now.\r\n\r\n\r\n\r\n#### Lambda version of last example\r\n\r\n```java\r\n\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n\r\n /** Look for user in users cache. */\r\n User user = users.get(userName);\r\n\r\n /** If the user not found, load the user from the user service. */\r\n if (user == null) {\r\n\r\n /* Load user using lambda expression. */\r\n userDataService.loadUser(\r\n loadedUser -> {\r\n handleLoadFromUserDataService(loadedUser,\r\n recommendationsCallback);\r\n }, userName);\r\n\r\n }\r\n ...\r\n\r\n```\r\n\r\nUsing lambdas like this makes the code more readable and terse, but remember don't deeply nest\r\nlambda expressions or you will create a code maintenance nightmare. Use them judiciously.\r\n\r\n\r\n### Queue Callbacks - Doing something later\r\n\r\nWhat we want is to handle the request for recommendations after the user service system loads\r\nthe user from its store.\r\n\r\n\r\n\r\n#### Handling UserServiceData callback methods once we get them.\r\n\r\n```java\r\n\r\npublic class RecommendationService {\r\n\r\n\r\n private final SimpleLRUCache users =\r\n new SimpleLRUCache<>(10_000);\r\n\r\n private UserDataServiceClient userDataService;\r\n\r\n\r\n private BlockingQueue callbacks =\r\n new ArrayBlockingQueue(10_000);\r\n\r\n\r\n ...\r\n\r\n public void recommend(final Callback> recommendationsCallback,\r\n final String userName) {\r\n\r\n ...\r\n\r\n }\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks queue. */\r\n callbacks.add(new Runnable() {\r\n @Override\r\n public void run() {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n }\r\n });\r\n }\r\n\r\n\r\n\r\n```\r\n\r\n\r\n\r\n\r\n#### handleLoadFromUserDataService rewritten using Lambda\r\n\r\n```java\r\n\r\n\r\npublic class RecommendationService {\r\n\r\n...\r\n\r\n /** Handle defered recommendations based on user loads. */\r\n private void handleLoadFromUserDataService(final User loadedUser,\r\n final Callback> recommendationsCallback) {\r\n\r\n /** Add a runnable to the callbacks list. */\r\n callbacks.add(() -> {\r\n List recommendations = runRulesEngineAgainstUser(loadedUser);\r\n recommendationsCallback.accept(recommendations);\r\n });\r\n\r\n }\r\n\r\n```\r\n\r\n\r\nThe important part there is that every time we get a callback call from `UserDataService`, we then\r\nperform our CPU intensive recommendation rules and callback our caller. Well not exactly, what we\r\ndo is enqueue an runnable onto our callbacks queue, and later we will iterate through those but when?\r\n\r\n\r\n### Queue Callbacks Handling callbacks when our receive queue is empty, a new batch started or we hit a batch limit\r\n\r\nThe `RecommendationService` can be notified when its queue is empty, it has started a new batch and when\r\nit has reached a batch limit. These are all good times to handle callbacks from the `UserDataService`.\r\n\r\n#### Draining our callback queue\r\n```java\r\n\r\n @QueueCallback({\r\n QueueCallbackType.EMPTY,\r\n QueueCallbackType.START_BATCH,\r\n QueueCallbackType.LIMIT})\r\n private void handleCallbacks() {\r\n\r\n flushServiceProxy(userDataService);\r\n Runnable runnable = callbacks.poll();\r\n\r\n while (runnable != null) {\r\n runnable.run();\r\n runnable = callbacks.poll();\r\n }\r\n }\r\n\r\n```\r\n\r\nIt is important to remember when handling callbacks from another microservice that you want to handle\r\ncallbacks from the other service before you handle more incomming requests from you clients.\r\nEssentially you have clients that have been waiting (async waiting but still), and these clients\r\nmight represent an open TCP/IP connection like an HTTP call so it is best to close them out\r\nbefore handling more requests and like we said they were already waiting around with an open connection\r\nfor users to load form the user service.\r\n\r\nTo learn more about CallBacks, plesae read [QBit Java MicroService Lib CallBack fundamentals]([Rough Cut] QBit Microservice Lib Working With CallBacks).\r\n\r\n\r\n\r\n\r\n## Workers - pools and shards\r\n\r\n```java\r\npublic class ServiceWorkers {\r\n\r\n public static RoundRobinServiceDispatcher workers() {...\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {...\r\n```\r\n\r\nYou can compose sharded workers (for in-memory, thread safe, CPU intensive services), or workers for IO\r\nor talking to foreign services or foreign buses.\r\n\r\nHere is an example that uses a worker pool with three service workers in it:\r\n\r\nLet's say you have a service that does something:\r\n\r\n```java\r\n\r\n //Your POJO\r\n public class MultiWorker {\r\n\r\n void doSomeWork(...) {\r\n ...\r\n }\r\n\r\n }\r\n\r\n```\r\n\r\nNow this does some sort of IO and you want to have a bank of these running not just one so you can do\r\nIO in parallel. After some performance testing, you found out that three is the magic number.\r\n\r\nYou want to use your API for accessing this service:\r\n\r\n```java\r\n public interface MultiWorkerClient {\r\n void doSomeWork(...);\r\n }\r\n\r\n```\r\n\r\nNow let's create a bank of these and use it.\r\n\r\nFirst create the QBit services which add the thread/queue/microbatch.\r\n\r\n```java\r\n\r\n /* Create a service builder. */\r\n final ServiceBuilder serviceBuilder = serviceBuilder();\r\n\r\n /* Create some qbit services. */\r\n final Service service1 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service2 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n final Service service3 = serviceBuilder.setServiceObject(new MultiWorker()).build();\r\n```\r\n\r\nNow add them to a ServiceWorkers object.\r\n\r\n```java\r\n\r\n ServiceWorkers dispatcher;\r\n dispatcher = workers(); //Create a round robin service dispatcher\r\n dispatcher.addServices(service1, service2, service3);\r\n dispatcher.start(); // start up the workers\r\n\r\n```\r\n\r\nYou can add services, POJOs and method consumers, method dispatchers to a service bundle.\r\nThe service bundle is an integration point into QBit.\r\n\r\nLet's add our new Service workers. ServiceWorkers is a ServiceMethodDispatcher.\r\n\r\n```Java\r\n /* Add the dispatcher to a service bundle. */\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nWe are probably going to add a helper method to the service bundle so most of this can happen in\r\na single call.\r\n\r\nNow you can start using your workers.\r\n\r\n```java\r\n\r\n /* Start using the workers. */\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n```\r\n\r\nNow you could use Spring or Guice to configure the builders and the service bundle.\r\nBut you can just do it like the above which is good for testing and understanding QBit internals.\r\n\r\nQBit also supports the concept of sharded services which is good for sharding resources like CPU\r\n(run a rules engine on each CPU core for a user recommendation engine).\r\n\r\nQBit does not know how to shard your services, you have to give it a hint.\r\nYou do this through a shard rule.\r\n\r\n```java\r\npublic interface ShardRule {\r\n int shard(String methodName, Object[] args, int numWorkers);\r\n}\r\n```\r\nWe worked on an app where the first argument to the services was the username, and then we used that to\r\nshard calls to a CPU intensive in-memory rules engine. This technique works. :)\r\n\r\nThe ServiceWorkers class has a method for creating a sharded worker pool.\r\n\r\n```java\r\n\r\n public static ShardedMethodDispatcher shardedWorkers(final ShardRule shardRule) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nTo use you just pass a shard key when you create the service workers.\r\n\r\n```java\r\n\r\n\r\n dispatcher = shardedWorkers((methodName, methodArgs, numWorkers) -> {\r\n String userName = methodArgs[0].toString();\r\n int shardKey = userName.hashCode() % numWorkers;\r\n return shardKey;\r\n });\r\n\r\n```\r\n\r\nThen add your services to the ServiceWorkers composition.\r\n```java\r\n int workerCount = Runtime.getRuntime().availableProcessors();\r\n\r\n for (int index = 0; index < workerCount; index++) {\r\n final Service service = serviceBuilder\r\n .setServiceObject(new ContentRulesEngine()).build();\r\n dispatcher.addServices(service);\r\n\r\n }\r\n```\r\n\r\nThen add it to the service bundle as before.\r\n```java\r\n\r\n dispatcher.start();\r\n\r\n bundle = serviceBundleBuilder().setAddress(\"/root\").build();\r\n\r\n bundle.addServiceConsumer(\"/workers\", dispatcher);\r\n bundle.start();\r\n```\r\n\r\nThen just use it:\r\n\r\n```java\r\n final MultiWorkerClient worker = bundle.createLocalProxy(MultiWorkerClient.class, \"/workers\");\r\n\r\n for (int index = 0; index < 100; index++) {\r\n String userName = \"rickhigh\" + index;\r\n worker.pickSuggestions(userName);\r\n }\r\n\r\n```\r\n\r\n### Built in shard rules\r\n\r\n```java\r\n\r\n\r\npublic class ServiceWorkers {\r\n...\r\n public static ShardedMethodDispatcher shardOnFirstArgumentWorkers() {\r\n ...\r\n }\r\n\r\n...\r\n\r\n public static ShardedMethodDispatcher shardOnFifthArgumentWorkers() {\r\n ...\r\n }\r\n\r\n\r\n public static ShardedMethodDispatcher shardOnBeanPath(final String beanPath) {\r\n ...\r\n }\r\n\r\n```\r\n\r\nThe shardOnBeanPath allows you to create a complex bean path navigation call and use its property to shard on.\r\n\r\n```java\r\n\r\n /* shard on 2nd arg which is an employee\r\n Use the employees department's id property. */\r\n dispatcher = shardOnBeanPath(\"[1].department.id\");\r\n\r\n /* Same as above. */\r\n dispatcher = shardOnBeanPath(\"1/department/id\");\r\n\r\n```\r\n\r\n[Read more about Service sharding and service workers here](https://github.com/advantageous/qbit/wiki/%5BRough-Cut%5D-QBit-Microservices-using-Service-Workers-and-sharded-service-workers)\r\n\r\n\r\nYou can find a lot more in the wiki. Also follow the commits.\r\nWe have been busy beavers.\r\n[QBit the microservice lib for Java - JSON, REST, WebSocket](https://github.com/advantageous/qbit/wiki).",
"note": "Don't delete this file! It's used internally to help with page regeneration."
}
\ No newline at end of file
From 419c0a2b86e80a67e596262aa658a34e39313eee Mon Sep 17 00:00:00 2001
From: Richard Hightower
Date: Tue, 19 Apr 2016 16:30:01 -0700
Subject: [PATCH 10/19] Create gh-pages branch via GitHub
---
index.html | 13 +++++++++----
params.json | 2 +-
2 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/index.html b/index.html
index 3339de78..72ee329f 100644
--- a/index.html
+++ b/index.html
@@ -41,25 +41,30 @@
diff --git a/params.json b/params.json
index 3efdd85d..647b0946 100644
--- a/params.json
+++ b/params.json
@@ -1,6 +1,6 @@
{
"name": "QBit - Microservices Lib",
"tagline": "The Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.",
- "body": "[QBit Micorservices tutorials](https://github.com/MammatusTech/qbit-microservices-examples/wiki) .. | .. [QBit uses Reakt](http://advantageous.github.io/reakt/) .. | .. [QBit works with Vert.x](http://vertx.io/) .. | .. [Reakt Vertx](http://advantageous.github.io/reakt-vertx/)\r\n\r\n#QBit - The Microservice Lib for Java - JSON, REST, WebSocket, Speed! \r\n\r\n## Quick overview of QBit\r\n\r\nThe Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.\r\n\r\nGot a question? Ask here: [QBit Google Group](https://groups.google.com/forum/#!forum/qbit-microservice).\r\n\r\nEverything is a queue. You have a choice. You can embrace it and control it. You can optimize for it.\r\nOr you can hide behind abstractions. QBit opens you up to peeking into what is going on, and allows you\r\nto pull some levers without selling your soul.\r\n\r\nQBit is a library not a framework. You can mix and match QBit with Spring, Guice, etc.\r\n\r\nQBit is FAST!\r\n\r\n\r\n\r\n#### Using from maven\r\n```xml\r\n\r\n io.advantageous.qbit\r\n qbit-admin\r\n 1.0.0.RELEASE\r\n\r\n\r\n io.advantageous.qbit\r\n qbit-vertx\r\n 1.0.0.RELEASE\r\n\r\n```\r\n\r\n#### Using from gradle\r\n```java\r\ncompile 'io.advantageous.qbit:qbit-admin:1.0.0.RELEASE'\r\ncompile 'io.advantageous.qbit:qbit-vertx:1.0.0.RELEASE'\r\n```\r\n\r\nCore Features\r\n============\r\n\r\n* Write REST based async microservices\r\n* Write ***WebSocket*** based async microservices (fast async RPC over WebSocket)\r\n* Actor Service Queues using micro-batching for high-speed message passing\r\n* Strongly async typed event bus which can be distributed\r\n* Async low overhead metrics gathering which can be queried and distributed (for doing fast lane analytics)\r\n* Complex async call coordination (with the Reactor) for reactive programming\r\n* Built-in support for ***health checks*** (and integration with tools like Consul)\r\n* Built-in support for ***monitoring*** (and integration with wire protocols like StatsD)\r\n* Built-in support for ***Service Discovery*** (with integration with health system, DNS SRV records and Consul)\r\n* Integration with persistent queues\r\n* [12 factor app port bindings](http://12factor.net/), health checks, KPI gathering, Logging MDC\r\n* API Gateway support for client generation and consumption via [Swagger](http://swagger.io/).\r\n* Our services can generate Swagger files (like idl for JSON/REST).\r\n* Remote client proxies for WebSocket (your interface is your IDL)\r\n\r\n\r\nStatus\r\n=====\r\nDeployed at several large fortune 100 companies. \r\nQBit now works with Vertx (standalone or embedded).\r\nYou can also use QBit on non-QBit projects, it is just a lib.\r\n\r\nLicense\r\n=====\r\nApache 2\r\n\r\n\r\n## Java Microservice Lib\r\n\r\nQBit has inproc services, REST microservices and WebSocket microservices as well as an\r\nin-proc service event bus (which can be per module or per app). It supports workers and in-memory services.\r\n\r\nBefore we describe more, here are two sample services:\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {...\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List list() {...\r\n```\r\n\r\n\r\n#### Adder Service using URI params\r\n```java\r\n\r\n @RequestMapping(\"/adder-service\")\r\n public class AdderService {\r\n\r\n @RequestMapping(\"/add/{0}/{1}\")\r\n public int add(@PathVariable int a, @PathVariable int b) {...\r\n }\r\n```\r\n\r\n\r\n\r\nQBit philosophy:\r\n====\r\nAt the end of the day QBit is a simple library not a framework.\r\nYour app is not a QBit app but a Java app that uses the QBit lib.\r\nQBit allows you to work with Java UTIL concurrent, and does not endeavor to hide it from you.\r\nJust trying to take the sting out of it.\r\n\r\nDoes it work\r\n=====\r\nWe have used techniques in Boon and QBit with great success in high-end, high-performance, high-scalable apps.\r\nWe helped clients handle 10x the load with 1/10th the servers of their competitors using techniques in QBit.\r\nQBit is us being sick of hand tuning queue access and threads.\r\n\r\n\r\nBoon and QBit humility policy\r\n=====\r\nIdeas for Boon and QBit often come from all over the web. We make mistakes. Point them out.\r\nAs a developer of Boon and QBit, we are fellow travelers.\r\nIf you have an idea or technique you want to share, we listen.\r\n\r\n\r\nInspiration\r\n====\r\n\r\nA big inspiration for Boon/QBit was Vertx, Akka, Go Channels, Active Objects, Apartment Model Threading, Actor,\r\nand the Mechanical Sympathy papers.\r\n\r\nQBit has ideas that are similar to many frameworks. We are all reading the same papers.\r\nQBit got inspiration from the LMAX disruptor papers and this blog post about\r\n[link transfer queue versus disruptor](http://php.sabscape.com/blog/?p=557). We had some theories about\r\nqueues that blog post inspired us to try them out. Some of these theories are deployed at some of the\r\nbiggest middleware backends and whose name brands are known around the world. And thus QBit was born.\r\n\r\nQBit also took an lot of inspiration by the great work done\r\nby Tim Fox on Vertx. The first project using something that could actually be called QBit (albeit early QBit)\r\n was using Vertx on an web/mobile microservice for an app that could potentially have 80 million users.\r\n It was this\r\nexperience with Vertx and early QBit that led to QBit development and evolution. QBit is built on the\r\nshoulders of giants (Netty/Vertx).\r\n\r\nDoes QBit compete with...\r\n====\r\nSpring Disruptor: No. You could use QBit to write plugins for Spring Disruptor I suppose, but QBit does\r\nnot compete with Spring Disruptor.\r\nSpring Boot/Spring MVC: No. We use the same annotations but QBit is geared for high-speed in-memory\r\nmicroservices. It is more like Akka than Spring Boot. QBit has a subset of the features of Spring MVC\r\ngeared only for microservices, i.e., WebSocket RPC, REST, JSON marshaling, etc.\r\nAkka: No. Well Maybe. Akka has similar concepts but they take a different approach. QBit is more focused\r\n on Java, and microservices (REST, JSON, WebSocket) than Akka.\r\nLMAX Disruptor: No. In fact, we can use disruptor as on of the queues that QBit uses underneath the covers.\r\n\r\n\r\n(Early benchmarks have been removed. They were here. QBit got a lot faster.\r\n Benchmarking QBit is a moving target at the moment.\r\n Links and reports will be created.)\r\n\r\n\r\nCode Examples\r\n\r\n\r\n## Basic Queue example (REST style services is further down)\r\n\r\n====\r\n\r\n```java\r\n\r\n BasicQueue queue = BasicQueue.create(Integer.class, 1000);\r\n\r\n //Sending threads\r\n\r\n SendQueue sendQueue = queue.sendQueue();\r\n for (int index = 0; index < amount; index++) {\r\n sendQueue.send(index);\r\n }\r\n sendQueue.flushSends();\r\n ...\r\n sendQueue.sendAndFlush(code);\r\n //other methods for sendQueue, writeBatch, writeMany\r\n\r\n\r\n //Receiving Threads\r\n ReceiveQueue receiveQueue = queue.receiveQueue();\r\n Integer item = receiveQueue.take();\r\n //other methods poll(), pollWait(), readBatch(), readBatch(count)\r\n```\r\n\r\n\r\n### What is QBit again?\r\n\r\nQBit is a queuing library for microservices. It is similar to many other projects like Akka, Spring Reactor,\r\netc. QBit is just a library not a platform. QBit has libraries to put a service behind a queue.\r\nYou can use QBit queues directly or you can create a service. QBit services can be exposed by WebSocket,\r\nHTTP, HTTP pipeline, and other types of remoting. A service in QBit is a Java class whose methods are\r\n executed behind service queues. QBit implements apartment model threading and is similar to the\r\n Actor model or a better description would be Active Objects. QBit does not use a disruptor (but could).\r\n It uses regular Java Queues. QBit can do north of 100 million ping pong calls per second which is\r\n an amazing speed (seen as high as 200M). QBit also supports calling services via REST, and WebSocket.\r\n QBit is microservices in the pure Web sense: JSON, HTTP, WebSocket, etc. QBit uses micro batching to\r\n push messages through the pipe (queue, IO, etc.) faster to reduce thread hand-off.\r\n\r\n### QBit lingo\r\n\r\nQBit is a Java microservice lib supporting REST, JSON and WebSocket. It is written in Java but we could\r\none day write a version in Rust or Go or C# (but that would require a large payday).\r\n\r\n**Service**\r\nPOJO (plain old Java object) behind a queue that can receive method calls via proxy calls or events\r\n(May have one thread managing events, method calls, and responses or two one for method calls and events\r\n 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.\r\n\r\n**ServiceBundle**\r\nMany POJOs behind one response queue and many receive queues. There may be one thread for all responses\r\nor not. They also can be one receive queue.\r\n\r\n**Queue**\r\nA thread managing a queue. It supports batching. It has events for empty, reachedLimit, startedBatch,\r\nidle. You can listen to these events from services that sit behind a queue. You don't have to use Services.\r\nYou can use Queue's direct. In QBit, you have sender queues and receivers queues. They are separated to\r\nsupport micro-batching.\r\n\r\n**ServiceEndpointServer**\r\nServiceBundle that is exposed to REST and WebSocket communication.\r\n\r\n**EventBus**\r\nEventBus is a way to send a lot of messages to services that may be loosely coupled.\r\n\r\n**ClientProxy**\r\nClientProxy is a way to invoke service through async interface, service can be inproc (same process) or\r\nremoted over WebSocket.\r\n\r\n**Non-blocking**\r\nQBit is a non-blocking lib. You use CallBacks via Java 8 Lambdas. You can also send event messages and get\r\nreplies. Messaging is built into the system so you can easily coordinate complex tasks.\r\nQBit takes an object-oriented approach to service development so services look like normal Java services\r\nthat you\r\nalready write, but the services live behind a queue/thread. This is not a new concept. Microsoft did this\r\nwith DCOM/COM and called it active objects. Akka does it with actors and called them strongly typed Actors.\r\nThe important concepts is that you get the speed of reactive and actor style messaging but you develop\r\nin a natural OOP approach. QBit is not the first. QBit is not the only.\r\n\r\n\r\n**Speed**\r\nQBit is VERY fast. There is a of course a lot of room for improvement. But already 200M+ TPS inproc ping pong, 10M-20M+ TPS event bus, 500K TPS RPC calls over WebSocket/JSON, etc.\r\nMore work needs to be done to improve speed, but now it is fast enough where we are focusing more on\r\nusability.\r\nThe JSON support uses Boon by default which is up to 4x faster than other JSON parsers for the\r\nREST/JSON, WebSocket/JSON use case.\r\n\r\n**Reactive Programming**\r\nQBit provides a **Reactor** to manage async calls. This allows callbacks to be handled on the same thread that called them and it provides for timeout and error handling. Read [Reactor tutorial for creating reactive micro service programming](https://github.com/MammatusTech/qbit-microservices-examples/wiki/Reactor-tutorial--%7C-reactively-handling-async-calls-with-QBit-Reactive-Microservices)\r\n\r\n**Service Discovery**\r\nBuilt in support for service discovery. This includes integration with Consul.\r\n\r\n\r\n**StatService**\r\nBuilt in support for stats. The **StatService** can be integrated with **StatsD** (Graphite, Grafana, DataDog, etc.) to publish passive stats. Or you can query the stats engine and react to the stats (counts, timings and levels). The **StatsService** is a reactive stats system that can be clustered. The StatService is reactive in that your services can publish to it and query it and react based on the results. You can implement things like rate limiting and react to an increased rate of something. The ServiceDiscovery system integrates with the HealthSystem and Consul to roll up each of your internal services that make up you micro service and publish the composite availably of your micro service to a single HTTP endpoint or a dead mans switch in Consul (TTL). \r\n\r\n\r\n\r\n### CURLable REST services example\r\n\r\nTalk is cheap. Let's look at some code. You can get a detailed walk through in the Wiki.\r\nWe have a lot of documentation already.\r\n\r\nWe will create a service that is exposed through REST/JSON.\r\n\r\nTo query the size of the todo list:\r\n\r\n```bash\r\ncurl localhost:8080/services/todo-service/todo/count\r\n```\r\n\r\nTo add a new TODO item.\r\n\r\n```bash\r\ncurl -X POST -H \"Content-Type: application/json\" -d \\\r\n'{\"name\":\"xyz\",\"description\":\"xyz\"}' \\\r\nhttp://localhost:8080/services/todo-service/todo\r\n```\r\n\r\nTo get a list of TODO items\r\n```bash\r\ncurl http://localhost:8080/services/todo-service/todo/\r\n```\r\n\r\nThe TODO example will use and track Todo items.\r\n\r\n#### Todo item POJO sans getter\r\n\r\n```java\r\npackage io.advantageous.qbit.examples;\r\n\r\nimport java.util.Date;\r\n\r\n\r\npublic class TodoItem {\r\n\r\n\r\n private final String description;\r\n private final String name;\r\n private final Date due;\r\n\r\n```\r\n\r\nThe TodoService uses Spring MVC style annotations.\r\n\r\n#### Todo Service\r\n```java\r\n\r\n@RequestMapping(\"/todo-service\")\r\npublic class TodoService {\r\n\r\n\r\n private List todoItemList = new ArrayList<>();\r\n\r\n\r\n @RequestMapping(\"/todo/count\")\r\n public int size() {\r\n\r\n return todoItemList.size();\r\n }\r\n\r\n @RequestMapping(\"/todo/\")\r\n public List