четверг, 11 сентября 2014 г.

Записки программиста #13. Разработка back-end’а.

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

MongoDB
Интересное решение которое работает из коробки и работает очень неплохо, C# драйвер порадовал своей простотой, пока только одни положительные моменты.
В качестве ID в документах (аналог таблицы) принято использовать ObjectId или GuId. Но я в своем решении хотел бы видеть int, так как использую Player_{id}. Покопавшись в документации я понял:
1) стандартными средствами нельзя использовать для генерации int.
2) что можно использовать свой генератор.
Собственно, я его и написал, выглядит это примерно так, может кому и пригодиться:

[BsonId(IdGenerator = typeof(EmptyIdGenerator<RegistrationEntity>))]
public int ClientId { get; set; }

        public static class EmptyIdGenerator
       {
               public static int EmptyId { get; set; }
        }

        public class EmptyIdGenerator<T> : IIdGenerator where T : class    {
       
        public object GenerateId(object container, object document)
        {
            if (EmptyIdGenerator.EmptyId <= 0)
            {
                var col = (MongoCollection<T>)container;
                var sortBy = SortBy.Descending("_id");
                var last = col.FindAll().SetSortOrder(sortBy).FirstOrDefault();
                EmptyIdGenerator.EmptyId = (last == null) ? 1 : (int)last.ToBsonDocument()["_id"] + 1;
            }
            else
            {
                EmptyIdGenerator.EmptyId++;
            }
            return EmptyIdGenerator.EmptyId;
        }

        public bool IsEmpty(object id)
        {
            return ((id is int) && (id as int? == 0));
        }
    }

Пока по использованию mongodb нечего сказать больше к сожалению, не могу, но проблем вроде не возникает.

Логирование
Что за сервер который не ведет логов?! Куда складировать логи, в файл или в БД? Писать свой велосипед или использовать готовые решения? Вопросов больше чем ответов…
Тк велосипеды свои уже надоели решил посмотреть в сторону готовых решений, их много:
NLog, Log4Net, Enterprise Library, SmartInspect. Сравнений в интернете нашел уйму и выбор мой пал на NLog. Пока выбор мой был полностью оправдан и не разочаровался...

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

Миграция в облако
В качестве облачного провайдера была выбрана azure, в силу некоторых причин которые останутся за кадром. Вот тут меня ожидали кучи подводных камней! Скажу сразу я полный профан в администрировании, поэтому я наступал на все грабли которые были.
Для тестирования была создана Большая ВМ (4 ЦП по 1,6 ГГц, 7 ГБ ОЗУ)
В панели управления в разделе конечные точки были прописаны порты для сервера, внутри сервера на файервол настроил необходимые правила. Залил сервер и запустил - проблема номер раз, пакеты тупо не приходят. Скачал wireshark, поглядел, пакеты действительно уходят, но не приходят. Длительный поиск в гугле результатов не дал. Решил поиграть с настройками, из самых не понятных мне были настройки порта в панели управления, там нужно было указать общий и частный порт. Изначально я поставил их разные, на сервере биндился на публичный, это не правильно, их следует выставлять либо одинаковые, либо вещаться на приватный, а я то думал это для локальной сети настройки… Повторный запуск, пакет уходит, приходит на сервер, отправляется обратно и тишина. Да здравствует NAT!
Я изначально сделал общение примерно таким: создавал два сокета, один отправляет, другой принимает, в первом пакете говорим какой порт мы будем слушать, все хорошо, но только в локальной сети. Собственно, решения не меньше двух, аналоги как сделано в SIPe и использовать один порт, я выбрал наименее затратное - слушать и отправлять с одного порта. Звучит конечно все просто и логично, но выходные я убил на то, чтобы это все заработало в облаке.

Итог
Сервер уже удачно работает без сбоев неделю.
Результат максимальной нормальной работы 50 пакетов в тик, те 1500 пакетов в секунду, много это или мало, пока тяжело сказать. Для эмуляции максимальной нагрузки мне потребовалось около 2 000 клиентов с повышенной интенсивность, это больше чем 10 000 реальных клиентов единовременно, обмен пактов у меня не особо интенсивный :-)

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

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