Good day!
I'm developing a web application to access an ancient Informix 7.31.UC4 database with IBM Informix Client SDK for .NET. The system is currently built so that each user must connect with his own DBMS credentials (not Identity credentials) which means that I either must
a) connect with different credentials upon each request which is way to slow (over 5 sec for creating, opening and closing connection, not to say about queried themselves)
or b) somehow store connections in Dictionary by username and make use of their pooling and avoid multiple connections for the same user in different sessions
or c) store a connection for each Session.
The first approach is unacceptable for its low speed. The second and the third approaches give me no way of disposing the IfxConnection : IDisposable, which makes me cry.
Am I missing a way to dispose objects stored in session upon session abandoning or ending? Is there a way to take advantages of the connection pooling in case of multiple sets of credentials? Or is it just that the system has been ill-designed in the first place and I should not care?
The only way I currently see is to create an Informix user with sufficient rights and keep one connection with pooling and use another SQLServer database for storing users and roles while ruling all the rights and roles at Controller level, but database designer won't hear me out.
P.S. I've seen several questions about disposable objects in sessions, all say it's bad, but I see no other option.
Related
I am working on a web application in C#, ASP.NET, and .NET framework 4.5 with the use of WebSockets. In order to plan for scalability in the future, the application pool has the option for web gardens enabled to simulate multiple web servers on my single development machine.
The issue I am having is how to handle re-connects on the websocket side. When a new websocket session is initially created, the client browser can indirectly lock records in a SQL database. But when the connection is lost, my boss would like the browser to attempt to re-connect to the same instance of the websocket server session so it doesn't need to re-lock anything.
I don't know if something like this is possible because on re-connect the load balancer will "randomly" select which web server to handle the new connection. I was thinking of some hack to work around this but it isn't very clean:
Client opens initial websocket connection on Server A and locks a record.
Client temporarily loses internet connection and the websocket closes. (It is important to note that the server side will wait up to 60 seconds before it "disposes" itself; therefore, the SQL record will remain locked until the 60 seconds has elapsed).
Client internet connection is restored and reconnects to the website but this time on Server B.
Server B sees that this context was initially connected on Server A; therefore, transfers the session to Server A.
Server A checks the process id to see if it is running in the correct worker process (in the case of a web garden).
Server A has found the initial instance and handles the connection.
I tried Googling this question but it doesn't seem like a very common issue because I don't think most websocket web apps keep records locked for as long that my applications does (which is could be up to an hour).
Thanks in advance for all of your help!
Update 3/15/2016
I was hoping that the Server.TransferRequest would have been helpful however it doesn't seem to work for web sockets. Would anyone know of a way to best transfer a websocket context from one process to another?
First, you might want to re-examine why you're locking records for a long time and requiring a client to come back to the same server every time. That is not the usual type of high scale web architecture and perhaps you're just creating this need to reconnect to the identical server because of that requirement when maybe you should rethink how that is designed so that your application would work just fine no matter which host a user connects to.
That would certainly simplify scaling to large numbers of users and servers if you could remove that requirement. You can always then implement local caching and semi-sticky connections later as a performance enhancement, but only after you release the requirement to 100% of the time connect to the same host.
If you're going to stick with that requirement to always connect to the same host, then you will ultimately need some sort of sticky load balancing. There are a lot of different schemes. Some are driven by the networking infrastructure in front of your server, some are driven by your server and some are even client driven. They all have different tradeoffs. Here's a brief run-down of some of the schemes:
Hardware, networking load balancer. Here you have a fairly transparent mechanism by which a hardware load balancer (which is really just software running on a custom piece of hardware) sits in front of your web server farm and uses various techniques to make sure whatever server a given user is originally connected to it will get reconnected to on subsequent connections. This can be based on various schemes (IP address, cookie value, etc...) as the key to identifying a particular user and it typically has a number of possible configurations for how it can work.
Proxy load balancer. This is essentially an all software version of the hardware load balancer. Here a proxy sits in front of your server farm and directs connections to a particular server based on some algorithm (IP address, cookie value, etc...).
Server Redirect. Here an incoming connection is randomly assigned to a server. Upon connection the server figures out where the connection is supposed to be connected to an returns a 302 redirect to the actual host causing the client to reconnect to the proper server. This involves one less layer of infrastructure (no physical load balancers), but exposes the different server endpoints to the outside world which the first two options do not.
Client Selection Algorithm. Here the client is given knowledge of the various server endpoints and is coded with an algorithm for consistently selecting one for this user. It could be a hash of a userID that is then divided into the server bucket pool and the end result is that client ends up choosing a particular DNS name such as cl003.myserver.com which it then connects to. This choice requires the least work server-side so can be simpler to implement, but it requires changing the client code in order to modify the algorithm.
For an article on sticky load balancing for Amazon Web Services to give you an idea on how one mechanism works, you can read this: Elastic Load Balancing: Configure Sticky Sessions for Your Load Balancer.
Here's another article on how the nginx proxy is configured for sticky load balancing.
You can find lots of other articles with a Google search for "sticky load balancing".
A discussion of the pros/cons of the various schemes is the subject of a much longer discussion and some of it involves knowledge of more specific requirements and specific capabilities of your infrastructure.
We are developing a multi-tenant application. With respect to architecture, we have designed shared middle tier for business logic and one database per tenant for data persistence. Saying that, business tier will establish set of connections (connection pool) with the database server per tenant. That means application maintain separate connection-pool for each tenant. If we expect around 5000 tenants, then this solution needs high resource utilization (connections between app server and database server per tenant), that leads to performance issue.
We have resolved that by keeping common connection pool. In order to maintain single connection pool across different databases, we have created a new database called ‘App-master’. Now, we always connect to the ‘App-master’ database first and then change the database to tenant specific database. That solved our connection-pool issue.
This solution works perfectly fine with on-premise database server. But it does not work with Azure Sql as it does not support change database.
Appreciate in advance to suggest how to maintain connection pool or better approach / best practice to deal with such multi-tenant scenario.
I have seen this problem before with multiple tenancy schemes with separate databases. There are two overlapping problems; the number of web servers per tenant, and the total number of tenants. The first is the bigger issue - if you are caching database connections via ADO.net connection pooling then the likelihood of any specific customer connection coming into a web server that has an open connection to their database is inversely proportional to the number of web servers you have. The more you scale out, the more any given customer will notice a per-call (not initial login) delay as the web server makes the initial connection to the database on their behalf. Each call made to a non-sticky, highly scaled, web server tier will be decreasingly likely to find an existing open database connection that can be reused.
The second problem is just one of having so many connections in your pool, and the likelihood of this creating memory pressure or poor performance.
You can "solve" the first problem by establishing a limited number of database application servers (simple WCF endpoints) which carry out database communications on behalf of your web server. Each WCF database application server serves a known pool of customer connections (Eastern Region go to Server A, Western Region go to Server B) which means a very high likelihood of a connection pool hit for any given request. This also allows you to scale access to the database separately to access to HTML rendering web servers (the database is your most critical performance bottleneck so this might not be a bad thing).
A second solution is to use content specific routing via a NLB router. These route traffic based on content and allow you to segment your web server tier by customer grouping (Western Region, Eastern Region etc) and each set of web servers therefore has a much smaller number of active connections with a corresponding increase in the likelihood of getting an open and unused connection.
Both these problems are issues with caching generally, the more you scale out as a completely "unsticky" architecture, the less likelihood that any call will hit cached data - whether that is a cached database connection, or read-cached data. Managing user connections to allow for maximum likelihood of a cache hit would be useful to maintain high performance.
Another method of restricting the number of connection pools per app server is to use Application Request Routing (ARR) to divide up your tenants and assign them to subsets of the web tier. This lends itself to a more scalable "pod" architecture where a "pod" is a small collection of web/app servers coupled to a subset of the databases. A good article on this approach is here:
http://azure.microsoft.com/blog/2013/10/31/application-request-routing-in-csf/
If you are building a multi-tenant DB application Azure you should also check-out the new Elastic Scale client libraries that simplify data-dependent routing and facilitate cross-shard queries and management operations. http://azure.microsoft.com/en-us/documentation/articles/sql-database-elastic-scale-documentation-map/
I want to map user's to connection id's when they connect to my hub class, what is a good strategy for doing this efficiently? I want to associate a user's profile with his connection id so when I check what users are in a particular signalr group I can each user's profile info easily
Technically if you're not worried about maintaining state you could solve this with a poor man's in memory ConcurrentDictionary<string, ConcurrentBag<string>>, but I would assume you are trying to be a little more scalable/fault tolerant than that.
JabbR, which is the flagship testbed chat application for the SignalR framework, stores the connected client details in a table in its DB (which happens to be SQL). It has a mapping of the single ChatUser -> to many ChatClient instances (one-to-many). This way, when a logical user is logged in, it knows who that user is logically and can also make sure it can direct the proper messages to all the connected client instances that user might currently have open. You can find that specific implementation here if you're interested in learning more about it.
I'm developing a high load web service that would provide as fast response as possible. The service should keep a bunch of connections to various databases for faster performance. I'm suggesting using connection pool for that. There may be connection problems to DB because we have a lot of remote access to the DB through VPN. As I have said, service should retain connection as long as possible.
What is the connection pool management algorithm?
I have a connection string:
Code:
User Id=inet;Password=somePassw0rd;Data Source=TEST11;Min Pool Size=5;Max Pool Size=15;Pooling=True
Then I simply open and close connection in my code. That's it.
At this moment everything is OK. There are five sessions on DB side. So I would kill a session to simulate connection problems. And in some cases the connection will be restored by pool manager and in some cases it won't.
If I kill all five connections they are never restored back.
How can I confiure pooling manager? Any settings for duration between checking DB connections?
I have used validate connection=true; it seems to work fine for me, but it would need some effort if reconnect to DB is needed, and therefore it would be more efficient to have an already good connection.
The component I used is devArt dotConnect for Oracle.
Thanks in advance!
I'm not sure what you're exactly looking after, but this can be useful: pools are automatically cleared if a connection is idle for some time or closed by the server. However you can force pool clearance, using OracleConnection's ClearPool or ClearAllPools methods (these methods usually exist on most ADO.NET providers, also it's not a requirement).
Note that if you're using Oracle 11g, DotConnect also supports Oracle's Database Resident Connection Pooling (DRCP) which is presumably the best way to do pooling, since it's provided by Oracle itself (I don't have any experience on this though).
I am looking for a way to detect if a SQL Server fails to respond (timeout/exceptions etc) so that if our C#/.net program trying to access the server asks a server that is down for maintenance, it will jump and try another automatically.
I would like a solution where we do the SQL connection and THEN get the timeout. We could build a WCF service and ask that one, but that is a bit of an overkill in my opinion.
The sync between multiple server locations is not the issue here.
Our development platform at the moment is SQL2008express as its plenty at the moment, but later on we might switch to real SQL2008 servers (or whatever is latest when the time comes).
Clients will connect to "first known" in a "last known dynamic list" asking a "rootserver" or hardcoded configs for first lookup.
When clients loses connections, they will automatically have to try to reconnect to other nodes in the clusters and use whatever returns a reply first. The nodes will individualle connect and share data through other services which we also distribute in the cloud.
We know that mirroring and clustering might be available through large licenses, but our setup demands a more dynamically "linking" and we believe this approach suits our needs better.
So... to be specific:
we need to detect when a SQL-server goes offline, when its not available anymore. Eg. in the middle of a transaction or when we try to connect.
Is the best approach to do a "try-catch" exception handling or is there better tricks when looking over WAN's and using C#/.net =
EDIT
I've received a lot of good ideas to use failover servers, but I would like a more programatical approach, so whats the best way to query the server if its available?
Situation:
4 different SQL servers running on seperate WAN/IP's, each will maintain a list of "where the others are" (peer-to-peer). They will automatically be moving data from each other (much like a RAID-setup where data is spread out on multiple drives)
A client retries the list from an entry-point-server and asks the first available.
If the client asks a server that is "down for maintance" or the data has moved to one of the other servers, it must automatically ask the next in the list.
What we are looking for..
is the best way from within C#/.net to detect that the server is currently unavailble.
We could have a service we connect to and when we loose this, the server is off
We could make a "dbConnectionSqlServer3.open()" and wait for the time out.
We could invest in "real cluster servers", and pay a lot + bind ourselfs to 1 SQL-server type (The SQL platform might change in future, so this is not a real option)
So whats your vote here: 1 or 2?
or can you come up with a number 4 that beats the h**k out of ideas? :o)
I would probably take a different approach.
I'd designate a server (with a failover partner) to be the holder of the server list. It should monitor all of the other servers for availability.
When the client initially wants to connect, it should contact the list server and ask it what to use. From that point forward the client should stick with it, unless a failure is detected. At which point it should contact the list server to get a new one.
The list server would be able to implement any type of load balancing you wanted just by telling the clients which one to connect to. Further, deploying new servers would be easy as the only "list" would be maintained by this primary server.
This completely ignores any sort of server synchronization issues you might have.
One major benefit is that by having a central server doing the monitoring your clients won't have to fall through 3, 5, or 10 servers just to find one that's up. which would increase responsiveness.
UPDATE
#BerggreenDK: The best, and probably only assured way, to detect if a server has failed is to connect to it and run a simple query. All other mechanisms such as pinging, a simple check if the port is open, etc. might give a false positive. Even having a process running on that server itself may give a false reading if the server itself is up but SQL Server is down (e.g: the database is offline).
Ultimately it sounds like your client will have to connect to one of the gateway servers and get a short list of sql servers to attempt to connect to. On failure, it will have to rotate through that short list. If all are down it will have to go back to the gateway and ask for a new list to start the process over.
In the ConnectionString you can specify a failover partner like
Data Source=<MySQLServer>;Failover Partner=<MyAlternateSQLServer>;Initial Catalog=<MyDB>;Integrated Security=True
On http://www.connectionstrings.com there is a section talking of DataBase mirroring.