Author Posts

January 4, 2018 at 3:35 pm

Hey guys!

Having a little bit of trouble with this segment of code.

I've got a script that I'm using to do the following:

    remove an azure webapp from the traffic manager
    check for the number of requests for that webapp every 60 seconds until requests drop below 300
    reboot the web app
    get the URL response of the web app every 60 seconds while it returns a status code not equal to 200
    re-add the web app to the TM after the URL Response status code is 200 3 time in a row.

I'm having trouble with the 3rd step, where the GetResponse times out and hangs even after the URL is back up and responding.

I've marked in the code 2 spots where I've tried a couple things I found in searching for a solution but so far nothing has worked.


$url = "http://webapp.azurewebsites.net"

Function GetURL {
    
    $webRequest = [net.WebRequest]::Create($url)
    $webRequest.Timeout = [System.Threading.Timeout]::Infinite #Read this on a blog but it didn't work
    $Response = $webRequest.GetResponse()
    $statusCode = [int]$Response.StatusCode
    $Response.close #Read this on a blog but it didn't work either
       Return $statusCode
} #Function to get URL Status

 ###Check the site every 60 seconds until it returns a status code of 200###
    While ($statusCode -ne 200) {
        Write-verbose "The webpage $url has not come back up. 
The current Status Code is $statusCode. Waiting 60 seconds and trying again"
        #sleep -Seconds 60
        . GetURL
    }   


Function VerifyUp {

    Param ($statusCode)
  ###Check the site every 60 seconds until it returns a status code of 200###
    While ($statusCode -ne 200) {
        Write-Host "The webpage $url has not come back up. 
The current Status Code is $statusCode. Waiting 60 seconds and trying again"
        #sleep -Seconds 60
        . GetURL
    }   

    While ($statusCode -eq 200) {
        $i = 1
        sleep -Seconds 60
        . GetURL
        $i++
        }
    for ($statusCode -ne 200) {
            VerifyUp
        }
    for ($i -eq 3) {
        Write-host "The Webpage $url has been up for 3 minutes. Readding $app to TM."
        break
        }
    }


###### Start Script ##################
ARMLogin 
    
TMRemove

. Requests 

 Reboot -RequestCount $RequestCount

 . GetURL

 VerifyUP -statusCode $statusCode

 TMAdd
      

January 4, 2018 at 3:46 pm

Unfortunately, this is more a lower-level .NET thing than PowerShell per se. The only workaround I can think of is to try a ping or something instead, since ping is designed more with the idea of failure in mind. Once you get a ping, try the HTTP request. That HttpRequest gets all tied up with DNS caching and all kinds of crazy in this kind of situation.

I'm not a huge fan of the logic approach you've taken – having GetURL recursively call itself over and over is not a stellar idea, as you're loading up the stack heap fairly unnecessarily. If you're going to do this in a loop like this, it'd make more sense to make it self-contained and synchronous:

Do {
# create the request
# try the request
# set a pass/fail flag or whatever
# delete the request
} Until # flag passes

What you're doing now is holding a crapload of Request objects in memory until it finally works, at which point the CLR has to unwind all the recursive calls and garbage-collect everything. It wouldn't shock me if you found that was your problem.

January 5, 2018 at 11:02 pm

Thanks for the help Don.

unfortunately ping isn't an option here because azure blocks ICMP.

I believe I've resolved this by using invoke-webrequest instead but also found that at least half the problem is our dev environment. still times out 90% of the time but when I run it against UAT and Prod it works everytime.

I also used your logic and came up with this which worked well in our UAT environment.
Also completely cut out the GETURL Function and cleaned up the VerifyUp a bit (I think at least).


    DO {
        $statuscode = (Invoke-WebRequest -Uri $url -Method Get).statuscode

        Try{
            $StatusChk = $statuscode -ne 200
            }
        Catch {
            Write-Host "The webpage $url has not come back up. The current Status Code is $statusCode. Waiting 60 seconds and trying again" #Remove before use in PROD
            $statusCode = $null
            sleep -Seconds 60
            if ($i -gt 0) {$i--}
            else {}

        }
        Sleep -Seconds 60
        $i++ 
        Write-Host "$URL has been up for $i minute(s)" #Remove before use in PROD   
        
    } Until ($statusCode -eq 200 -and $i -eq 3)
    for ($i -eq 3) {
        Write-host "The Webpage $url has been up for 3 minutes. Readding $app to TM." #Remove before use in PROD
        break
        }

See any room for improvement?