Performing Sticky load balancing in Camel - soap

Hi I would like to perform sticky load balncing in apache camel based on the SOAP session, whcih is embedded in ServiceGroupID node of the first response.
I wrote a small route as follow:
from(uri)
.loadBalance().sticky(xpath(query).namespaces(env).namespaces(wsa).namespaces(ax))
.to(BE1,BE2);
Where URI is the string to which the requests are passed and BE1 and BE2 are the two backend servers.
And my query is
String query = "/soapenv:Envelope/soapenv:Header/wsa:ReplyTo/wsa:ReferenceParameters/axis2:ServiceGroupId/text()";
If i am not wrong this query would extract the servicegroupID from my SOAP header.
But when I try to perform the balancing, due to some reason whatsoever, the requets are not being passed to the same backend server.
and my env, wsa and ax are the namespaces, which are :
Namespaces env = new Namespaces("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
Namespaces wsa = new Namespaces("wsa", "http://www.w3.org/2005/08/addressing");
Namespaces ax = new Namespaces("axis2", "http://ws.apache.org/namespaces/axis2");
Am I doing something wrong here?
If so what? I would appreciate any help.

Also being discussed at the mailing list
http://camel.465427.n5.nabble.com/Performing-Sticky-load-balancing-in-Camel-tp5719170.html
Please dont start the same topic in multiple places at the same time. And if you do, then at least tell us, so we would know this.
People get upset when they spend time to help you, when its already been answered in another place!

Related

Project Reactor and Server Side Events

I'm looking for a solution that will have the backend publish an event to the frontend as soon as a modification is done on the server side. To be more concise I want to emit a new List of objects as soon as one item is modified.
I've tried implementing on a SpringBoot project, that uses Reactive Web, MongoDB which has a #Tailable cursor that publish an event as soon as the capped collection is modified. The problem is that the capped collection has some limitation and is not really compatible with what I want to do. The thing is I cannot update an existing element if the new one has a different size(as I understood this is illegal because you cannot make a rollback).
I honestly don't even know if it's doable, but maybe I'm lucky and I'll run into a rocket scientist right here that will prove otherwise.
Thanks in advance!!
*** EDIT:
Sorry for the vague question. Yes I'm more focused on the HOW, using the Spring Reactive framework.
When I had a similar need - to inform frontend that something is done on the backend side - I have used a message queue.
I have published a message to the queue from the backend and the frontend consumed the message.
But I am not sure if that is what you're looking for.
if you are using webflux with spring reactor, I think you can simply have a client request with content-type as 'text/event-stream' or 'application/stream+json' and You shall have API that can produce those content-type. This gives you SSE model without too much effort.
#GetMapping(value = "/stream", produces = {MediaType.TEXT_EVENT_STREAM_VALUE, MediaType.APPLICATION_STREAM_JSON_VALUE, MediaType.APPLICATION_JSON_UTF8_VALUE})
public Flux<Message> get(HttpServletRequest request) {
Just as an idea - maybe you need to use a web socket technology here:
The frontend side (I assume its a client side application that runs in a browser, written in react, angular or something like that) can establish a web-socket communication with the backend server.
When the process on backend finishes, the message from backend to frontend can be sent.
You can do emitting changes by hand. For example:
endpoint:
public final Sinks.Many<SimpleInfoEvent> infoEventSink = Sinks.many().multicast().onBackpressureBuffer();
#RequestMapping(path = "/sseApproach", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ServerSentEvent<SimpleInfoEvent>> sse() {
return infoEventSink.asFlux()
.map(e -> ServerSentEvent.builder(e)
.id(counter.incrementAndGet() + "")
.event(e.getClass().getName())
.build());
}
Code anywhere for emitting data:
infoEventSink.tryEmitNext(new SimpleInfoEvent("any custom event"));
Watch out of threads and things like "subscribeOn", "publishOn", but basically (when not using any third party code), this should work good enough.

REST API designing for resource with aggregated property

We are currently trying to come up with a set of REST API that would fit our resource models.
A simplified example of the resource is:
CompanyInfo: {
totalNumberOfEmployees: Number,
employees: [...employees],
}
Employee: {
name: String,
}
In this case, "CompanyInfo" is like a virtual resource that does not exist in DB. It is a short cut for getting all the data related to the Company resource. The idea was to reduce the amount of logic on FE and create more convenient endpoint instead.
Our current endpoint design is:
GET /api/companyInfos/{companyId}/employees
GET,POST,PUT,DELETE /api/companyInfos/{companyId}/employees/{employeeId}
The reason for the extra {companyId} is because these endpoint does not return "Employees", it instead return a "CompanyInfo" that contains "Employees" embedded in the payload.
This is to avoid the aggregated property "totalNumberOfEmployees" not being updated in case sync when we call POST to create a new "Employee"
So my questions are:
Is this the correct approach to the problem of "too many requests" or "too much logic in FE"?
Is it acceptable for the endpoint to return a completely different resource than what its url describe?
Thanks a lot :)
For your Fist question
Is this the correct approach to the problem of "too many requests" or "too much logic in FE"?
yes Sometimes this is how it is suppose to be done. when data sent is small in each request. to many request does not affect the performance so This is how it is suppose to be done .
And Generally it is recommended to write one monolithic Ajax call in front end which will be capable of making any kind of call , By taking callback as parameter, and method , arguments as parameters .
So it will not be to much of logic if you follow this approach . All you have to write is callback for each of Ajax call . How ever sometimes situation may not allow for this Example:if you are using content-type like 'multipart/mixed'
there you have to write another ajax call code
However nowdays most front end has too much of logic based on how interactive website is . So your primary concern should be about look of web site .
For you second question
Is it acceptable for the endpoint to return a completely different resource than what its url describe?
yes . It is acceptable . but it is recommended that client mention all the MIME types which it expects in Accept header and Only those MIME types should be returned by Api.

How do you use the serviceNameFilter when calling QueryClient.GetServiceListAsync

I'm using Azure Service Fabric with stateless services. I have a list of services deployed under an application, and there's a naming convention used with those service names. I'd like to get a list of services that match a filter expression.
Here is a link to a screenshot of my service fabric explorer. I don't have the reputation points to post an image.
Service Fabric Explorer screenshot
In this example, the name of my application is SFApp1, and the name of my service is HelloWorldStateless. I'd like to query the service fabric cluster to locate all services with the name "HelloWorldSt*" (under the SFApp1 application of course).
I know I can query to find all services with the application name "fabric:/SFApp1", and it'll return all services under that application. This overload of GetServiceListAsync takes just an application URI.
FabricClient client = new FabricClient();
ServiceList serviceList = client.QueryManager.GetServiceListAsync(new Uri("fabric:/SFApp1")).Result;
I also know I can query to find a specific service. This overload takes an application URI AND a service URI and will return a single-item list.
FabricClient client = new FabricClient();
ServiceList serviceList = client.QueryManager.GetServiceListAsync(new Uri("fabric:/SFApp1"), new Uri("fabric:/SFApp1/HelloWorldStateless")).Result;
What I'm trying to find out is if there's any way to do something like a wildcard search.
FabricClient client = new FabricClient();
ServiceList serviceList = client.QueryManager.GetServiceListAsync(new Uri("fabric:/SFApp1"), new Uri("fabric:/SFApp1/HelloWorldSt*")).Result;
The name of the parameter where the service name is specified is serviceNameFilter, and the method returns a list. I'm wondering why they would return a list for this overload if the result was always going to be a single-item list. Also, the parameter name "serviceNameFilter" suggests (to me at least) that there's the ability to supply some kind of expression to narrow down your list.
Here's what I've tried already. I've tried the code above, where I chop off a few characters and put an asterisk. I've tried without the asterisk to see if it was a substring match. I've tried SQL-style, with a percent symbol. I've tried a question mark. All of those attempts returned an empty list.
My current workaround is just to ask for all services under that application, and I'll filter them on the client code end with a linq expression. That'll work, but I worry about performance if my list of services gets really big.
Would be nice if I could inspect the source code to answer this myself.
Is there a way to do what I'm trying to do, or am I just misinterpreting what "serviceNameFilter" means, and it just means you have to put the entire service URI that you're looking for?
Thanks for any help you can provide!
Unfortunately that API parameter is terribly named. It's not really a filter at all, it's just the name of the service (since there's no other query that just returns one service, this is how you "filter" from all the services in an application down to just one in particular).
The nearest thing to what you're looking for is EnumerateSubnames. It's not a wildcard search, but you can get all the names that exist "underneath" a given name (for example, all of the service names that exist within an application, or all names with some specific prefix). Depending on the structure of how you create your service names this could work for you.
// System.Fabric.FabricClient.PropertyManagementClient
public Task<NameEnumerationResult> EnumerateSubNamesAsync(Uri name, NameEnumerationResult previousResult, bool recursive)
For example: Presume the following names exist in the cluster:
fabric:/SomeApplication/Zone1/Service1
fabric:/SomeApplication/Zone1/Service2
fabric:/SomeApplication/Zone2/Service1
Note that in this case the application would have been created with the name "fabric:/SomeApplication" and then the services with the detailed names above incorporating the "Zone" segment.
If you now EnumerateSubnames("fabric:/SomeApplication/Zone1", null, true) you'd get back a result that gave you the full names that matched (1 & 2 above).

Should a RESTful API avoid requiring the client to know the resource hierarchy?

Our API's entry point has a rel named "x:reports" (where x is a prefix defined in the HAL representation, by way of a curie - but that's not important right now).
There are several types of reports. Following "x:report" provides a set of these affordances, each with a rel of its own - one rel is named "x:proofofplay". There is a set of lookup values associated with this type of report (and only this type of report). The representation returned by following "x:proofofplay" has a rel to this set of values "x:artwork".
This results in the following hierarchy
reports
proofofplay
artwork
While the "x:artwork" resource is fairly small, it does take some time to fetch it (10 sec). So the client has opted to async load it at app launch.
In order to get the "x:artwork"'s href the client has to follow the links. I'm not sure whether this is a problem. It seems potentially unRESTful, as the client is depending on out-of-band knowledge of the path to this resource. If ever path to artwork changes (highly unlikely) the client will break (though the hrefs themselves can change with impunity).
To see why I'm concerned, the launch function looks like this:
launch: function () {
var me = this;
Rest.getLinksFromEntryPoint(function(links) {
Rest.getLinksFromHref(links["x:reports"].href, function(reportLinks){
Rest.getLinksFromHref(reportLinks["x:proofofplay"].href, function(popLinks){
me.loadArtworks(popLinks["x:artwork"].href);
});
});
});
}
This hard-coding of the path simultaneously makes me think "that's fine - it's based on a published resource model" and "I bet Roy Fielding will be mad at me".
Is this fine, or is there a better way for a client to safely navigate such a hierarchy?
The HAL answer to this is to embed the resources.
Depending a bit on your server-side technology, this should be good enough in your case because you need all the data to be there before the start of the application, and since you worry about doing this sequentially, you might parallelize this on the server.
Your HAL client should ideally treat things in _links and things in _embedded as the same type of thing, with the exception that in the second case, you are also per-populating the HTTP cache for the resources.
Our js-based client does something like this:
var client = new Client(bookMarkUrl);
var resource = await client
.follow('x:reports')
.follow('x:proofofplay')
.follow('x:artwork')
.get();
If any of these intermediate links are specified in _links, we'll follow the links and do GET requests on demand, but if any appeared in _embedded, the request is skipped and the local cache is used. This has the benefit that in the future we can add new things from _links to _embedded, and speeding up clients who don't have to be aware of this change. It's all seamless.
In the future we intend to switch from HAL's _embedded to use HTTP2 Push instead.

How to represent instantiation of DocumentClient in Powershell

Having a hard time figuring out how to do the same thing in powershell as the followings lines:
(in namespace Microsoft.Azure.Documents)
DocumentClient client = new DocumentClient(new Uri("endpoint"), "authKey")
Database database = client.CreateDatabaseQuery().Where(d => d.Id == "collectionName").AsEnumerable().FirstOrDefault()
Can anyone help?
tx
Look here: https://alexandrebrisebois.wordpress.com/2014/08/23/using-powershell-to-seed-azure-documentdb-from-blob-storage/
It shows you how use the authKey endpoint uri in a raw REST request.
Also, study the REST API for DocumentDB here: https://msdn.microsoft.com/en-us/library/azure/dn781481.aspx?f=255&MSPPError=-2147217396.
It'll allow you to look up how to do more operations following the Alexandre's example.
There is also this powershell commandlet DLL that makes many of the operations easy: https://github.com/savjani/Azure-DocumentDB-Powershell-Cmdlets