O produto Magic xpi necessita de uma licença de uso explícita (arquivo de licenças) para poder iniciar o servidor de integração. O modelo de licenciamento (atual) define que cada licença possui um número máximo de threads.
NOTA: embora algumas vezes possa se ouvir falar em ‘número de filas da licença’, tecnicamente existe sempre apenas 1 fila. O que varia é o número de threads. Logo, o correto é ‘número de threads da licença’.
E o que isso significa?
Num projeto de integração/automatização com o Magic xpi, é perfeitamente normal haver a necessidade de se executar mais de um fluxo ao mesmo tempo. Especialmente quando há triggers(como WebServices, HTTP, Scheduler, SalesForce, R/3, DirScanner, etc.) neste fluxos. Lembre-se que estamos sempre tratando de automação de processos corporativos, e os processos possuem atividades paralelas (simultâneas).
Pois bem. Existem duas regras básicas que precisam ser decoradas:
- Cada fluxo em execução ocupa uma thread da licença, desde seu início até o seu final, incluindo-se também o tempo total de cada fluxo invocado dentro de algum outro, linearmente.
- O total de threads da licença determina o máximo de fluxos que poderão estar executando simultaneamente
E quando o número de fluxos em execução é maior que o número de threads da licença?
Bom, de fato, isso nunca acontece :).
Quando há necessidade de se executar um fluxo do projeto, nasce uma solicitação de execução de fluxo, ou popularmente chamada, uma requisição. Não há limite explícito para o número de requisições simultâneas geradas em um projeto Magic xpi. Mas antes que um fluxo inicie, é verificado quantas threads da licença estão disponíveis, ou seja, não estão ocupadas por algum outro fluxo já em execução. Se houver ao menos uma disponível, o fluxo inicia imediatamente. Senão, ele entra na fila de requisições a serem atendidas e fica aguardando por um tempo máximo ‘x’ (configurável) até que outro fluxo em execução finalize e libere uma thread para atender a esta requisição.
Mais ou menos assim:
Suponha uma licença com limite de 4 threads:
- Num determinado momento, o Magic xpi Server recebeu 3 requisições simultâneas: todas poderão ser atendidas de imediato.
- Em outro momento, o Magic xpi Server recebeu 7 requisições simultâneas: 4 serão atendidas de imediato, e 3 ficarão em espera.
Então, não é um processo complicado: cada requisição é primeiramente analisada e se houver thread livre no momento, ela é atendida. Senão, entra num fila de espera até que possa ser atendida.
Mas mesmo simples, existe uma dúvida (ou pergunta) que sempre atormenta os desenvolvedores: quantas threads são necessárias na licença para o projeto executar a contento?
Para chegar a uma conclusão, devemos iniciar respondendo a duas perguntas:
- Quantas execuções simultâneas de fluxos poderá ocorrer no projeto que está sendo desenhado?
- O que é “a contento”?
A resposta do item #1 pode ser um número, ou uma ordem de grandeza (ex: muitos).
A resposta do item #2 é ainda mais subjetiva, pois o que é desempenho razoável para um processo, pode não ser para outro. Quanto mais tempo um requisição estiver enfileirada, mais tempo vai levar para o requisitante (que pode ser um sistema ‘x’ que está chamando um webService provido pelo Magic xpi, ou um usuário que clicou um botão num sistema ‘y’ que acionou um fluxo de um projeto Magic xpi) receber o seu resultado. Claro, estamos enfatizando as atividades síncronas. Em atividades assíncronas, onde o mais importante é que ela inicie, mas “é permitido” levar mais tempo para concluir, o fator desempenho se torna menos crítico.
Mas existe um ensinamento claro aqui: cada projeto tem as suas próprias respostas. Não busque “receita de bolo”. Avalie “com serenidade” cada novo projeto que estiver criando.
Na vida real porém, existe ainda uma outra situação comum (infelizmente): o total de threads da licença já foi determinado antes da criação do projeto L.
Por isso (principalmente), mas também por uma questão de boas práticas, existem uma regra de desenvolvimento que devemos sempre levar em consideração:
- Manter o tempo de duração dos fluxos de integração, o mais curto possível.
Não estamos determinando limites de minutos ou segundos, mas sim, determinado um esforço “de lógica” para que um fluxo demore o mínimo possível para concluir (atenção na palavra possível, pois existem coisas que simplesmente não são possíveis J). E o motivo é simples: quando um fluxo termina ele libera a thread que estava ocupando, permitindo a alguma “pobre requisição enfileirada” que também tenha a sua chance de ser atendida. E com isso, a “fila anda” com mais eficiência.
Existem técnicas conhecidas para isso
Por exemplo: suponha que um determinado processo sendo automatizado com um projeto Magic xpi é levar notas ficais geradas em um sistema ‘x’ para um sistema ‘y’. No momento que o fluxo (código) entre em execução para fazer esta tarefa, existem 28.000 notas aguardando esta transferência. Sabemos que muito provavelmente, temos que levar junto a cada nota os seus itens, talvez também as suas faturas, ou outros dados que fazem parte da nota. E programar uma lógica que leve este conjunto toda de uma só vez (da 1 até a 28.000) é provavelmente o tipo de erro mais comum ocorrido nos projetos. Certamente vai levar um tempo considerável fazer toda esta transferência. Tempo este que estará ocupando uma thread só para si. E enquanto isso, quem está na fila está esperando.
Logo, com um pouco de paciência, esforço e dedicação, podemos chegar à conclusão que será mais “eficiente” levar 100 conjuntos de 280 notas de uma lado para o outro (1 a 280, 281 a 560, etc.), do que um único conjunto de 28.000 notas. E para isso, ao terminar a execução de um fluxo que está levando um conjunto de 280 notas, solicitamos que este fluxo execute outra vez levando as próximas 280, até que não existam mais notas a levar. E muito importante: pedimos que esta nova requisição de execução entre “no fim da fila”.
E como poderia se fazer isso?
Considerando o exemplo acima, no Magic xpi poderia ser:
- PSS para o próprio fluxo
- Schedule Flow para o próprio fluxo
- Invoke Flow Delay para o próprio fluxo
- Invoke Flow no modo Stand Alone, para o próprio fluxo
Claro que teria de haver um controle adicional onde cada invocação do fluxo precisaria definir bem a primeiro e última nota a ser processada naquele momento. E este cenário das notas é apenas um exemplo. Situações diferentes vão exigir estratégias diferentes.
Mas a mensagem final é clara: é preciso entender o que o limite de threads na licença impacta nos projetos, tanto na execução quanto na estratégia de desenvolvimento.
Muitos (também eu) por não atentarem para este fato, acabam criando projetos que não atingem aos seus objetivos. Ou, também em muitos casos, criam projetos que não conseguem se beneficiar de todas as threads disponíveis na licença.
E se já se fez todo o possível?
Se o desenho do projeto já prevê o possível para uma boa utilização das filas existentes, mas o desempenho geral ainda não atinge o necessário, bom, você chegou naquele momento: os seus processos estão demandando mais threads na licença, para poderem ser executados satisfatoriamente :).