Son zamanlarda, aslında oldukça basit olan, ancak genellikle göz ardı edilen bir şey nedeniyle başarısız olan O365 göçlerinde bir artış görünüyor.
TCP Canlı Tutma Süresi ayarlanmamışsa, varsayılan değer 2 saat olan kullanılır. Ağ ekipmanı genellikle çok daha düşük bir şeye ayarlanır ve bu da oturumun sonlandırılmasına neden olurken, kaynak ve hedefin her ikisi de oturumun hala aktif olduğuna inanır. Ardından, geçici bir hata nedeniyle geçiş başarısız olur. Bu, bir yük dengeleyici kullanıldığında istemci bağlantısı üzerinde de olumsuz bir etkiye sahip olabilir.
Microsoft destek mühendislerinin oluşturduğu TCP Keep Alive Time Report blunuyor, ortamda ki keep alive time değerinin raporunu oluştururken, aynı zaman da regedit tarafında bulunan kaydın güncellemesini yapabiliyor. Senaryonun, özellikle büyük ortamlarda, son derece yararlı olduğu kanıtlanmıştır. TCP Keep Alive Times’ın tümünün kuruluş genelinde ayarlanmadığını fark ettik. Hatta bazılarının, eğer ayarlanmışlarsa uyumsuz değerleri bile vardı. Daha sonra gözden geçirmek ve eksikse anahtarı eklemek ve varsa değeri değiştirmek için komut dosyasının işlevselliğini ekledim. Bunun yararı, yerel AD sitesindeki tüm Exchange sunucularında aynı olmasıdır. Tutarlılık anahtardır, Exchange 2013 Karma sunucularında 30 dakikaya ayarlanmışsa, arka uç Posta Kutusu sunucularında da aynı şekilde ayarlanmalıdır.
Komut dosyası içinde bir site sınırını sabit kodladım, böylece belirli bir AD sitesinde yürütürseniz, başka bir AD sitesindeki Exchange sunucularını rapor etmez. Bilgi alabildiği sunucuların adlarını listeleyen bir CSV raporu oluşturur ve TCP KeepAliveTime kayıt defteri anahtarının var olup olmadığını ve varsa hangi değerin bulunduğunu size bildirir. Farklı bir Active Directory sitesindeki sunucuları sorgulamanız gerekirse, komut dosyasını Exchange Server’a kopyalayıp bu siteye yürütmeniz yeterlidir.
Kayıt Defteri anahtarlarını değiştirmek isteyip istemediğiniz sorusunu size sunduğunda komut dosyasının Varsayılan eylemi “HAYIR” dır. TCP Canlı Tutma Süresi’ni değiştirmeye devam etmesi için “Y” veya “Evet” yazmanız gerekir. Daha sonra TCP KeepAliveTime kayıt defteri anahtarının da kaç milisaniye içinde ayarlanmasını istediğinizi soracaktır. Varsayılan olarak 30 dakika olan 1,8 milyon milisaniyeye ayarladım. Varsayılanı kullanmaya karar verirseniz, enter tuşuna basmanız yeterlidir ve varsayılan değer AD sitesindeki tüm Exchange sunucularında ayarlanır. Kendi değerinizi kullanmaya karar verirseniz, nokta veya virgül kullanmayın ve sadece yuvarlak bir sayı koyun (örneğin, 15 dakika olan 900000). Tüm zamanlar milisaniye cinsinden olmalıdır.
TCP Canlı Kalma Süresini düşük olarak ayarlamanın sunucu CPU iş yükünü artıracağını unutmayın, bu nedenle yukarıda atıfta bulunduğum blog, ayarlanması gereken süre olarak 15 ila 30 dakika önerir.
TCP Canlı Tutma Zamanı değerlerini değiştirmeye karar verirseniz, sunucuları yeniden başlatana kadar değişikliklerin etkili olmayacağını unutmayın.
<# .NOTES Name: TCPKeepAliveTimeChecker.ps1 Author: Josh Jerdon Email: jojerd@microsoft.com Requires: PowerShell 3.0, Exchange Management Shell as well as administrator rights on the target Exchange server. Version History: 1.0 - 5/15/2017 1.01 - 6/28/2017 Fixed Foreach loop bug asking for KeepAliveTime Value for each server when changing multiple servers. 1.02 - 3/7/2018 Fixed PSSnapin load errors if script was executed more than once in a single PowerShell session. Also refined how script checks for PowerShell version. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. .SYNOPSIS Checks all of the Exchange Servers within a given AD site and generates a report of it's findings, namely if the TCP KeepAliveTime registry key exists and if so what the value is. It also provides the functionality to modify the TCP Keep Alive Settings of all Exchange servers in the local AD site. This is extremely useful in large Exchange organizations but should be used with care. #> #Checking Powershell Version to Ensure Script Works as Intended if ($PSVersionTable.PSVersion.Major -gt 3) { Write-Host "PowerShell meets minimum version requirements, continuing" -ForegroundColor Green Start-Sleep -Seconds 3 Clear-Host #Add Exchange Management Capabilities Into The Current PowerShell Session. $CheckSnapin = (Get-PSSnapin | Where {$_.Name -eq "Microsoft.Exchange.Management.PowerShell.E2010"} | Select Name) if ($CheckSnapin -like "*Exchange.Management.PowerShell*") { Write-Host "Exchange Snap-in already loaded, continuing...." -ForegroundColor Green } else { Write-Host "Loading Exchange Snap-in Please Wait..." Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction SilentlyContinue } #Search local AD Site for all Exchange Servers. $ADSite = [System.DirectoryServices.ActiveDirectory.ActiveDirectorySite]::GetComputerSite().Name Write-Host "Searching Active Directory Site $ADSite for Exchange Servers, Please Wait..." $Servers = Get-ExchangeServer | Where-Object {$_.Site -match $ADSite} #File Output parameters for report output $OutputFilePath = "." $OutPutReportName = "TCPKeepAliveTimeReport" + "-" + (Get-Date).ToString("MMddyyyyHHmmss") + ".csv" $OutPutFullReportPath = $OutputFilePath + "\" + $OutPutReportName if ($Servers.count -gt 0) { #Connect to Each server that it finds from above and open the KeepAliveTime registry key if it exists and record the value. foreach ($Server in $Servers) { $EXCHServer = $Server.name $OpenReg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $EXCHServer) $RegKeyPath = 'SYSTEM\CurrentControlSet\Services\Tcpip\Parameters' $RegKey = $OpenReg.OpenSubKey($RegKeyPath) $TCPKeepAlive = $RegKey.GetValue('KeepAliveTime') $Exists = if ($TCPKeepAlive) {$true} else {$false} #Dump the scripts findings into an object. $Report = [PSCustomObject]@{ "Server Name" = $EXCHServer; "Key Present" = $Exists; "TCP Keep Alive Time" = $TCPKeepAlive } #Write the output to a report file $Report | Export-Csv ($OutPutFullReportPath) -Append -NoTypeInformation } } else { Write-Host "Found 0 Exchange Servers, Exiting Script..." -ForegroundColor Red Write-Host " " Write-Host " " Write-Host "Press Any Key To Continue ..." $x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") Exit } #Asks if you'd like to change the TCP Keep Alive Times. Clear-Host $Message = "Do You Want To Create And Or Modify The TCP KeepAliveTime Registry Key?" $Yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "help"; $No = New-Object System.Management.Automation.Host.ChoiceDescription "&No", "help"; $choices = [System.Management.Automation.Host.ChoiceDescription[]]($Yes, $no); $answer = $host.UI.PromptForChoice($caption, $message, $choices, 1) switch ($answer) { 0 {Write-Host "Continuing Script As You Have Confirmed That You Want To Create And Or Modify The TCP KeepAliveTime Registry Key"; Start-Sleep -Seconds 5} 1 {Write-Host "Exiting Script..."; exit} } Clear-Host $TimeValue = Read-Host 'How Many Milliseconds Do You Want The TCP Keep Alive Time Set Too? (Default is 1,800,000ms (30 minutes)' $DefaultValue = "1800000" $KeyName = "KeepAliveTime" Clear-Host foreach ($Server in $Servers) { $EXCHServer = $Server.name $BaseKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $EXCHServer) $SubKey = $BaseKey.OpenSubkey("SYSTEM\CurrentControlSet\Services\Tcpip\Parameters", $true) if ($TimeValue) { $SubKey.SetValue($KeyName, $TimeValue, [Microsoft.Win32.RegistryValueKind]::DWORD) } Else { $SubKey.SetValue($KeyName, $DefaultValue, [Microsoft.Win32.RegistryValueKind]::DWORD) } } Clear-Host Write-Host 'Each Server That Had Its TCP Keep Alive Time Value Changed Will Require A Reboot For The Changes To Take Affect.' -ForegroundColor Green $x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") Exit } else { Write-Host "PowerShell Version does not meet minimum requirements of at least 3.0, please update to at least PowerShell 3.0 and try again." -ForegroundColor Red $x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") Exit } Exit