how to control if web service is unavailable? - c#

I have a webservice that gets a list from client and inserts it to database. Client has a windows service that is sending a list per 10 seconds. But there is a problem. What if it cannot reach to webservice(server). I should not lost any of the data. I decided to save data to a txt or binary if server is not reachable, and then upload them after the server starts to run. However, how can I decide whether the webservice is unavaliable. If I store the data to a file in a catch block, it will store when ever it gets an error, not only webservice unavaliable error. Any advice?

You can make an http request on the service's endpoint url and check if everything is ok :
var url = "http://....";
//OR
var url = service_object.Url;
var request = (HttpWebRequest)WebRequest.Create(url);
request.Timeout = 2000; //timeout 20 seconds
HttpWebResponse response = null;
try
{
response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode != HttpStatusCode.OK)
{
throw new ApplicationException(response.StatusDescription);
}
}
catch (ApplicationException ex)
{
//Do what you want here, create a file for example...
}

I'd introduce a queuing system (such as MSMQ or NServiceBus) so that the windows service only needs to place message(s) into the queue and something else (co-located with the web service) can dequeue messages and apply them (either directly or via the web service methods).
When everything is up and running, it shouldn't introduce much more overhead over your current (direct) web service call, and when the web service is down, everything just builds up in the queuing system.

Related

How to handle multiples accesses to azure service bus

my application is using Azure Service Bus to store messages. I have an Azure function called HttpTriggerEnqueuewhich allow me to enqueue messages. The problem is that this function can be invoked hundreds times in a little interval of time. When I call the HttpTriggerEnqueue once, twice, 10 times, or 50 times everything works correctly. But when I call it 200, 300 times (which is my use case) I get an error and not all messages are enqueued. From the functions portal I get the following error.
threshold exceeded [connections]
I tried both the .NET sdk and the HTTP request. Here is my code
HTTP REQUEST:
try
{
var ENQUEUE = "https://<MyNamespace>.servicebus.windows.net/<MyEntityPath>/messages";
var client = new HttpClient(new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip });
var request = new HttpRequestMessage(HttpMethod.Post, ENQUEUE);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var sasToken = SASTokenGenerator.GetSASToken(
"https://<MyNamespace>.servicebus.windows.net/<MyEntityPath>/",
"<MyKeyName>",
"<MyPrimaryKey>",
TimeSpan.FromDays(1)
);
client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", sasToken);
request.Content = new StringContent(message, Encoding.UTF8, "application/json");
request.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
request.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("deflate"));
var res = await client.SendAsync(request);
}
catch (Exception e) { }
And the code using the SDK:
var qClient = QueueClient.CreateFromConnectionString(MyConnectionString, MyQueueName);
var bMessage = new BrokeredMessage(message);
qClient.Send(bMessage);
qClient.Close();
I have the standard tier pricing on Azure.
If I call the function 300 (for example) times in a little interval of time I get the error. How can I solve?
The actual issue here isn't with the Service Bus binding (although you should follow the advice that #Mikhail gave for that), it's a well known issue with HttpClient. You shouldn't be re-creating the HttpClient on every function invocation. Store it in a static field so that it can be reused. Read this blog post for a great breakdown on the actual issue. The main point being that unless you refactor this to use a single instance of HttpClient you're going to continue to run into port exhaustion.
From the MSDN Docs:
HttpClient is intended to be instantiated once and re-used throughout the life of an application. Especially in server applications, creating a new HttpClient instance for every request will exhaust the number of sockets available under heavy loads. This will result in SocketException errors.
You should use Service Bus output binding to send messages to Service Bus from Azure Function. It will handle connection management for you, so you shouldn't be getting such errors.

Transactional messages without receiver look - session peeking

I have a distributed service that takes anywhere from 10 sec to 10 min to process a message. The service starts on a user's (== browser) request which is received through an API. Due to various limitations, the result of the service has to be returned outside of the initial request (timeouts, dropped client connections ...) Therefore I return a SessionId to the requesting user which can be used to retrieve the result until it expires.
Now it can happen that a user makes multiple consecutive requests for the result while the session is still locked. For example the following code gets hit with the same SessionId within 60 seconds:
var session = await responseQueue.AcceptMessageSessionAsync(sessionId);
var response = await session.ReceiveAsync(TimeSpan.FromSeconds(60));
if (response == null)
{
session.Abort();
return null;
}
await response.AbandonAsync();
What I need is a setup without locking and the ability to read a message multiple times until it expires plus the ability to wait for yet non-existent messages.
Which ServiceBus solution fits that bill?
UPDATE
Here's a dirty solution, still looking for a better way:
MessageSession session = null;
try
{
session = await responseQueue.AcceptMessageSessionAsync(sessionId);
}
catch
{
// ... and client has to try again until the 60 sec lock from other requests is released
}
var response = await session.ReceiveAsync(TimeSpan.FromSeconds(60));
// ...

HttpWebRequest possibly slowing website

Using Visual studio 2012, C#.net 4.5 , SQL Server 2008, Feefo, Nopcommerce
Hey guys I have Recently implemented a new review service into a current site we have.
When the change went live the first day all worked fine.
Since then though the sending of sales to Feefo hasnt been working, There are no logs either of anything going wrong.
In the OrderProcessingService.cs in Nop Commerce's Service, i call a HttpWebrequest when an order has been confirmed as completed. Here is the code.
var email = HttpUtility.UrlEncode(order.Customer.Email.ToString());
var name = HttpUtility.UrlEncode(order.Customer.GetFullName().ToString());
var description = HttpUtility.UrlEncode(productVariant.ProductVariant.Product.MetaDescription != null ? productVariant.ProductVariant.Product.MetaDescription.ToString() : "product");
var orderRef = HttpUtility.UrlEncode(order.Id.ToString());
var productLink = HttpUtility.UrlEncode(string.Format("myurl/p/{0}/{1}", productVariant.ProductVariant.ProductId, productVariant.ProductVariant.Name.Replace(" ", "-")));
string itemRef = "";
try
{
itemRef = HttpUtility.UrlEncode(productVariant.ProductVariant.ProductId.ToString());
}
catch
{
itemRef = "0";
}
var url = string.Format("feefo Url",
login, password,email,name,description,orderRef,productLink,itemRef);
var request = (HttpWebRequest)WebRequest.Create(url);
request.KeepAlive = false;
request.Timeout = 5000;
request.Proxy = null;
using (var response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusDescription == "OK")
{
var stream = response.GetResponseStream();
if(stream != null)
{
using (var reader = new StreamReader(stream))
{
var content = reader.ReadToEnd();
}
}
}
}
So as you can see its a simple webrequest that is processed on an order, and all product variants are sent to feefo.
Now:
this hasnt been happening all week since the 15th (day of the
implementation)
the site has been grinding to a halt recently.
The stream and reader in the the var content is there for debugging.
Im wondering does the code redflag anything to you that could relate to the process of website?
Also note i have run some SQL statements to see if there is any deadlocks or large escalations, so far seems fine, Logs have also been fine just the usual logging of Bots.
Any help would be much appreciated!
EDIT: also note that this code is in a method that is called and wrapped in A try catch
UPDATE: well forget about the "not sending", thats because i was just told my code was rolled back last week
A call to another web site while processing the order can degrade performance, as you are calling to a site that you do not control. You don't know how much time it is going to take. Furthermore, the GetResponse method can throw an exception, if you don't log anything in your outer try/catch block then you won't be able to know what's happening.
The best way to perform such a task is to implement something like the "Send Emails" scheduled task, and send data when you can afford to wait for the remote service. It is easy if you try. It is more resilient and easier to maintain if you upgrade the nopCommerce code base.
This is how I do similar things:
Avoid modifying the OrderProcessingService: Create a custom service or plugin that consumes the OrderPlacedEvent or the OrderPaidEvent (just implement the IConsumer<OrderPaidEvent> or IConsumer<OrderPlacedEvent> interface).
Do not call to a third party service directly while processing the request if you don't need the response at that moment. It will only delay your process. At the service created in step 1, store data and send it to Feefo later. You can store data to database or use an static collection if you don't mind losing pending data when restarting the site (that could be ok for statistical data for instance).
Best way to implement point #2 is to add a new scheduled task implementing ITask (remember to add a record to the ScheduleTask table). Just recover the stored data do your processing.
Add some logging. It is easy, just get an ILogger instance and call Insert.
As far as I can see, you are making a blocking synchronous call to other websites, which will definitely slow down your site in between the request-response process. What Marco has suggested is valid, try to do it in an ITask. Or you can use an asynchronous web request to potentially remove the block, if you need things done immediately instead of scheduled. :)

Speeding up http web request in WCF invoked method

Hi I am writing a WCF service not hosted on IIS. It runs on my server as console application.
I have a static method that is invoked by the mentioned service.
In this method I have async web request that sends sms.
Sometimes it happens that sms is never recieved. After some debuging I found out that when I remove async call the web request sometimes throws an exception with message: 'The operation has timed out'. This happens when i try to send many smss in short period of time.
But when i type the address of the web request in browser everything works fine. (the times i press refresh, no matter how fast, that number of times i receive sms) how can this be achived with what i've got.
So far i have
public static bool DoTheRequest(string number, string message)
{
try
{
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(string.Format("http://SomeURL?With={0}&something={1}", number, message));
myReq.BeginGetResponse(FinishWebRequest, myReq);
}
catch (Exception ex)
{
throw ex;
}
return true;
}
static void FinishWebRequest(IAsyncResult result)
{
HttpWebResponse response = (result.AsyncState as HttpWebRequest).EndGetResponse(result) as HttpWebResponse;
}
EDIT:
And the service definition:
[OperationContract]
void TestSms(string number);
and implementation:
public void TestSms(string number)
{
Utilities.DoTheRequest(number, "THIS IS A TEST");
}
Please help
Depending on how many times you are calling the send-sms function in a short period of time, I surmise that it's doing it a lot faster than you can refresh in your browser - and you're managing to flood whatever service it is you are using with your SMS calls.
In this scenario, I would suggest that your web-service method actually puts the SMS in to a queue, and some kind of a background worker thread that is designed not to throttle the API that actually sends the SMS, has the job of batching up these SMSs and sending them.
Better yet, to facilitate the issue that machines and software are not perfect, and lightning does indeed strike, I would suggest that you push SMSs in to some kind of back-end data store and leave it at that. A background worker job/thread then has the job of finding all SMSs that are unsent and trying to send them (but sending no more than "x per minute"), each one being marked as "Sent" upon completion.
This has the added advantage that you can throw as many SMSs as you want at your backing data storage, if the machine dies it can pick up where it left off, and if you get some failures, they can be retried.

C#: How to programmatically check a web service is up and running?

I need to create an C# application that will monitor whether a set of web services are up and running. User will select a service name from a dropdown. The program need to test with the corresponding service URL and show whether the service is running. What is the best way to do it? One way I am thinking of is to test whether we are able to download the wsdl. IS there a better way?
Note: The purpose of this application is that the user need to know only the service name. He need not remember/store the corresponding URL of the service.
I need a website version and a desktop application version of this C# application.
Note: Existing services are using WCF. But in future a non-WCF service may get added.
Note: My program will not be aware of (or not interested in ) operations in the service. So I cannot call a service operation.
REFERENCE
How to check if a web service is up and running without using ping?
C program-How do I check if a web service is running
this would not guarantee functionality, but at least you could check connectivity to a URL:
var url = "http://url.to.che.ck/serviceEndpoint.svc";
try
{
var myRequest = (HttpWebRequest)WebRequest.Create(url);
var response = (HttpWebResponse)myRequest.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
// it's at least in some way responsive
// but may be internally broken
// as you could find out if you called one of the methods for real
Debug.Write(string.Format("{0} Available", url));
}
else
{
// well, at least it returned...
Debug.Write(string.Format("{0} Returned, but with status: {1}",
url, response.StatusDescription));
}
}
catch (Exception ex)
{
// not available at all, for some reason
Debug.Write(string.Format("{0} unavailable: {1}", url, ex.Message));
}
This approach works for me.
I used Socket to check if the process can connect.
HttpWebRequest works if you try to check the connection 1-3 times but if you have a process which will run 24hours and from time to time needs to check the webserver availability that will not work anymore because will throw TimeOut Exception.
Socket socket
= new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
var result = socket.BeginConnect("xxx.com", 80, null, null);
// test the connection for 3 seconds
bool success = result.AsyncWaitHandle.WaitOne(3000,false);
var resturnVal = socket.Connected;
if (socket.Connected)
socket.Disconnect(true);
socket.Dispose();
return resturnVal;

Categories

Resources