Cannot get MassTransit response after successfully initiating request - .net-core

I am implementing request/response with MassTransit and Amazon MQ. The (.NET 6 WebApi) host is configured like:
services
.AddMassTransit(x =>
{
x.AddConsumer<ConfigurationConsumer>();
x.UsingRabbitMq((context, cfg) =>
{
cfg.Host(new Uri($"amqps://{rabbitMqSettings.Host}:{rabbitMqSettings.Port}/{Uri.EscapeDataString("/vhostname")}"), h =>
{
h.Username(rabbitMqSettings.Username);
h.Password(rabbitMqSettings.Password);
});
cfg.ConfigureEndpoints(context);
});
x.AddRequestClient<IConfigurationCommand>();
})
.AddMassTransitHostedService();
The client uses the same configuration without x.AddConsumer() and cfg.ConfigureEndpoints(context).
The problem is: calling GetResponse on the client will successfully execute the consumer on the host which seems to respond as intended, but the client never gets a result and times out.
On the other hand, when I am using a web api controller on the same host to initiate GetResponse, everything works as expected.

Ensure that the message types between the host and the client applications are the same.
ALSO, make sure the bus is started on the client using the hosted service or otherwise.

Related

gRpc error "Incomplete Message" When Not Using GrpcWeb, using F5 Load Balancer

We have a grpc service deployed to multiple servers and an F5 pointer/load balancer to those servers. The service(s) are setup as windows services, bound to a specific port. This is working...fine, with the exception of consuming the service when using the F5 address, and the call originating from a server, unit test, or testing suite (Kreya); grpcweb/wasm calls are having no issues. Implementation below:
builder.Services.AddCodeFirstGrpcClient<INTERFACE>(client =>
{
client.Address = new Uri(<<address>>);
client.ChannelOptionsActions.Add(option =>
{
var handler = new Grpc.Net.Client.Web.GrpcWebHandler(Grpc.Net.Client.Web.GrpcWebMode.GrpcWeb, new HttpClientHandler());
option.HttpClient = new HttpClient(handler);
option.DisposeHttpClient = true;
// can't have an HttpClient and a HttpHandler so make sure this is null
option.HttpHandler = null;
option.MaxReceiveMessageSize = int.MaxValue;
});
});
So, server/test(s) calls to the individual servers (https://servername:port/) each return data; when using the F5 url: "Incomplete Message." Implementation, below:
services.AddCodeFirstGrpcClient<INTERFACE>(implementation =>
{
implementation.Address = new Uri(<<address>>);
});
Even in the unit tests/suite, when switching to using grpcweb or grpcwebtext, there is no difference, I still get the error message, "Incomplete Message."
Using Kreya, I can see that the connection is established, tls handshake completed, message sent, but, no message response/sent, it just fails.
I know I can implement load balancing from the client calls themselves, but, that defeats the purpose of utilizing F5 for our organization, and we all just needing to know a single url, and all the other benefits of such an implementation.
Can anyone provide any insight into why this error is occuring, only when the calls originate from a server/unit test? I wrote/implemented the service, and have been the primary deployer of the service, and worked with the server folk regarding the F5 implementation. We're utilizing protobuf-net grpc, if that helps. This dangole issue sounds like something hella dumb that I'm over looking.
Thanks much.

How to start another SignalR connection based on another one

I'm using a javascript web app which was connecting through SignalR to aspnet core service A, residing in a docker container. I have to add another service B as a middle between the 2. My guess was that I should split the SignalR connection in 2: first between javascript web app and service B, and second between service B and service A.
So far SignalR works between javascript web app and service B. While service B message arrives at service A, service A answer doesn't receive response from service B (for negotiation of the transport).
In service B I get 404 error, and in service A I see ws-connection time out.
This is what I did in service B:
targetUrl = serviceA_signalR_Url + javascript_app_request_query_string
_connection = new HubConnectionBuilder()
.WithUrl(targetUrl, options => {
{
options.Transports = HttpTransportType.WebSockets;
})
.Build();
_connection.StartAsync.Wait();
Funnily it was my fault. I was trying to use id parameter in the query string. It worked once I removed it

Signalr with redis backplane, sending message to user

I am researching to use signalr to send messages from an api to a specific user (keyword). Locally, I have everything working as designed (even using redis backplane).
When I move up to an actual environment with multiple servers (azure app service), it seems like messages to specific users don't flow through the backplane. If I send a message to Clients.All it works. But, if I send a message to Clients.User(username), the message is never received. This works locally because it's a single server, but doesn't seem to work in multiple servers.
await this.impersonationContext.Clients.User(mainUserName).SendAsync("msguser", new object[] { mainUserName });
await this.impersonationContext.Clients.All.SendAsync("msg", new object[] { "wtf" });
If I call the above code, only the msg event is fired, but the msguser is never recieved.
Could I be missing something on the setup? That's my assumption, I cannot be the only one doing this.
Below is my setup in the startup.cs. This is using .net core 5 with the latest nugets, etc
services.AddSignalR(options =>
{
options.EnableDetailedErrors = true;
})
.AddStackExchangeRedis(this.Configuration["Redis:Cache"], options => {
options.Configuration.ChannelPrefix = "ImpersonationService";
});
services.AddSingleton<IUserIdProvider, NameUserIdProvider>();
Any help would be appreciated.
Update #1
Looks like the user info is being pushed through the backplane (username hidden). So maybe its the connection from javascript client?
Update #2
Getting closer...looks like the subscription isn't setup for the specific user like I see locally. Could this be websockets?
Update #3
Found it....sorta.
I was missing the authorize attribute on the hub, which was allowing the websocket to connect, even though websockets isn't authenticating for some reason (different issue). Once I added the authorize, it will drop down to long polling with the user info and works as designed

Proxy error: Could not proxy request from localhost:3000 to http://localhost:44381/ (ECONNREFUSED)

I am developing a Single Page Application (SPA) with ReactJS and ASP.NET. I I am trying to execute an HTTP Request to an endpoint from client side code. I used the default ASP.NET SPA template and changed my configuration as shown below.
fetch(`/items/${id}`).then((response: any) => {
return response.data;
})
I modified the default web api template and use a Proxy Server in development instead. Like so:
app.UseSpa(spa =>
{
spa.Options.SourcePath = "Client";
if (env.IsDevelopment())
{
spa.UseProxyToSpaDevelopmentServer("http://127.0.0.1:3000/");
//spa.UseReactDevelopmentServer(npmScript: "start");
}
});
When I execute the fetch in React client code, I get this error: Proxy error: Could not proxy request /items/1 from localhost:3000 to http://localhost:44381/ (ECONNREFUSED).
How do I configure my server-side code to proxy the request?
According to the linked issue on GitHub, the spa.UseReactDevelopmentServer should already setup the proxy server itself as of .Net Core 3.1. So you might not need to be calling the spa.UseProxyToSpaDevelopmentServer yourself manually.
https://github.com/dotnet/AspNetCore.Docs/issues/12008#issuecomment-573453266

SignalR fails to send message to a group when running through LoadBalancer

In order to send SignalR message to a specific user I create a Group for each user upon connection
public override Task OnConnected()
{
log.DebugFormat("Connected. Connection Id = {0} UserId = '{1}'", Context.ConnectionId, UserHelper.UserId);
Groups.Add(Context.ConnectionId, UserHelper.UserId);
return base.OnConnected();
}
Now when a message comes in I send it a group in the following way:
var hubContext = GlobalHost.ConnectionManager.GetHubContext<AlertsHub>();
foreach (var recipient in recipients)
{
hubContext.Clients.Group(recipient).broadcastAlertMessage("Group", msg);
}
That works fine when deployed to a server, but for some reason not working when i access the server through our company load balancer (Citrix Netscaler SDX 11500) but eventually hitting the same sole box.
There is no issue sending messages to all clients
hubContext.Clients.All.broadcastAlertMessage("All", msg);
Also i can keep the connection IDs internally and send messages to a specific client works
hubContext.Clients.Client(AlertsHub.UserToConnectionIdDict["admin"]).broadcastAlertMessage("trageted client", msg);
Why "Group" message doesn't work?
By default, a SignalR server is only aware of and will only send messages to clients connected directly to itself. This is because each SignalR server manages its own messages using its own message bus. Without special configuration, SignalR has no way to know there are other clients connected to a different SignalR server at the same global address.
Fortunately SignalR has scaleout providers that allow you to configure all your SignalR servers in such a way that they can communicate with each other by sharing single message bus.
This "Introduction to Scaleout in SignalR" should provide you with the info you need to get SignalR working properly behind a load balancer: http://www.asp.net/signalr/overview/signalr-20/performance-and-scaling/scaleout-in-signalr

Resources