
En este artículo, le contaré cómo puede crear un gráfico de ruta para aplicaciones con Apache Camel, rastrear el estado de estas rutas y recopilar métricas para ellas.
Utilizamos Apache Camel en aplicaciones de primavera y en Apache ServiceMix. Y si las rutas en un servicio separado son comprensibles y fácilmente visibles, entonces dentro del bus de datos, donde hay muchas rutas de este tipo, no es tan simple.
¿Qué es Apache ServiceMix?Apache Camel es un marco de código abierto para integrar aplicaciones mediante el uso de dsl simple y un amplio conjunto de componentes de acceso a datos listos para usar.
Apache ServiceMix es una solución de código abierto basada en Apache ActiveMQ, Camel, CXF, Karaf, que le permite crear una plataforma para soluciones de integración. Apache ServiceMix se puede utilizar como un bus de servicio empresarial. Camel en este caso simplificará la creación de rutas en el bus usando dsl en forma de xml, java, scala, etc. Por ejemplo, si necesitamos transferir mensajes de una cola a otra (no pensemos por qué necesitamos esto), podemos describir la ruta en el archivo xml (ejemplo a continuación), soltarlo en el directorio de servicio deseado y se implementará.
<?xml version="1.0" encoding="UTF-8"?> <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"> <camelContext xmlns="http://camel.apache.org/schema/blueprint"> <route> <from uri="file:camel/input"/> <log message="Moving ${file:name} to the output directory"/> <to uri="file:camel/output"/> </route> </camelContext> </blueprint>
La ruta descrita transfiere archivos de un directorio a otro.
Con los años de uso, el neumático ha acumulado más de cien rutas de complejidad variable, y hemos llegado a comprender que cada vez es más difícil recordar todas estas conexiones. Dibujar esquemas de ruta con las manos o describirlos en forma de tablas ha dejado de parecer una solución conveniente y fácilmente compatible. Pero comenzó a parecer que la construcción automática de un gráfico de ruta salvaría a todos.
Para construir un gráfico, necesitas vértices y aristas. ¡Y de estos, cegamos algo hermoso!
Elementos de ruta
El punto de entrada (es uno) para la ruta se describe mediante la declaración from
con una indicación del punto final. Es decir para
<from uri="file:camel/input"/>
El punto final será file:camel/input
. Nos dice que al comienzo de la ruta los archivos se tomarán del directorio camel/input
.
Los puntos de salida de la ruta (hay muchos de ellos, es por eso que indiqué el plural) se determinan de manera diferente, dependiendo de la plantilla de mensajería también con el punto final indicado. En el ejemplo anterior, dicho punto se describe mediante to
. Es decir para
<to uri="file:camel/output"/>
El punto final será el file:camel/output
. Nos dice que al final de la ruta, los archivos se guardarán en el directorio camel/output
.
Los puntos finales son los mejores que necesitamos. Las costillas determinarán las rutas por sí mismas.
Obteniendo descripciones de ruta
Servicemix proporciona la capacidad de acceder a información diversa usando JMX y usaremos jolokia para acceder a esta información a través de http.
Como ejemplo, tome esta descripción de rutas
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> <camelContext xmlns="http://camel.apache.org/schema/spring"> <route id="the-clock-is-ticking"> <from uri="timer://foo?fixedRate=true&period=1000"/> <to uri="jms:topic:timer?connectionFactory=demo"/> </route> <route id="service-a"> <from uri="jms:topic:timer?connectionFactory=demo"/> <to uri="jms:queue:service-a?connectionFactory=demo"/> </route> <route id="service-a-log"> <from uri="jms:queue:service-a?connectionFactory=demo"/> <to uri="log:service-a"/> </route> </camelContext> </beans>
Lista de ruta
El método http://host:8181/jolokia/read/org.apache.camel:type=routes,*
devuelve una lista de rutas con detalles.
Ejemplo de datos de retorno para el service-a
ruta:
"org.apache.camel:context=a.xml,name=\"service-a\",type=routes": { "StatisticsEnabled": true, "EndpointUri": "jms:\/\/topic:timer?connectionFactory=demo", "CamelManagementName": "a.xml", "ExchangesCompleted": 173, "LastProcessingTime": 2, "ExchangesFailed": 0, "Description": null, "FirstExchangeCompletedExchangeId": "ID-...", "StartTimestamp": "2018-12-17T07:01:12Z", "FirstExchangeCompletedTimestamp": "2018-12-17T07:01:13Z", "LastExchangeFailureTimestamp": null, "MaxProcessingTime": 35, "LastExchangeCompletedTimestamp": "2018-12-17T07:04:05Z", "Load15": "", "DeltaProcessingTime": -8, "OldestInflightDuration": null, "ExternalRedeliveries": 0, "ExchangesTotal": 173, "ResetTimestamp": "2018-12-17T07:01:12Z", "ExchangesInflight": 0, "MeanProcessingTime": 4, "LastExchangeFailureExchangeId": null, "FirstExchangeFailureExchangeId": null, "Uptime": "2 minutes", "CamelId": "camel-3", "TotalProcessingTime": 827, "FirstExchangeFailureTimestamp": null, "RouteId": "service-a", "RoutePolicyList": "", "FailuresHandled": 0, "MessageHistory": true, "Load05": "", "OldestInflightExchangeId": null, "State": "Started", "InflightExchanges": 0, "Redeliveries": 0, "MinProcessingTime": 0, "LastExchangeCompletedExchangeId": "ID-...", "Tracing": false, "Load01": "" }
Hay muchos RouteId
y entre ellos, RouteId
, Context
, EndpointUri
, State
, Uptime
son de especial interés para la construcción de gráficos.
Es importante mencionar que el método devuelve métricas a lo largo de la ruta: ExchangesTotal
, ExchangesCompleted
, ExchangesFailed
, ExchangesInflight
, etc.
El método anterior cubre el 90% de nuestras necesidades de datos, pero lo que no devuelve es información sobre los puntos de salida de la ruta. Para obtener esta información, debe utilizar el método para obtener detalles de la ruta y el método para obtener el esquema. Uno de los métodos no es suficiente, ya que en algunos casos los métodos no devuelven todos los datos necesarios para formar una lista de puntos de salida.
Detalles de ruta
Los detalles de la ruta se obtienen del método
http://host:8181/jolokia/exec/org.apache.camel:context=a.xml,type=routes,name="service-a"/createRouteStaticEndpointJson(boolean)/true
Ejemplo de datos devueltos:
{ "request": { "mbean": "org.apache.camel:context=a.xml,name=\"service-a\",type=routes", "arguments": ["true"], "type": "exec", "operation": "createRouteStaticEndpointJson(boolean)" }, "value": "{\"routes\": { \"service-a\": { \"inputs\": [ { \"uri\": \"jms:\/\/topic:timer?connectionFactory=demo\" } ], \"outputs\": [ { \"uri\": \"jms:\/\/queue:service-a?connectionFactory=demo\" } ] }}\n}\n", "timestamp": 1545040570, "status": 200 }
Mapa de ruta
El diagrama de ruta se obtiene del método.
http://host:8181/jolokia/exec/org.apache.camel:context=a.xml,type=routes,name="service-a"/dumpRouteAsXml(boolean)/true
.
El método devuelve el diagrama de ruta en forma xml solo si se dibujó en él. Por ejemplo, si una ruta se describe usando org.apache.camel.builder.RouteBuilder
(usado cuando se describen rutas en una aplicación de primavera), entonces el método no devolverá nada.
Ejemplo de datos devueltos:
{ "request": { "mbean": "org.apache.camel:context=a.xml,name=\"service-a\",type=routes", "arguments": ["true"], "type": "exec", "operation": "dumpRouteAsXml(boolean)" }, "value": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<route customId=\"true\" id=\"service-a\" xmlns=\"http:\/\/camel.apache.org\/schema\/spring\">\n <from uri=\"jms:topic:timer?connectionFactory=demo\"\/>\n <to uri=\"jms:queue:service-a?connectionFactory=demo\" id=\"to5\"\/>\n<\/route>\n", "timestamp": 1545040727, "status": 200 }
Dibujar un gráfico
Combinando toda la información recibida, puede dibujar con seguridad un gráfico, utilicé vis.js
y obtuve este resultado

Los puntos son puntos de entrada y salida, los bordes son rutas y los números grises en las rutas son la métrica Total de ExchangesTotal
.
Graficando para múltiples servicios
El enfoque descrito para la construcción de gráficos también es adecuado para el caso en que se usa camello no solo en el bus de datos, sino también en aplicaciones. Por ejemplo, habiendo descrito la ruta en la aplicación de esta manera:
@Component public class EventRoutes extends RouteBuilder { @Override public void configure() throws Exception { from("jms:topic:timer") .inOnly("bean:service?method=handle"); } }
Puede combinar todos los datos en rutas desde servicemix
y la aplicación y dibujar un gráfico común

Observe que una nueva ruta de jms:topic:timer
to bean:service
aparecido en el diagrama.
Conclusión
Al implementar el enfoque descrito para construir un gráfico de ruta, pudimos obtener una imagen general tanto del autobús como de los servicios integrados. En realidad, el gráfico de nuestro neumático se ve así

Las aplicaciones de prueba de concepto se pueden ver aquí - github