
Neste artigo, mostrarei como criar um gráfico de rota para aplicativos com o Apache Camel, rastrear o status dessas rotas e coletar métricas para elas.
Usamos o Apache Camel em aplicativos de primavera e no Apache ServiceMix. E se as rotas em um serviço separado forem compreensíveis e facilmente visíveis, então no barramento de dados, onde existem muitas dessas rotas, não é tão simples.
O que é o Apache ServiceMixO Apache Camel é uma estrutura de código-fonte aberto para integrar aplicativos através do uso de dsl simples e um rico conjunto de componentes de acesso a dados já prontos.
O Apache ServiceMix é uma solução de código aberto baseada no Apache ActiveMQ, Camel, CXF, Karaf, que permite criar uma plataforma para soluções de integração. O Apache ServiceMix pode ser usado como um barramento de serviço corporativo. Camel, neste caso, simplificará a criação de rotas no barramento usando dsl na forma de xml, java, scala, etc. Por exemplo, se precisarmos transferir mensagens de uma fila para outra (não vamos pensar no porquê disso), podemos descrever a rota no arquivo xml (exemplo abaixo), soltá-la no diretório de serviço desejado e ela será implantada.
<?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>
A rota descrita transfere arquivos de um diretório para outro.
Ao longo dos anos de uso, o pneu acumulou mais de uma centena de rotas de complexidade variada e passamos a entender que está ficando cada vez mais difícil lembrar de todas essas conexões. Desenhar esquemas de rotas com as mãos ou descrevê-los na forma de tabelas deixou de parecer uma solução conveniente e de fácil suporte. Mas começou a parecer que a construção automática de um gráfico de rota salvaria a todos.
Para criar um gráfico, você precisa de vértices e arestas. E destes, cegamos algo bonito!
Elementos da rota
O ponto de entrada (é um) para a rota é descrito pela instrução from
com uma indicação do ponto final. I.e. para
<from uri="file:camel/input"/>
endpoint será file:camel/input
. Ele nos diz que no início da rota os arquivos serão retirados do diretório camel/input
.
Os pontos de saída da rota (existem muitos deles, razão pela qual indiquei o plural) são determinados de maneira diferente - dependendo do modelo de mensagens também com o ponto de extremidade indicado. No exemplo acima, esse ponto é descrito por to
. I.e. para
<to uri="file:camel/output"/>
endpoint será file:camel/output
. Ele nos diz que no final da rota, os arquivos serão salvos no diretório camel/output
.
Os pontos finais são os pontos mais altos que precisamos. As costelas determinarão as próprias rotas.
Obtendo descrições de rota
O Servicemix fornece a capacidade de acessar várias informações usando JMX e usaremos o jolokia para acessar essas informações através de http.
Como exemplo, considere esta descrição de rotas
<?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 rotas
O método http://host:8181/jolokia/read/org.apache.camel:type=routes,*
retorna uma lista de rotas com detalhes.
Dados de retorno de exemplo para a rota service-a
:
"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": "" }
Existem muitos RouteId
e, entre eles, RouteId
, Context
, EndpointUri
, State
, Uptime
são de interesse especial para a construção de gráficos.
É importante mencionar que o método retorna métricas ao longo da rota: ExchangesTotal
, ExchangesCompleted
, ExchangesFailed
, ExchangesInflight
etc.
O método acima cobre 90% de nossas necessidades de dados, mas o que não retorna são informações sobre os pontos de saída da rota. Para obter essas informações, você precisa usar o método de obter detalhes da rota e o método de obter o esquema. Um dos métodos não é suficiente, pois, em alguns casos, os métodos não retornam todos os dados necessários para formar uma lista de pontos de saída.
Detalhes da Rota
Os detalhes da rota são obtidos a partir do método
http://host:8181/jolokia/exec/org.apache.camel:context=a.xml,type=routes,name="service-a"/createRouteStaticEndpointJson(boolean)/true
Exemplo de dados retornados:
{ "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 rotas
O diagrama de rota é obtido a partir do método
http://host:8181/jolokia/exec/org.apache.camel:context=a.xml,type=routes,name="service-a"/dumpRouteAsXml(boolean)/true
.
O método retorna o diagrama de rota no formato xml apenas se ele tiver sido elaborado. Por exemplo, se uma rota for descrita usando org.apache.camel.builder.RouteBuilder
(usado ao descrever rotas em um aplicativo spring), o método não retornará nada.
Exemplo de dados retornados:
{ "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 }
Desenhe um gráfico
Combinando todas as informações recebidas, você pode desenhar com segurança um gráfico, usei o vis.js
e obtive esse resultado

Os pontos são pontos de entrada e saída, as arestas são rotas e os números em cinza nas rotas são a métrica ExchangesTotal
.
Gráficos para vários serviços
A abordagem descrita para a construção de gráficos também é adequada para o caso em que o camelo é usado não apenas no barramento de dados, mas também em aplicações. Por exemplo, tendo descrito a rota no aplicativo desta maneira:
@Component public class EventRoutes extends RouteBuilder { @Override public void configure() throws Exception { from("jms:topic:timer") .inOnly("bean:service?method=handle"); } }
Você pode combinar todos os dados nas rotas do servicemix
e do aplicativo e desenhar um gráfico comum

Observe que uma nova rota de jms:topic:timer
para bean:service
apareceu no diagrama.
Conclusão
Ao implementar a abordagem descrita para a construção de um gráfico de rota, conseguimos obter uma visão geral dos serviços integrados e de ônibus. Na verdade, o gráfico do nosso pneu se parece com isso

A prova de aplicativos conceituais pode ser vista aqui - github