Проектирование архитектуры распределенной и сервис-ориентированной ERP-системы

задняя часть Архитектура дизайн

ERPболь

Когда-то я работал в сфере электронной коммерции и ювелирных изделий более 4 лет и разработал две масштабные бизнес-системы (ERP) для этих двух отраслей. В качестве ERP-системы основными функциональными модулями системы являются не что иное, как управление заказами, управление товарами, производственные закупки, управление складом, управление логистикой, управление финансами и так далее. Что касается системы управления, то общая привычка разработчиков состоит в том, чтобы использовать технологию .Net или Java для создания приложения с одноблочной (однопроцессной) архитектурой и только с одной базой данных SQLServer или MySql. Затем разделите каждый модуль в файле проекта и организуйте написание кода и разработку в виде трехуровневой структуры. Финальный тест, доставка онлайн.

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

Чтобы повысить производительность системы, мы можем взять на себя инициативу изучить технический опыт некоторых интернет-компаний, таких как высокий параллелизм, высокая производительность, большие данные, разделение чтения-записи и другие решения, и обнаружить, что у нас нет возможности начать. . Мы почувствуем это, потому что бизнес-характеристики системы различны. Параллелизм системы ERP невысок, в основном из-за сложности бизнеса. Степень связанности различных предприятий намного выше, чем у Интернет-приложений. Ее нелегко разделить. Логика запроса данных намного сложнее, чем в Интернете. Данные, запрашиваемые со страницы списка, часто требуют сопоставления 4 или 5 таблиц для получения результата. Некоторые классы отчетов имеют даже больше. Кроме того, транзакционный характер различных бизнес-операций и высокие требования к согласованности данных часто застают нас врасплох и не позволяют оптимизировать систему дальше.

Когда-то я тоже расстраивался по той или иной причине, думая, что ERP-системы особенные и неизлечимые, но потом. . .

Я так больше не думаю, кажется, есть новое решение O(∩_∩)O, ха-ха~

Рассвет

Прежде чем рассказывать конкретный план, давайте поговорим о ваших собственных идеях. Прежде всего, я думаю, что прежде чем мы сможем построить ERP-систему, мы должны иметь сегодняшнее интернет-мышление. Мы больше не хотим делать универсальную систему. Нам нужно разделить большую систему на маленькие системы. Затем эти небольшие системы связываются друг с другом через системный интерфейс. Таким образом формируется большая система, в частности, Интернет, мыслящий как «распределенный» и «сервисно-ориентированный». Архитектурный дизайн системы — это врожденная поддержка высоко масштабируемой системы.

Как это сделать? В частности, управление заказами, управление товарами, производственные закупки, управление складом, управление логистикой и управление финансами следует разделить на подсистемы. Эти подсистемы могут проектироваться и разрабатываться независимо друг от друга, а интерфейсы данных, требуемые различными другими подсистемами, могут быть доступны внешнему миру. Каждая подсистема имеет отдельную базу данных. Даже эти подсистемы могут разрабатываться и поддерживаться разными командами, с использованием разных технических систем и разных баз данных. Вместо того, чтобы быть интегрированным в ту же самую большую и всеобъемлющую систему, как раньше, большая и всеобъемлющая база данных.

Какие преимущества она имеет для системы с новой архитектурой?

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

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

Общий дизайн системы

Вид физического развертывания системы

детальный дизайн

Разделить слой приложения

Разделение прикладного уровня — это концепция реализации «микросервисной» архитектуры. Исходная крупная и всеобъемлющая архитектура с одним процессом разделена на независимо развертываемые приложения в соответствии с бизнес-модулями, чтобы обеспечить плавное обновление системы и облегчить увеличение нагрузки. В частности, технически вы можете использовать интерфейс в стиле restfull или вы можете использовать фреймворк, такой как dubbo в java, чтобы упростить разработку. ERP Web или другие мобильные терминалы также представляют собой отдельное приложение, которое действует как уровень представления. Очень тонкий, просто примите параметры и вызовите интерфейсы различных других микросервисных программ в фоновом режиме, чтобы получить данные для отображения. Микросервисы действуют как уровень бизнес-логики.Каждый микросервис представляет собой программу, которая может быть развернута независимо и предоставляет интерфейсы доступа к данным.

Микросервисы могут использовать различные популярные фреймворки RPC, такие как dubbo, которые могут поддерживать несколько протоколов вызовов Http, TCP и т. д. Эти фреймворки упрощают кодирование, а фреймворк инкапсулирует базовые детали передачи данных, так что клиент может выполнять удаленные методы, как будто выполнение локальных методов.

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

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

разделить слой данных

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

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

Таблица материалов:

Идентификатор материала

название

Идентификатор категории

Z0001

Iphone6 ​​красный чехол для телефона

Z

Z0002

iPhone6 ​​черный чехол для телефона

Z

Инвентарная таблица:

Идентификатор материала

идентификатор склада

количество

Z0001

W1

10

Z0002

W1

20

Таблицы категории и склада опущены. . .

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

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

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

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

Система отчетности

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

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

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

Распределенная транзакция

Возможно, кто-то еще раз спросил, а многие операции в ERP-системе требуют транзакции, как добиться транзакции после раздельной системы, защитить согласованность данных?

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

Возможно, вы слышали о концепции распределенных транзакций. Возможны два сценария. Первый заключается в том, что в приложении используется несколько баз данных. Для обеспечения согласованности данных необходимо использовать распределенные транзакции. Другая ситуация для нашей архитектуры. Например, распределенные транзакции в микросервисной среде. Операция закупок и складирования спроектирована в службе управления складом. После получения необходимо обновить количество поступления в заказе на покупку в подсистеме закупок. Этот процесс требует согласованности данных, т. е. количества, записанного в таблицу запасов после того, как заказ на покупку был успешно помещен в хранилище, и одновременно необходимо обновить введенное количество в таблице заказа на покупку. Мы не можем напрямую обратиться к базе данных в службе закупок в службе склада, а должны пройти через интерфейс службы, предоставляемый службой закупок. Если да, то как мы можем гарантировать согласованность данных? Потому что очень вероятно, что инвентарная таблица записывается успешно, но вызов службы закупок для записи данных заказа на покупку завершается неудачно. Это может быть вызвано проблемами с сетью, поэтому данные несовместимы.

В технологии распределенных транзакций есть поговорка о достижении окончательной согласованности, что означает, что пока я могу гарантировать, что данные на обеих сторонах в конечном итоге достигнут согласованности, нет необходимости использовать транзакции. Итак, есть план. Например, подсистеме склада необходимо добавить несколько таблиц, таких как данные складских документов, и обновить данные запасов при обработке складских запасов. Все эти несколько таблиц находятся в подсистеме хранилища, и мы можем использовать локальную транзакцию для обеспечения согласованности данных таблицы в подсистеме хранилища. Затем вызовите подсистему закупок, чтобы обновить количество на складе в заказе на покупку. Чтобы предотвратить внезапное прерывание этого процесса и вызвать сбой вызова, мы рассматриваем возможность добавления промежуточного программного обеспечения очереди сообщений, такого как ActiveMQ. Если интерфейс не возвращается, мы записываем запрос на обработку в MQ.После того, как подсистема закупок возвращается в нормальное состояние, MQ уведомляет подсистему закупок о необходимости обработки операции обновления. Поскольку дальнейшего уведомления после потребления сообщения не будет, а во время обработки подсистемы закупок возникает исключение, обновление завершается сбоем, и проблему необходимо записать в локальную библиотеку журналов, чтобы администратор мог быть уведомлен для последующего компенсационная обработка. Таким образом, окончательная согласованность данных может быть достигнута с помощью различных методов. Хотя это звучит немного сложно, это решение. Нет другого лучше. Или после сбоя обновления вызовите подсистему хранилища, чтобы откатить заказ инвентаризации и данные инвентаризации, чтобы добиться согласованности в конечном итоге! как показано на рисунке:

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