Не так давно я как архитектор завершил строительство бизнес-центра для известной FMCG компании. После того, как система была подключена к сети, она пережила пик трафика события Double Eleven, и в целом работа была стабильной. Когда у меня будет время в последнее время, я поделюсь идеями и опытом этой архитектуры в этом блоге. Он не будет вдаваться в каждую техническую деталь, но сделает краткий обзор технологий, фреймворков и инструментов, используемых для дальнейшего использования.
бизнес-архитектура
С точки зрения бизнес-архитектуры, система, как бизнес-центр, в основном отвечает за управление активами клиентов, включая карты клиентов, купоны и другие виртуальные активы. Предоставляйте услуги, открывая стандартные интерфейсы Restful для внешнего мира. В число абонентов сервиса входят приложения и мини-программы собственных каналов, а также партнерские каналы, в том числе China Merchants Bank и Ali. Сама система также будет вызывать другие интерфейсы бизнес-систем внутри компании через сервисный шлюз, такие как синхронизация информации об участниках через интерфейс центра обслуживания клиентов.
Согласно текущей статистике, ежедневный объем служебных вызовов этого бизнес-центра составляет около 7 миллионов раз, а во время работы он превысит 10 миллионов раз. Большинство транзакций происходит во время работы, обеденного перерыва и около 15:00 (послеобеденный чай).
Из-за особенностей бизнеса заказчика бизнес-архитектура здесь подробно описываться не будет.
Технологическая архитектура
В данном случае используется микросервисная архитектура на основе SpringBoot. В сочетании с собственными инфраструктурными объектами предприятия осуществляется контейнерное развертывание K8S, а Kong API Gateway используется для унифицированного управления API-интерфейсами, предоставляемыми промежуточной платформой каждого бизнеса.
Kong API Gateway
С ростом популярности микросервисной архитектуры на предприятиях первоначальная большая и комплексная система делится на более мелкие, а большинство функций в системе заменяется службами, предоставляемыми в виде Restful API, что делает ИТ-систему более быстрой. к проблемам, вызванным бизнес-изменениями, но в то же время, с увеличением количества услуг, как эффективно управлять этими услугами, стало проблемой.
В некоторых небольших и средних проектах мы обычно используем стек технологий Spring Cloud и выбираем Spring Cloud Gateway в качестве сервисного шлюза. Однако для некоторых крупных предприятий управление службами, производительность шлюза и другие расширенные функции необходимо рассматривать глобально.
В данном случае компания использовалаKongв качестве шлюза API. Центральной платформе потребуется открыть API для внешнего использования, зарегистрироваться через консоль шлюза, добавить сертификаты и сгенерировать ключи аутентификации для использования связанными сторонами.
Kong обладает следующими характеристиками, которые вполне могут удовлетворить потребности крупных организаций в сервисных шлюзах:
- Открытый исходный код (в данном случае используется корпоративная версия Kong, предоставляющая оригинальные заводские сервисы)
- Задержка отклика менее миллисекунды благодаря сверхвысокой производительности на основе Nginx и OpenResty.
- 25 000 операций в секунду на узел
- Сертификация, авторизация, лимитированный поток, конвертация данных (идентификатор участника в этом случае добавляется в заголовок запроса), лог, статистический анализ
Архитектура приложений
Вся система использует java для разработки серверной части и vue для разработки внешнего интерфейса.Прикладная часть разделена на четыре сервисных компонента, каждый из которых контейнеризован и развернут, а также открытые сервисы через балансировку нагрузки Ingress Controller:
- Служба активов: предоставление интерфейса службы, связанного с активами клиентов.
- Служба потребления активов: служба прослушивания MQ, асинхронно обрабатывающая запросы, связанные с активами.
- Служба консоли: управление активами и интерфейс службы обслуживания для внешнего интерфейса консоли.
- Консольный внешний интерфейс: консольное внешнее приложение, разработанное с помощью Vue (как показано ниже).
SpringBoot
За исключением внешнего интерфейса консоли, остальные три компонента разрабатываются с использованием текущей основной микросервисной среды Java SpringBoot 2.3.4 (с учетом стабильности последняя версия 2.4 не используется).
В этом случае за счет разработки и разработки приложений для достижения формы представления данных единой системы и стандартного преобразования данных, проверки, связывания сообщений, функций обработки ошибок. Архитектор отвечает за структуру приложения, простую, эффективную и унифицированную структуру приложения, чтобы повысить эффективность разработки, согласованный стандартный код вывода, чтобы обеспечить доставку качества.
Прикладные рамки не в рамках этой статьи, а некоторые из следующих советов или сторонних пакетов, но в большинстве Sprilboot мы создаем приложения для использования.
####Пользовательский MyBatis Платформа уровня данных принимает MyBatis, В крупномасштабных приложениях MyBatis может помочь программистам лучше контролировать взаимодействие уровня данных и выполнять настройку. Как правило, MyBatis можно настроить в application.yml, но когда нам нужно разрешить MyBatis поддерживать дополнительные пользовательские функции (например, поддержку нескольких баз данных), это можно сделать, определив bean-компонент SqlSessionFactory.
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean sfb = new SqlSessionFactoryBean();
sfb.setDataSource(dataSource);
sfb.setVfs(SpringBootVFS.class);
Properties props = new Properties();
props.setProperty("dialect", dataConfiguration.getDialect());
props.setProperty("reasonable", String.valueOf(dataConfiguration.isPageReasonable()));
PageHelper pagePlugin = new PageHelper();
pagePlugin.setProperties(props);
Interceptor[] plugins = {pagePlugin};
sfb.setPlugins(plugins);
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sfb.setMapperLocations(resolver.getResources("classpath*:mappers/"+ dataConfiguration.getDialect()+"/*.xml"));
sfb.setTypeAliasesPackage("com.xxx.bl.core.data.model");
SqlSessionFactory factory = sfb.getObject();
factory.getConfiguration().setMapUnderscoreToCamelCase(true);
// factory.getConfiguration().addInterceptor(new CoreResultSetHandler());
factory.getConfiguration().setCallSettersOnNulls(dataConfiguration.isCallSettersOnNulls());
return factory;
}
Использование компонента логбэка
Используя структуру ведения журнала, вы можете указать в файле конфигурации журнала, чтобы использовать разные уровни журнала и разные приложения для разных профилей Spring в разных средах. В то же время вводится зависимость spring-cloud-starter-sleuth, и при установке traceId все журналы по всей цепочке запросов выводят один и тот же traceId, что значительно облегчает совместное исследование производственных проблем между различными системами. Кроме того, использование асинхронной записи журнала также способствует уменьшению блокировки ввода-вывода.
<springProfile name="stg">
<root level="error">
<appender-ref ref="STDOUT"/>
<appender-ref ref="SAVE-ERROR-TO-FILE-STG"/>
</root>
<logger name="org.xxx" level="error" additivity="false">
<appender-ref ref="STDOUT"/>
<appender-ref ref="ASYNC-SAVE-TO-FILE-STG"/>
</logger>
</springProfile>
<springProfile name="prod">
<root level="error">
<appender-ref ref="STDOUT"/>
<appender-ref ref="SAVE-ERROR-TO-FILE-PROD"/>
</root>
<logger name="org.xxx" level="error" additivity="false">
<appender-ref ref="ASYNC-SAVE-TO-FILE-PROD"/>
</logger>
</springProfile>
SSL-шифрование и безопасность паролей
Полноканальное шифрование при передаче стало важной мерой безопасности предприятия. Введя сертификат jks, выданный ЦС (или самоподписанный) в пути к классам, и просто настроив его в файле конфигурации приложения, можно реализовать SSL-шифрование приложения SpringBoot.
ssl:
enabled: true
key-store: classpath:xxx.net.jks
key-store-type: JKS
key-store-password: RUIEIoUD
key-password: RUIEIoUD
require-ssl: true
Пароли хранятся в конфигурационном файле в виде открытого текста, что также небезопасно. Вы можете jasypt пароль, используемый в зашифрованном файле конфигурации, или использовать решение Key-Vault напрямую, Например, в этом случае мы будем использовать Azure Key Vault в облачной среде Microsoft или решение Cyberark Conjur в локальном IDC соответственно. .
###Синхронные и асинхронные сервисы Мы не использовали Spring Webflux для поддержки реактивной функции, потому что это увеличило бы сложность разработки, и хотя Webflux улучшает механизм блокировки веб-контейнера, он не может принципиально решить проблему блокировки при поступлении большого количества одновременных запросов.
В этом случае 3-узловой зеркальный кластер RabbitMq строится как промежуточное ПО сообщений, и при поддержке фреймворка приложения реализуется функция синхронного и асинхронного переключения сервиса. Мы регистрируем предоставляемые извне сервисы в базе данных и считываем их в кеш Redis при запуске приложения. Когда приходит запрос, код API используется для определения режима ответа на запрос: синхронный или асинхронный. Если это синхронный запрос, он будет обработан напрямую, а если это асинхронный запрос, он будет отправлен в RabbitMq, а затем асинхронно использован инкапсулированным потребительским компонентом, в конечном итоге достигнув цели ограничения пиков.
Для разработчиков им нужно сосредоточиться только на разработке бизнес-логики службы, а структура приложения единообразно обрабатывает синхронизацию и асинхронное переключение службы, обработку исключений при отправке или сбое сообщения и обслуживание недоставленных сообщений. очередь.
Dockerfile
Четыре компонента в этом случае должны реализовать контейнерное развертывание, создавая файлы Dockerfile для приложений SpringBoot и приложений Vue соответственно.
Типичный файл Dockerfile приложения SpringBoot выглядит следующим образом.Как правило, крупные организации создают частные репозитории образов.Образы быстрее извлекать через частные репозитории, что может сэкономить время CICD.
FROM openjdk:11-jre
#FROM cargo.xxx.net/library/openjdk:11-jre
ARG JAR_FILE=console-service/build/libs/*.jar
COPY ${JAR_FILE} app.jar
EXPOSE 9002
EXPOSE 9003
ENTRYPOINT [ "java", "-jar", "/app.jar" ]
Dockerfile приложения vue выглядит следующим образом, и для шифрования передачи также добавлен сертификат SSL:
FROM cargo.xxx.net/library/nginx:stable-alpine
COPY /dist /usr/share/nginx/html/console
COPY nginx.conf /etc/nginx/nginx.conf
ARG KEY_FILE=stg.xxx.net.key
ARG PEM_FILE=stg.xxx.net.pem
COPY ${KEY_FILE} /etc/ssl/certs/cert.key
COPY ${PEM_FILE} /etc/ssl/certs/cert.pem
EXPOSE 80
CMD [ "nginx", "-c", "/etc/nginx/nginx.conf", "-g", "daemon off;" ]
Есть несколько соображений при написании dockerfile:
- Базовое изображение: рекомендуется максимально использовать официальное изображение.
- Выберите версию среднего размера: если выбранный базовый образ слишком велик, после запуска будет потребляться больше ресурсов, что повлияет на производительность системы. Если он слишком мал, может отсутствовать важная функциональность.
- Использовать кеш: запишите неизменяемый контент в файл докер-файла в верхней части файла докер-файла.
##Схема базы данных В системе с сотнями миллионов данных учетных записей и десятками миллиардов данных транзакций требуется решение для подбазы данных и подтаблицы. В этом случае используется схема архитектуры базы данных MyCat+MySQL. Используя mycat для проксирования Master и Slave, он может гибко переключаться между master и slave. Ведомое устройство можно использовать в качестве главного горячего резервного копирования, а также в качестве библиотеки чтения для обеспечения разделения чтения и записи. Помимо использования в качестве резервного копирования в квазиреальном времени, резервная база данных также может использоваться в качестве базы данных для эксплуатации и обслуживания или обеспечивать извлечение данных из платформы больших данных.
В то же время он использует дизайн с двумя машинными залами с 1 ведущим, 2 ведомыми и 1 резервным.
- Полусинхронные программы Master to Slave для обеспечения согласованности данных из библиотеки.
- Когда ведущий неисправен, переключитесь на ведомого с помощью Mycat, ведомый преобразуется в новый ведущий
- После нештатного восстановления ведущего устройства сначала установите исходное ведущее устройство в качестве ведомого, а затем переключитесь обратно на официальное ведущее устройство после завершения синхронизации данных.
высокая доступность mycat
Mycat использует контейнерную операцию k8s, использует службу k8s для балансировки нагрузки mycat и обеспечивает высокую доступность кластера mycat. Если узел-контейнер mycat неисправен, приложение автоматически подключается к другому узлу mycat.
Большое количество операций в базе данных — это операции чтения, на которые обычно приходится более 70% всех операций. Поэтому необходимо разделять чтение и запись, если не разделить чтение и запись, то ведомая библиотека тоже большая трата. Mycat может легко разделить чтение и запись с помощью конфигурации, операций чтения в подчиненной библиотеке, улучшить использование ресурсов и операций записи в основной библиотеке, чтобы снизить нагрузку на основную библиотеку.
Подбиблиотека и подтаблица
- Вертикальная подбиблиотека: разделите данные в соответствии с функцией и поместите данные в разные базы данных и серверы. Например, разные данные в таких областях бизнеса, как учетные записи, активы и транзакции, размещаются в разных библиотеках, чтобы распределить давление, уменьшить взаимное влияние и уменьшить связанность, а независимые модули выпускаются независимо друг от друга.
- Горизонтальный подрепозиторий: когда вертикальный подрепозиторий не может удовлетворить требования, модель делится по горизонтали, а данные одного и того же объекта и разных диапазонов распределяются по разным базам данных, сохраняя количество и давление одной базы данных, увеличивая количество подключений и достижение горизонтального расширения.
Горячий и холодный тарифный план
кеш горячих данных
- Для часто используемых данных, таких как информация о клиентах часто используемых приложений, соответствующим образом увеличьте кэш запросов к базе данных, чтобы повысить производительность запросов к базе данных.
- На уровне приложения кэш памяти, такой как Redis, используется для кэширования некоторых часто используемых данных, что сокращает время ответа на запрос, повышает беглость системы и улучшает качество обслуживания клиентов.
- Разделите чтение и запись, используйте подчиненную библиотеку для предоставления услуг запроса данных, улучшите использование аппаратных ресурсов подчиненной библиотеки, уменьшите давление чтения главной библиотеки и увеличьте производительность записи главной библиотеки. Повысить общую эффективность.
Холодное архивирование данных
- Для холодных данных, которые редко используются или не используются вообще, таких как исторические транзакции, исторические купоны и т. д., данные архивируются для повышения производительности базы данных.
- Он также может предоставлять функцию запроса исторических транзакций, которая используется реже, и использовать резервную базу данных для предоставления услуг.
- Для транзакционных данных рекомендуется разбивать базы данных и таблицы по дате.Ежедневные транзакции разбиваются на одну или несколько частей.Для исторических транзакций, таких как транзакции годичной давности, выполняется регулярная миграция и архивирование для повышения производительности базы данных.
Контейнерное развертывание DEVOPS и K8S
####Конвейер DEVOPS В этом случае через платформу CICD на базе jenkins код приложения берется из кодовой базы github, собирается с помощью gradle (фронт-энд собирается с помощью npm), а затем после создания образа через dockerfile развертывается на контейнерной платформе K8S. .
В процессе непрерывной интеграции добавляются этапы проверки безопасности, проверки соответствия и модульного тестирования (JUnit для приложения SpringBoot и среда тестирования Jest для внешнего приложения Vue), чтобы обеспечить качество каждого выпуска. ###Карта конфигурации ConfigMap используется для отделения информации о конфигурации приложения от программы.Этот метод может не только реализовать повторное использование прикладной программы, но и реализовать более гибкие функции за счет различных конфигураций. В этом случае при развертывании приложения SpringBoot в K8S файл application.yml монтируется в виде файла ConfigMap. Следует отметить, что SpringBoot будет предпочтительно читать файл конфигурации в пути к классам, поэтому необходимо исключить файл конфигурации при печати пакета jar приложения springboot и сформулировать файл конфигурации подключенного приложения через параметры команды запуска контейнера.
-spring.profiles.active=prod
-spring.config.location=/config/application.yml
###Развертывание контейнера K8S В платформе развертывания K8S для каждой службы можно указать начальные ресурсы и количество узлов. Например, мы применяем исходную конфигурацию для SpringBoot, конфигурацию ресурсов 2core 4g и количество узлов 20.
Мы можем постепенно масштабировать количество pod по мере необходимости. не вызывая недоступность услуги.
Кроме того, мы также можем использовать эластичное масштабирование, чтобы инициировать контейнер для выполнения эластичного масштабирования на основе определенных ключевых показателей, таких как использование ЦП контейнера в качестве порогового значения. В этом случае благодаря механизму эластичного масштабирования компонентам бизнес-службы предоставляется больше модулей в рабочее и полуденное время пиковой нагрузки, а в ночное время модули изымаются из бизнес-компонентов и предоставляются для выполнения пакетной обработки и выполнения A. сервисный компонент для асинхронного потребления.
Эксплуатация и мониторинг
ELK
ELK — это набор решений, а не часть программного обеспечения, а три буквы — это аббревиатуры трех программных продуктов. E — Elasticsearch, отвечающий за хранение и извлечение логов; L — Logstash, отвечающий за сбор, фильтрацию и форматирование логов; K — Kibana, отвечающий за отображение статистики логов и визуализацию данных.
Dynatrace
Dynatrace может быть лучшим инструментом управления производительностью приложений (APM) в настоящее время, он может не только контролировать инфраструктуру, такую как серверы, контейнеры K8S, но также автоматически обнаруживать и отслеживать динамические микросервисы, работающие в контейнерах, понимать, как они выполняются и как они взаимодействуют с каждым. др. Как общаться и сразу обнаруживать плохо работающие микросервисы. В нашем случае данные мониторинга, на которых нам нужно сосредоточиться, добавляются путем настройки панели мониторинга.
Dynatrace также может автоматически идентифицировать сервисы и предоставлять более точные данные об обнаружении, что очень помогает разработчикам или персоналу по эксплуатации и техническому обслуживанию в поиске проблем.
некоторые размышления
- Проблема вторжения кода, вызванная схемой подтаблиц базы данных: хотя MyCat+MySQL физически реализует подбазу данных и подтаблицу, это создает навязчивые проблемы для разработки и требует специальной конструкции структуры таблицы для ключа сегмента, использование ключа сегмента необходимо дополнительно учитывать при запросе, чтобы повысить эффективность запроса. Другие, такие как обработка транзакций, из-за взаимосвязи между подбазами данных, мы больше не полагаемся на транзакции, а обрабатываем их за счет возможной согласованности данных и компенсации ошибок.
- Выбор будущей базы данных: MyCat+MySQL усложняет эксплуатацию и обслуживание базы данных.В будущем для приложений с большими объемами данных, когда позволяют аппаратные ресурсы, вы можете рассмотреть возможность обращения к решениям NewSQL, таким как TiDB.
- JVM-оптимизация: после выхода приложения в сеть время от времени возникала проблема Long GC в случае высокого параллелизма, которая была решена путем анализа файла дампа и оптимизации использования памяти. Кроме того, для приложений с большими изменениями памяти вы также можете рассмотреть возможность использования jdk13 и включения ZGC.
- Оптимизация кеша: в этом случае информация о конфигурации службы кэшируется Redis, и Redis необходимо считывать каждый раз, когда служба отвечает, что оказывает большое давление на Redis.При введении кеша Guava копия кеша устанавливается локально для достижения многоуровневое кэширование и настройка Установка разумного времени сбоя может значительно снизить нагрузку на Redis.
- Внедрение low-code через фреймворки приложений: Инвестиции в фреймворки приложений очень выгодны.Сосредоточив внимание на общих проблемах, которые необходимо решить в фреймворках приложений, можно в определенной степени реализовать характеристики платформ low-code. Разработчики также могут больше сосредоточиться на реализации бизнес-логики.
- Управление разработкой: позволяя каждому разработчику полностью понимать структуру приложения и формировать унифицированный шаблон для решения схожих проблем, это может значительно повысить эффективность разработки и сократить количество некачественного кода.
Сегодня запишу здесь.По мере углубления практики,думаю,что в будущем будет больше новых дополнений.Также можете поделиться своим опытом.