Kafka Consumers in Onion Architecture - java

I am working with a project following DDD and has consumers to a Kafka Queue. My question is straight forward, where do the consumers reside in the Onion Architecture and Hexagonal Architecture? Are they event handlers or should they be a part of the infrastructure?
I am using Kafka Consumers to listen to change events of other aggregate roots and want to store the data in my current aggregate. Basically replicating the data from one microservice to another.

The way I see it is:
Your aggregates are the Core
The message handlers are Use Cases, which use dependencies (like repository interfaces) and the core to execute the business use case.
There is infrastructure code that peeks messages from the queue and triggers use cases
With this approach, you can unit test your use cases without worrying about infrastructure and you can replace the whole messaging queue technology. The same approach works for handling API requests. In practice, the only difference is that with the API you can return a response synchronously, and with messaging you can't.
As a practical note, in .NET I use a library called Mediatr to implement and trigger the use cases. In java, I found PipelinR which looks similar at first sight. This type of approach allows you to implement all use cases the same way for all your synchronous and asynchronous usages.

Think this way: if the same message your application receives from a Kafka Queue should also be received with a RESTful endpoint, would it be any difference between the consumer and the RESTful endpoint from the PoV of their place in the architectural layers? no, it wouldn't, they'd part of the same layer because they do the same: they accept an external message, despite the fact that the communication channel & type is (very) different.
According to The Onion Architecture : part 2:
SpeakerController is part of the user interface
and I'd say that the same (i.e. user interface) is for the RESTful endpoint and the Kafka Queue consumer. Both of them would contain no business logic at all but they'll delegate to an Application Service. If the message types are not exactly the same, there might be message-integrity-validation & conversion-to-DTO particular to each other before delegating to the target Application Service.
The ideea is that one could add more communication channels (e.g. command line, web sockets, etc) but as long as the use cases don't change than the entire Application Core remains unchanged because it doesn't depend on the User Interface but the opposite.

Related

Best Practices for Micro-service interaction with Event-Sourcing (CQRS)

I have an API call that will need to work with more than one aggregate. I have the 2 below ideas in my head to how it should be interacting with the aggregates but I'm open to other ideas.
Is it good practice to send commands from one microservice to another one? Or is it better to have an event handler on microservice B that reacts to events from service A and generates the command all within the microservice B?
Is it good practice to send commands from one microservice to another one? Or is it better to have an event handler on microservice B that reacts to events from service A and generates the command all within the microservice B?
An important thing to recognize in a service architecture: we want the services to be autonomous. So A should continue working while B is down for maintenance, and vice versa.
This implies that we need to support asynchronous messaging from A to B.
Current "best practice" is that you are dealing with messages being delivered asynchronously, then the semantics should be past tense: SomethingHappened at A, and B will react to it, or not, in its own time at its own discretion.
Does it matter? Hard to say -- handle(Event) is a command, CommandReceived is an event.
Note: this is really just services and messaging -- Event-Sourcing/CQRS really don't enter into it.
Martin Fowler described Domain Events in 2005.
Each Domain Event captures information from the external stimulus.
If you think of A as being external to B (which makes sense, if there are service boundaries between them), then the semantics of the Domain Event pattern may be a very good fit.
Why not both?
I approach these "micro-services" slightly differently. I usually have a messaging endpoint for each bounded context. I guess this fits in nicely with the micro-service idea and that endpoint only responds to commands sent to it that apply to that BC. It would then also publish the relevant events.
What I then may also have is an orchestration endpoint that responds to process managers that "belong" to the relevant BC. This endpoint only deals with the state of the process managers and issues commands to whichever BC messaging endpoint it needs to talk to. For instance, after an OrderRegisteredEvent has been received a SendEMailCommand may be issued. OK, that is more of a technical endpoint/BC but none-the-less.
On the BC-only messaging endpoint there is absolutely no between the different BCs. It is only there to service its own BC.
I hope that makes sense.

Asynchronous Message-Passing and Microservices

I am planning the develop of a microservice based architecture application and I decided to use kafka for the internal communicaton while I was reading the book Microservice Architecture by Ronnie Mitra; Matt McLarty; Mike Amundsen; Irakli Nadareishvili where they said:
letting microservices directly interact with message brokers (such as
RabbitMQ, etc.) is rarely a good idea. If two microservices are
directly communicating via a message-queue channel, they are sharing a
data space (the channel) and we have already talked, at length, about
the evils of two microservices sharing a data space. Instead, what we
can do is encapsulate message-passing behind an independent
microservice that can provide message-passing capability, in a loosely
coupled way, to all interested microservices.
I am using Netflix Eureka for Service registration and discovery, Zuul as edge server and Hystrix.
Said so, in practice, how can I implement that kind of microservice? How can I make my microservices indipendent from the communcation channel ( in this case Kafka)?
Actually I'm directly interacting with the channel, so I don't have an extra layer between my publishers/subscribers and kafka.
UPDATE 06/02/2018
to be more precise, we have a couple of microservices: one is publishing news on a topic (activemq, kafka...) and the other microservice is subscribed on that topic and doing some operations on the messages that are coming through. So we have these services that are coupled to the message broker (to the channel)... we have the the message broker's apis "embedeed" on our code and for example, if we want to change the message broker we have to change all the microservices that made use of the message broker's api. So, they are suggesting to use a microservice(in the picture I assume is the Events Hub) that is the "dispatcher" of the various messages. In this way it is the only component that interacts with the channel.
A general foreword - Don't do it if you don't need it. Introducing a queue system can be a big improvement if you are dealing with high number of events and events backing up issues etc. But if you don't face any issues you are probably better off with the lower complexity of a direct service communication.
Back to your question - It sounds like you want to abstract your communication with the queue because you are worried about the effort for replacing the queue with a different system - Is that correct?
In this case you can either do what you proposed - Develop a new service in the middle. This comes with all the baggage of a physical service (including deployment, scaling, etc).
Or the second alternative is to write a client library that abstracts the queue the way you want and allows you to reuse it in all services requiring to participate in the queue. This way you don't have to physically deploy another service for this purpose but you are still in full control of what your interface to the queue should look like and you have a single piece of code to incorporate changes (at least toward the direction of the queue). This would work given you are sure the app-facing side of the library can be stable enough.
But, again, don't do any of those in the first iteration when you are not sure you need all the complexity. (Over-engineering is a dangerous thing)
You should create a Interface lets say "Queue" which provide all functionalities which you want from Kafka or RabbitMQ, the create diff. impl like KafkaQueue and RabbitMQQueue of the Queue interface and inject the right impl which you want to use in your system.
In this your if new queue system is used , your existing code will not be changed
Creating another microservice is an extra overhead in this case
In a service architecture proper way to make your code independent out of constraints of communication channel is by having properly modeled self-sufficient messages. Historic examples would be WSDL in document mode, EDIFACT, HATEOAS etc. From this point of view microservices with spring-boot and kafka are just different implementation of same old thing done since mainframes ruled the world.
Essentially if you take a view of your app as blackbox asynchronous server; everything app does is receives events and produces new ones. It should not matter how events are raised within app. Http requests, xml within jms messages, json in kafka, whatever - all those things are just a way to pass events and business layer of application should respond only to a content of events.
So business layer is usually structured around some custom model/domain which are delivered as payload. Business layer is invoked/triggered by listener/producer layer which talks to communcation channel (kafka listener, http listener etc..). Aside from logging and enforcing security you should not have communication channel logic in app. I have seen unfortunate examples of business logic driven by by originating jms connection or parsing url of request. If you ever have this in your code you have failed to properly structure your code.
However that is easier to say than to implement. Some people are good at this level of modeling, and some never learn.
And there is no other way to learn but to try and fail.

What is the difference between SEDA, VM and direct in Apache Camel?

I had worked with both SEDA and direct, and I've also read the documentation.
But I still cannot visualize the usage of SEDA and direct. Vm is new to me.
Please explain it with an example.
There are at least four different mechanisms by which one Camel route can directly pass data to another. By "directly" I mean without using a network or some form of intermediate storage (file, database). These mechanisms can be grouped according to whether they can pass data between CamelContext instances or not, and whether they are synchronous or asynchronous.
direct -- single CamelContext, synchronous (blocks producer)
SEDA -- single CamelContext, asynchronous (does not block producer)
VM -- multiple CamelContext, asynchronous (does not block producer)
direct-VM -- multiple CamelContext, synchronous (blocks producer)
The direct and direct-VM mechanisms are synchronous, in the sense that the producing endpoint blocks until the consuming endpoint, and all the rest of its routing logic, is complete. The SEDA and VM mechanisms both use a pool of threads on the consumer, such that each request made by the producer is assigned to one of the threads in the pool. This allows the consumer endpoint and its associated routing logic to act independently of the producer.
Both the VM endpoints are required in situations where communication is between different Camel contexts. In many cases it is possible to combine routes into the same CamelContext. However, it may sometimes be inadvisable, for reasons of modularity, or impossible, because some application framework makes it so. For example, I might implement some Camel routing logic in a library (or component) with the intention that the library be used by other code. To be complete, this library will probably define a self-contained CamelContext with various routes. If I want to invoke the Camel logic in the library, I will need to use VM or direct-VM, because direct and SEDA endpoints do not contain the logic needed to route between Camel contexts.
The difference between direct: and seda: components is that the first is synchronous and the second is asynchronous, with a queue.
The practical difference is that for sending synchronous messages, you must wait for the route to complete, whereas with asynchronous messages, its "fire and forget" - you put them onto a queue and presume a consumer will process them. You can also have multiple consumers (parallelisation).
The last example, vm: is also asynchronous, but it can also call routes in different camel contexts within the same JVM. Imagine application 1 has a camel context, and application 2 has a camel context, in this way they can communicate with each other.
edit:
In relation to "what to use when" :
use direct: for calling normally between endpoints in a camel context
use seda: when you need parallelisation or queues, but dont want to use jms:
use vm: when calling between applications.
There are of course many other use cases but those are the common ones (subjective to my own experience)

Best way to utilize multiple instances of a service

We have a component called Workflow which exposes SOAP web service. We are trying to introduce a asynchronous processing in Workflow by allowing it to consume messages from WebSphere MQ. We also want to utilize multiple instances of Workflow. So there can be 4 instances of Workflow listening to same queue. The problem here is, how to make sure all Workflow instances are utilized evenly and not single instance is overloaded.
Workflow is completely written in Java. We use Spring and Hibernate extensively. The processes which will be submitting message to Workflow are written in Java. For message processing and MQ, we use Spring Integration.
The best way to ensure that no Workflow instance is overloaded is to have each individual Workflow instance not consume a message from the message queue that will overload it. In this case, you may not care whether the work is distributed evenly, as long as all the work gets done promptly.
If you really want to make sure all Workflow instances are used evenly even when your load is so light that you don't need all of the instances, you may need to check whether there's a way of reconfiguring WebSphere MQ to distribute messages on a FIFO basis rather than a LIFO basis, or if WebSphere MQ can't be configured that way, to switch to a different message queue. However, I don't recommend this: the system as a whole can work perfectly fine even if, at low loads, only some of the Workflow instances are utilized, with all being utilized only at high loads.

Non-blocking queue of HTTP POST requests with persistence

Before we develop our custom solution, I'm looking for some kind of library, which provides:
Non-blocking queue of HTTP requests
with these attributes:
Persisting requests to avoid it's loss in case of:
network connectivity interruption
application quit, forced GC on background app
etc..
Possibility of putting out all these fields:
Address
Headers
POST data
So please, is there anything usable right know, what could save us whole day on developing this?
Right now we don't need any callbacks on completed request and neither saving result data, as there won't be such.
In my humble opinion, a good and straightforward solution would be to develop your own layer (which shouldn't be so complicated) using a sophisticated framework for connection handling, such as Netty https://netty.io/ , together with a sophisticated framework for asynchronous processing, such as Akka http://akka.io/
Let's first look inside Netty support for http at http://static.netty.io/3.5/guide/#architecture.8 :
4.3. HTTP Implementation
HTTP is definitely the most popular protocol in the Internet. There are already a number of HTTP implementations such as a Servlet container. Then why does Netty have HTTP on top of its core?
Netty's HTTP support is very different from the existing HTTP libraries. It gives you complete control over how HTTP messages are exchanged at a low level. Because it is basically the combination of an HTTP codec and HTTP message classes, there is no restriction such as an enforced thread model. That is, you can write your own HTTP client or server that works exactly the way you want. You have full control over everything that's in the HTTP specification, including the thread model, connection life cycle, and chunked encoding.
And now let's dig inside Akka. Akka is a framework which provides an excellent abstraction on the top of Java concurrent API, and it comes with API in Java or Scala.
It provides you a clear way to structure your application as a hierarchy of actors:
Actors communicate through message passing, using immutable message so that you have not to care about thread-safety
Actors messages are stored in message boxes, which can be durable
Actors are responsible for supervising their children
Actors can be run on one or more JVM and can communicate using a wide numbers of protocols
It provides a lightweight abstraction for asynchronous processing , Future, which is easier to use then Java Futures.
It provides other fancy stuff such as Event Bus, ZeroMQ adapter, Remoting support, Dataflow concurrency, Scheduler
Once you become familiar with the two frameworks, it turns out that what you need can easily be coded through them.
In fact, what you need is an http proxy coded in Netty, that upon a request receival sends immediately a message to an Akka Actor of type FSM (http://doc.akka.io/docs/akka/2.0.2/java/fsm.html) which using a durable mailbox (http://doc.akka.io/docs/akka/2.0.2/modules/durable-mailbox.html )
Here is a link to open-source library that was a Master Thesis of a student at Czech Technical University in Prague. It is very large and powerful library and mainly focuses on location. The good thing about it, though, is that it omitted the headers and other -ish that REST has.
It is the latest fork and hopefully it will give you at least inspiration for "own" solution.
how about those concurrent collections:
http://mcg.cs.tau.ac.il/projects/concurrent-data-structures
i hope that the license is ok .
You'll want to have a look to these to posts. (added at the end of the document)
Very basically an approach that works in a proficient way for me is to separate requests from the queue and the executor.
Requests are executed as Runnables or Callables. Inherit from them to create different kind of requests to your API or service. Set them up there adding headers and or body prior to to executing them.
Enqueue those requests in a queue (choose which fits better for you - I'd say LinkedBlockingQueue will make the job) linked to an executor from within a bound service and calling them from your activity or any other scope. If you don't need to get responses and callbacks you can avoid using Guava for listening to futures or create your own callbacks.
I'll stay tuned. If you need more depth I can post some specific pieces of code. There's the source of a basic example in the first link though.
http://ugiagonzalez.com/2012/08/03/using-runnables-queues-and-executors-to-perform-tasks-in-background-threads-in-android/
http://ugiagonzalez.com/2012/07/02/theres-life-after-asynctasks-in-android/
Update:
You can create another queue for those requests that were impossible to execute.
One approach that comes to my mind would be to add all your failed requests to the retry queue. The retry queue would be trying to re-run these tasks while the phone still thinks that there's any kind of internet connection available. In the request object you can set a max number of retrials and compare it to a currentRetry number increasing it in every retrial.
Mmm this might be interesting. I'll definitely think about including that in my library.

Categories