Занимаюсь коммерческой разработкой 22 года.

Имею пять международных сертификатов.

Первый интернет магазин разработал в возрасте 18 лет в 1998 году.

5 лет работал удалённо в компаниях США.

Разрабатывал:
- CRM, ERP системы (системы управления предприятиями, клиентами);
- интернет магазины;
- высоконагруженные сервисы, сканеры, индексаторы сайтов;
- балансировщики нагрузок, сервисы очередей;
- систему слежения за автомобилями;
- панели управления серверами;
- ПО для медицинского оборудования;
- ПО для управления линиями по производству композитной арматуры;
- и многое другое.

С радостью поделюсь накопленным опытом и знаниями.

Контакты:
Skype: evgeny.mamonov
WhatsApp, Viber: +79885762574
Telegram: EvgenyMamonov
Местоположение
Россия, Краснодарский край, Горячий Ключ

Достижения

Все достижения (3)

Наибольший вклад в теги

Все теги (28)

Лучшие ответы пользователя

Все ответы (45)
  • Структура проекта на Golang?

    EvgenyMamonov
    @EvgenyMamonov
    Senior software developer, system architect
    Добрый день.

    Это попытка стандартизировать структуру проекта (многие ориентируются на неё)
    https://github.com/golang-standards/project-layout

    Go-Kit - очень грамотная структура, очень
    https://github.com/go-kit/kit

    И обязательно стоит посмотреть
    https://12factor.net/ru/

    Что касается "Т.е. в одном файле может быть сразу модель, сервис и репозиторий. Есть ли какие-то бестпркатики по этому вопросу?" - то это не совсем так, в одном пакете (папке) может быть и модель, и сервис, и репозиторий". Например вот так:
    yourpackage/service.go
    yourpackage/repo.go
    yourpackage/model.go
    И это всё будет доступно в рамках пакета.

    Лично я использую такую схему:
    cmd/ - команды исполняемого файла
    conf/ - конфиги приложения (env файлы)
    init/ - конфиги logrotated, nginx, systemd и т.д.
    pkg/ - публичные пакеты
    pkg/packagename/ - тут определяются интерфейсы (сервиса, репозитория и т.д.) в разных файлах
    pkg/packagename/endpoints/http - endpoint'ы для HTTP
    pkg/packagename/repo/mysql - реализация репозитория на MySQL
    pkg/packagename/repo/gorm - реализация репозитория на GORM (для примера)
    pkg/packagename/service/ реализация сервиса

    Я написал очень кратко, если что-то не понятно или есть вопросы - пишите, я опишу подробнее
    Ответ написан
  • Есть ли смысл для увеличения производительности использовать несколько подключений к одной БД?

    EvgenyMamonov
    @EvgenyMamonov
    Senior software developer, system architect
    Нет, там уже используется пул соединений.

    Можно указать количество ожидающих (IDLE) соединений db.SetMaxIdleConns и максимальное количество одновременно открытых соединений через db.SetMaxOpenConns
    Ответ написан
  • Как работают современные мессенджеры?

    EvgenyMamonov
    @EvgenyMamonov
    Senior software developer, system architect
    как сервер за столь короткое время умеет прошерстить базу данных, найти сообщения конкретного пользователя и отдать их

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

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

    Что касается безопасности, если не использовать e2e шифрование, как вариант, можно использовать обычные RSA ключи. Например на сервере генерируем два ключа, открытый отправляем кленту, он шифрует им сообщение и передает сообщение на сервер. Вы на сервере его расшифровываете при помощи закрытого ключа. Для отправки сообщения клиенту, можно сделать тоже самое. Клиент также генерирует два RSA ключа и открытый ключ отправляет серверу. Когда серверу нужно доставить сообщение клиенту, он шифрует сообщение открытым ключём, который ему высылал клиент и отправляет ему.

    Мне тоже интересно узнать другие варианты решения этой задачи, буду следить за этой темой :)

    Хорошее дополнение по хранению сообщения и организации поиска от Ильи
    Распределение нагрузки решается шардингом — получается много небольших БД вместо одной огромной. Скорее всего каждое сообщение разбивается по словам/частям слов и сохраняется в поисковый индекс типа слово—message_id и такой индекс строится для каждого пользователя и тоже шардируется. При поиске сначала получаем идентификаторы подходящих сообщений из поискового индекса, потом выгружаем сообщения из БД с сообщениями.

    Дополнение от Stalker_RED
    только не "сообщения одного пользователя всегда были на одном и том же сервере" а сообщения из одного чата/канала/группы (включая чаты, в котором всего два участника). То-же самое касается построения индекса.
    Ответ написан
  • Есть ли примеры структуры go проекта с воркерами?

    EvgenyMamonov
    @EvgenyMamonov
    Senior software developer, system architect
    Есть смысл скомпилировать CLI приложение и запускать уже бинарник с нужными параметрами, например так
    yourprog worker1
    yourprog worker2

    Можно использовать вот эти библиотеки:
    https://github.com/urfave/cli (хороший и простой, советую начать с него)
    https://github.com/spf13/cobra (очень мощный, его использует Docker)

    Структура проекта у вас также немного изменится, в Go принято делать папочку cmd, типа так:
    cmd/
    cmd/worker1.go
    cmd/worker2.go

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

    По структуре проекта на Go уже был вопрос, вот тут хорошо описано Структура проекта на Golang?
    Ответ написан
  • Как приспособить программу к многочисленным изменениям?

    EvgenyMamonov
    @EvgenyMamonov
    Senior software developer, system architect
    Если я верно понял задачу, то у вас база в одном формате, а данные приходят в разных.
    Если это так, тогда вам нужно просто сделать 3 класса:
    1 - преобразовывает данные в формате 1 во внутреннюю структуру (пригодную для сохранения в базу)
    2 - преобразовывает данные в формате Х во внутреннюю структуру
    3 - сохраняет данные из внутренней структуры в базу
    Это стандартная практика для подобных задач.
    Если вам будет нужно сохранять данные не в базу, а куда то еще, например в облако - вы просто добавите еще один класс, который умеет сохранять данные в нужном формате/на облако.
    Ответ написан