пятница, 20 мая 2011 г.

Новая версия доступна. Обновить?

В жизни приложений, помимо "просто работы", есть масса интересных, пусть и относительно редких событий.
Приложение должно корректно устанавливаться – и нам нужно проверять это.
Приложение должно корректно удаляться (а вдруг!) – и нам нужно проверять это.
Приложение должно корректно обновляться до новой версии – и нам… подождите-подождите… нужно проверять это!
Об апгрейдах и пойдет речь.

Порой мне начинает казаться, что “забыть про апгрейд” – дело не то чтобы обычное, но и нередкое. Ну ладно, забыть – слишком сильно сказано, просто – отложить. Нет, конечно,  процедуру апгрейда сделаем, но пока вот сосредоточимся на доведении функциональности до ума. А потом все разом прикрутим и протестируем.

Ну, мы знаем, сколько того "потом" обычно остается.

Отложить тестирование апгрейда "на потом", проводить такое тестирование на простейших сценариях означает создать проблемы своим клиентам. Хочу отдельно обратить внимание: не потенциальным клиентам, а людям, которые уже используют наш продукт и собирались использовать и дальше. А тут вдруг апгрейд сломался в середине и похоронил все данные за два года работы. Беда… Неудивительно, если клиенты разбегутся, когда что-то пойдет не так.

Ладно, будем считать, что все согласны: аккуратная проверка апгрейдов необходима. Будем проверять.

Что проверять – зависит от приложения, а они бывают разными, и апгрейдиться могут различными способами. Впрочем, многие проблемы актуальны для самых разнообразных программ. Некоторые из таких проблем я и хочу упомянуть.

Disclaimer. Все "диалоги" выдуманы, совпадения случайны, слова перепутаны, буквы стоят не на своих местах.

 
Всего лишь набор файлов

Что может пойти не так при апгрейде, если все наше приложение это набор файлов, некоторые из которых – исполняемые?

Да вроде как и особо ничего, а? Берем новые файлы, копируем их на место старых – и готово. Ну для порядка можно "инструкцию апгрейда" написать, что-то вроде
    1. Откройте папку, в которую установлено приложение (путь по умолчанию: ХХХ).
    2. Скопируйте в нее файлы входящие в новую версию приложения
А лучше – использовать инсталлятор/скрипт, который все файлы сам по местам разложит.

Все так, пока программист проверяет апгрейд, выполняя "очевидные" действия, которые "и так сами собой разумеются". У пользователя же потом апгрейд может сломаться, потому что
- File is locked – Ой, мы не проверили, что приложение не запущено.
- Access is denied – Из под какого пользователя они запускают апгрейд?
- Диск полон – И это в век терабайтных дисков?

Или – апгрейд успешно отработал, но приложение не запускается, ведь
- Method not supported – Упс, а версия одной библиотеки старая. Забыли файл обновить.
- ОЙ, какая-то мистика – Эээ, какая у них древняя ОС. А мы-то писали-проверяли только с последними апдейтами. Хотя прежняя версия и без них работала…

А еще – апгрейд отработал, а версия программы запускается прежняя. – Хех. У них программа стояла по кастомному пути, а мы "проапгрейдились" в дефолтный :)
 
Список, понятно, не полон. Но, дает понять, что проблемы могут возникнуть даже с простейшим приложением.

 
Сервис/демон

С файлами разобрались, пойдем дальше.

Если приложение работает как сервис, то появляются новые интересные проблемы и вопросы в дополнение к рассмотренным в предыдущей части.

- Апгрейд закончился, а сервис работает точно как раньше! – А рестартануть-то демона мы забыли!
- Все работает, все здорово, только сервис перестал запускаться после рестарта сервера. – Даа, а настройки запуска мы сбросили в "умолчальные" во время апгрейда…
- Эй, сервис не работал все время, пока шел апгрейд! Кто мне заплатит за простой бизнеса? – Хм, надо бы предупреждать, наверное, что сервис будет приостанавливаться во время апгрейда.
- Будет простой сервиса? Ну ладно, спасибо, что предупредили. А долгий простой-то? – Слушай, и правда надо измерять время даунтайма. И, кстати, попробовать как-то минимизировать его.
- Я апгрейд выполнил, и уехал по делам. А сервис после апгрейда не запустился оказывается! – Надо бы запоминать, в каком состоянии сервис был до апгрейда – и возвращать его в то же состояние после.

Да, стоит помнить, что клиенты не для развлечения наши сервисы разворачивают…

 
Клиент-Сервер

Отношения Клиент-Сервер – обычное дело в современных программах. Впрочем, и эти отношения бывают "разной степени усложненности".

Простейший случай – это когда есть четко выделенные клиентская и серверная часть размещенные на одном хосте. Более сложный – когда много инстансов клиентов крутятся на удаленных хостах и обращаются к одному серверу. А еще интереснее становится, если приложение распределено по нескольким серверам, и различные его части выступают по отношению друг к другу то как клиент, то как сервер.

- Не могу подключиться к серверу. Никогда такой ошибки не было! – Как мы забыли предупредить, что клиентскую часть тоже надо апгрейдить, а старая версия клиента не сможет работать с сервером???
- Мне что, запускать апгрейд на каждом хосте, где стоит какой-то модуль системы?? – Кстати да, мы могли бы и автоматически обновлять все хосты – параллельно или один за другим, надо подумать, как лучше. А то боком нам распределенность выходит.
- Что-то апгрейд упал на середине… – ОЙ, вот мы молодцы! Модуль Первый на хосте 01 проапгрейдился и пытается пнуть модуль Второй на хосте 02. А интерфейс общения-то другой после апгрейда! Где ты, обратная совместимость? Даа, на свежих инсталляциях таких проблем не возникает…

И по-прежнему, все проблемы из предыдущих частей могут оказаться актуальными и в этом случае.

 
База Данных

Если приложение использует БД, то вкусного еще больше!

Поскольку БД хранит данные (на которых обычно и делается бизнес) то тут в случае фейла используется очень яркая лексика, так что обойдемся без примеров, пусть и выдуманных. Просто перечислю некоторые возможные проблемы.

В целом БД состоит из структуры базы данных (таблицы, индексы, ограничения и т.д.) и собственно данных. Пострадать при апгрейде может и то, и другое.

Неверная структура БД может аукнуться по-разному: от явного сбоя в работе приложения (когда оно не найдет требуемую таблицу или поле) до накопления несовместимых, неверных данных в этих самых таблицах. Трудно сказать, что хуже. Пожалуй, все-таки второе.

Хороший способ контроля структуры БД – сравнивать структуру проапгрейженой БД со структурой БД, полученной в результате свежей установки приложения. Другой вариант – не изменять "боевую" БД, а создавать рядом новую, как в случае свежей установки, а потом просто переносить данные из одной БД в другую. Заодно и копия данных остается в старой БД.

С самими данными все хитрее. Их целостность контролировать сложнее, особенно если меняется структура таблиц, и данные переносятся в процессе апгрейда из одного места в другое. Тут, кроме сравнения содержимого БД до и после апгрейда, ничего особо в голову не приходит, а как это сделать правильно – сильно зависит от совершаемых изменений.

Кроме того, сами данные могут повлиять на ход апгрейда. Например, если в результате неверной работы приложения (или самого апгрейда) в таблице появились дублирующиеся записи, а процедура апгрейда добавляет на поле таблицы требование уникальности значения, то апгрейд ожидаемо сломается с соответствующим сообщением. И решать проблему в этом случае придется руками. И хорошо, если в тестовой лабе, а не на боевом сервере. Потом, конечно, желательно изменить процедуру апгрейда таким образом, чтоб подобные проблемы не возникали или решались заранее.

Другой аспект, на который могут влиять данные, – это время апгрейда. Чем больше в таблице записей, тем больше времени потребуется на изменение структуры этой таблицы и обновление данных в ней. А время потраченное на апгрейд – это время потерянное для бизнеса, и его надо минимизировать. Тут тоже в зависимости от ситуации, требований и ожиданий можно применять разные подходы, от выполнения низкоуровневых функций до использования отдельного сервера для апгрейда БД, пока приложение работает со старым.

Еще интересен случай, когда приложение умеет работать с разными движками БД. SQL, как известно, "немного свой" у каждого движка – MySQL, PgSQL, MSSQL… Всегда есть шанс, что запрос, работающий на PgSQL, окажется нерабочим на MSSQL. На этот случай вариантов немного – нужно проверять на всем, что поддерживается.

Если приложение состоит из нескольких компонент, каждая из которых работает со своей базой данных, то это тоже нужно учитывать во время апгрейда. Например, не стоит пытаться править БД, относящуюся к компоненте, которую даже не устанавливали (и соответственно – не создавали саму БД). Ну и в чужие БД лазить не стоит, конечно.

Пожалуй, пока достаточно. Не будем рассматривать случаи переполнения диска или потери связи до сервера БД, равно как и использование несколько таких серверов, реплицирующих данные между собой (или не реплицирующих).

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

 
Инсталер

Кстати, если апгрейд выполняется с помощью отдельного приложения-инсталера или скрипта, то неплохо бы проверить работу самого этого приложения.

Все ли у него гладко с логикой? Что случится, если в середине апгрейда что-то произойдет, и мы перезапустим апгрейд заново? Пишет ли он логи, какие и куда? Все ли опции работают верно? В конце концов, нет ли орфографических ошибок в интерфейсе?

Нагрузочному тестированию инсталер, наверное, подвергать незачем, но в целом стоит не забывать про этот кусочек продукта.

 
Пара общих соображений

Напоследок выскажу еще несколько соображений, не вошедших в предыдущие части.

К апгрейду вполне применимо одно из простейших правил тестирования: не верь "очевидному", проверь. Пусть кажется, что все очень просто, и проблеме вылезти неоткуда. Практика показывает, что жизнь богаче, чем можно представить.

Полезную практику непрерывной интеграции хорошо бы распространять и на тестирование апгрейдов. Так и проблемы быстрее будут обнаруживаться, и соблазна отложить создание процедур апгрейда "на потом" будет меньше.

Имеет смысл даже после тщательного тестирования быть готовым к возможным проблемам у клиентов, особенно в случае апгрейда баз данных. Наполнение БД на боевых серверах обычное хитрее и разнообразнее того, что можно придумать в тестовой лабе, а значит могут вылезать неучтенные проблемы.

На этом, пожалуй, хватит.

 
Удачи вам и быстрых беспроблемных апгрейдов.

Комментариев нет:

Отправить комментарий