Is it possible to change querystring on a SignalR connection without perform a stop and start?
I´m doing this:
$.connection.hub['qs'] = {arg1: 'kkkk', arg2: 'xxx',...};
$.connection.hub.stop();
$.connection.hub.start();
This stop/start is causing my system to interpret it is as a connection break up, what is undesirable for many reasons.
When I remove it, methods are invoked with older querystring arguments.
The code you have to update the query string ($.connection.hub.qs = {arg1: 'kkkk', arg2: 'xxx',...};) will be reflected in the query string of any future requests SignalR makes for that connection.
In the case of anything but the WebSocket transport, i.e. server-sent events, forever frame, and long polling, any subsequent server hub invocation should be made by an Ajax request with the updated querystring.
However, if WebSockets is in use, there shouldn't ever be a subsequent request to attach the updated query string to. At least this is the case if the connection doesn't die forcing a reconnect.
One solution is to restart the connection like you did. It would be better yet if you would set the query string before you start the connection in the first place.
If you really need to change the query string after the connection starts and you don't want the system to interpret this as a brand new connection, you might be able to do something like the following:
$.connection.hub.qs = {arg1: 'kkkk', arg2: 'xxx',...};
$.connection.hub.transport.lostConnection($.connection.hub);
This will basically trick the transport into thinking the connection is dead and cause it to reconnect with the updated query string without renegotiating and connecting with a new ConnectionId. The problem with this approach is that the second line uses an undocumented API.
Related
We have an ASP.NET API web site which connects using NHibernate to a SQL Server.
The problem we are experiencing is that gradually throughout the day, the number of connections to the SQL server creeps up, and there are many connections that do not appear to be returned to the pool. By this, I mean that if I run the following query:
select * from master..sysprocesses s where datediff(minute, s.last_batch, getdate())>10
the number of rows returned just keeps climbing. Nothing in the API should be taking 10 minutes to complete. And there are connections in there from hours ago.
Here's another clue: the open_tran column of all these rows has a value of 1. So it seems to me that somewhere inside the API call, we're creating a transaction boundary, and that transaction is never being closed. Perhaps DTC may have a hand in this (we sometimes do connect to more than one database in a call).
The thing is, I haven't a clue how to troubleshoot this further. I've tried running DBCC INPUTBUFFER on the rogue spids, and there's nothing consistent between them.
What are some of the anti-patterns/other possible causes that might lead to this behavior?
Update: here's how the DB connection is being created. We're using StructureMap for Dependency Injection. We create two DB connections on each unit of work: one "normal" connection for regular read/write access, and an "uncommitted" connection that runs in a transaction with "ReadUncommitted" access (we were having a problem with table locking when reading from large tables).
Here's the code from the DI Registry:
For<ISession>().Transient().Use(context => context.GetInstance<ISessionFactory>().OpenSession());
For<ISessionUncommittedWrapper>().Transient().Use(context => new SessionUncommittedWrapper { Session = context.GetInstance<ISessionFactory>().OpenSession() });
Then, inside the unit of work middleware, we create a UnitOfWork (with a using block, of course), which takes an ISession and an ISessionUncommittedWrapper in the constructor. In the Begin() method, we have:
_uncommittedTransaction = SessionUncommittedWrapper.Session.BeginTransaction(IsolationLevel.ReadUncommitted);
which gets disposed (along with the ISession and ISessionUncommittedWrapper) in the UnitOfWork's Dispose() method.
I eventually found the problem.
The way I found the problem was by creating a logging table that tracked the creation and disposal of Sessions, along with the URI of the endpoint called. By querying all the undisposed connections, I found that in every case where the connection was not disposed, the path began with "/signalr".
<facepalm>D'oh!</facepalm>
Since the OWIN middleware was proactively creating the Sql connections, it was also doing so for SignalR, which in its nature, keeps the transaction open! So every client that logged in with SignalR was hogging two Sql connections.
I made the appropriate changes to exclude SignalR connections from the middleware, and now we have no more hanging Sql connections.
I am using Signalr in an application I'm writing and storing all the user connections in a concurrent dictionary
ConcurrentDictionary<string, User> _users = new ConcurrentDictionary<string, User>();
e.g.
https://github.com/SignalR/SignalR/blob/master/samples/SignalR.Hosting.AspNet.Samples/Hubs/ShapeShare/ShapeShare.cs
I have implemented the IDisconnect interface on my Hub and I'm removing users from the dictionary when they disconnect
I am wondering how reliable the Disconnect method really is?
Does it capture all the different ways that a user could diconnect?
I dont want the dictionary to grow and grow indefinitely
I was thinking of maybe having a timer to periodically traverse the dictionary and remove users who havent had any recent activity
Is this necessary? Can I rely on the disconnect method?
Check out https://github.com/SignalR/SignalR/wiki/Configuring-SignalR , there are settings for :
DisconnectTimeout
KeepAlive
& Heatbeat interval
These could all be applied to help in maintaining your dictionary.
In my experience a graceful disconnect seems to work perfectly on signalR (still problems with win-apps) , if it ungracefully disconnects in a few minutes the connection will timeout and the disconnect method will fire and remove it from your dictionary like Drew said.
You could create a method that sends a message to all clients and log the returned connection ID and then remove any entries that are old, but in practice the disconnect method does work/work itself out, I would only implement the heartbeat interval if you really need to keep a very close eye on the connections.
If it doesn't fire it's a bug and you should report an issue to the SignalR project on GitHub. Here's a list of open issues with Disconnects at this time.
Be aware that diff. transports have diff. disconnect detection logic and so, depending on which transport the user is using, you will see diff. patterns of when the Disconnect fires, but it SHOULD fire eventually for all transports.
I have an ASP.NET web page that connects to a number of databases and uses a number of files. I am not clear what happens if the end user closes the web page before it was finished loading i.e. does the ASP.NET life cycle end or will the server still try to generate the page and return it to the client? I have reasonable knowledge of the life cycle but I cannot find any documentation on this.
I am trying to locate a potential memory leak. I am trying to establish whether all of the code will run i.e. whether the connection will be disposed etc.
The code would still run. There is a property IsClientConnected on the HttpRequest object that can indicate whether the client is still connected if you are doing operations like streaming output in a loop.
Once the request to the page is generated, it will go through to the unload on the life cycle. It has no idea the client isn't there until it sends the information on the unload.
A unique aspect of this is the Dynamic Compilation portion. You can read up on it here: http://msdn.microsoft.com/en-us/library/ms366723
For more information the the ASP.NET Life Cycle, look here:
http://msdn.microsoft.com/en-us/library/ms178472.aspx#general_page_lifecycle_stages
So basically, a page is requested, ASP.NET uses the Dynamic Compilation to basically create the page, and then it attempts to send the page to the client. All code will be run in that you have specified in the code, no matter if the client is there or not to receive it.
This is a very simplified answer, but that is the basics. Your code is compiled, the request generates the response, then the response is sent. It isn't sent in pieces unless you explicitly tell it to.
Edit: Thanks to Chris Lively for the recommendation on changing the wording.
You mention tracking down a potential memory leak and the word "connection". I'm going to guess you mean a database connection.
You should ALWAYS wrap all of your connections and commands in using clauses. This will guarantee the connection/command is properly disposed of regardless of if an error occurs, client disconnects, etc.
There are plenty of examples here, but it boils down to something like:
using (SqlConnection conn = new SqlConnection(connStr)) {
using (SqlCommand cmd = new SqlCommand(conn)) {
// do something here.
}
}
If, for some reason, your code doesn't allow you to do it this way then I'd suggest the next thing you do is restructure it as you've done it wrong. A common problem is that some people will create a connection object at the top of the page execution then re-use that for the life of the page. This is guaranteed to lead to problems, including but not limited to: errors with the connection pool, loss of memory, random query issues, complete hosing of the app...
Don't worry about performance with establishing (and discarding) connections at the point you need them in code. Windows uses a connection pool that is lightning fast and will maintain connections for as long as needed even if your app signals that it's done.
Also note: you should use this pattern EVERY TIME you are using an un-managed class. Those always implement IDisposable.
Using Asp.net webforms I want to track down visitor info just like Google Analytics does. Of course, I can use Google Analytic for this purpose but I want to know how can I achieve the same thing with Asp.net 3.5 and SQL Server 2008.
I want to store IP, Country, URL Referrer of the visitor, Resolution on each page request except postback. I am expecting 50k+ visit everyday..
Main concern is I want to do it in a way that it should not block current request.
i.e In general it happens when we save data in to db, current request stops on particular SP calling statment and moves ahead when it finishes executing SP or tsql statement. I want to follow "Insert and Forget" approach. It should insert in background when I pass parameter to particular event or function.
I found below alternatives for this :
1. PageAsynchTask
2. BeginExecuteNonQuery
3. Jquery Post method and Webservice (But I am not confident about this, and wondering how should I go about it)
I hope I've mentioned my problem properly.
Can anybody tell me which one is better approach? Also let me know if you've any other ideas or better approach than the listed one. Your help will be really appreciated.
Problems with any background thread in server side is each and every request is going to occupy two threads. One for serving the ASP.NET request and one for logging the stuff you want to log. So, you end up having scalability issues due to exhaustion of ASP.NET threads. And logging each and every request in database is a big no no.
Best is to just write to log files using some high performance logging library. Logging libraries are highly optimized for multi-threaded logging. They don't produce I/O calls on each and every call. Logs are stored in a memory buffer and flushed periodically. You should use EntLib or Log4net for logging.
You can use an HttpModule that intercepts each and every GET, POST and then inside the HttpModule you can check whether the Request.Url is an aspx or not. Then you can read Request.Headers["__ASYNCPOST"] and see if it's "true", which means it's an UpdatePanel async update. If all these conditions are true, you just log the request into a log file that stores the
You can get the client IP from:
HttpContext.Current.Request.UserHostAddress;
or
HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
To get the IP address of the machine and not the proxy use the following code
HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
However you cannot get the country. You will have to log the IP in your log files and then process the log files using some console application or job which will resolve the country of the IP. You need to get some IP->Country database to do the job. I have used http://www.maxmind.com/app/geoip_country before.
For screen size, you will have to rely on some javascript. Use a javascript on each page that finds the size of the screen on the client side and stores in a cookie.
var screenW = 640, screenH = 480;
if (parseInt(navigator.appVersion)>3) {
screenW = screen.width;
screenH = screen.height;
}
else if (navigator.appName == "Netscape"
&& parseInt(navigator.appVersion)==3
&& navigator.javaEnabled()
)
{
var jToolkit = java.awt.Toolkit.getDefaultToolkit();
var jScreenSize = jToolkit.getScreenSize();
screenW = jScreenSize.width;
screenH = jScreenSize.height;
}
Once you store it in a cookie (I haven't shown that code), you can read the screen dimensions from the HttpModule by using Request.Cookies and then log it in the log file.
So, this gives you solution for logging IP, screensize, finding country from IP, and filtering UpdatePanel async postback from logging.
Does this give you a complete solution to the problem?
Talking about server side, if you're running on IIS, and you don't need absolute real time information, I recommend you use IIS logs.
There is nothing faster than this, as it's been optimized for performance since IIS 1.0
You can append your own information in these logs (HttpRequest.AppendToLog), they have a standard format, there is an API if you want to do custom things with it (but you can still use text parser if you prefer), and there are a lots of free tools, for example Microsoft Log Parser which can transfer data in a SQL database (among others).
The first approach is looking good. (And I recommend it.) But it has 2 downsides:
Request will still block until task completes (or aborts on timeout).
You'll have to register your Task on every page.
The second approach looks inconvenient and might lead to errors. (You have to watch for a situation when your page renders faster than your query is processed. I'm not sure what will happen if your query is not complete when your page object is destroyed and GC goes on finalize() spree... but nothing good, I assume. You can avoid it by waiting for IAsyncResult.IsCompleted after render, but that's inconvenient.)
The third method is plain wrong. You should initiate your logging on the server side while processing the request you're going to log. But you still can call a web service from the server side. (Or a win service).
Personally, I'd like to implement logging in BeginRequest to avoid code duplication, but you need IsPostback... Still there might be a workaround.
Hii,
you can fire an asynchronous request and don't wait for response.
here i have some implemented code..
for that you need to create a web service to do your database operation or you can use it for your whole event handling.
from server side you have to call the web service asynchronously like this
Declare a Private Delegate
private delegate void ReEntryDelegate(long CaseID, string MessageText);
Now the method will contain web service calling like this
WebServiceTest.Notification service = new WebServiceTest.Notification();
IAsyncResult handle;
ReEntryDelegate objAscReEntry = new ReEntryDelegate(service.ReEntryNotifications);
handle = objAscReEntry.BeginInvoke(CaseID, MessageText, null, null);
break;
And the variable values will be passed by method here (CaseID,MessageText)
Hope this is clear to you
All the Best
Suppose that I have an ASP.NET page. In the page load event handler, I open a database connection and do some processing. But after the processing is done, I don't close the connection explicitly by calling the CLOSE method of the connection object.
Now when the page processing at the server side is finished, the GC will dispose all the variables in my page, and also, the connection object too. But when it is disposed, does the connection that was opened previously is automatically closed? I mean, when GC disposes the connection object, does it automatically close the connection that was established with the database server; or it simply dispose the connection object, and the connection at the database is remained open, until the connection timeout occurs at the database and then the database server closes the connection by itself?
The MSDN documentation is pretty clear about this:
If the SqlConnection goes out of
scope, it won't be closed. Therefore,
you must explicitly close the
connection by calling Close or
Dispose. Close and Dispose are
functionally equivalent.
Either use the using blocks to have it disposed automatically, or explicitly .Close() it. The using blocks are preferred.
By leaving connections open your application may eventually run out of connections when new requests are attempted, resulting in errors. I've faced such a problem in an application I was debugging. The original developers failed to close the connections explicitly on a few pages and traffic was high enough that users started getting errors. I wrapped the offending connections in a using block and the problem went away.
Connection is remained open. If you have lots of pageviews, and lots open connections, you can get 500 error.
Your connections won't be closed until after (not when) your page object is finalized, and that might be a while. It would be very easy to max out the number of available connections and start getting errors.
You should use using blocks, then you won't have to ask the question:
using (var conn = new SqlConnection(connectionString))
{
using (var cmd = new SqlCommand(commandText, conn))
{
using (var reader = cmd.ExecuteReader())
{
while (reader.Read()) { /* ... */ }
}
}
}
your connection won't be closed unless chosen by GC and if you have many visitors resulting in lots of connections then this may be horrible. Also if you try to open an opened connection it will throw error so you have to check for that better is either write it in using block or close the connection yourself.