Ускоряем работу WSUS

  • Tutorial

Свежеустановленный сервер обновлений WSUS через несколько лет эксплуатации превращается в неповоротливое чудовище. Клиенты медленно обновляются и долго ищут обновления, журналы WindowsUpdate.log пестрят ошибками HTTP, а администратор впадает в депрессию.
Вот несколько советов, которые могут во многих случаях значительно ускорить сервер.

1. Настройка IIS
2. Очистка базы
3. Переиндексация
4. Настройка TempDB

Настройка Internet Information Server


В конфигурации «по-умолчанию» пул приложений «WsusPool» незаслуженно обделён памятью. Это является главной причиной HTTP-ошибок сервера в журналах клиентов.

Чтобы прибавить процессу память, запустите оснастку IIS и откройте Advanced settings:





Установите в качестве лимита 0.



Очистка базы


В консоли WSUS можно запустить «Server Cleanup Wizard». Главный секрет в том, что запускать его надо регулярно, не реже одного раза в месяц.


Одобрили свежую пачку обновлений — очистите сервер. Если этого не делать, мастер прекращает нормально работать. После запуска он висит несколько часов, после чего консоль падает с ошибкой.

Для начала можно попробовать запускать каждый пункт по отдельности, сверху вниз:



Если это не помогает, надо выполнить очистку напрямую в базе. Для этого необходимо подключиться к экземпляру SQL Server инструментом Management Studio. Management Studio стала отдельным продуктом. Его можно скачать по этой ссылке.

Если вы используете Windows Internal Database, необходимо поставить Management Studio на сервер с WSUS. Для подключения к экземпляру используется строка:

\\.\pipe\MICROSOFT##WID\tsql\query



Для очистки базы выполните 4 волшебные команды:

EXEC SUSDB.dbo.spDeclineExpiredUpdates;1

EXEC SUSDB.dbo.spDeclineSupersededUpdates;1

Для команды spCompressUpdate используется «обёртка»:

USE SUSDB
DECLARE @var1 INT, @curitem INT, @totaltodelete INT
DECLARE @msg nvarchar(200)
CREATE TABLE #results (Col1 INT) INSERT INTO #results(Col1)
EXEC spGetUpdatesToCompress
SET @totaltodelete = (SELECT COUNT(*) FROM #results)
SELECT @curitem=1
DECLARE WC Cursor FOR SELECT Col1 FROM #results
OPEN WC
FETCH NEXT FROM WC INTO @var1 WHILE (@@FETCH_STATUS > -1)
BEGIN SET @msg = cast(@curitem as varchar(5)) + '/' + cast(@totaltodelete as varchar(5)) + ': Compressing ' + CONVERT(varchar(10), @var1) + ' ' + cast(getdate() as varchar(30))
RAISERROR(@msg,0,1) WITH NOWAIT
EXEC spCompressUpdate @localUpdateID=@var1
SET @curitem = @curitem +1
FETCH NEXT FROM WC INTO @var1
END
CLOSE WC
DEALLOCATE WC
DROP TABLE #results

Такая же обертка для spDeleteUpdate:

USE SUSDB
DECLARE @var1 INT, @curitem INT, @totaltodelete INT
DECLARE @msg nvarchar(200)
CREATE TABLE #results (Col1 INT) INSERT INTO #results(Col1)
EXEC spGetObsoleteUpdatesToCleanup
SET @totaltodelete = (SELECT COUNT(*) FROM #results)
SELECT @curitem=1
DECLARE WC Cursor FOR SELECT Col1 FROM #results
OPEN WC
FETCH NEXT FROM WC INTO @var1 WHILE (@@FETCH_STATUS > -1)
BEGIN SET @msg = cast(@curitem as varchar(5)) + '/' + cast(@totaltodelete as varchar(5)) + ': Deleting ' + CONVERT(varchar(10), @var1) + ' ' + cast(getdate() as varchar(30))
RAISERROR(@msg,0,1) WITH NOWAIT
EXEC spDeleteUpdate @localUpdateID=@var1
SET @curitem = @curitem +1
FETCH NEXT FROM WC INTO @var1
END
CLOSE WC
DEALLOCATE WC
DROP TABLE #results

Во время работы «обёрток» клиенты прекращают получать обновления. Вы можете в любой момент прервать выполнение скрипта без потери прогресса. Для того, чтобы продолжить процесс, не забудьте удалить временную таблицу:

DROP TABLE #results

В мастере очистки 5 команд, мы вполнили 4 из них. Команду «Delete computers not contacting server» следует выполнить из мастера.

Переиндексация базы


Для переиндексации базы используйте следующий скрипт:

Скрипт переиндексации
/****************************************************************************** 
This sample T-SQL script performs basic maintenance tasks on SUSDB 
1. Identifies indexes that are fragmented and defragments them. For certain 
   tables, a fill-factor is set in order to improve insert performance. 
   Based on MSDN sample at http://msdn2.microsoft.com/en-us/library/ms188917.aspx 
   and tailored for SUSDB requirements 
2. Updates potentially out-of-date table statistics. 
******************************************************************************/ 
 
USE SUSDB; 
GO 
SET NOCOUNT ON; 
 
-- Rebuild or reorganize indexes based on their fragmentation levels 
DECLARE @work_to_do TABLE ( 
    objectid int 
    , indexid int 
    , pagedensity float 
    , fragmentation float 
    , numrows int 
) 
 
DECLARE @objectid int; 
DECLARE @indexid int; 
DECLARE @schemaname nvarchar(130);  
DECLARE @objectname nvarchar(130);  
DECLARE @indexname nvarchar(130);  
DECLARE @numrows int 
DECLARE @density float; 
DECLARE @fragmentation float; 
DECLARE @command nvarchar(4000);  
DECLARE @fillfactorset bit 
DECLARE @numpages int 
 
-- Select indexes that need to be defragmented based on the following 
-- * Page density is low 
-- * External fragmentation is high in relation to index size 
PRINT 'Estimating fragmentation: Begin. ' + convert(nvarchar, getdate(), 121)  
INSERT @work_to_do 
SELECT 
    f.object_id 
    , index_id 
    , avg_page_space_used_in_percent 
    , avg_fragmentation_in_percent 
    , record_count 
FROM  
    sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, 'SAMPLED') AS f 
WHERE 
    (f.avg_page_space_used_in_percent < 85.0 and f.avg_page_space_used_in_percent/100.0 * page_count < page_count - 1) 
    or (f.page_count > 50 and f.avg_fragmentation_in_percent > 15.0) 
    or (f.page_count > 10 and f.avg_fragmentation_in_percent > 80.0) 
 
PRINT 'Number of indexes to rebuild: ' + cast(@@ROWCOUNT as nvarchar(20)) 
 
PRINT 'Estimating fragmentation: End. ' + convert(nvarchar, getdate(), 121) 
 
SELECT @numpages = sum(ps.used_page_count) 
FROM 
    @work_to_do AS fi 
    INNER JOIN sys.indexes AS i ON fi.objectid = i.object_id and fi.indexid = i.index_id 
    INNER JOIN sys.dm_db_partition_stats AS ps on i.object_id = ps.object_id and i.index_id = ps.index_id 
 
-- Declare the cursor for the list of indexes to be processed. 
DECLARE curIndexes CURSOR FOR SELECT * FROM @work_to_do 
 
-- Open the cursor. 
OPEN curIndexes 
 
-- Loop through the indexes 
WHILE (1=1) 
BEGIN 
    FETCH NEXT FROM curIndexes 
    INTO @objectid, @indexid, @density, @fragmentation, @numrows; 
    IF @@FETCH_STATUS < 0 BREAK; 
 
    SELECT  
        @objectname = QUOTENAME(o.name) 
        , @schemaname = QUOTENAME(s.name) 
    FROM  
        sys.objects AS o 
        INNER JOIN sys.schemas as s ON s.schema_id = o.schema_id 
    WHERE  
        o.object_id = @objectid; 
 
    SELECT  
        @indexname = QUOTENAME(name) 
        , @fillfactorset = CASE fill_factor WHEN 0 THEN 0 ELSE 1 END 
    FROM  
        sys.indexes 
    WHERE 
        object_id = @objectid AND index_id = @indexid; 
 
    IF ((@density BETWEEN 75.0 AND 85.0) AND @fillfactorset = 1) OR (@fragmentation < 30.0) 
        SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REORGANIZE'; 
    ELSE IF @numrows >= 5000 AND @fillfactorset = 0 
        SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REBUILD WITH (FILLFACTOR = 90)'; 
    ELSE 
        SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REBUILD'; 
    PRINT convert(nvarchar, getdate(), 121) + N' Executing: ' + @command; 
    EXEC (@command); 
    PRINT convert(nvarchar, getdate(), 121) + N' Done.'; 
END 
 
-- Close and deallocate the cursor. 
CLOSE curIndexes; 
DEALLOCATE curIndexes; 
 
 
IF EXISTS (SELECT * FROM @work_to_do) 
BEGIN 
    PRINT 'Estimated number of pages in fragmented indexes: ' + cast(@numpages as nvarchar(20)) 
    SELECT @numpages = @numpages - sum(ps.used_page_count) 
    FROM 
        @work_to_do AS fi 
        INNER JOIN sys.indexes AS i ON fi.objectid = i.object_id and fi.indexid = i.index_id 
        INNER JOIN sys.dm_db_partition_stats AS ps on i.object_id = ps.object_id and i.index_id = ps.index_id 
 
    PRINT 'Estimated number of pages freed: ' + cast(@numpages as nvarchar(20)) 
END 
GO 
  
--Update all statistics 
PRINT 'Updating all statistics.' + convert(nvarchar, getdate(), 121)  
EXEC sp_updatestats 
PRINT 'Done updating statistics.' + convert(nvarchar, getdate(), 121)  
GO 


Настройка TempDB


Microsoft рекомендует:
As a general rule, if the number of logical processors is less than or equal to 8, use the same number of data files as logical processors. If the number of logical processors is greater than 8, use 8 data files and then if contention continues, increase the number of data files by multiples of 4 (up to the number of logical processors) until the contention is reduced to acceptable levels or make changes to the workload/code.



Эту рекомендацию не следует игнорировать. Я останавливаюсь на четырех файлах. Начальный размер файлов должен быть одинаковым. После этого ожидания, как правило, исчезают.

Спасибо за внимание. Знаете еще какие-то фишки — делитесь!

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 25

    +1
    1) Экземпляр SQL базы не обязательно будет иметь такое имя. параметры можно посмотреть HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Update Services\Server\Setup
    параметр SqlServerName
    2) Management Studio запускается исключительно от имени администратора, в противном случае к экземпляру базы подключиться не удастся
    3) для настройки и решения проблем с wsus очень полезная утилита WsusUtil.exe, которая находится C:\Program Files\Update Services\Tools>
      0
      По делу комментарий, спасибо.
      Что касается Management Studio, то в первый раз ее надо, конечно, от администратора запустить. После этого следует назначить роль sysadmin экземпляра хорошей доменной группе, и больше под администратором не запускать.
        0
        да согласен, можно создать пользователя с правамиsysadmin, об этом не подумал :) :) :)
      0
      Хотелось бы вопрос задать, а что вы делаете если компьютеры не отправляют отчет о своем состоянии.
      Сразу скажу
      net stop wuauserv
      net start wuauserv
      wuauclt /resetauthorization /detectnow
      а так же удаление SusClientId не помогают, какие еще есть варианты?
        +1
        Делаю чуть по-другому:
        net stop wuauserv
        rmdir /s /q %windir%\SoftwareDistribution
        net start wuauserv
        wuauclt /detectnow
        


        Некоторые ошибки исправляю как в этой статье.
        0
        1257936 килоБайт лимита вам мало? А куда уж больше то?
          0
          На 2000+ клиентов его и больше 4Gb раздувает.
            0
            Это всего лишь 1,2 гигабайта. Думаете, WSUS этого достаточно?
              0
              У нас 250 клиентов — не замечали проблем. И вся работа его — только дать скачать файл — зачем там гигабайты памяти? Web сервера обходятся и меньшим количеством памяти.

              2000 клиентов — а есть ли смысл их на одном WSUS держать? Логично раскидать на несколько через подчиненные WSUS.
                0
                Одобряешь десяток обновлений и наблюдаешь как процесс набирает память. Каждый клиент устанавливает https сессию и делает долгоиграющий запрос. Можно посмотреть детально в SQL Activity Monitor.

                Ставить подчиненные серверы — дублировать хранилище обновлений, а это 110Gb на сервер.
                Поэтому основной критерий для нас при установке подчиненного сервера — утилизация канала для скачивания обновлений.

                А так один WSUS без проблем обслуживает эти 2000 клиентов, думаю потянет и значительно больше — добавляй только процессоры да память.
                  0
                  Ситуация такая. Когда одобряешь пачку обновлений, после патчинга десяток-другой клиентов выпадают в ошибку обновления. Тогда начинаешь с каждым разбираться. До того, как подняли лимит памяти, на клиентах висела такая ошибка:
                  GetCookie failure, error = 0x8024400D, soap client error = 7, soap error code = 300, HTTP status code = 200
                  SyncUpdates failure, error = 0x80072EE2, soap client error = 5, soap error code = 0, HTTP status code = 200
                  Windows Update Client failed to detect with error 0x80072ee2

                  По-простому — ERROR_INTERNET_TIMEOUT. IISreset помогал, но причина была найдена и исправлена.
              +1
              После изменения лимита еще и очистку пула рекомендуется делать.
              image
                +1
                Мы люди простые, iisreset не брезгуем, или просто перезапуском сервера.
                0
                Когда настраивате TempDB то ставьте пожалуйста Autogrowth не по 1Мб, а хотя бы по 10Мб. Или больше. Зависит от текущего размера TempDB.
                И лучше ставить Мбайты, чем проуенты — здесь все верно.
                  0
                  Очень правильное замечание. На «серьезных» базах так и делаем, правда стараемся сделать совокупный initial size превышающий реально рабочий. Здесь схалтурил немножко.
                  0
                  Коллеги, как вы решаете задачу просмотра лога WindowsUpdate на Windows 10?
                  Его просто так теперь посмотреть нельзя, только через выполнение Powershell команды.
                  Может есть какое централизованное решение?
                    0
                    Два способа, один чудовищнее другого https://blogs.technet.microsoft.com/charlesa_us/2015/08/06/windows-10-windowsupdate-log-and-how-to-view-it-with-powershell-or-tracefmt-exe/

                    Спасибо телеметрии, она как раз и отсылается в etl формате, Microsoft решил сделать администраторам удобно.
                      0
                      Это я видел. Думал есть попроще варианты.
                      Кроме как запускать сессию Powershell от админа домена, потом коннектиться на комп юзера, запускать там get-windowsupdatelog, возможно сразу с записью лога на какую шару.
                        0
                        Попробовал такой варинт
                        psexec \\computer powershell.exe get-windowsupdatelog

                        Получил бесполезный лог
                        2017/06/01 13:26:03.8240088 4212 16064 Unknown( 38): GUID=107f070f-4372-3a30-c1fd-8ce7f568096d (No Format Information found).
                        2017/06/01 13:26:03.8240098 4212 16064 Unknown( 31): GUID=107f070f-4372-3a30-c1fd-8ce7f568096d (No Format Information found).
                        2017/06/01 13:26:03.8240101 4212 16064 Unknown( 23): GUID=107f070f-4372-3a30-c1fd-8ce7f568096d (No Format Information found).
                        2017/06/01 13:26:03.8240156 4212 16064 Unknown( 36): GUID=46641f75-366c-31f6-7f30-83631c82b255 (No Format Information found).
                        2017/06/01 13:26:03.8240213 4212 16064 Unknown( 42): GUID=46641f75-366c-31f6-7f30-83631c82b255 (No Format Information found).
                        2017/06/01 13:26:03.8240313 4212 16064 Unknown( 14): GUID=dc58b7a2-b4cb-301e-a01f-d9a58e6e171d (No Format Information found).
                        2017/06/01 13:26:03.8240367 4212 16064 Unknown( 11): GUID=dc58b7a2-b4cb-301e-a01f-d9a58e6e171d (No Format Information found).


                          0
                          Поисками по такому варианту наткнулся на такой вариант
                          Запустить powershell от имени администратора домена и выполнить такую команду

                          Get-WindowsUpdateLog -ETLPath \\\C$\windows\Logs\WindowsUpdate -SymbolServer https://msdl.microsoft.com/download/symbols -LogPath C:\LOGS\windowsupdate_.log


                          Но не прокатывает такой способ - не хочет качать symbols из интернета.
                          Вывод получаю в виде
                          2017/06/01 13:26:03.8240367 4212 16064 Unknown( 11): GUID=dc58b7a2-b4cb-301e-a01f-d9a58e6e171d (No Format Information found)
                        0
                        Коллеги, что скажите про совет увеличить размер файла XML в запросе?

                        The current number of round trips allowed by WSUS is 200 per client session.
                        The default maximum size of XML data that WSUS allows during each request is currently 200 KB.
                        To reduce the number of round trips to be within the 200 round trips limit per client session, you can adjust the adjust the maximum size of XML data downloaded per request from the 200 KB limit to an unlimited size.

                        To adjust the maximum size of XML allowed per request, you will need to adjust a setting within the WSUS SUSDB database.

                        You can adjust this setting by running the following SQL script on the WSUS server:

                        ==========
                        USE SUSDB
                        GO
                        UPDATE tbConfigurationC SET MaxXMLPerRequest = 0
                        ==========
                          0
                          Неплохо!
                          Проверить просто. На Windows 7:
                          net stop wuauserv
                          rmdir /s /q %windir%\SoftwareDistribution
                          net start wuauserv
                          wuauclt /detectnow

                          Если после в логе не появится ошибка
                          Failed to find updates with error code 80244010

                          то это победа
                            0
                            Да, я один сервак так вылечил и он стал получать обновления с WSUSa нашего :)

                            Но вообще творится что-то странное — железные компы на 10-ах массово не хотят ставить обновления, самая распространенная проблема — процесс загрузки обновлений стоит на 0% и все, никакого эффекта.
                            Некоторые компы и виртуалки просто не могут отправить отчет — в всусе видно, что они подключались недавно, а отчеты — месяц-два назад, или вообще никогда.

                            Пока борьба шаманская — 8, 8.1 — стоп сервиса, удаление папки SoftwareDistribution, потом wuauclt /resetAuthorization и wuauclt /detectnow

                            С Win10 — всего вообще непонятно как лечить. Еще отчеты еще как-то лечатся таким же способом, то скачивание обновлений стопорится на 0%.
                            Вроде как помогает стоп сервисов bits wuauserv appidsvc cryptsvc

                            удаление "%ALLUSERSPROFILE%\Microsoft\Network\Downloader\*.*"
                            удаление SoftwareDistribution
                            зачистка "%SYSTEMROOT%\system32\Catroot2"

                            Потом старт сервисов. Но и то не всегда лечится.
                              0
                              OMG, эта боль нам предстоит.
                          0
                          Есть интересный набор Powershell скриптов — Windows Update PowerShell Module

                          https://gallery.technet.microsoft.com/scriptcenter/2d191bcd-3308-4edd-9de2-88dff796b0bc

                          Закинул на удаленный комп, подключился к сессии powershell на нем и можно работать.

                          Правда остается проблема со штатным скриптом Get-WindowsUpdateLog на Windows 10 в таком режиме — выдает, что не знает таких GUID.

                          Only users with full accounts can post comments. Log in, please.