0

I am developing Windows Service in VS2017. While debugging service, first 2 3 calls are working after that getting below errors

System.Net.WebException: 'The remote server returned an error: (503) Server Unavailable.'

The remote server returned an error: (429)

I have tried many things increasing timeout, adding keepAlive etc.. nothing workout. In few articles I found Application pool in IIS that could help me.

But I am not sure if any role of my machine's application pool in windows service when service consuming third party rest API and getting data.

This is my code

private void timer1_Tick(object sender, ElapsedEventArgs e)
 {
    string jsonString = "";
    string jsonstring2 = "";
    string prodfetchurl = HOST;
    string prodfetchurl1 = "testURL";

    var req =
        WebRequest.Create(prodfetchurl) as HttpWebRequest;

    req.Method = "GET";
    req.KeepAlive = true;
    InitializeRequest(req);
    //req.Proxy = null;
    req.Accept = MIME_TYPE;
    System.Threading.Thread.Sleep(200000);
    var response = (HttpWebResponse)req.GetResponse();
    WriteToFile("First service called...");
    if (response.StatusCode == HttpStatusCode.OK)
    {
        Stream responseStream = response.GetResponseStream();
        StreamReader responseReader = new StreamReader(responseStream);
        jsonString = responseReader.ReadToEnd();
    }

    var deserialsseobj = JsonConvert.DeserializeObject<ProductList>(jsonString).Products.Where(i => i.Failed > 0).ToList();
    foreach (var a in deserialsseobj)
    {
        var pid = a.ID;
        string url = FailedDevicesUrl + pid.Value + "/failed";
        var req2 = WebRequest.Create(url) as HttpWebRequest;
        req2.Method = "GET";
        req2.KeepAlive = true;
        InitializeRequest(req2);
        //req2.Proxy = null;
        req2.Timeout = 300000;
        req2.Accept = MIME_TYPE;     
        System.Threading.Thread.Sleep(200000);

        var response1 = (HttpWebResponse)req2.GetResponse();
        Stream responsestream2 = response1.GetResponseStream();
        WriteToFile("Second service called...");
        if (response1.StatusCode == HttpStatusCode.OK)
        {
            StreamReader responsereader1 = new StreamReader(responsestream2);
            jsonstring2 = responsereader1.ReadToEnd();
        }
        var output = JsonConvert.DeserializeObject<List<FailedDeviceList>>(jsonstring2);  // Will get List of the Failed devices
        AutoReprocess(pid.Value, output);
        List<int> deviceids = new List<int>();
        Reprocessdata reproc = new Reprocessdata();
        Reprocessdata.DeviceId rprod = new Reprocessdata.DeviceId();

        reproc.ForceFlag = true;
        reproc.ProductID = pid.Value;
        foreach (var dd in output)
        {
            rprod.ID = dd.DeviceId;
            reproc.DeviceIds.Add(rprod);
        }
        // Reprocess the Product in Devices
        var req3 = WebRequest.Create(ReprocessUrl) as HttpWebRequest;
        req3.Method = "POST";
        InitializeRequest(req3);
        req3.Accept = MIME_TYPE;
        req3.ContentType = "application/json";
        using (StreamWriter writer = new StreamWriter(req3.GetRequestStream()))
        {
            string json = new JavaScriptSerializer().Serialize(reproc);

            writer.Write(json);
            writer.Close();
        }
        var response5 = (HttpWebResponse)req3.GetResponse();
        WriteToFile("Third service called...");
        if (response5.StatusCode == HttpStatusCode.OK)
        {
            string result;
            using (StreamReader rdr = new StreamReader(response5.GetResponseStream()))
            {
                result = rdr.ReadToEnd();
            }
        }
    }
    response.Close();
 }

Methods used in above code

public void AutoReprocess(int pid, List<FailedDeviceList> output)
{
    List<int> deviceids = new List<int>();
    Reprocessdata reproc = new Reprocessdata();
    Reprocessdata.DeviceId rprod = new Reprocessdata.DeviceId();
    reproc.ForceFlag = true;
    reproc.ProductID = pid;
    foreach (var dd in output)
    {
        rprod.ID = dd.DeviceId;
        reproc.DeviceIds.Add(rprod);
    }
    var req3 = WebRequest.Create(ReprocessUrl) as HttpWebRequest;
    req3.Method = "POST";
    req3.KeepAlive = true;
    InitializeRequest(req3);
    req3.Accept = MIME_TYPE;
    req3.Timeout = 300000;
    req3.ContentType = "application/json";
    using (StreamWriter writer = new StreamWriter(req3.GetRequestStream()))
    {
        string json = new JavaScriptSerializer().Serialize(reproc);

        writer.Write(json);
        writer.Close();
    }
    System.Threading.Thread.Sleep(100000);
    var response5 = (HttpWebResponse)req3.GetResponse();
    WriteToFile("Third service called...");
    if (response5.StatusCode == HttpStatusCode.OK)
    {
        string result;
        using (StreamReader rdr = new StreamReader(response5.GetResponseStream()))
        {
            result = rdr.ReadToEnd();
        }
    }
}

public void InitializeRequest(HttpWebRequest request)
{
    request.Headers.Add("aw-tenant-code", API_TENANT_CODE);
    request.Credentials = new NetworkCredential(USER_NAME, PASSWORD);
    request.KeepAlive = true;
    //request.AddRange(1024);
    //request.Proxy = null; 
}

Please help me regarding this.

Community
  • 1
  • 1
R15
  • 13,982
  • 14
  • 97
  • 173
  • 1
    What 3rd party service are you calling? Is it a public service on the internet? Some of these may have a flood-protection. That is you are only allowed so many calls in a specific amount of time. Could that be an issue here? I got the idea from looking up **HTTP status code [429](https://httpstatuses.com/429): _"Too many Requests"_** – Fildor Apr 01 '20 at 11:03
  • @Fildor - I am using VMvare Airwatch third party rest apis. https://resources.workspaceone.com/view/zv5cgwjrcv972rd6fmml/en\ – R15 Apr 01 '20 at 11:07
  • 1
    ^^ So, to solve your problem, you should investigate at the 3rd party what the actual allowed frequency is and throttle your calls to make sure you stay below that threshold. – Fildor Apr 01 '20 at 11:08
  • @Fildor - I talk then, I said within 1 mins I am calling 1 service. They said their few clients making laks of calls for them no issue. – R15 Apr 01 '20 at 11:11
  • 1
    How often does `timer1_Tick` fire? **Are you sure?** – mjwills Apr 01 '20 at 11:14
  • 1
    If you tried throttling by adding `Sleep`s then that's not the way to go. The timer will keep on triggering and kick off new Requests. You should deactivate the timer until one round of processing is done, then reactivate it to trigger the next. – Fildor Apr 01 '20 at 11:19
  • @mjwills - That is being called every 10 mins. Thread.Sleep I am using to wait control to go next line as I was getting errors so I thought to give some time before hitting next service. – R15 Apr 01 '20 at 11:19
  • 1
    The problem is, once you ran into a rate limit, you need to stay silent for x amount of time. If you do not wait long enough, the penalty most probably will be extended. So instead of sleeping, you should cancel the run and make sure the next is only triggered after you are allowed to make requests again. – Fildor Apr 01 '20 at 11:22
  • @Fildor -Sleep is not mean for throttling from my side. How to add/implement throttling programmatically. After getting data from first service `foreach` loop should be repeating nearly 20 times but that is not getting competed. I am using `timer1.AutoReset = false` on timer. – R15 Apr 01 '20 at 11:24
  • 1
    If set to false (i.e. run once), why use a timer at all? Plus earlier you said `That is being called every 10 mins.` Now I am confused. – mjwills Apr 01 '20 at 11:25
  • 1
    `How to add/implement throttling programmatically.` Every time you get a 429 do a sleep **then** (and a long sleep). So if your vendor, for example, does rate limiting on a per minute basis - sleep for 5 minutes. Additionally, do some maths. Let's say the vendor says you can do 10 requests a minute. In that case, sleep 7 seconds before every request - that way you can be *quite sure* you'll never hit the rate limit (since 70 seconds > 60 seconds). – mjwills Apr 01 '20 at 11:26
  • @mjwills - After getting 503 on service x I if I try same on postman I am getting result w/o any problem. That Is what they said to me Vmvare people – R15 Apr 01 '20 at 11:29
  • 1
    Then you are probably being rate limited, and part of the rate limiting may be based on user agent (which is why Postman worked) etc etc. – mjwills Apr 01 '20 at 11:29
  • 1
    That's really hard to tell without seeing the whole (relevant) codebase and probably a little bit too broad for an SO answer. To me, it seems you are exceeding rate limits already with those 20 requests. So first of all, you should investigate what the rate limits actually are. Then rethink your algorithm. Would it make more sense to have a queue of requests, that can be throttled more conveniently? Many design decisions that may depend on one another. – Fildor Apr 01 '20 at 11:30
  • 1
    Have you read https://stackoverflow.com/questions/25028580/dealing-with-throttling-rate-limits-429-error-when-using-async-await ? – mjwills Apr 01 '20 at 11:30
  • @Fildor - VMware people said, if you are able to make requests from postman means your code is not working. Please check this https://stackoverflow.com/questions/60520411/https-calls-are-not-connecting-to-server – R15 Apr 01 '20 at 11:33
  • 1
    Your previous question (duplicate link above) and your question here are fundamentally the same question (i.e. why am I getting 429s?). The fact you are unhappy with the answers (although, to be fair, they are great answers) does not warrant asking the same question a second time. – mjwills Apr 01 '20 at 11:38
  • 1
    VMware people are correct. The Server and Service are working as expected. Your code _is_ running into a rate limit. So either lift off the rate limit from the API, if you have the rights to do so, or (which is probably better) change your code, so the rate limit does not get exceeded. The answers in the other question tell you the same thing. It won't change no matter how many questions you ask. It will always come back to this. – Fildor Apr 01 '20 at 11:43

0 Answers0