I'm not an infrastructure guy so this maybe obvious to other people more familiar to TMG!
The problem
My problem was that SQL Azure connections were being forcibly closed after about 30 seconds. This was when connecting to a SQL Azure instance hosted in the cloud from a workstation behind TMG 2010. Although I imagine this would probably have happened with a standard SQL instance as well.
For example:
1. Run a query from SSMS which will run successfully
2. Wait 30+ seconds
3. Run the query again and it will fail with the following error
4. Run the query again and it will work correctly.
I'm assuming that the error in step 3 occurred because SSMS doesn't realise the existing connection has been closed and when we get to step 4, SSMS opens a new connection.
1. Run a query from SSMS which will run successfully
2. Wait 30+ seconds
3. Run the query again and it will fail with the following error
A transport-level error has occurred when sending the request to the server. (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.
4. Run the query again and it will work correctly.
I'm assuming that the error in step 3 occurred because SSMS doesn't realise the existing connection has been closed and when we get to step 4, SSMS opens a new connection.
The TMG logs showed that the SQL connections were being closed with the following info:
Closed Connection Log type: Firewall service Status: Unspecified errorRule: Internal Internet Access Source: Internal (xx.xx.xx.xx) Destination: External (xx.xx.xx.xx:1433) Protocol: Microsoft SQL (TCP) The result code is: 0x80004005
A few failed attempts
I read a few blog posts about TCP Chimney settings and flood protection configuration but neither of these options helped me.
The actual solution
I read a few blog posts about TCP Chimney settings and flood protection configuration but neither of these options helped me.
The actual solution
Eventually Microsoft support solved the problem.
The solution was to tell TMG to forward keep alive packets. It appears that TMG doesn't forward these on by default and so while my workstation was sending a keep-alives to TMG, TMG never forwarded them on to SQL Azure. This meant SQL was closing the connection while Management Studio thought is was still open.
The solution was to tell TMG to forward keep alive packets. It appears that TMG doesn't forward these on by default and so while my workstation was sending a keep-alives to TMG, TMG never forwarded them on to SQL Azure. This meant SQL was closing the connection while Management Studio thought is was still open.
To forward the keep-alives I needed to run a vb script which I've included below. Please don't blame me if anything goes wrong, you use it at your own risk. It's worth noting that there maybe a way to do this in the UI, I just don't know how.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' ' Copyright (c) Microsoft Corporation. All rights reserved. ' THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE ' RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE ' USER. USE AND REDISTRIBUTION OF THIS CODE, WITH OR WITHOUT MODIFICATION, IS ' HEREBY PERMITTED. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' This script adds a KeepAlive value to a given protocol definition. ' The value is in seconds. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Sub AddKA2Protocol() ' Create the root object. Dim root ' The FPCLib.FPC root object Set root = CreateObject("FPC.Root") 'Declare the other objects needed. Dim array ' An FPCArray object Dim RuleElements ' an FPCRuleElements objects. Dim ProtocolDefinitions ' an FPCProtocolDefinitions collection. Dim ProtocolDefinition ' an FPCProtocolDefinition object. Dim VendorSets ' An FPCVendorParametersSets collection Dim VendorSet ' An FPCVendorParametersSet object ' Get references to the array object ' and the protocols collection. Set array = root.GetContainingArray On Error Resume Next Set RuleElements = array.RuleElements CheckError Set ProtocolDefinitions = RuleElements.ProtocolDefinitions CheckError Wscript.Echo "Number of protocols- " & ProtocolDefinitions.Count Set ProtocolDefinition = ProtocolDefinitions.Item("Microsoft SQL (TCP)") Set VendorSets = ProtocolDefinition.VendorParametersSets Set VendorSet = VendorSets.Item( "{80ad2d9c-725e-4fcd-a1d4-32c8042c774f}" ) If Err.Number <> 0 Then Err.Clear ' Add the item Set VendorSet = VendorSets.Add( "{80ad2d9c-725e-4fcd-a1d4-32c8042c774f}") CheckError WScript.Echo "New VendorSet added... " & VendorSet.Name Else WScript.Echo "Existing VendorSet found..." End If VendorSet.Value("KeepAliveTimeout") = 30 ' value in seconds. VendorSets.Save false, true WScript.Echo "Done..." End Sub Sub CheckError() If Err.Number <> 0 Then WScript.Echo "An error occurred: 0x" & Hex(Err.Number) & " " & Err.Description Err.Clear End If End Sub AddKA2ProtocolIf it does go all wrong you can try this script:
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' ' Copyright (c) Microsoft Corporation. All rights reserved. ' THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE ' RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE ' USER. USE AND REDISTRIBUTION OF THIS CODE, WITH OR WITHOUT MODIFICATION, IS ' HEREBY PERMITTED. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' This script Remove a KeepAlive value from a given protocol definition. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Sub RemoveKAFromProtocol() ' Create the root object. Dim root ' The FPCLib.FPC root object Set root = CreateObject("FPC.Root") 'Declare the other objects needed. Dim array ' An FPCArray object Dim RuleElements ' an FPCRuleElements objects. Dim ProtocolDefinitions ' an FPCProtocolDefinitions collection. Dim ProtocolDefinition ' an FPCProtocolDefinition object. Dim VendorSets ' An FPCVendorParametersSets collection Dim VendorSet ' An FPCVendorParametersSet object ' Get references to the array object ' and the protocols collection. Set array = root.GetContainingArray On Error Resume Next Set RuleElements = array.RuleElements CheckError Set ProtocolDefinitions = RuleElements.ProtocolDefinitions CheckError Wscript.Echo "Number of protocols- " & ProtocolDefinitions.Count Set ProtocolDefinition = ProtocolDefinitions.Item("Microsoft SQL (TCP)") Set VendorSets = ProtocolDefinition.VendorParametersSets Set VendorSet = VendorSets.Item( "{80ad2d9c-725e-4fcd-a1d4-32c8042c774f}" ) If Err.Number <> 0 Then CheckError WScript.Echo "VendorSet does not exit." Else WScript.Echo "Existing VendorSet found..." VendorSets.Remove( "{80ad2d9c-725e-4fcd-a1d4-32c8042c774f}" ) If Err.Number <> 0 Then CheckError WScript.Echo "Cannot remove VendorSet" Else WScript.Echo "VendorSet removed..." End If End If VendorSets.Save false, true WScript.Echo "Done..." End Sub Sub CheckError() If Err.Number <> 0 Then WScript.Echo "An error occurred: 0x" & Hex(Err.Number) & " " & Err.Description Err.Clear End If End Sub RemoveKAFromProtocol
Hi Dan,
ReplyDeletethanks for the article.
Please be Aware that there's an error in the "remove" script...
you Need to remove the line:
VendorSets.Remove( "{VendorSetID}" )
and replace it with
VendorSets.Remove( "{80ad2d9c-725e-4fcd-a1d4-32c8042c774f}" )
otherwise the script won't be able to delete the VPS.
cheers,
Philipp Sand
Thanks Philipp, I've updated the post.
ReplyDelete