Подтвердить что ты не робот

Управление выпуском - выпуск подмножества пользователей - как он будет работать для публичного сайта

Я где-то читал (извините, точно не помню источник), что facebook выпустил вторник. Сначала они выпускают новые функции для своих внутренних сотрудников, а затем к небольшому набору внешних пользователей, а затем ко всему миру. Я считаю, Google также делает что-то подобное

Я работаю в основном с стеком Microsoft (TFS для управления исходным кодом, IIS, asp.net, sql-сервер с огромными данными). Разумеется, для публичных сайтов, поэтому они должны быть 24x7x365. Хотя я могу представить себе выпуск api/dll только на одном из серверов (в webfarm) и проверять его, как бы это сделать, если есть DB (сохраненные подписи proc, изменения схемы таблицы)? В настоящее время мы являемся версиями SPs (новыми будут mySPNameV2, где старым будет mySPNameV1 - как с учетом различных параметров, так и с переименованием), а новые API будут использовать SP-V2, где, поскольку старый API будет продолжать работать с SP -V1.

Я вижу некоторый дизайн запаха, но есть ли лучший способ сделать это?

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

4b9b3361

Ответ 1

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

Решение состоит в том, чтобы ваши таблицы включали как столбцы V1, так и V2 (например, одну таблицу пользователей, которая будет включать поля из обоих API). Примечание. Все не общие поля должны иметь значения по умолчанию.

Чтобы это работало без сбоев, вы должны создавать представления для V1 и V2, отображая только соответствующие поля для каждой версии API, и вы должны разрабатывать для представлений вместо таблиц (аналогично концепции разработки для интерфейсов вместо реализация).

То же самое касается хранимых процедур - все не общие параметры должны иметь значения по умолчанию и т.д.

Ответ 2

В моей компании мы почти всегда делаем какой-то крупный выпуск в шахматном порядке. Мы достигаем этого, добавляя флаг для каждой новой функции в таблице users. По умолчанию для этого флага установлено значение false; и поскольку мы развертываем эту функцию для большего числа пользователей, мы просто переключаем флаг в таблице DB.

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

На уровне базы данных мы гарантируем, что любые изменения в SP будут "обратно совместимы". Это делается с помощью следующих простых правил:

  • Любые новые параметры, добавленные в SP, должны перейти в конец списка параметров.
  • Новые параметры должны иметь значение по умолчанию. Это делается для того, чтобы существующие вызовы SP не прерывались.
  • Если существующие параметры для SP необходимо изменить (или если порядок параметров должен измениться), то, очевидно, все вызовы SP изменяются. Но SP закодирован таким образом, что он поддерживает пользователей, у которых есть функция, а также пользователи, у которых нет ее.
  • Большинство изменений таблицы связаны с добавлением новых столбцов. Это действительно редко, когда мы должны изменить существующий столбец. Все новые столбцы добавляются со значением по умолчанию или разрешают NULL.

Что касается API, большинство наших параметров передаются как пользовательские объекты (структуры). Таким образом, мы можем добавить новый параметр к методам API и по-прежнему препятствовать нарушению существующих вызовов API.

Кроме того, для каждого пользователя мы храним версию API, которую они используют. В зависимости от версии пользователи переходят на другой URL-адрес API. Поэтому, когда пользователи делают первый вызов API для аутентификации, мы передаем новый URL-адрес API (на основе версии API для пользователя). Для всех последующих вызовов они должны вызывать новый URL. Salesforce.com также следует за их вызовами API.

Ответ 3

Я был в QCon в прошлом году, когда парень из Facebook Web Team говорил об этом подобным образом. Вы на 100% верны, что для его реализации будут запахи кода. Но это требует гораздо больше, чем просто запах кода (на самом деле они называют эти запахи кода Gate Keepers:).

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

Что вы можете сделать, так это добавить хранителей ворот (если (пользователь из Новой Зеландии) {используйте затем новую версию с новыми классами} else {stick ot the old one}).

Возможно, вы можете представить себе, какое именно дублирование кода это приведет в случае структурированной модели (например, вам нужно будет иметь 2 пользователя, 2 ордера, 2 детали заказа). Оставив это в стороне, я думаю, что большая регрессия также будет иметь место, если вы не будете предельно осторожны.

Насколько я помню - они выпускаются намного чаще, чем только вторники. Я думаю, что у них есть непрерывное развертывание, и код идет каждый день, только они чистят старые ворота Хранители/схемы изменений вторников, поскольку к тому времени они переключили всех пользователей на новые функциональные возможности.

Итак, в основном:

  • Вы добавляете хранителей ворот везде, где происходит новое функциональное место.
  • Вы поддерживаете две версии схемы.
  • Вы добавляете все больше и больше пользователей для переключения на новый.
  • Вы очищаете старый.
  • Вы переходите к пункту 1 (если другая команда еще не существует:).

Я понимаю, что этот ответ может быть недостаточно полным, чтобы претендовать на ответ, но я слышал об этом от своего парня и думал, что его стоит разделить.

Ответ 4

Вариант 1:

A (под) домен для (полу) (public?) devsite. Некоторые пользователи принимаются в devsite на основе набора файлов cookie вручную (сотрудники и т.д.) < частное тестирование

Основной домен, который устанавливает cookie для определенных пользователей (набор файлов cookie, когда время находится между временем X и временем Y) в зависимости от вашего трафика. Если вы получаете 1000 (уникальных) посетителей каждый час, и вы хотите 10% на домене dev, вы убедитесь, что время дельта составляет 6 минут. Вы можете просто удалить файлы cookie, если вы хотите, чтобы пользователи перенаправлялись на обычный сайт. (Убедитесь, что вы перенаправляете весь входящий URL-адрес, чтобы предотвратить разбитые закладки.

Вариант 2:

Загрузка баланса определенного процента трафика на серверы, на которых запущено новое приложение.

База данных

1: взаимодействие с живой базой данных при разработке < регулярные резервные копии + обычные квалифицированные разработчики = безопасные

2: посмотрите на главную подчиненную репликацию, чтобы создать "живую" теневую копию вашего БД

Ответ 5

Простейший подход ИМО заключается в том, чтобы отделить функции наборами страниц, которые используют безопасность, чтобы определить, какую страницу пользователь получает. Помимо безопасности и других средств для обеспечения того, чтобы пользователь не мог попасть на страницу, к которой у них нет доступа (карты сайта и т.д.), Вы можете сохранить в базе данных список функций, доступ к которым у пользователей или ролей:

Create Table Features
    (
    Code varchar(10) not null Primary Key
    , StartPage nvarchar(max) not null
    , Description nvarchar(max) not null
    )

Create Table UserFeatures 
    ( 
    UserId ... not null
    , FeatureCode varchar(10) References Features ( Code )
    )

Во-первых, причина, по которой я буду использовать текстовый код для первичного ключа функции, а не суррогатный ключ, такой как столбец IDENTITY или guid, заключается в том, что только система будет запрашивать функции. У пользователей никогда не будет возможности произвольно добавлять функцию. Таким образом, ваш код намного чище и проще читать для запроса ...Where FeatureCode = 'AdvancedEntry', чем ...Where FeatureId = 13.

Во-вторых, в этом подходе код самих страниц будет определять, какую процедуру вызывать. Однако это может означать довольно много дублирования, если функции просто связаны с дополнительными полями информации.

Таким образом, если функции тесно интегрированы в существующую базу кода и уровень представления (что, кстати, является причиной того, что управление версиями настолько сложно), альтернативный подход состоял в том, чтобы сохранить имя хранимой процедуры, которое должно использоваться в таблицу Features. Ваш код будет запрашивать соединение с приведенными выше таблицами и возвращать имя хранимой процедуры, которое должно использоваться. Для аргументов вы можете сохранить параметризованный вызов в базе данных (например, exec Schema.Foo @bar, @gamma, @beta), а при выполнении запроса просто проверьте, содержит ли эта строка данный параметр, и если это так, добавьте это значение параметра:

if ( ProcTemplate.Contains( "@bar")
    commandInstance.Parameters.AddWithValue( "@bar", barValue );
if ( ProcTemplate.Contains( "@gamma")
    commandInstance.Parameters.AddWithValue( "@gamma", gammaValue );
...

Если вы привязываете функции к ролям или группам пользователей, вам нужно будет разработать правила "перескакивания", которые определяют, какая функция должна использоваться в случае множественного возвращения. В этом подходе вы оставите только существующие хранимые процедуры, запрещающие изменение схемы, требующее изменения хранимой процедуры (например, удаление столбца). Бонусный результат этого подхода заключается в том, что вы могли бы добавить дату в таблицу Features, чтобы определить, когда новая функция должна выходить в Интернет.

Ответ 6

Я действительно думал, что этот вопрос получил бы гораздо больше внимания. Учитывая то, что вы сказали, и существующие ответы, я думаю, что ваше существующее решение является самым прямым и простым в управлении. Как вы сказали, есть "запах дизайна" (мне нравится эта фраза), но это имеет наибольший смысл.

Возможно, сделав еще один шаг и объединяя некоторые небольшие изменения в предложениях со своими:

  • Сохраняйте существующее соглашение о версии базы данных
  • Выделите конкретные версии кандидата либо на субдомен кандидат01.yoururl.com, либо на определенный сервер, если у вас есть ферма серверов
  • Используйте флаг в своей таблице user/member, чтобы указать, какой производственный сервер или поддомен должен быть направлен пользователю
    • Предоставляет возможность направить некоторых пользователей на сервер (-ы) кандидата на выпуск
    • Не требуется количество кода для каждой функции кодирования, упомянутой в ответе DK (вы могли бы пойти в любом случае, хотя в зависимости от того, насколько целевым вы хотите быть, но я думаю, что наименее сложный маршрут будет лучше всего здесь и будет направлять пользователей к конкретным версиям приложения, а не пытаться включить или отключить отдельные функции для каждого пользователя).

Кроме этого, большой вопрос! О да, и когда все это будет готово, вы просто переверните переключатель флюгера, чтобы задействовать механизм двойного буфера, и все вы настроены.

Ответ 7

Возможно, я упрощаю здесь, но почему бы не просто добавить базу данных дальше?

Когда вы выполняете подмножество пользователей для "тестирования", будь то внутреннее, подмножество внешнего или мира, вы не выполняете что-то вроде бета-теста? Разве это не вызовет другой экземпляр базы данных с бета-версией хранимых процессов против текущей версии/экземпляра? Просто вопрос указания строк подключения в веб-конфигурациях в этой точке не так ли?

Может быть, ограничение здесь - это затраты на серверы и "огромные данные" на них, что я признаю, что я просматриваю вопрос или действительно вопрос о версировании хранимых prococedures и т.д.? Не могут ли они быть только контролируемыми источниками, а также изменениями схемы?

Вероятно, я спросил больше, чем ответил.