010
Установка компонента MyBPM API
011
012
Подготовка баз данных
013
014
Прежде чем установить компонент MyBPM API необходимо подготовить
015 доступы к следующим базам данных:
016
017
018 - MongoDB - в этой БД будет храниться оперативная информация. Так
019 же в ней будут храниться файлы. Если количество файлов будет
020 велико, то их стоит вынести в отдельный кластер. В этом случае
021 необходимо подготовить два кластера MongoDB: один для оперативной
022 информации, другой для хранилища файлов.
023
024 - ElasticSearch - в этой БД будет тоже храниться оперативная
025 информация - копия MongoDB. Но использоваться будет по другому. В
026 MongoDB платформа отправляет запросы только по идентификаторам -
027 никаких поисковых запросов туда не отправляется, чтобы не замедлить
028 работу этой БД. Все запросы связанные с поиском отправляются в
029 ElasticSearch.
030
031 - PostgreSQL - в ней храниться различная служебная информация для
032 решения внутренних задач. Также в ней хранятся данные для
033 отчётов.
034
035 - Apache Kafka - в эту БД выгружаются все изменения данных в
036 системе. Их можно хранить, при этом можно хранить историю
037 изменений. Также Apache Kafka используется как брокер сообщений,
038 для обмена точечными сообщениями между различными компонентами
039 платформы.
040
041 - Apache Zookeeper - данная БД используется для хранения
042 конфигурации системы (конфигурационных файлов). Тут настраиваются
043 различные взаимодействия платформы как внутри между подсистемами,
044 так и снаружи - с другими сторонними системами.
045
046
047
Установка Kubernetes
048
049
После того как подготовлены все базы данных нужно установить
050 кластер Kubernetes.
051
052
Подбор имени пространства имён для
053 компонентов платформы MyBPM внутри Kubernetes
054
055
После установки кластера kubernetes необходимо подобрать имя
056 пространства имён. Его рекомендуется выбирать из двух частей:
057
058
059 - первая часть - имя самой платформы в рамках её назначения,
060 например, если Вы используете платформу как CRM, то назовём первую
061 часть как crm.
062
063 - Вторая часть соответствует типу среды: например у нас имеется
064 три среды: test, stage, prod. (тестовая, подготовительная,
065 продуктивная). Например, на если данном этапе мы устанавливаем
066 продуктивную среду, тогда в качестве имени второй части выбираем:
067 prod.
068
069
070
Дальше эти две части соединяем тире, в нашем случае получается
071 следующее имя:
072
073
074 crm-prod
075
076
077
078
079
080
В данном руководстве везде для пространства имён будет
081 использоваться crm-prod
. Вам стоит везде заменять его
082 на то, которое у Вас получилось.
083
084
Вы можете использовать свои подходы для придумывания данного
085 имени, но тот подход, зарекомендовал себя как удобный при условии,
086 если у Вас много различного программного обеспечения размещённого
087 на разных кластерах Kubernetes. По такому имени сразу становиться
088 понятным, что имеется ввиду, и можно ли там смело что-то менять.
089 Например, если Вы все продуктивные среды называете с окончанием
090 -prod
, то увидев такое окончание, Вы будете работать
091 аккуратно.
092
093
Установка MyBPM API
094
095
Для установки MyBPM API можно воспользоваться yaml-файлом:
096
097
Файл: 10-mybpm-api.yaml
098
099
100 apiVersion: v1
101 kind: Service
102 metadata:
103 name: mybpm-api
104 labels:
105 app: mybpm-api
106 namespace: crm-prod
107 spec:
108 #type: NodePort
109 ports:
110 - protocol: TCP
111 port: 8080
112 targetPort: 8080
113 #nodePort: 30207
114 selector:
115 app: mybpm-api
116 ---
117 apiVersion: apps/v1
118 kind: Deployment
119 metadata:
120 name: mybpm-api
121 labels:
122 app: mybpm-api
123 namespace: crm-prod
124 spec:
125 selector:
126 matchLabels:
127 app: mybpm-api
128 replicas: 1
129 template:
130 metadata:
131 labels:
132 app: mybpm-api
133 spec:
134 nodeSelector:
135 mybpm-api: ok
136 containers:
137 - name: main
138 image: hub.mybpm.kz/mybpm-api-release:4.24.18.7 # здесь нужно указать актуальную версию
139 imagePullPolicy: IfNotPresent
140 resources:
141 requests:
142 memory: "3Gi"
143 limits:
144 memory: "3Gi"
145 ports:
146 - containerPort: 8080
147 env:
148 - { name: MYBPM_JAVA_OPTS, value: "-Xmx2Gi -Xms2Gi" }
149 - { name: MYBPM_ALL_CONSUMERS_OFF, value: "true" }
150 - { name: MYBPM_CONSUMER_DIR, value: "api" }
151 - { name: MYBPM_COMPANY_CODE, value: "greetgo" }
152 - { name: MYBPM_LICENCE_NUMBER, value: "6120b632-f91a-416d-a7d0-180ffd7ce380" } # поставьте сюда Ваш номер лицензии
153 - { name: MYBPM_MONGO_SERVERS, value: "mongo:27017" } # поставьте сюда правильный доступ к MongoDB
154 - { name: MYBPM_ZOOKEEPER_SERVERS, value: "zookeeper-1:2181" } # поставьте сюда правильный доступ к Zookeeper
155 - { name: MYBPM_KAFKA_SERVERS, value: "kf-1:9092,kf-2:9092,kf-3:9092" } # поставьте сюда правильный доступ к Kafka
156 - { name: MYBPM_AUX1_HOST, value: "pg-aux1-host" }# поставьте сюда правильный доступ к PG
157 - { name: MYBPM_AUX1_PORT, value: "5432" }
158 - { name: MYBPM_AUX1_DB_NAME, value: "mybpm_aux1" }
159 - { name: MYBPM_AUX1_USER_NAME, valueFrom: { secretKeyRef: { name: pg_mybpm_aux1, key: username } } }
160 - { name: MYBPM_AUX1_PASSWORD, valueFrom: { secretKeyRef: { name: pg_mybpm_aux1, key: password } } }
161 - { name: MYBPM_ELASTIC_SEARCH_SERVERS, value: "elastic:9200" }
162 - { name: MYBPM_NODE_NAME, valueFrom: { fieldRef: { fieldPath: spec.nodeName } } }
163 - { name: MYBPM_MEMORY_LIMIT, valueFrom: { resourceFieldRef: { containerName: main, resource: limits.memory } } }
164 - { name: MYBPM_NODE_NAME, valueFrom: { fieldRef: { fieldPath: spec.nodeName } } }
165 startupProbe:
166 httpGet: { path: /web/health, port: 8080 }
167 initialDelaySeconds: 15
168 failureThreshold: 175
169 periodSeconds: 4
170 readinessProbe:
171 httpGet: { path: /web/health, port: 8080 }
172 initialDelaySeconds: 10
173 periodSeconds: 4
174 livenessProbe:
175 httpGet: { path: /web/health, port: 8080 }
176 initialDelaySeconds: 13
177 periodSeconds: 4
178 volumeMounts:
179 - { name: log-dir, mountPath: "/var/log/mybpm" }
180 volumes:
181 - name: log-dir
182 #... определение этого volume
183
184
185
186
Применить это файл можно с помощью команды:
187
188
189 kubectl apply -f 10-mybpm-api.yaml
190
191
192
193
194
195
Для работы этого файла, нужно завести секрет
196 pg_mybpm_aux1
. Его можно создать с помощью
197 yaml-файла:
198
199
200 apiVersion: v1
201 kind: Secret
202 metadata:
203 name: pg_mybpm_aux1
204 data:
205 username: mybpm # здесь нужно поставить правильного пользователя к postgres-у
206 password: 4jk1v23k4j231j4b # а здесь пароль
207
208
209
210
Подредактируйте в этих файлах параметры, как указано в
211 комментариях.
212
213
При запуске сервера в логах будет информация о запуске.
214
215
При старте программа проверит доступы ко всем базам данных. Если
216 какого-то доступа не будет, то произойдёт ошибка и программа
217 остановиться с ошибкой.
218
219
Если доступы все будут, то система активирует все указанные
220 сервисы.
221
222
Инициирует конфиги значениями по умолчанию.
223
224
И выдаст сообщение об успешном запуске. Выглядеть оно будет
225 примерно так:
226
227
228 2024-08-12T10:27:10.581 k.g.m.s.d.l.MybpmServer INFO Started MybpmServer in 19.982 seconds (process running for 24.588)
229
230
231
232
233
234
После этого активирует получатели кафки.
235
236
Примечания
237
238
Настройка доступа к базам данных
239
240
Смотрите здесь: Настройка п.о.,
241 для доступа к базам данных
242
243
Параметр nodeSelector
244
245
Этот параметр позволяет контролировать на каких node-ах можно
246 запускать данную программу, а на каких нет.
247
248
Обратите внимание, что в yaml-файле есть параметр:
249
250
251 nodeSelector
252
253
254
255
256
257
Этот параметр определяет node-у, на которой будет запускаться
258 данная программа.
259
260
В нашем случае у этой настройки указано значение:
261 mybpm-api: ok
. Это значение обозначает, что данная
262 программа будет запускаться только на тех node-ах, на которых
263 установлен атрибут: mybpm-api
, и значение этого
264 атрибута должно быть ok
. На node-ах, где это не
265 соблюдается, данная программа запускаться не будет.
266
267
Пожалуйста, установите данный атрибут на тех node-ах, на которых
268 Вы планируете запускать данную программу.
269
270
Если Вы хотите, чтобы программа запускалась на любых node-ах, то
271 просто удалите этот параметр из yaml-файла.
272
273
Масштабирование в ширину - параметр
274 replicas
275
276
Обратите внимание, что в yaml-файле есть параметр:
277
278
279 replicas
280
281
282
283
284
285
Он обозначает количество подов, которые надо запустить. Если
286 один под не справляется с текущей нагрузкой, то можно этот параметр
287 увеличить. Тогда Kubernetes запустит дополнительные поды, и, через
288 встроенный балансировщик нагрузки, запросы в программу
289 распределяться равномерно.
290
291
Компонент MyBPM API не содержит в себе состояния, а значит можно
292 запускать несколько серверов этого компонента и случайным образом
293 распределять запросы между ними, и логических ошибок не будет
294 появляться.
295
296
Заключение
297
298
После того как Вы установили компонент MyBPM API, можно установить компонент MyBPM WEB, и
300 получить доступ к Web-интерфейсу платформы.
301
302
Далее Установка компонента MyBPM
303 WEB
304
305
306
at kz.greetgo.md_reader.util.MdUtil.xmlTextToDoc(MdUtil.java:80)
at kz.greetgo.md_reader.core.MdConverter.prepareHtmlFileFrom(MdConverter.java:136)
at kz.greetgo.md_reader.core.MdConverter.convert(MdConverter.java:208)
at kz.greetgo.md_reader.controller.RenderController.downloadToc(RenderController.java:360)
at kz.greetgo.md_reader.controller.RenderController.request(RenderController.java:108)
at jdk.internal.reflect.GeneratedMethodAccessor3.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:207)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:152)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:884)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1081)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:974)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1011)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
at kz.greetgo.md_reader.interceptors.TextReplaceFilter.doFilter(TextReplaceFilter.java:36)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:166)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:341)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:390)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:894)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.io.IOException: Server returned HTTP response code: 429 for URL: http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:2000)
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1589)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:677)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLEntityManager.startEntity(XMLEntityManager.java:1397)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLEntityManager.startEntity(XMLEntityManager.java:1333)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl.startPE(XMLDTDScannerImpl.java:732)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl.skipSeparator(XMLDTDScannerImpl.java:2101)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl.scanDecls(XMLDTDScannerImpl.java:2064)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl.scanDTDExternalSubset(XMLDTDScannerImpl.java:299)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$DTDDriver.dispatch(XMLDocumentScannerImpl.java:1165)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$DTDDriver.next(XMLDocumentScannerImpl.java:1040)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:943)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:605)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:542)
at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:889)
at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:825)
at java.xml/com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
at java.xml/com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:247)
at java.xml/com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:342)
at java.xml/javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:122)
at kz.greetgo.md_reader.util.MdUtil.xmlTextToDoc(MdUtil.java:71)
... 48 more