Powershell New-WebServiceProxy causing ephemeral port exhaustion

This topic contains 4 replies, has 2 voices, and was last updated by Profile photo of T S T S 9 months ago.

  • Author
    Posts
  • #36200
    Profile photo of T S
    T S
    Participant

    I use powershell to update a service with content from a file (csv) using SOAP via new-webserviceproxy. Often the content can have thousands of rows and references different calls to the SOAP service. As such the NWSP is called from within a For Loop. This has not been a problem in the past but recently has started causing ephemeral port exhaustion and the update service slows to a crawl. Once the NWSP updates the service the TCP port stays open in 'Time_Wait' until it timesout.

    My questions:
    1. Is there a way/command to close the NWSP or TCP port at the end of each loop in order to protect the server from port exhaustion?
    2. OR- Is there a way I can initiate the NWSP outside the loop and somehow reference the proxy from within the loop?

  • #36206
    Profile photo of Don Jones
    Don Jones
    Keymaster

    You can certainly create your web proxy before entering the loop, and keep a reference to it in a variable. I mean, without seeing your code, it's a little tough to be specific, but...

    $connection = New-Connection
    foreach ($this in $those) {
    $connection.Stuff($this)
    }
    $connection.close()

    Kinda thing.

  • #36214
    Profile photo of T S
    T S
    Participant

    Here is a portion of the code:

    $wsdl_string= "http://$server/Service/AcquisitionService.svc?WSDL"
    $nwsp = New-WebServiceProxy -uri $wsdl_string
    
    
    # Loop through the rows
    For ($i=0; $i -lt $data.Length; $i++)
    {
    
    # Parse the row to get the data
    $parameter = $data[$i].Parameter
    $label = $data[$i].Label
    $location = $data[$i].Location
    $csvStr = $data[$i].Timestamp + "," + $data[$i].Value
    
    # Get the parameter ID
    $param_id = ($params | where { $_.DisplayId -eq $parameter }).Parameter
    
    # Define the dataset ID
    $dataset_id = "$param_id.$label" + "@" + $location
    
    
    $TS_ID = $result = $null
    #Read Dataset
    $nwsp.GetTSID($dataset_id, [ref]$TS_ID, [ref]$result)
    
    #Write new Data
    $nwsp.AppendTSFromBytes2($TS_ID, 1, $csvStr.ToCharArray(), "api")
    }
    
  • #36256
    Profile photo of Don Jones
    Don Jones
    Keymaster

    Gotcha.

    So, I've two thoughts here. First, the web proxy generated by the command doesn't have distinct connect/disconnect methods, because it treats the connection as more or less stateless. The proxy _shouldn't_ be leaving a keep-alive going, which means it _shouldn't_ be holding the port open.

    Second thought is that your Web server might not be exhibiting the correct behavior. Once it fires over its response, it shouldn't be holding the port open – it should drop it more or less immediately, as there's no longer a contextual reason to keep it open. This is pretty standard web server behavior, and a web service is nothing more than a web server.

    Given that this _appears_ to be a design problem on the part of the server, if you can't correct that, all you can probably do is implement some kind of counter. After x number of requests, your code just sleeps, allowing those ports to time out, before continuing. There's nothing I'm aware of in the underlying HTTP protocol to tell a server "I'm done, shut it down," because that's supposed to be the default behavior in HTTP1.1. If you need a port open, you're supposed to send keep-alive packets.

  • #36275
    Profile photo of T S
    T S
    Participant

    Doing some research I found an article from Microsoft cautiously recommending adding two dwords to the TCPIP parameters in the server registry to increase maximum user ports (default 5000) and to decrease time-wait period (default 240 sec).

    TS

You must be logged in to reply to this topic.