I want to run a "background job" in my ASP.NET application (periodically, as separate thread). And I need host name (DNS name or IP) to do my tasks. The problem is that the HttpContext.Current may be not available here (it's NULL).
Is there any way to get a host name in not using HttpContext.Current.Request.Url.Host.
When the host name is available in HttpContext.Request.Url.Host, it is a result of the host name being part of the request sent by the client. As an example, take a request to this page:
GET /questions/2164261/get-host-name-without-using-httprequest HTTP/1.1
Host: stackoverflow.com
...
When running in a background thread, no request context is available, and there really is no concept of a host name at all. Your only alternative is to store the hostname within the code or in configuration.
Slightly off topic: Running scheduled tasks within a web application is asking for trouble, and spawning threads only deals with a few of them. If at all possible, consider running your scheduled jobs from a Windows service, possibly built using a framework like NCron.
probably you can add a class variable in your thread class, and set this variable with request.url.host before you run the thread class.
this method can also apply to the session object.
Keep in mind that it's a bad idea to initiate that "background job" from a web application if you need that background process to run 24/7 independently. Even if you start it in a new thread. Your web app may have no requests for some time. In this case the run time will shut down the process and all its "child" threads. For continuous running you need to run it as a Windows service. Otherwise, the Darren is right, use the System.Net.Dns.GetHostName().
I'm using the same approach as you for scheduling regular tasks and the way I worked around this is to store the machine name for later use when the application gets any kind of web request.
It's a rather dirty hack, but the only way to do this unless you want to hard-code it or retrieve it from an external configuration file, which was too dangerous (unreliable) for my purposes.
Related
I have a .Net core application that consists of some background tasks (hosted services) and WEB APIs (which controls and get statuses of those background tasks). Other applications (e.g. clients) communicate with this service through these WEB API endpoints. We want this service to be highly available i.e. if a service crashes then another instance should start doing the work automatically. Also, the client applications should be able to switch to the next service automatically (clients should call the APIs of the new instance, instead of the old one).
The other important requirement is that the task (computation) this service performed in the background can’t be shared between two instances. We have to make sure only one instance does this task at a given time.
What I have done up to now is, I ran two instances of the same service and use a SQL server-based distributed locking mechanism (SqlDistributedLock) to acquire a lock. If a service could acquire a lock then goes and do the operation while the other node waiting to acquire the lock. If one service crashed the next node could be able to acquire the lock. On the client-side, I used Polly based retry mechanism to switch the calling URL to the next node to find the working node.
But this design has an issue, if the node which acquired the lock loses the connectivity to the SQL server then the second service managed to acquire the lock and started doing the work while the first service is also in the middle of doing the same.
I think I need some sought of leader election (seems done it wrongly), Can anyone help me with a better solution for this kind of a problem?
This problem is not specific to .Net or any other framework. So please make your question more general so as to make it more accessible. Generally the solution to this problem lies in the domain of Enterprise Integration Patterns, so consult the references as the status quo may change.
At first sight and based on my own experience developing distributed systems, I suggest two solutions:
use a load balancer or gateway to distribute requests between your service instances.
use a shared message queue broker to put requests in and let each service instance dequeue a request for processing.
Either is fine and I can use both for my own designs.
For manually testing an HTTP client in my application, I'd like to use a tool which starts an HTTP server my application can connect to and that lets me respond to request from my application manually. I'm basically looking for a tool with a GUI that lists all incoming requests and allows me to select a status code and type a response message. I've already tested the functionality with unit tests but I also want to verify it manually with no mocking etc.
Sounds simple but I didn't find such a tool. I've found some that can be scripted but no interactive one. Do you know one?
This can probably be written relatively easily by creating the Swing GUI dialog popup inside the servlet servicing methods. Have never seen Tomcat running this way but probably it would. Only, mind the server time out. It may be not long enough for you to make an input and require to be configured, also on the client side. Also, parallel calls will make multiple popups that may be difficult to respond but probably this is a single client app.
As a simplest solution, server GUI can be simply disposed after call and newly created as the next call arrives. This will make eveything indepenent on how servlet container is managing the servlets (does it stays, is it destroyed, maybe class is unloaded, who knows). Advanced solution could include the "server servlet" that would interact through its own JSP page but then it may be complex to update it when the new call arrives (unless maybe refresh periodically).
I have a WCF service with ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple). I want to use ThreadStatic variable to srore data.
I start worrying about is it possible two parallel requests for the same or different operationContracts get handled by the same thread serverside, because if this happens my ThreadStatic variable will get overriden.(I.e. something like the thread changing between HttpHandlers and HttpModules in ASP.NET)
I made a spike service with the same ServiceBehaviour and maxConcurrentCalls="2". After that a wcf client called the service with 50 parallel requests and my worry did not occur. However this is not a 100% proof.
Thank in advance!
Irrespective of the ConcurrencyMode, a ThreadStatic value will persist when your request terminates and the thread is returned to the thread pool. The same thread can be reused for a subsequent request, which will therefore be able to see your ThreadStatic value.
Obviously this won't be true for two concurrent requests, because by definition they will be executed on different threads.
From comments:
Also by definition MSDN says: 'The service instance is multi-threaded. No synchronization guarantees are made. Because other threads can change your service object at any time, you must handle synchronization and state consistency at all times.' So it is not so obvious:)
This means that a single instance of your service class can be accessed concurrently by multiple requests. So you would need to handle synchronization for any accesses to instance members of the service class.
However ThreadStatic members are by definition only used by one thread (and hence one request) at a time, so don't need synchronization.
The direct answer to your question is Joe's answer.
However you mention in the comments you are using an ambient design pattern. That pattern is already implemented in WCF as the OperationContext and is specifically designed to be extensible. I highly recommend using OperationContext over any custom thread storage.
See Where to store data for current WCF call? Is ThreadStatic safe?
I wanted to add to Joe's answer here because I would recommend that you use some sort of correlation for your requests if you're needing to store state. The threading model will become very convoluted and unreliable in production.
Further, now imagine you have two IIS servers hosting this service and a hardware or software load balancer forward facing so that you can consume it. To ensure that the correct state is gathered you'll need correlation because you never know which server the service will be started on. In the post below I mocked up a simplified version of how that might work. One thing to keep in mind is that the SessionState would need to be kept in a shared location to all instances of the service, an AppFabric Cache server for example.
Global Variable between two WCF Methods
I'm looking into building an ASP.NET MVC application that exposes (other than the usual HTML pages) JSON and XML REST services, as well as Web Sockets.
In a perfect world, I would be able to use the same URLs for the Web Sockets interface as I do for the other services (and determine which data to return by what the user agent requests) but, knowing that IIS wasn't built for persistent connections, I need to know if there's a way that I can accept (and possibly even handshake) the Web Sockets connection and then pass the connection off to another service running on the server.
I do have a workaround in mind if this isn't possible that basically involves using ASP.NET to check for the Web Sockets connection upgrade headers, and responding with a HTTP/1.1 302 Found that points to a different host that has my Web Sockets service configured to directly listen to the appopriate endpoint(s).
If I completely understand your goal, I believe you can use the IIS7/7.5 Application Request Routing module to accomplish this.
Here's a quick reference: http://learn.iis.net/page.aspx/489/using-the-application-request-routing-module/
Rather than 302 responses you could use ISAPI_rewrite to direct to an appropriate endpoint (and manipulate the HTTP header to get it there)
http://www.isapirewrite.com/docs/
Otherwise no, IIS cannot natively pass off an HTTP connection. The current MSFT method is to use a 302 or something else that is intercepting the raw socket and performing header manipulation prior to sending to IIS (or whatever other application)
It strikes me that this would be a better question to ask Microsoft than to ask us. Web Sockets is new technology, and rather than looking for a hack, you might want to ask Microsoft how they plan to support it. IIS is their software. Poke around on http://iis.net (maybe in http://forums.iis.net) and see what you learn.
The way to do this is to use a unique Session ID that is associated with the Http Session. From the description, it seems like you might want to scope this to a single HttpApplication instance, but this is not necessary (you may also persist a session across many application instances). Anyway, this session ID needs to be attached somehow to each Http Request (either with a cookie, querystring, static variable with the HttpApplication instance, form data). Then you persist the identifying information about the Http session somewhere with the ID.
This identifying information may vary depending on your needs but could entail the entire http request or just some stripped down representation that serves your particular purpose.
Using this SessionID somewhere in the Http request allows you to restore whatever information you need to call and interact with the appropriate services. The instances of the services may also need to be scoped to the session as well.
Basically, what I am suggesting is that you NOT directly pass the Http connection to an external process, but instead pass the necessary data to the external process, and allow create a mechanism for sending callback data. I think looking into the mediator pattern may be helpful for you in understanding what I mean here. http://en.wikipedia.org/wiki/Mediator_pattern . I hope this helps.
I have a web service that executes a task that may take hours to finish (asynchronously)
I would like to share the status of that task by all the clients that connects to the server (I'm using a web application for this)
For example, the first client that calls the page http://localhost/process.aspx
will instantiate the web service and it will call a method to start executing the task. A percentage number will be displayed showing the status of completion. I can do this by polling the web service using AJAX.
If there is another client that tries to opens that page, it should get the same percentage information so no new instances of the web service are created.
How is the best way of doing this?
I thought about different solutions but sooner or later I find new problems.
These are some of the possible alternatives:
Create an static object of the Web service.
Create the object in the global.asax file.
Do you guys have any other ideas? I'm not too familiar designing web sites and this is driving me crazy. I would appreciate if you guys could provide some code snippets.
Thanks
The issue is ensuring that the information pertaining to the single instance of a process is stored in exactly one place.
Your initial thinking can be applied, for instance, by using the Application object, but that will break down in a clustered IIS scenario.
I am not posative that a database is the absolute best solution, but I believe it would give you what you want.
If 100 clients try to start the process at the same time, only one can succeed, right? The databases locking facility will help you make that happen.
There's a method (I'm assuming WCF for the web service) that allows you to have exactly one instance of the service run... link
I think this is what you are trying to accomplish.
Assuming I have understood your requirements correctly. Your webservice should not be creating the instance of the “worker” object.
Your webservice request should log to either a database (as the other poster noted) or a messagequeue of somesort. At this point your “worker” processer (probably some type of service) should take over the job as it requires.
Basically you want to break up your application into something like this
| Webservice | ---------- | Datastore |-----------| Worker |
Any further requests regarding the batch should be managed by the webservice querying the datastore.
Remember webservices are NOT DESIGNED TO DO WORK.