Why is NServiceBus receiving notifications from two different servers? - msmq

My app has two components. One is a notifier process (Notifier) that runs on a media server and publishes a message using NServiceBus when a file is modified. The other is a MVC web application (PhotoWeb) that subscribes to these messages to perform cache invalidation, etc.
I'm setting up a staging environment for QA, and the problem is that the PhotoWeb app that's running in the staging environment is receiving notifications from both the staging media server AND the live media server - which is unexpected, and a little odd...
The PhotoWeb instance that's deployed to production has this configuration:
<MsmqTransportConfig InputQueue="PhotoWebInputQueue" ErrorQueue="PhotoWebErrorQueue" NumberOfWorkerThreads="1" MaxRetries="5" />
<UnicastBusConfig>
<MessageEndpointMappings>
<clear/>
<!-- Where do we subscribe to messages about filesystem changes? -->
<add Messages="MyProject.Messages" Endpoint="NotifierInputQueue#webmedia"/>
</MessageEndpointMappings>
</UnicastBusConfig>
and the configuration that's in the staging environment is:
<MsmqTransportConfig InputQueue="PhotoWebInputQueue" ErrorQueue="PhotoWebErrorQueue" NumberOfWorkerThreads="1" MaxRetries="5" />
<UnicastBusConfig>
<MessageEndpointMappings>
<clear/>
<!-- Where do we subscribe to messages about filesystem changes? -->
<add Messages="MyProject.Messages" Endpoint="NotifierInputQueue#staging_media"/>
</MessageEndpointMappings>
</UnicastBusConfig>
A couple of theories spring to mind:
I've misunderstood what a queue actually is - and the PhotoWebInputQueue is actually a shared network resource instead of a queue that's local to a specific server
A previous deployment has caused NServiceBus to subscribe to the live webmedia queue on the staging web server, and this subscription is persisting across restarts, etc.
However, my NServiceBus-fu isn't strong enough to know how to test either of those theories. Anything obviously wrong with this configuration or architecture that you can see?
Thanks,
Dylan

The only way your notifier can be sending messages to both subscribers is if there is a subscription for both subscribers in the notifier's subscription store. The subscription consists of:
The message type (including assembly, version, and public key token)
The input queue address of the subscriber.
When the publisher receives a message it evaluates the message against each subscription in turn, and sends the message on to each matching subscriber.
If you clear down the live notifier's subscription store and then restart the live subscriber this should resolve the issue.

Related

How to define contract for both messaging and http API using sping-contract

I have a situation where there are 2 services. Service A is exposing query API through HTTP endpoint and also is listening for incomming asynchronous command messages (service A owns both of CQRS contracts).
Service B is using both endpoints of service A: to GET data and to invoke commands.
While implementing contract (stub and tests) for HTTP flow is quite simple, configuring messaging part is a tricky for me and actually I've stucked at this one.
Docs says that there is publisher side test generation what is suitable for publishing event case where publisher owns the contract.
But how to makes it working for situation where message consumer owns the contract??
I can't figure out any solution on that one as I need to have a stub used in service A to verify if service A is properly consuming commands messages and also I need genereated tests on service B that will verify that service B if it is producing compliant command message.
I'd appreciate any help.
Many thanks in advance.
Service A is the producer of the API and the consumer of messages. It owns only contracts for HTTP. The messaging contracts are owned by Service B. Service B is the producer of messages. You should have an HTTP contract defined on the Service A side and a Stub Runner test to test if it can receive the message sent by Service B. Service B should have the messaging contract to assert whether the message is properly sent and Stub Runner test for HTTP
That might lead to a dependency cycle. If you have a cycle between your apps then, yeah, what you have to do is ignore a stub runner test on one side until the jars got uploaded.
You've asked about storing contracts in a separate repository. You can do it - here are the docs https://cloud.spring.io/spring-cloud-static/Edgware.SR3/multi/multi__spring_cloud_contract_faq.html#_common_repo_with_contracts and here is an example https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/beer_contracts
You've asked about not generating the tests for some reason (IMO that's a wrong thing to do). You can not use <extensions>true</extensions> in Maven but manually provide which goals you want to execute (omit the test generation). In Gradle just disable generateContractTests task AFAIR

sftp channel outbound adapter with retry

I am using spring batch and spring integration where once my batch job is completed,it creates texts files and those needs to be uploaded to some ftp server. Sometimes we noticed that those connections drops and it needs to be retried. Is there anyway we can use spring retry project to try few sec later to see if it can upload those files. we want it to be configurable.
If so is there any example out there.
Thanks
Yes, Spring Integration provide retry component for you. It is called RequestHandlerRetryAdvice:
<int-sftp:outbound-channel-adapter>
<int-sftp:request-handler-advice-chain>
<bean class="org.springframework.integration.handler.advice.RequestHandlerRetryAdvice" />
</int-sftp:request-handler-advice-chain>
</int-sftp:outbound-channel-adapter>
Please, find more info in the Reference Manual.
Consider to you use RequestHandlerCircuitBreakerAdvice also for your "connections drops" cases.
And here you are the sample.

Websphere Message Broker SOAP Request Node calling .NET web service in gateway mode (no WSDL)

I have been struggling with this issue for a while now and all of the search results (and there are many that I have read) do not seem to apply to my situation.
I have a Websphere Message Broker message flow with a subflow that is calling a web service that was written in Visual Studio. I am trying to call this web service in Gateway Mode which means that I do not have the WSDL to plug into in the properties of the SOAP Request Node in the Broker Toolkit I am using to write this flow.
The error message I am getting is a common one:
The message with Action SendEmail cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).
I am unsure how to proceed with this. Because of the Gateway mode, many of the properties are not configurable in the properties of the SOAP Request Node. Can I set these in the ESQL code, perhaps in the message someplace such as the HTTPRequestHeader?
I am using Websphere 8, Broker Toolkit 7.5. Transport for the message is HTTP and SSL is not used. WS-Addressing is also not being used.
Any suggestions would be most welcome.
Yes, in gateway mode you do not need a WSDL. Your target web service required additional info like below.
le.getRootElement().evaluateXPath("?Destination/?SOAP/?Request/?WSA/?Action[set-value('"+Action+"')]");
Try setting your local environment destination as above. The action can be set according to the WSDL file you have gotten.
How to search for action: First use the provider url:
http://URL?WSDL
After that search for the action word. you can see request action like below.
<input wsam:Action="http//ActionURL.bla.bla.bla" message="tns:blabla" />
So just SET Action = 'http//ActionURL.bla.bla.bla'

MassTransit messages not picked up

I'm using MassTransit version 2.7.0 to communicate between a web service and a web site. The web service publishes messages and the website subscribes to them.
Publisher service:
ServiceBus = ServiceBusFactory.New(sbc =>
{
sbc.UseMsmq();
sbc.VerifyMsmqConfiguration();
sbc.ReceiveFrom("msmq://localhost/publisher");
sbc.UseMulticastSubscriptionClient();
});
Subscriber website:
ServiceBus = ServiceBusFactory.New(sbc =>
{
sbc.UseMsmq();
sbc.VerifyMsmqConfiguration();
sbc.ReceiveFrom("msmq://localhost/website");
sbc.UseMulticastSubscriptionClient();
sbc.Subscribe(s =>
{
s.Handler<SomethingHappened>(HandleSomethingHappened);
});
});
Everything works fine on my dev machine but not on the live site. The messages are showing up in the website_subscriptions MSMQ queue, but they aren't getting picked up by the subscribed website. The server does have multiple NICs so I added the registry settings to support that. I don't get any errors or anything - it just doesn't pickup the messages from the queue.
Am I missing some configuration or permissions problem? Is there some way to see why it isn't working?
[edit]
I just noticed that the website_subscriptions queue is all messages from the framework: AddPeerMessage and AddPeerSubscriptionMessage. All the messages from the service (SomethingHappened in the above example) are in the error queue.
You might try setting up the Log4Net or NLog integration to see what is happening in MassTransit. They did a great job of logging lots of useful troubleshooting information.

How to distribute cache using memchached approach between multiple servers?

I'm trying to distribute cache across multiple servers. I have installed Memcached on 2 Linux servers. I'm using .Net Client Libraries to manipulate cache on those servers.
It's always store value on the first server from configuration. I tried to change sequence of the servers and it stores but only on the first in the list.
I use Putty to check if object exist on the server.
The questions are:
How to store object on both servers at the same time?
if I want to verify that this object stored on all servers from configuration file
How I can do it from client libraries?
Here is the example of my code:
static void Main(string[] args)
{
var mc = new MemcachedClient();
mc.FlushAll();
mc.Store(StoreMode.Add, "key1", "some information");
Console.WriteLine(mc.Get("key1"));
}
and configuration
<enyim.com>
<memcached>
<servers>
<add address="20.23.24.105" port="11211"/>
<add address="20.23.24.106" port="11211"/>
</servers>
<socketPool minPoolSize="10" maxPoolSize="100" connectionTimeout="00:10:00" deadTimeout="00:02:00"/>
</memcached>
</enyim.com>
I don't think that it is possible to do this with the .NET client because that's not how Memcached is supposed to work. Internally the client will hash each key to only one server. If that server goes down the client will take that into account when hashing future keys. One way around this though would be to do a separate set for each server. This would require you to create two clients, one connected to each server, and send the request twice. If the .NET client provides async sets then you can do this with the latency only being as long as the longest of the two set operations.