Русский
Русский
English
Статистика
Реклама

Ocp

OCP Experience Lab как мы строили мини-ЦОД в офисе

06.01.2021 00:04:36 | Автор: admin

Начиналось всё с создания стенда для тестирования серверов нашей собственной разработки. Потом стенд разросся и мы решили сделать небольшой датацентр для пилотирования различных софтовых решений. Сейчас это единственная в Россси и вторая в Европе лаборатория OCP Experience Lab.


Вообще я недавно в разработке вычислительной техники. Мне это всегда казалось чем-то невозможно сложным и доступным только огромным командам с очень большими бюджетами. И, наверное, поэтому очень привлекательным. В прошлом году звёзды сошлись и мне удалось привлечь инвесторов и найти стартовых клиентов, чтобы запустить свой собственный проект создания российского сервера. Выяснилось, что в России в этом направлении работает пара десятков команд совершенно разных размеров и специализаций. Одни просто привозят комплекты деталей от тайваньских производителей и делают в России только сборку, а другие копают сильно глубже, вплоть до написания собственного BIOS. Короче, стало понятно, что тема хоть и сложная, но вполне посильная.

Для старта разработки выбрали сервера стандарта OCP. ОСР это Open Compute Project, открытое сообщество, в котором конструкторская документация на все продукты выкладывется в открытый доступ для свободного использования. Настоящий Open Source Hardware, и как следствие, самый прогрессивный, бурно растущий и перспективный стандарт, к тому же продвигаемый преимущественно не поставщиками, а потребителями оборудования. Помимо всех технических преимуществ, открытая документация должна была упростить нам старт разработки и ускорить встраивание в такую тяжелую тему, как серверное железо. Но это, наверное, тема для отдельной статьи.

А компанию, кстати, назвали GAGAR>IN. Скоро вы про неё ещё услышите.

Готовимся

Моё же личное знакомство с ОСР состоялось лет пять назад, когда я участвовал в продвижении решений американской Stack Velocity на российский рынок. Уже тогда у нас была идея локализовать их производство и сделать собранные в России сервера с открытой документацией для нужд госкомпаний и госзаказчиков. Но тогда импотрозамещение было ещё не в тренде, и все потенциальные заказчики в итоге предпочли купить тайваньское оборудование. Именно тогда произошел первый сдвиг в популяризации OCP в России: Яндекс установил в свой новый датацентр как-бы-OCP сервера от небольшого тайваньского вендора AIC, а Сбербанк, РЖД и Mail вовсю тестировали полноценные OCP решения от гиганта Quanta, крупнейшего мирового производителя вычислительной техники.

С тех пор прошло довольно много времени и поэтому первым шагом моего плана было обойти всех основных вендоров и ближайших дистрибьюторов OCP, чтобы подружиться, запартнёриться и посмотреть-пощупать реальные железки. До начала карантинных ограничений я чудом успел объехать с десяток поставщиков в России, Тайване, Китае и Европе это был стремительный и весьма продуктивный тур, из которого стало многое понятно. Не боги горшки обжигают и у нас точно есть шанс успешно воспроизвести сервер OCP, и более того сделать его немного лучше по характеристикам.

Сборочная линия небольшого тайваньского производителя серверовСборочная линия небольшого тайваньского производителя серверовКалифорнийское производство серверов крупного азиатского производителяКалифорнийское производство серверов крупного азиатского производителя

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

Стойка OCP Experience Center в Амстердаме выглядит очень красиво, но довольно бессмысленноСтойка OCP Experience Center в Амстердаме выглядит очень красиво, но довольно бессмысленно

Стартуем

Создание тестового стенда всегда стояло одним из первых пунктов плана развития компании, но то, что мы увидели в Голландии, понравилось нам настолько сильно, что было решено совместить стенд тестирования своего железа, шоу-рум и лабораторию для отладки программно-аппаратных решений клиентов в одном месте, назвав это OCP Experience Lab. То есть мы создадим лабораторию, максимально соответствующую духу открытых сообществ удобное и легко доступное место, где и конечные потребители, и интеграторы могут своими руками пощупать и потестировать реальное, боевое и самое прогрессивное железо.

Все эти наши прекрасные планы были перечеркнуты карантином, и первые тестовые стенды были собраны в спальных районах столицы на коленке, а специально арендованное под лабораторию помещение в центре Москвы стояло пустым.

Тестирование новейшего сервера в домашних условияхТестирование новейшего сервера в домашних условиях

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

В июне, как только карантин немного ослаб, мы смогли начать сборку лаборатории нашей мечты.

Затащить серверные стойки в неприспособленный под это офис - само по себе нетривиальная задачаЗатащить серверные стойки в неприспособленный под это офис - само по себе нетривиальная задача

Наконец-то получилось собрать всё закупленное оборудование в одном месте и нормально установить в стойки. Нам повезло, что в помещении был трехфазный электрический ввод, и существовала возможность проложить оптику. Тем не менее, первое время, пока мы согласовывали с арендодателем проект, тащили оптику и подводили электричество к стойкам всё наше оборудование работало от обычной розетки и через LTE модем. Причем из-за толстых стен и плотной застройки, этот модем пришлось приклеить скотчем к окну.

Монтаж очередного сервера в стойкуМонтаж очередного сервера в стойку

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

Три стойки, рабочий стол инженера и большой плакат - так выглядела наша лаборатория в сентябре 2020Три стойки, рабочий стол инженера и большой плакат - так выглядела наша лаборатория в сентябре 2020

Комплектующие в лабораторию мы собирали со всего мира: заказали всё самое новое и интересное, что есть в мире OCP. В итоге у нас образовалось три стойки от трёх разных производителей, полтора десятка различных вычислительных серверов, несколько дисковых массивов и целых шесть коммутаторов! Такое многообразие позволило одновременно запускать два-три функциональных стенда и проводить на них долговременные тесты.

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

Что и как тестируем

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

Всё началось с базовых тестов производительности железа. Мы прогнали через испытания множество компонент: модули памяти Samsung, Micron, Hynix; SSD от тех же Samsung, Micron и Intel; сетевые карты Mellanox, Broadcom, Emulex и Intel. И даже сравнили между собой процессора Intel SkyLake и AMD EPYC2.

Но понятно, что лаборатория не только место для тестирования новых железок. Потребители не бенчмарки будут мерять, им нужны рабочие программно-аппаратные конфигурации. И поэтому мы стали потихоньку собирать конфигурации различного софта и проверять его работоспособность и производительность. Начали с российских Линуксов: Альт, Астра и Роса. На базовых тестах всё прошло без сюрпризов - возможно стоит делать более глубокие исследования и сравнение в сложных задачах. Потом собрали несколько различных стендов систем виртуализации. Для начала попробовали VmWare, Proxmox, Virtuozzo с ними также всё прошло довольно гладко и скучно. Мы сохранили конфигурации и решили вернуться к этим системам позже, уже с реальными клиентскими задачами.

Так как основная идея OCP оборудование без излишеств, то всё разнообразие функционала перенесено на уровень софта. Фактически, любые конфигурации собираются из двух кирпичиков вычислительного сервера и присоединяемого к нему дискового массива JBOD (Just a Bunch Of Discs). Мы же собрали в лаборатории несколько различных исполнений как серверов, так и дисковых массивов, и следующим логичным шагом было тестирование их совместной работы.

В ходе всех этих тестов, постоянного конфигурирования и переконфигурирования серверов и сетей, стало понятно, что без полноценного мониторинга систем нам не справиться, и с этого момента у нас завёлся Zabbix.

Дашборд ZabbixДашборд Zabbix

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

Кстати, одним из преимуществ оборудования OCP, является его способность работать при температурах до 30 градусов, а максимум допустимой температуры составляет как раз 35 градусов. Получилось, что мы сами того не желая, устроили своего рода стресс-тест нашим серверам. Но всё же оставлять серверную без кондиционирования опасно ещё несколько серверов и температура уползёт под сорок, да и клиентов приводить в такую жаркую комнату неудобно.

Финальный рывок

Наши продажники всегда просили красивый шоу-рум, но я до последнего надеялся обойтись малой кровью. Чистенько, удобно, функционально и достаточно. Однако в планах было сделать большой анонс открытия лаборатории уже в октябре и для этого нужно было снять небольшое видео. Позвали съемочную группу и получили суровый приговор дорисовывать красоту в кадре будет не сильно дешевле, чем сделать нормальный, полноценный ремонт. В результате торжественное открытие лаборатории отложилось ещё на пару месяцев, и появились дизайнеры, чтобы "сделать красиво".

Один из первых вариантов дизайнаОдин из первых вариантов дизайна

Дизайн и ремонт мы заказали у застройщиков выставочных стендов они как никто умеют делать яркие конструкции. Месяц согласований, месяц строительства и получилось вот так:

Лаборатория после ремонтаЛаборатория после ремонта

Теперь можно было проводить официальное открытие и снимать полноценное видео:

В итоге, у нас есть не только лаборитория, шоурум, но и удобная съемочная площадка для производства серии видеороликов про оборудование Open Compute.


Так что продолжение следует!

Самое главное - табличка на входе!Самое главное - табличка на входе!
Подробнее..

Open-Closed Principle в Angular

19.01.2021 12:23:47 | Автор: admin

Всем привет! Меня зовут Вова, я фронтендер в Тинькофф. Сейчас перед нашей командой стоит задача редизайна функциональности на пересечении нескольких продуктов. Данная ситуация заставила нас задуматься во-первых о DDD, а во-вторых о гибкости наших решений, применяемых при разработке, и достичь этого нам помогли принципы SOLID, а точнее OCP и Dependency Inversion (не путать с Dependency Injection), о чем и хочется дальше поговорить.

Open-Closed Principle

Принцип открытости-закрытости хорошо описан в статье Роберта Мартина Open-Closed Principle, также можно прочитать адаптацию моего коллеги. Разбирать этот принцип всегда легко на разного рода списках. Проанализировать его правильное использование можно так: добавление нового типа элементов в список должно происходить без изменения старого кода, но изменение бизнес-поведения элементов может происходить через изменение старого кода.

Применение OCP в Angular

Самым сложным во всей этой теории была именно сама адаптация принципа на наш любимый framework. Вопрос решили с помощью Dependency Injection механизма. Чтобы лучше понять, как давайте вместе решим типичную задачу на Angular со следующим ТЗ:

  1. Есть расчетные счета, у которых должны отображаться имя и баланс счета

  2. Есть депозитные счета, у которых должны отображаться имя, баланс и дата закрытия счета

  3. Есть кредитные счета, у которых должны отображаться имя, баланс и статус счета. Статус счета выводим красным цветом

  4. Данные по счетам получаем из разных источников, так как они могут относиться к разным бизнес контекстам

У нас будет компонент, отвечающий за получение списка всех счетов и их отображение:

@Component({...})export class AccountsListComponent {  readonly accounts$ = combineLatest([    this.getBaseAccounts(),    this.getLoanAccounts(),    this.getDepositAccounts()  ]).pipe(map(accounts => accounts.flat()));  constructor(    private readonly baseAccounts: BaseAccounts,    private readonly deposits: DepositsService,    private readonly loans: LoansService  ) {}  private getBaseAccounts(): Observable<AccountListItem[]> {    return this.baseAccounts.getAccounts().pipe(      map(accounts =>        accounts.map(account => ({          info: account,          type: "base"        }))      )    );  }  private getDepositAccounts(): Observable<AccountListItem[]> {    return this.deposits.getAccounts().pipe(      map(accounts =>        accounts.map(account => ({          info: account,          type: "deposit"        }))      )    );  }  private getLoanAccounts(): Observable<AccountListItem[]> {    return this.loans.getAccounts().pipe(      map(accounts =>        accounts.map(account => ({          info: account,          type: "loan"        }))      )    );  }}
<ng-container *ngFor="let account of accounts$ | async">  <div class="account" [ngSwitch]="account.type">        <ng-container *ngSwitchCase="'deposit'">      <div class="name">{{account.info.name}} - {{account.info.amount}}</div>      <div class="status">Закроется {{account.info.closeDate}}</div>    </ng-container>        <ng-container *ngSwitchCase="'loan'"> {{account.info.info.name}} - {{account.info.info.amount}} |      <span style="color: red">{{account.info.info.status}}</span>    </ng-container>        <ng-container *ngSwitchCase="'base'">      {{account.info.name}} - {{account.info.balance}}    </ng-container>      </div></ng-container>

Сервисы по получению этих счетов и их модельки (пример одного из сервисов):

export type BaseAccount = Readonly<{  id: number;  name: string;  balance: number;}>;@Injectable()export class BaseAccounts {  getAccounts(): Observable<BaseAccount[]> {    return of([      {        id: 1000,        name: "Рублевый",        balance: 150      }    ]);  }}

Полный пример реализации можно посмотреть в stackblitz

Итак, задача выполнена, тесты написаны, все работает, но через месяц приходит заказчик и просит ввести новый тип счетов, значит, нам придется изменять компонент списка счетов. Здесь и появляется проблема компонент отвечает за вывод списка счетов и в то же время определяет как отображать конкретный счет.

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

Перед стартом можно вспомнить примеры механизмов в Angular, в которых уже используется этот принцип:

  1. Control Value Accessor

  2. Event Manager

  3. Interceptors

Давайте вспомним как добавляется новый Interceptor. Сначала реализуем сервис, который имплементирует HttpInterceptor:

@Injectable()export class DummyInterceptor implements HttpInterceptor {  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {    return next.handle(req);  }}

Подключим наш Interceptor в модуле:

@NgModule({  providers: [{    provide: HTTP_INTERCEPTORS,    useClass: DummyInterceptor,    multi: true  }]})export class AppModule {}

Как видим по примеру выше, секрет в подключении провайдера с параметром multi: true. Такой способ подключения провайдера говорит системе DI, что при получении значения токена HTTP_INTERCEPTORS мы получим массив подключенных провайдеров.

Применим полученные знания для решения задачки со списком счетов, но сначала выделим 2 основных понятия:

  1. Плагин / Plugin - сервис, использующийся для расширения существующего функционала

  2. Менеджер плагинов / Plugin Manager (опционален) - сервис, агрегирующий все подключенные плагины

Опишем интерфейс плагина счета и создадим для него токен:

export type AccountListItem = Readonly<{  id: number;  name: string;  amount: number;  status?: string;}>;export interface AccountListItemPlugin {  getItems(): Observable<AccountListItem[]>;}export const ACCOUNT_LIST_ITEM_PLUGIN = new InjectionToken<  AccountListItemPlugin>("Плагин для подключения счетов");

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

@Injectable()export class AccountsListManager {  constructor(    @Inject(ACCOUNT_LIST_ITEM_PLUGIN)    private readonly accountListItemPlugins: AccountListItemPlugin[]  ) {}  getAccounts(): Observable<AccountListItem[]> {    return combineLatest(      this.accountListItemPlugins.map(plugin => plugin.getItems())    ).pipe(map(items => items.flat()));  }}

Опишем плагин с основными счетами:

@Injectable()export class BaseAccountsPluginService implements AccountListItemPlugin {  getItems(): Observable<AccountListItem[]> {    return of([      {        id: 1000,        name: "Рублевый",        amount: 150      }    ]);  }}

И подключим его в главном модуле:

@NgModule({  providers: [    {      provide: ACCOUNT_LIST_ITEM_PLUGIN,      useClass: BaseAccountsPluginService,      multi: true    },  ]})export class AppModule {}

Теперь самое интересное: смотрим на преображение нашего компонента со списком счетов:

@Component({  ...})export class AccountsListComponent {  readonly accounts$ = this.accountsListManager.getAccounts();  constructor(private readonly accountsListManager: AccountsListManager) {}}

и его шаблон:

<div *ngFor="let account of accounts$ | async" class="account">  <div class="name">{{account.name}} - {{account.amount}}</div>  <div *ngIf=accounts.status class="status">{{account.status}}</div></div>

Полный пример реализации можно посмотреть в stackblitz

В момент времени, когда список счетов перестал зависеть от конкретной реализации счета, мы и применили OCP. НО! Мы потеряли стилизацию для статуса кредитного счета. Решать такую проблему можно разными способами, и мы решили использовать для таких случаев библиотеку от коллег ng-polymorheus (статья на хабре), которая позволяет не привязываться к конкретному типу данных для отображения информации в шаблоне. Сделаем несколько ВЖУХ, и отображение статуса станет полиморфным.

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

export type AccountListItem<A> = Readonly<{  id: number;  name: string;  amount: number;  account: A;  status?: PolymorpheusContent<AccountListItemContext<A>>;}>;export type AccountListItemContext<A> = Readonly<{   account: A;}>

Второй вжух - добавляем компонент для отображения статуса у кредитных счетов:

@Component({    selector: 'loan-account-status',    template: `<span class="negative">{{context.account.info.status}}</span>`,    styles: ['.negative {color: red;}'],    changeDetection: ChangeDetectionStrategy.OnPush,})export class LoanAccountStatusComponent {    constructor(      @Inject(POLYMORPHEUS_CONTEXT)    readonly context: AccountListItemContext<LoanAccount>  ) {}}

Третий вжух - правим плагин кредитных счетов:

@Injectable()export class LoanAccountsPluginService  implements AccountListItemPlugin<LoanAccount> {  private readonly accountStatus = new PolymorpheusComponent(    LoanAccountStatusComponent,    this.injector  );  constructor(private readonly injector: Injector) {}  getItems(): Observable<AccountListItem<LoanAccount>[]> {    return this.getAccounts().pipe(      map(accounts => {        return accounts.map(account => ({          id: account.id,          name: account.info.name,          amount: account.info.amount,          account,          status: this.accountStatus        }));      })    );  }  private getAccounts(): Observable<LoanAccount[]> {    return of([      {        id: 1,        info: {          name: "Кредитный счет",          amount: 1000,          status: "Activation"        }      }    ]);  }}

Последний вжух - учимся рисовать polymorpheus в шаблоне списка счетов для статуса:

<div *ngFor="let accountItem of accounts$ | async" class="account">  <div class="name">{{accountItem.name}} - {{accountItem.amount}}</div>  <div class="status">    <polymorpheus-outlet      [content]="accountItem.status"      [context]="{account: accountItem.account}"    >    </polymorpheus-outlet>  </div></div>

Полный пример реализации можно посмотреть в stackblitz

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

Еще чуть-чуть про плагины

Думаю, с OCP мы разобрались. А где же здесь Dependency Inversion Principle? В конечной реализации компонент со списком счетов предоставляет интерфейс плагина, который может подключаться без изменения кода компонента списка счетов.

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

Компонент списка счетов без использования DIКомпонент списка счетов без использования DI

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

Компонент списка счетов при использовании DIКомпонент списка счетов при использовании DI

Итог

В результате проделанной работы мы смогли добиться следующего:

  • Добавление новых типов счетов не меняет компонент со списком счетов

  • Изменение стиля отображения статуса не меняет компонент со списком счетов

  • Работа с конкретным типом счета изолирована в пределах его плагина и не пересекается с другими типами счетов (превентивный подход к нарушению Single Responsibility Principle из SOLID)

Главное, помните - никакую систему нельзя закрыть на 100%, так что изменения в модели плагина при добавлении новых бизнес-правил - это нормально.

Разберем на примерах:

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

  2. Для расчетных счетов теперь при выводе баланса необходимо учитывать и долги клиента перед банком.Делать изменения в модели плагина в таком случае плохо

На данный момент мы применяем подход с плагинами везде, где работаем со списком сущностей, относящихся к разным бизнес контекстам (примеры списков - список счетов, список операций, список нотификаций). Такое разделение дает еще один бонус сущности, относящиеся к единому бизнес контексту, можно упаковывать в отдельную папку. Разберем на примере депозита. Он отображается в списке счетов, у него есть своя страница счета и есть плашка с открытием депозита, весь этот код мы не разносим по конкретным реализациям списком, а держим реализации плагинов в единой папке deposit, что добавляет прозрачности при работе с конкретным бизнес контекстом

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru