.Net core gRPC unmanaged memory usage - .net-core

I have a simple service that listens to RabbitMQ, calls some gRPC services and does other stuff like DB updates etc. I started noticing Kubernetes pods failing with OOM exception so I took out all the logic from Consume method and controller constructor and started adding back parameters one by one. Everything is normal until I pass my gRPC client to constructor- then unmanaged memory starts going up with each new message and never goes down (the Consume method is still empty). Any ideas what I'm doing wrong?
My client is added in Program.cs like this:
services.AddGrpcClient<Notification.Api.Notification.NotificationClient>(o => { o.Address = new Uri(sso.GrpcOptions.ApiBaseAddress); })
.ConfigureChannel(c =>
{
c.LoggerFactory = LoggerFactory.Create(logging =>
{
logging.AddConsole();
logging.SetMinimumLevel(LogLevel.Warning);
});
c.HttpHandler = new SubdirectoryHandler(new HttpClientHandler()
{
}, sso.GrpcOptions.NotifSubdirectory);
});

Eventually I added gRPC clients with services.AddSingleton() instead of using services.AddGrpcClient() and it fixed the increasing memory consumption.

Related

Asp net core SignalR websocket connection time more then 1 second

I created dot net core SignalR client using https://learn.microsoft.com/en-us/aspnet/signalr/overview/getting-started/tutorial-getting-started-with-signalr
Using StartAsync connection takes more than 1 second.
That is too long.
How can we reduce start time? Any parameters to tweak?
Thanks for response and the rectified link.
Solution is using ASP.NetCore and transport is configured to use WebSocket ONLY.
Server side (Startup/ Configure)
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<LiveHub>("/signalr/livehub", options =>
{
options.Transports = HttpTransportType.WebSockets;
});
});
Console Client application was built as per:
https://github.com/aspnet/AspNetCore.Docs/tree/master/aspnetcore/signalr/dotnet-client/sample/SignalRChatClient
Under Client
connection = new HubConnectionBuilder()
.WithUrl("http://localhost:xxxx/signalr/livehub", options =>
{
options.SkipNegotiation = true;
options.Transports = HttpTransportType.WebSockets;
})
.Build();
Time for code execution was calculated on client, on
await connection.StartAsync();
With multiple test cases, average connection time hovers around 900msec to 1200 msec.
This is a very long time.

Rebus RabbitMQ IHandleMessage Not working

I have a .NET Core service publishing events to Rebus with RMQ Transport with the following configuration:
services.AddRebus(configure => configure
.Logging(x => x.Serilog())
.Transport(x => x.UseRabbitMq(rabbitMqConnection, "ServiceA"))
.Routing(x => x.TypeBased()));
When I run it, it appears to publish the event to the RebusTopics exchange. So then service B has config like this:
services.AutoRegisterHandlersFromAssemblyOf<MyHandler1>();
services.AddRebus(configure => configure
.Logging(x => x.Serilog() )
.Transport(x => x.UseRabbitMq(rabbitMqConnection, "ServiceB"))
.Routing(x => x.TypeBased()));
and a handler:
public class MyHandler1: IHandleMessages<ServiceAEvent>
{
public CreateMinisiteWhenPageIsCreated(){}
public Task Handle(PageCreated message)
{
//do stuff..
return Task.CompletedTask;
}
There appears to be a binding to the RebusDirect exchange to a new ServiceB queue, but when I publish an event from ServiceA, the handler never fires in ServiceB... there is no binding on the RebusTopics exchange for that message type also.
Im going crazy wondering why, its quite similar in syntax to NServiceBus so very confused as to why its not working.
just add app.ApplicationServices.UseRebus(); in the Consumer's Starup.cs no need to subscribe also. ProducerApp can bus.Send() instead of bus.Publish();
It sounds to me like your subscriber needs to
await bus.Subscribe<ServiceAEvent>();
If the bus instance with the input queue named ServiceB makes the call above, a binding will be created from a topic, whose name is derived from the ServiceAEvent type, to the bus' input queue.
After that is done, it will receive the event whenever another bus instance calls
await bus.Publish(new ServiceAEvent(...));

SignalR: getting error: WebSocket closed

I am working on project of Ionic with angular and AspNet with SignalR that have chat module.
I use SignalR for Chat.It's working smoothly but some time i am getting error as per below screen shot and because of that it's get stop working at all.
I have hosted my service on IIS and creating proxy and communicating with client and server. Here is sample
(function () {
angular
.module('app')
.factory('SignalRFactory', SignalRFactory);
SignalRFactory.$inject = ['$rootScope', 'Hub', 'ionicToast'];
function SignalRFactory($rootScope, Hub, ionicToast) {
var signalRLocal = this;
var serverURL = 'https://serivcerURL.com/signalr';
//Hub setup
var hub = new Hub('CommunicationHub', {
rootPath: serverURL,
listeners: {
'send': function (data) {
console.log("send " + data);
}
},
errorHandler: function (error) {
//Here i am getting that websocket closed error
console.error(error);
}
});
signalRLocal.Connect = function (user) {
console.log("SignalR Connecting as :" + user.UserName);
hub.invoke('connect', user);
};
return signalRLocal;
}
})();
I have hosted service on IIS. I search for the solution and find something like this link
I also try with above link solution by using "long Polling" as per below
Hub.connection.start({ transport: 'longPolling' });
But i don't want to use "long Polling" at all.
So can someone help me to figure out this issue without use of 'long Polling'.
Can someone tell me what configuration i have to do at client side or at IIS level.
As we said in comments, SignalR client will try to reconnect after the connection is lost. Besides, many factors (such as physical network interruption, client browser failure, server offline etc) can cause the connection lost, this article explains some disconnection scenarios, you can refer to it and find the possible causes of the issue.
Besides, as I mentioned in comment, you can call the Start method from your Closed event handler (disconnected event handler on JavaScript clients) to start a new connection to make client automatically re-establish a connection after it has been lost.
edit:
The connection to ws://localhost:3156/signalr/signalr/connect?transport=webSoc‌​kets&clientProtocol=‌​1.5&connectionToken=‌​g8vpRv9ncVDjPIYB9UuE‌​pAAILEaOcTMTG9p46IA2‌​4 was interrupted while the page was loading.
Under "Client disconnection scenarios" section in the article, you can find:
In a browser client, the SignalR client code that maintains a SignalR connection runs in the JavaScript context of a web page. That's why the SignalR connection has to end when you navigate from one page to another, and that's why you have multiple connections with multiple connection IDs if you connect from multiple browser windows or tabs. When the user closes a browser window or tab, or navigates to a new page or refreshes the page, the SignalR connection immediately ends because SignalR client code handles that browser event for you and calls the Stop method.
I am trying same and my client is in vue.js. I have changed below in vue.config.js
module.exports = {
devServer: {
proxy: {
'/hub': {
target: 'https://localhost:5001',
changeOrigin: false,
secure: false,
headers: {
'x-forwarded-proto': 'http',
},
},
},
},
}
Previously i am trying 'x-forwarded-proto': 'https', when I changed to http its work.
https://localhost:5001 is my .net endpoint and http://localhost:8080 is my vue enpoint
Changed in Startup.csbelow,
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHub<CardsHub>("/hub/cardsHub");
});
Added below code in vue component
this.connection = new signalR.HubConnectionBuilder()
.withUrl('/hub/cardsHub')
.build()
In my case the culprit was the wrong version of Microsoft.AspNetCore.SignalR.Common
the default one installed was 5.0.3
but I was targeting 3.1.0
Downgrading to 3.1.12 fixed the issue with the connection.

Hangfire and ASP.NET MVC

I'm currently using Hangfire in an ASP.NET MVC 5 project, which uses Ninject to use the same Context in RequestScope.
In Hangfire dashboard, I get random errors like:
System.Data.Entity.Core.EntityException: An error occurred while starting a transaction on the provider connection. See the inner exception for details. ---> System.Data.SqlClient.SqlException: New transaction is not allowed because there are other threads running in the session.
How can I make Entity, ASP.NET and Hangfire work without getting all those transaction errors?
I bet those errors can happen on the other side (in web).
We also encountered some issues like this with Hangfire along side Ninject. So we actually create a separate kernel for Hangfire, where everything is bound in thread scope. Something like this:
public class NinjectHangfire
{
public static IKernel CreateKernelForHangfire()
{
var kernel = new StandardKernel(/*modules*/);
try
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel).InThreadScope();
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>().InThreadScope();
//other bindings
}
catch
{
kernel.Dispose();
throw;
}
}
}
And then in Startup:
GlobalConfiguration.Configuration.UseNinjectActivator(NinjectHangfire.CreateKernelForHangfire());

Signalr (1.0.0-alpha2) Hubs - Can you add client functions after connection has been started?

Using Signalr (1.0.0-alpha2), I want to know if it is possible to add client functions after a connection has been started.
Say I create my connection and grab the proxy. Then I add some Server Fired client functions to the hub to do a few things. Then I start my connection. I then want to add some more Server Fired functions to my hub object. Is this possible?
var myHub= $.connection.myHub;
myHub.SomeClientFunction = function() {
alert("serverside called 'Clients.SomeClientFunction()'");
};
$.connection.hub.start()
.done(function() {
myHub.SomeNewClientFunction = function() {
alert("serverside called 'Clients.SomeNewClientFunction()'");
}
})
This example is not realistic, but I basically want to send my 'myHub' variable to a different object after the hub is started to subscribe to new events that the original code did not care for.
Real Life Example: A dashboard with a number of different hub events (new site visits, chat message, site error). I 'subscribe' after the connection has started and then pass my hub proxy to all of my different UI components to handle their specific 'message types'. Should I create separate Hubs for these or should I be able to add more Server Fired client functions on the fly?
Yes you can. Use the .on method.
Example:
myHub.on('somethingNew', function() {
alert("This was called after the connection started!");
});
If you want to remove it later on use the .off method.
I have the exact same situation. You might want to consider adding another layout of abstraction if you're trying to call it from multiple places.
Here's a preliminary version of what I've come up with (typescript).
I'll start with the usage. SignalRManager is my 'manager' class that abstracts my debuggingHub hub. I have a client method fooChanged that is triggered on the server.
Somewhere in the module that is using SignalR I just call the start method, which is not re-started if already started.
// ensure signalR is started
SignalRManager.start().done(() =>
{
$.connection.debuggingHub.server.init();
});
Your 'module' simply registers its callback through the manager class and whenever the SignalR client method is triggered your handler is called.
// handler for foo changed
SignalRManager.onFooChanged((guid: string) =>
{
if (this.currentSession().guid == guid)
{
alert('changed');
}
});
This is a simple version of SignalRManager that uses jQuery $.Callbacks to pass on the request to as many modules as you have. Of course you could use any mechanism you wanted, but this seems to be the simplest.
module RR
{
export class SignalRManager
{
// the original promise returned when calling hub.Start
static _start: JQueryPromise<any>;
private static _fooChangedCallback = $.Callbacks();
// add callback for 'fooChanged' callback
static onfooChanged(callback: (guid: string) => any)
{
SignalRManager._fooChangedCallback.add(callback);
}
static start(): JQueryPromise<any>
{
if (!SignalRManager._start)
{
// callback for fooChanged
$.connection.debuggingHub.client.fooChanged = (guid: string) =>
{
console.log('foo Changed ' + guid);
SignalRManager._fooChangedCallback.fire.apply(arguments);
};
// start hub and save the promise returned
SignalRManager._start = $.connection.hub.start().done(() =>
{
console.log('Signal R initialized');
});
}
return SignalRManager._start;
}
}
}
Note: there may be extra work involved to handle disconnections or connections lost.

Resources