Este artigo compara a operação dos serviços mais simples implementados usando o framework Camel e seus dois componentes: HTTP e AHC. Não vamos nos aprofundar na estrutura e trabalhar com a própria estrutura, presume-se que o leitor já esteja um pouco familiarizado com ela.
Vamos considerar um serviço Camel simples que recebe solicitações do componente jetty, processa-as, por exemplo, exibe-as no log, chama outro serviço via http e processa a resposta dele, por exemplo, grava no log.
Para o teste, scripts JMeter foram usados para chamar nosso serviço de acordo com a frequência e intervalos pretendidos, bem como um pequeno serviço Http que desempenha o papel de externo ao nosso serviço e realiza um atraso de 5 segundos. Toda a comunicação ocorre em um loop local (127.0.0.1), portanto as latências da rede não são levadas em consideração, mas não são necessárias para a análise comparativa.
Componente HTTP
Esta seção examinará o componente HTTP padrão para comunicação HTTP. Código de serviço simples:
from("jetty:http://localhost:8080/test")
.log("receive request body ${body}")
.removeHeaders("CamelHttp*")
.to("http://{{another.url}}")
.log("finish process body ${body}");
Nota: A remoção dos cabeçalhos começando com "CamelHttp" é necessária porque eles estão expostos no componente Jetty e podem afetar a operação do componente Http.
Para testar o funcionamento deste serviço, vamos rodar o script JMeter que envia 25 requisições simultâneas.
Amostras |
Min |
Max |
Erro% |
25 |
5012 |
7013 |
20.000% |
, 20% 5 25 (Read timed out). , http- 20 . connectionsPerRoute
from("jetty:http://localhost:8080/test")
.log("receive request body ${body}")
.removeHeaders("CamelHttp*")
.to("http://{{another.url}}?connectionsPerRoute=200")
.log("finish process body ${body}");
25 . – jetty-, 200. 4 JMeter:
200
300
300 5 , 5
200 5 , 5
1 JVM 214 , .
:
|
|
200 |
0% |
300 |
34.667% |
300 5 |
71.733% |
200 5 |
0% |
300 , 200 jetty-, 100 jetty, 5 , 10. 34% – 100 .
, – 300 5 , 5 , .. 60 , 200 5 , .
, , , , jetty- .
, jetty-, JVM 1 , Docker- , . .
AHC-
AHC- - Camel HTTP. AsyncHttpClient, () . – http- , , .. 5 . , . :
from("jetty:http://localhost:8080/test")
.log("receive request body ${body}")
.removeHeaders("CamelHttp*")
.to("ahc:http://{{another.url}}")
.log("finish process body ${body}");
, 300 . , http- . JVM:
, . :
|
|
300 5 |
0% |
800 5 |
0% |
1200 5 |
1.533% |
1600 5 |
15.02% |
, , .
, , 1200 1600 http-, - , .
AHC-
AHC-, . :
from("jetty:http://localhost:8080/test")
.log("receive request body ${body}")
.removeHeaders("CamelHttp*")
.setHeader("rand", ()->new Random().nextInt(10000) )
.toD("ahc:http://{{another.url}}?rand=${headers.rand}")
.log("finish process body ${body}");
Depois de executar o script com um início único de 300 solicitações, o estado dos threads na JVM:
Como você pode ver, há muito fluxo. O fato é que, por padrão, o componente AHC para cada endpoint cria sua própria instância do objeto AsyncHttpClient, cada um com seu próprio pool de conexões e threads, como resultado, para cada solicitação, 2 threads são criados - um thread de E / S, outro thread de timer para controlar tempos limite e manter as conexões no estado KeepAlive. Para evitar isso, você precisa configurar a instância AsyncHttpClient no nível do componente, que será passada ao terminal quando for criada.
AhcComponent ahc = getContext().getComponent("ahc", AhcComponent.class);
ahc.setClient(new DefaultAsyncHttpClient());
Depois disso, a criação de várias instâncias de AsyncHttpClient será interrompida.