Uma matriz de maturidade para extensões Quarkus
O que faz uma boa extensão Quarkus? Que recursos se espera que uma extensão do Quarkus ofereça? É claro que isso depende da extensão que você está criando. Porém, encontramos um conjunto de características comuns a muitas extensões. Essa documentação explica quais são elas.
Isso não está definindo uma ordem exata, mesmo em uma única linha. Extensões diferentes têm objetivos diferentes, e desenvolvedores diferentes terão visões diferentes sobre quais recursos são mais importantes. Você pode desejar (por exemplo) priorizar um modelo de programação fantástico, em vez de aprimorar o bloco de interface de usuário do desenvolvedor da sua extensão. E tudo bem!
Além disso, nem todas as etapas se aplicam a todas as extensões. Por exemplo, você não precisa de um serviço de desenvolvimento se sua extensão não depender de serviços externos.
Não há problema algum em publicar uma primeira versão de uma extensão que não lide com tudo. Na verdade, não tem problema se sua extensão nunca chegar aos recursos mais avançados. Este é um caminho sugerido, não um conjunto mínimo de funcionalidades.
Observe também que esta lista inclui apenas as funcionalidades técnicas de sua extensão. Você talvez também queira pensar, sobre como você compartilha sua extensão e como ela se apresenta ao mundo. O checklist para novas extensões no Quarkiverse Hub tem uma lista útil de maneiras pelas quais as extensões podem participar do ecossistema. Também é uma boa ideia dedicar algum tempo aos metadados no arquivo quarkus-extension.yaml
, que é usado pelas ferramentas do Quarkus.
Aqui estão algumas dicas sobre como obter esses recursos.
Modos de execução
As aplicações Quarkus podem ser executadas como uma aplicação jar baseada na JVM, ou codificadas ao vivo no modo de desenvolvimento, ou compiladas para um binário nativo. Cada ambiente impõe diferentes demandas às extensões do framework.
Funciona em modo JVM
Para a maioria das extensões, essa é a expectativa mínima. Quando encapsulamos uma biblioteca existente, isso é geralmente trivial de se conseguir; se uma extensão está fornecendo um recurso totalmente novo, pode ser um pouco mais trabalhoso. O Quarkus fornece ferramentas para testes de unidades e testes de integrações em extensões.
Funciona em modo de desenvolvimento
Em alguns casos, pode ser necessário um trabalho extra para garantir que bibliotecas encapsuladas consigam tolerar o modo de desenvolvimento, já que o carregamento de classes é diferente e o hot reloading pode quebrar algumas suposições. As extensões podem também querer adicionar algum tratamento especial para o modo de desenvolvimento. Para adicionar testes automatizados que validem o modo de desenvolvimento, você pode adicionar testes que estendem o QuarkusDevModeTest
.
Funciona como uma aplicação nativa
Para muitas bibliotecas, o suporte ao modo nativo é a principal motivação para a criação de uma extensão. Consulte o guia de suporte para executáveis nativos para mais informações sobre algumas das adaptações que podem ser necessárias.
Alegria em desenvolver
A alegria do desenvolver é um principio importante do Quarkus. Aqui estão algumas extensões de recursos que contribuem para um desenvolvimento feliz.
Suporte de configuração
As extensões devem oferecer suporte à configuração unificada do Quarkus, por meio da integração com o modelo de configuração do Quarkus. O guia Writing Extensions oferece mais orientações sobre a filosofia de configuração do Quarkus.
CDI Beans
As extensões do Quarkus devem buscar expor componentes via CDI, permitindo que sejam consumidas de forma descomplicada por aplicações dos usuários. Ter tudo injetável como beans CDI também ajuda nos testes, especialmente os mocks.
Serviço de desenvolvimento
Serviço de desenvolvimento são geralmente relevantes para extensões que "se conectem" a algo, tal como banco de dados para fonte de dados, uma instância do Keycloack para segurança, uma instância do Apache Kafka para sistemas de mensagens, etc.
Para fornecer um serviço de desenvolvimento, use o item de compilação DevServicesResultBuildItem
. Consulte o guia de como criar um serviço de desenvolvimento para mais informações.
Interface de usuário para desenvolvimento básica
Cada extensão possui um bloco na interface de usuário do desenvolvedor. O bloco padrão extrai informações dos metadados da extensão, o que é mais um motivo para dedicar algum tempo para obter os metadados corretos.
As extensões também utilizam ganchos da interface de usuário do desenvolvedor para apresentar informações adicionais aos usuários. Por exemplo, o bloco poderia incluir um link para um console externo, ou uma página interna que exiba métricas simples em texto. Consulte o guia de interface de usuário do desenvolvedor para desenvolvedores de extensões.
Interface de usuário para desenvolvimento avançada
Algumas extensões fornecem interfaces de usuário para desenvolvedores extremamente sofisticadas. Por exemplo, eles podem permitir que usuários interajam com a aplicação em execução, respondam a recarregamentos, visualizem métricas da aplicação, ou transmitam um log específico da aplicação. O guia interface de usuário de desenvolvimento para desenvolvedores de extensões também explica essas opções mais avançadas.
Modelo de programação agradável
Quarkus’s build-time philosophy means extensions can tidy up API boilerplate and make programming models more concise and expressive. A good starting point is usually to use Jandex to scan user code for annotations and other markers. Although providing new, joyful, ways to do things is good, it’s important to not break the normal patterns that users may be familiar with.
Para se inspirar nessa área, confira o logging simplificado, o Hibernate ORM simplificado com Panache, a anotação @RestQuery
, ou a maneira como o Quarkus permite que os test containers sejam usados sem qualquer configuração.
Modelo de aplicação de Codestart
Codestarts são modelos que podem ser usados para gerar aplicações para usuários. Extensões podem fornecer seus próprios modelos de codestart.
Desempenho Subatômico Supersônico
As extensões devem usar o conhecimento da aplicação em tempo de compilação, para eliminar caminhos de código desnecessários em tempo de execução. Chamamos isso de desempenho subatômico supersônico. Como o Quarkus transfere o trabalho para o estágio de compilação, aplicações Quarkus devem ter uma inicialização rápida, alta taxa de transferência e requerer pouca memória. O ajuste de desempenho é um assunto extenso, mas as extensões devem usar o conhecimento da aplicação em tempo de compilação para eliminar caminhos de código desnecessários em tempo de execução.
Inicialização estática
Faça o máximo de inicialização possível de forma estática. Isso evita a sobrecarga em tempo de execução.
Substitua a reflexão por bytecode gerado
Many Java libraries make heavy use of reflection to delay decisions to run-time. Quarkus aims to improve performance by moving logic to build time, reducing unnecessary dynamism. Extensions should aim to replace reflection with build-time code. This is enabled by Jandex, an "offline reflection" library. It may also be necessary to do some bytecode transformation of existing libraries.
Para um caso de estudo em como eliminar reflexão e o que beneficia a performance transformado fora de ser, veja a serialização Jackson sem reflexão
Suporte a threads virtuais
Nem toda biblioteca é adequada para o uso de threads virtuais de imediato. "Por que não usar threads virtuais em todos os lugares?" explica o motivo.
Para que sua biblioteca funcione corretamente com threads virtuais, você deve garantir que ela não esteja fixando a thread de transporte. O Quarkus possui test helpers para fazer essas verificações de forma automatizada. Para despachar o trabalho, você deve usar o executor virtual gerenciado pelo Quarkus. A extensão WebSockets-next utiliza o despachante virtual e o despacho inteligente, e é um bom exemplo a ser seguido.
Otimização do desempenho do hot path
Embora o Quarkus ofereça algumas oportunidades únicas para o desempenho de extensões, os desenvolvedores de extensão não devem esquecer os fundamentos de otimização de desempenho.
Internos não bloqueantes
O núcleo reativo do Quarkus é um dos principais responsáveis por sua excelente taxa de transferência e escalabilidade. As extensões devem considerar adotar esse modelo para suas próprias operações internas.
Adicione APIs baseadas no Mutiny
Para obter a máxima escalabilidade, vá além do núcleo reativo e habilite a programação totalmente reativa, usando o Mutiny. A maioria dos projetos que suportam um modelo de programação reativa oferece duas extensões distintas: uma -reactive
e outra padrão. Veja, por exemplo, as extensões ElasticSearch e ElasticSearch Reactive.
Operações
A satisfação do desenvolvedor é importante, mas a observabilidade, a manutenibilidade e outras considerações operacionais também são. Muitas dessas características vêm por padrão com o framework Quarkus ou com extensões focadas em observabilidade. No entanto, as extensões podem ir além.
Registrando
O Quarkus utiliza JBoss Logging como seu mecanismo de log e suporta várias APIs de logging. (Isso é o logging normal em Java, não logging do OpenTelemetry.)
Evite usar erros e avisos para condições que não afetarão a operação normal. Essas saídas podem causar alarmes falsos nos sistemas de monitoramento do usuário.
Definir endpoints de saúde
As extensões podem querer definir endpoints específicos da biblioteca para critérios de saúde que sejam específicos dessa extensão. Para adicionar um novo endpoint, as extensões devem produzir um NonApplicationRootPathBuildItem
.
Contexto de rastreamento
Você deve testar se a saída do OpenTelemetry para aplicações que utilizam sua extensão possui spans definidos. Talvez seja necessário realizar trabalho adicional para garantir que os spans sejam criados com o ID de rastreamento correto. Por exemplo, as extensões que possuem internos reativos devem suportar contextos duplicados para a propagação de contexto correta.
Integração avançada de Kubernetes e contêineres
O Quarkus foi projetado para ser um runtime nativo do Kubernetes. As extensões podem dar continuidade a essa filosofia adicionando pontos de integração específicos de bibliotecas com o Kubernetes. Ser nativo do Kubernetes implica ser nativo do contêiner. No mínimo, as extensões devem sempre funcionar bem em contêineres, mas também podem ter oportunidades para se integrar aos níveis inferiores da pilha de contêineres.