How can I improve the performance of the JbossFuse (v6.3) DSL route code? - java-8

APPLICATION INFO:
Code below: reads from IBM MQ queue and then posts the message to a REST service
(note: reading from the MQ queue is fast and not an issue - rather, it is the post operation performance I am having trouble improving)...
PROBLEM:
Unable to output/post more than 44-47 messages per second...
QUESTION:
How can I improve the performance of the JbossFuse (v6.3) DSL route code below?... (What techniques are available that would make it faster?)
package aaa.bbb.ccc;
import org.apache.camel.Exchange;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.cdi.ContextName;
#ContextName("rest-dsl")
public class Netty4HttpSlowRoutes extends RouteBuilder {
public Netty4HttpSlowRoutes() {
}
private final org.apache.camel.Processor proc1 = new Processor1();
#Override
public void configure() throws Exception {
org.apache.log4j.MDC.put("app.name", "netty4HttpSlow");
System.getProperties().list(System.out);
errorHandler(defaultErrorHandler().maximumRedeliveries(3).log("***FAILED_MESSAGE***"));
from("wmq:queue:mylocalqueue")
.log("inMessage=" + (null==body()?"":body().toString()))
.to("seda:node1?concurrentConsumers=20");
from("seda:node1")
.streamCaching()
.threads(20)
.setHeader(Exchange.HTTP_METHOD, constant(org.apache.camel.component.http4.HttpMethods.POST))
.setHeader(Exchange.CONTENT_TYPE, constant("application/json"))
.toD("netty4-http:http://localhost:7001/MyService/myServiceThing?textline\\=true");
}
}

Just a couple of thoughts. First things first: did you measure the slowness? How much time do you spend in Camel VS how much time you spend sending the HTTP request?
If the REST service is slow there's nothing you can do in Camel. Depending on what the service does, you could try reducing the number of threads.
Try to disable streamCaching since it looks like you're not using it.
Then use a to instead of toD to invoke the service, I see that the URL is always the same. In the docs of ToD I read
By default the Simple language is used to compute the endpoint.
There may be a little overhead while parsing the URI string each time you invoke the route.

Related

coordinating multiple outgoing requests in a reactive manner

this is more of a best practice question.
in my current system (monolith), a single incoming http api request might need to gather similarly structured data from to several backend sources, aggregate it and only then return the data to the client in the reponse of the API.
in the current implementation I simply use a threadpool to send all requests to the backend sources in parallel and a countdown latch of sorts to know all requests returned.
i am trying to figure out the best practice for transforming the described above using reactice stacks like vert.x/quarkus. i want to keep the reactiveness of the service that accepts this api call, calls multiple (similar) backend source via http, aggregates the data.
I can roughly guess I can use things like rest-easy reactive for the incoming request and maybe MP HTTP client for the backend requests (not sure its its reactive) but I am not sure what can replace my thread pool to execute things in parallel and whats the best way to aggregate the data that returns.
I assume that using a http reactive client I can invoke all the backend sources in a loop and because its reactive it will 'feel' like parralel work. and maybe the returned data should be aggragated via the stream API (to join streams of data)? but TBH I am not sure.
I know its a long long question but some pointers would be great.
thanks!
You can drop the thread pool, you don't need it to invoke your backend services in parallel.
Yes, the MP RestClient is reactive. Let's say you have this service which invokes a backend to get a comic villain:
#RegisterRestClient(configKey = "villain-service")
public interface VillainService {
#GET
#Path("/")
#NonBlocking
#CircuitBreaker
Uni<Villain> getVillain();
}
And a similar one for heroes, HeroService. You can inject them in your endpoint class, retrieve a villain and a hero, and then compute the fight:
#Path("/api")
public class Api {
#RestClient
VillainService villains;
#RestClient
HeroService heroes;
#Inject
FightService fights;
#GET
public Uni<Fight> fight() {
Uni<Villain> villain = villains.getVillain();
Uni<Hero> hero = heroes.getRandomHero();
return Uni.combine().all().unis(hero, villain).asTuple()
.chain(tuple -> {
Hero h = tuple.getItem1();
Villain v = tuple.getItem2();
return fights.computeResult(h, v);
});
}
}

OptaPlanner threads are not getting released in SpringBoot application

We are using OptaPlanner(8.2.0) library in Spring Boot to solve knapsack problem using construction heuristic algorithm.
While running the application we observed that threads created by SolverManager are not getting released even after solving the problem. Because of that, performance of the application starts degrading after some time. Also, solver manager starts responding slowly of the increased thread count.
We also tried with latest version(8.17.0) but issue still persist.
Termination conditions:
<termination>
<millisecondsSpentLimit>200</millisecondsSpentLimit>
</termination>
optaplanner:
solver:
termination:
best-score-limit: 0hard/*soft
Code:
#Component
#Slf4j
public class SolutionManager {
private final SolverManager<Solution, String> solutionManager;
public SolutionManager(SolverManager<Solution, String> solutionManager) {
this.solutionManager = solutionManager;
}
public Solution getSolutionResponse(String solutionId, Solution unsolvedProblem)
throws InterruptedException, ExecutionException {
SolverJob<Solution, String> solve = solutionManager.solve(solutionId, unsolvedProblem);
Solution finalBestSolution = solve.getFinalBestSolution();
return finalBestSolution;
}
}
Thread metrics:
I wasn't able to reproduce the problem; after a load represented by solving several datasets in parallel, the number of threads drops back to the same value as before the load started.
The chart you shared doesn't clearly suggest there is a thread leak either; if you take a look at ~12:40 PM and compare it with ~2:00 PM, the number of threads actually did decrease.
Let me also add that the getFinalBestSolution() method actually blocks the calling thread until the solver finishes. If you instead use solve(ProblemId_ problemId, Solution_ problem, Consumer<? super Solution_> finalBestSolutionConsumer), this method returns immediately and the Consumer you provide is called when the solver finishes.
It looks like you might not be using OptaPlanner Spring Boot Starter.
If that's the case, upgrade to a recent version of OptaPlanner and add a dependency to optaplanner-spring-boot-starter. See the docs spring quickstart and the optaplanner-quickstarts repository (in the directory technology) for an example how to use it.

How to send message to WebSphere MQ using Apche Camel and Receive message from MQ Queue

I didnt see enough examples on web using apache camel with websphere mq to send and receive messages. I had a example code but I got struck at the middle of code. could any one help on this..
import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
import org.apache.camel.ExchangePattern;
import org.apache.camel.Producer;
import org.apache.camel.util.IOHelper;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Client that uses the Mesage Endpoint
* pattern to easily exchange messages with the Server.
* <p/>
* Notice this very same API can use for all components in Camel, so if we were using TCP communication instead
* of JMS messaging we could just use <code>camel.getEndpoint("mina:tcp://someserver:port")</code>.
* <p/>
* Requires that the JMS broker is running, as well as CamelServer
*/
public final class CamelClientEndpoint {
private CamelClientEndpoint() {
//Helper class
}
// START SNIPPET: e1
public static void main(final String[] args) throws Exception {
System.out.println("Notice this client requires that the CamelServer is already running!");
AbstractApplicationContext context = new ClassPathXmlApplicationContext("camel-client.xml");
CamelContext camel = context.getBean("camel-client", CamelContext.class);
// get the endpoint from the camel context
Endpoint endpoint = camel.getEndpoint("jms:queue:numbers");
// create the exchange used for the communication
// we use the in out pattern for a synchronized exchange where we expect a response
Exchange exchange = endpoint.createExchange(ExchangePattern.InOut);
// set the input on the in body
// must be correct type to match the expected type of an Integer object
exchange.getIn().setBody(11);
// to send the exchange we need an producer to do it for us
Producer producer = endpoint.createProducer();
// start the producer so it can operate
producer.start();
// let the producer process the exchange where it does all the work in this oneline of code
System.out.println("Invoking the multiply with 11");
producer.process(exchange);
// get the response from the out body and cast it to an integer
int response = exchange.getOut().getBody(Integer.class);
System.out.println("... the result is: " + response);
// stopping the JMS producer has the side effect of the "ReplyTo Queue" being properly
// closed, making this client not to try any further reads for the replies from the server
producer.stop();
// we're done so let's properly close the application context
IOHelper.close(context);
}
}
I got struck at this point of code..
exchange.getIn()
Do I have to use exchange.getOut() to send message?? and How to construct message using string and add headers to it.
Welcome to stackoverflow!
I am still not sure what exactly is the problem you are stuck at and it prevents me (and possibly others as well) in helping you resolve your roadblock.
Perhaps you need to familiarize a bit more on what camel is and how it works. Camel in Action is a great book to help you with that.
If you are unable to get a copy at this point, a preview of the first few chapters of the book is available online and it should give you much better leverage. Source code repository for chapter 2 should give you some more ideas around how to process JMS messages.
In addition to it. Please don't expect full blown solutions from StackOverflow. You may read this page on how to ask a good question

Elasticsearch upgrade path from transport client to high level REST client

What is the upgrade path for an application using the Elasticsearch native Java client API (TransportClient) to move to using the high-level REST client for Java?
Documentation (preliminary?) seems to indicate:
The Java High Level REST Client depends on the Elasticsearch core
project. It accepts the same request arguments as the TransportClient
and returns the same response objects.
(Source: https://www.elastic.co/guide/en/elasticsearch/client/java-rest/5.x/java-rest-high.html)
But I am not entirely clear what this means. Will I be able to switch my entire codebase over to the high level REST client without rewriting my queries, or other client-type operations? It doesn't seem like the REST client implements the Client interface. That may make sense from a decoupling point-of-view.'
What I need to know is whether I should be building my own abstraction around client operations, or whether HighLevelRestClient will be basically implementing the Client interface already.
Should I continue, for the time being, to write code against the TransportClient API or will that code all need to be rewritten when TransportClient is deprecated?
Note that I am looking at the high-level REST client, not the low-level REST client.
The high level REST client doesn't implement the Client interface. The plan is described in this blogpost that I wrote a while ago.
We are also in the process of writing documentation, which will contain a page with instructions on how to migrate from the transport client.
The new client reuses requests and responses from the existing transport client, but the client object is not compatible, that means that for instance the following:
IndexRequest indexRequest = new IndexRequest("index", "type", "id");
indexRequest.source("field", "value");
IndexResponse indexResponse = transportClient.index(indexRequest).get();
will become something like:
IndexRequest indexRequest = new IndexRequest("index", "type", "id");
indexRequest.source("field", "value");
IndexResponse indexResponse = restHighLevelClient.index(indexRequest);
As for async requests, the call is slightly different (see the method name), in the new client we went for a different method with a name that ends with the "Async" suffix, you would go from the following:
transportClient.index(indexRequest, new ActionListener<IndexResponse>() {
#Override
public void onResponse(IndexResponse indexResponse) {
// called when the operation is successfully completed
}
#Override
public void onFailure(Exception e) {
// called on failure
}
});
to the following:
restHighLevelClient.indexAsync(indexRequest, new ActionListener<IndexResponse>() {
#Override
public void onResponse(IndexResponse indexResponse) {
// called when the operation is successfully completed
}
#Override
public void onFailure(Exception e) {
// called on failure
}
});
Unfortunately the Client#prepare* methods won't be available in the high level client, so something like:
IndexResponse indexResponse = transportClient.prepareIndex("index", "type", "id").setSource("field", "value").get();
needs to be migrated to the above using ActionRequests rather then ActionRequestBuilders. We are making this change as there was always confusion between requests and builders in the transport client, two ways of doing exactly the same thing. The new client will have a single way to provide requests.
If you want to have a look at the current documentation, it is already live although work in progress: https://www.elastic.co/guide/en/elasticsearch/client/java-rest/master/java-rest-high.html .
The High Level REST Client will replace the Transport Client, although its first upcoming release will only support index, bulk, get, delete, update, search, search scroll and clear scroll APIs. Support for missing APIs will come next, we are also open to contributions from users as usual.
The Transport Client will be soon deprecated, hence I would advice to move over the the High Level REST Client as soon as possible, it shouldn't be a huge change and it will pay off as we will be improving it overtime, already going through REST is a great improvement.

Spring-boot metrics count and gauge every requestURI for RESTful service

I'm using starter-jersey and starter-actuator. If I have an endpoint as below,
#Component
#Path("/greeting")
public class GreetingEndpoint {
#GET
#Path("{id}/{message}")
#Produces(MediaType.APPLICATION_JSON)
public Greeting sayHello(#PathParam("id") Long id, #PathParam("message") String message) {
return new Greeting(id, message);
}
}
I would have counters/gauges for every request URI. Will this cause memory blowup?
counter.status.200.greeting.1000.look: 1
counter.status.200.greeting.1001.watch-out: 1
counter.status.200.metrics: 1
gauge.response.greeting.1000.look: 109
gauge.response.greeting.1001.watch-out: 6
gauge.response.metrics: 32
To answer the question asked, yes it could blow up if you have essentially unlimited id/message combos. All that information is getting stored in memory. Which unless you control the client calling the endpoint is certainly the case. It might take a long time, but nothing is reaping the metrics repository so they will live indefinitely for the life of the app.
There may be a workaround for you (I can't explain why this works however). Use #RestController+#RequestMapping+#PathVariable. In my experience it will create 1 entry for counter.status.200.greeting.id,message. If you just want to get rid of the counters/gauges for HTTP request but keep all the other auto-configure features then you can include this
#EnableAutoConfiguration(exclude={MetricFilterAutoConfiguration.class})
Hope this helps.

Resources