Como configurar um Load Balancer (Layer 7) para expor um Streaming privado na OCI e exemplos em Java para produzir e consumir mensagens utilizando SDK da OCI.
IMPORTANTE: Este blog foi desenvolvido exclusivamente para fins educacionais e de estudo. Ele fornece um ambiente para que aprendizes possam experimentar e adquirir experiência prática em um cenário controlado. É importante destacar que as configurações e práticas de segurança utilizadas neste laboratório podem não ser adequadas para cenários do mundo real. As considerações de segurança para aplicações reais costumam ser muito mais complexas e dinâmicas. Portanto, antes de implementar qualquer uma das técnicas ou configurações demonstradas aqui em um ambiente de produção, é essencial realizar uma avaliação e revisão de segurança abrangente. Essa revisão deve incluir todos os aspectos de segurança, como controle de acesso, criptografia, monitoramento e conformidade, garantindo que o sistema esteja alinhado com as políticas e padrões de segurança da organização. A segurança deve sempre ser uma prioridade máxima ao fazer a transição de um ambiente de laboratório para uma implementação no mundo real.
Para esse exemplo nós não iremos utilizar a biblioteca do Apache Kafka, nós iremos utilizar a SDK da OCI para Streaming, que vai interagir através da porta 443 e protocolo https (essa informação é importante para configurarmos o backend no Load Balancer).
- criação de um Streaming e de um Streaming Pool privado;
- criação e configuração de um Load Balancer OCI de camada 7:
- configuração do Streaming como backend;
- extração dos certificados do Streaming privado e como configurar isso no backend do Load Balancer.
- exemplos de códigos em Java para consumir e produzir mensagens, além dos erros que ocorrem no caso de problemas de configuração do Load Balancer.
O projeto usa:
- Java 17;
- Maven;
- OCI Java SDK (
common,streaminge cliente HTTP Jersey); - Guava;
- Apache Commons Lang;
Arquivo: src/main/java/com/example/Producer.java
Responsável por publicar mensagens no OCI Streaming.
Principais pontos:
- necessário informar o OCID do
Stream; - informar o endpoint do serviço, neste caso será o endereço do Load Balancer;
- permite duas formas de conexão:
- autenticação padrão via arquivo de configuração OCI;
- autenticação usando
truststoreJKS eSSLContextcustomizado, porque vamos demonstrar um exemplo utilizando um certificado autoassinado, para nos comunicarmos com o listener do Load Balancer através do protocoloHTTPS;
- cria 50 mensagens de exemplo com chave e valor;
- envia o lote com
putMessages; - exibe no console o resultado de cada envio, incluindo partição, offset e erros.
Arquivo: src/main/java/com/example/Consumer.java
Responsável por consumir mensagens do OCI Streaming.
Principais pontos:
- usa autenticação baseada na configuração padrão OCI;
- cria um
StreamClientapontando para o endpoint do stream; - cria um cursor de grupo (
group cursor) para o grupoexampleGroup; - usa o tipo
TrimHorizon, ou seja, começa a leitura desde o início disponível do stream; - lê mensagens em lotes de até 25 registros;
- imprime no console a chave e o valor de cada mensagem lida;
- atualiza o cursor a cada iteração usando
opc-next-cursor.
O método simpleMessageLoop executa 10 ciclos de leitura com pausa de 1 segundo entre as requisições.
Hoje o código possui alguns valores fixos diretamente nas classes:
- OCID do stream;
- endpoint do OCI Streaming;
- path da
truststore; - senha da
truststore; - perfil OCI
DEFAULT.
Para uso em ambiente real, o ideal é externalizar essas configurações para:
- variáveis de ambiente;
- arquivo
.propertiesou.yaml; - argumentos de linha de comando;
- perfis Maven ou configuração centralizada.
Navegue no Menu Principal -> Analytics & AI -> Messaging -> Streaming.
Vamos começar pela criação de um Stream pool privado:
Podemos deixar as demais informações conforme abaixo:
Agora que já temos o nosso Stream Pool Privado configurado, vamos para criação do Stream.
Navegue no Menu Principal -> Analytics & AI -> Messaging -> Streaming -> Streams, clique no botão Create stream.
Selecione o Stream Pool Privado que criamos anteriormente, deixe as demais informações como estão e clique no botão create:
- o atributo
OCID; - o atributo
Messages endpoint;
Atenção:
- Essas informações serão utilizadas no código Java e na configuração do Load Balancer.
- Por se tratar de conexão privada, você pode escolher:
- utilizar um Bastion para que você consiga acessar esse ambiente privado;
- criar uma VM que tenha IP público, para se conectar via chave privada, e por sua vez, essa VM ter acesso ao Stream criado;
- utilizar o Cloud Shell da console OCI.
vamos testar primeiro apontando para o Stream, para isolar problema de código vs. problema de rede/LB
Altere nas classes abaixo, os seguintes atributos:
ociStreamOcid: informe o OCID do Stream que foi coletado no passo anterior;ociMessageEndpoint: utilize o valor que consta em Messages endpoint do seu Stream.
Classes Java:
- Produtor:
src/main/java/com/example/Producer.java - Consumidor:
src/main/java/com/example/Consumer.java
Produza e consuma as mensagens. Valide se não há erros nos logs de execução.
Atenção: Neste momento, deixe o atributo
usarJks = false;, depois abordaremos isso.
Vamos considerar o caso de uso! Normalmente queremos utilizar Streaming para produzir e consumir mensagens, usando porta TCP e querendo muita performance. Em alguns casos, precisamos estabelecer perímetros de segurança e evitar a exposição de protocolos nativos de mensageria na internet. Para o nosso caso, vamos utilizar uma abordagem diferente, expor um Stream privado através de um Load Balancer via protocolo HTTPS e na porta 443, usando a SDK da OCI, que nos ajuda a implementar esse cenário.
Lembrete: podemos associar um WAF no Load Balancer da OCI, para deixarmos tudo ainda mais seguro!
Navegue no Menu Principal -> Networking -> Load balancers -> Load balancers -> Clique no botão Create load balancer
The load balancer service provides layer 4 and layer 7 (TCP and HTTP) load balancing that routes network traffic in a more complex manner. Load balancing improves resource utilization, facilitates scaling, and helps to ensure high availability.
Observações:
- Vamos utilizar um Load Balancer privado;
- Garanta que a VCN e Subnet escolhida para criar seu Load Balancer tenha as devidas liberações para se conectar no Stream;
- Além disso, onde seu código Java for executado, também precisará de conectividade ao Load Balancer que será criado!
Vamos manter essas informações conforme sugeridas:
Vamos agora configurar o Backend do Load Balancer:
Vamos manter as informações default, e após criação, vamos editar para informar o IP do Message EndPoint do Stream para o BackEnd. Vamos detalhar mais sobre isso nos próximos passos!
Para configurar o health check policy vamos utilizar:
- Protocol: TCP
- Port: 443
As demais informações manteremos como estão:
Vamos iniciar as configurações do Listener do Load Balancer:
- Neste momento vamos configurar o protocolo como HTTP;
- Nosso listener vai utilizar a porta 443;
- Não iremos configurar nenhum certificado neste momento, apenas vamos deixar a informação padrão.
Na configuração de Logs vamos criar neste momento apenas o Log de Erro:
Não iremos ativar o Access Logs, vamos manter como está:
Vamos revisar as configurações e submeter as informações para iniciar a criação do nosso Load Balancer.
Quando o Load Balancer for criado o mesmo terá um IP privado atribuído e o campo Overall health = Incomplete:
Precisamos acessar o mesmo e navegar até a aba Backend sets, que estará com o campo Health = Incomplete.
Depois vamos clicar no link do Backend set que está criado:
Estamos na configuração do Backend set do Load Balancer, e vamos navegar até a aba Backends, e clicar no botão Add backends:
Precisamos informar o IP associado ao endpoint privado do Stream.
Nos passos anteriores, coletamos o atributo Messages endpoint do Stream.
Vamos usar o comando telnet para identificar o IP, informando o host e a porta 443:
telnet a4irodirgieq.streaming.sa-saopaulo-1.oci.oraclecloud.com 443
Trying 10.0.10.222...
Connected to a4irodirgieq.streaming.sa-saopaulo-1.oci.oraclecloud.com.
Informamos o IP coletado no campo abaixo, usamos a porta 443, e depois clicamos no botão Add:
Temos que aguardar o Load Balancer ficar com o atributo Health = Ok:
Agora vamos aos testes, mas antes vamos coletar algumas informações do Load Balancer:
- IP address, que fica na aba Details;
- Protocolo e Port, que ficam na aba Listener.
Juntando todas as informações, temos o seguinte endereço para acessarmos o nosso Load Balancer:
http://10.0.10.127:443
Atenção: neste momento estamos usando o protocolo HTTP no Listener e porta 443.
Vamos alterar a classe Producer: src/main/java/com/example/Producer.java, mudando o atributo ociMessageEndpoint para o endereço do nosso Load Balancer:
final String ociMessageEndpoint = "http://10.0.10.127:443";
Ao executar a classe vamos encontrar alguns erros:
logs de erro do Load Balancer (habilite o mesmo no Load Balancer):
errorLog":{"errorDetails":"Backend 10.0.10.222 closed connection abruptly","type":"backEnd"}
logs de execução da sua classe Java
<head><title>502 Bad Gateway</title></head>
<body>
<center><h1>502 Bad Gateway</h1></center>
<hr><center></center>
</body>
</html>
Atenção
Aqui está um ponto muito importante: temos que extrair alguns certificados do Stream e importá-los no Load Balancer, para usarmos no Back End, porque ao comunicarmos com Stream via Load Balancer, temos que manter internamente a comunicação como HTTPS.
Vamos extrair os certificados necessários do Stream, informando o fqdn completo e a porta 443:
openssl s_client -connect a4irodirgieq.streaming.sa-saopaulo-1.oci.oraclecloud.com:443 -showcerts
Você encontrará uma cadeia de certificados (texto que inicia com -----BEGIN CERTIFICATE----- e termina com -----END CERTIFICATE-----).
O primeiro certificado normalmente corresponde ao certificado do serviço, e os demais fazem parte da cadeia de CA/intermediários.
O primeiro será o SSL certificate e o outro será o CA certificate.
Vamos importar ambos no Load Balancer.
Ao entrar no Load Balancer criado, acessaremos a aba Certificates and ciphers e depois vamos na opção Load balancer managed certificates, e clicaremos no botão Add Certificate:
Informe o nome do certificado a ser criado.
Utilize a opção "Paste SSL certificate" e cole o primeiro certificado que extraímos do Stream.
Habilite a opção Specify CA certificate, use "Paste CA certificate" e cole o outro certificado:
Depois de criar o certificado, vamos na aba Backend sets e clicar em Edit, opção do botão "...":
Habilite a opção Use SSL, e no campo Certificate resource, escolha a opção Load balancer managed certificate.
Vamos escolher o certificado que acabamos de criar e depois em Save Changes:
Vamos executar a classe Producer: src/main/java/com/example/Producer.java e podemos notar que não há mais erros, as mensagens foram publicadas com sucesso:
Publishing 50 messages to stream ocid1.stream.oc1.sa-saopaulo-1.xxx.
Published message to partition 0, offset 600.
Published message to partition 0, offset 601.
Published message to partition 0, offset 602.
Published message to partition 0, offset 603.
Published message to partition 0, offset 604.
Published message to partition 0, offset 605.
Published message to partition 0, offset 606.
Published message to partition 0, offset 607.
Published message to partition 0, offset 608.
Published message to partition 0, offset 609.
Published message to partition 0, offset 610.
Published message to partition 0, offset 611.
Published message to partition 0, offset 612.
Published message to partition 0, offset 613.
Published message to partition 0, offset 614.
Published message to partition 0, offset 615.
Published message to partition 0, offset 616.
Published message to partition 0, offset 617.
Published message to partition 0, offset 618.
Published message to partition 0, offset 619.
Published message to partition 0, offset 620.
Published message to partition 0, offset 621.
Published message to partition 0, offset 622.
Published message to partition 0, offset 623.
Published message to partition 0, offset 624.
Published message to partition 0, offset 625.
Published message to partition 0, offset 626.
Published message to partition 0, offset 627.
Published message to partition 0, offset 628.
Published message to partition 0, offset 629.
Published message to partition 0, offset 630.
Published message to partition 0, offset 631.
Published message to partition 0, offset 632.
Published message to partition 0, offset 633.
Published message to partition 0, offset 634.
Published message to partition 0, offset 635.
Published message to partition 0, offset 636.
Published message to partition 0, offset 637.
Published message to partition 0, offset 638.
Published message to partition 0, offset 639.
Published message to partition 0, offset 640.
Published message to partition 0, offset 641.
Published message to partition 0, offset 642.
Published message to partition 0, offset 643.
Published message to partition 0, offset 644.
Published message to partition 0, offset 645.
Published message to partition 0, offset 646.
Published message to partition 0, offset 647.
Published message to partition 0, offset 648.
Published message to partition 0, offset 649.
O importante é lembrar que ao configurar o roteamento para o back end, caso o mesmo seja HTTPS, você precisará importar os certificados, para estabelecer de forma segura a conexão.
Até o momento usamos o nosso Load Balancer com Listener utilizando o protocolo HTTP. Nosso objetivo é utilizar o protocolo HTTPS e para isso, temos alguns procedimentos:
- gerar um certificado autoassinado;
- configurar o certificado autoassinado no Listener do Load Balancer;
- fazer ajustes no código Java para utilizar um JKS com o certificado gerado, criando uma relação de confiança entre a aplicação e o ambiente com certificado autoassinado.
Para gerar o certificado autoassinado:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout chave.key -out certificado.crt \
-subj "/C=BR/ST=SP/L=SaoPaulo/O=OracleLab/CN=10.0.10.127"
Atenção Utilizei o IP privado do Load Balancer no atributo CN (common name) no certificado. O ideal é incluir subjectAltName com o IP/DNS. O código contorna isso usando NoopHostnameVerifier. Isso deve ser usado apenas em ambiente de testes.
Ao final desta execução, teremos dois arquivos gerados:
- chave.key: chave privada;
- certificado.crt: certificado
Vamos voltar ao Load Balancer e criar um novo certificado. Ao entrar no Load Balancer criado, acessaremos a aba Certificates and ciphers e depois vamos na opção Load balancer managed certificates, e clicaremos no botão Add Certificate.
Informe o nome do certificado a ser criado. Utilize a opção "Paste SSL certificate" e cole o conteúdo do arquivo certificado.crt. Não vamos habilitar a opção Specify CA certificate. Habilite a opção Specify private key, use "Paste private key" e cole o conteúdo do arquivo chave.key. Ao final, clique no botão "Add certificate".
Precisamos alterar o Listener do Load Balancer. Na aba Listeners, clique no botão "..." e depois em "Edit":
Neste momento, vamos:
- alterar
Protocolpara HTTPS; - manter
Portigual 443; - em
Certificate resourceutilizar Load balancer managed certificate e selecionar o certificado criado anteriormente para o listener do Load Balancer (não utilize o certificado criado para o backend set)
Clique em "Save changes":
O seu Listener estará desta forma:
Agora nosso endereço para acessar o Load Balancer ficou desta forma, assim como o atributo ociMessageEndpoint nas Classes Java:
https://10.0.10.127
final String ociMessageEndpoint = "https://10.0.10.127";
Se executarmos o código vamos ter o seguinte erro porque nosso certificado é auto assinado:
Exception in thread "main" com.oracle.bmc.model.BmcException: (-1, , true) javax.ws.rs.ProcessingException: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target (outbound opc-request-id: 8399EAE78093406D94BCC80CF4987C7F)
at com.oracle.bmc.http.internal.ClientCall.lambda$callAsyncImpl$23(ClientCall.java:1080)
at java.base/java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:934)
at java.base/java.util.concurrent.CompletableFuture$UniHandle.tryFire(CompletableFuture.java:911)
at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2162)
at org.glassfish.jersey.client.JerseyInvocation$InvocationResponseCallback.failed(JerseyInvocation.java:1063)
at org.glassfish.jersey.client.ClientRuntime.processFailure(ClientRuntime.java:250)
at org.glassfish.jersey.client.ClientRuntime.processFailure(ClientRuntime.java:245)
at org.glassfish.jersey.client.ClientRuntime.access$100(ClientRuntime.java:62)
at org.glassfish.jersey.client.ClientRuntime$2.lambda$failure$1(ClientRuntime.java:181)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
at org.glassfish.jersey.internal.Errors.process(Errors.java:292)
at org.glassfish.jersey.internal.Errors.process(Errors.java:274)
at org.glassfish.jersey.internal.Errors.process(Errors.java:244)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:288)
at org.glassfish.jersey.client.ClientRuntime$2.failure(ClientRuntime.java:181)
at org.glassfish.jersey.apache.connector.ApacheConnector.apply(ApacheConnector.java:545)
at org.glassfish.jersey.client.ClientRuntime.lambda$null$6(ClientRuntime.java:185)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
at org.glassfish.jersey.internal.Errors.process(Errors.java:292)
at org.glassfish.jersey.internal.Errors.process(Errors.java:274)
at org.glassfish.jersey.internal.Errors.process(Errors.java:244)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:288)
at org.glassfish.jersey.client.ClientRuntime.lambda$createRunnableForAsyncProcessing$7(ClientRuntime.java:159)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:842)
Caused by: java.util.concurrent.CompletionException: javax.ws.rs.ProcessingException: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:332)
at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:347)
at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:636)
... 28 more
Caused by: javax.ws.rs.ProcessingException: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at org.glassfish.jersey.apache.connector.ApacheConnector.apply(ApacheConnector.java:534)
at org.glassfish.jersey.apache.connector.ApacheConnector.apply(ApacheConnector.java:541)
... 13 more
Caused by: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:383)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:326)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:321)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:654)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:473)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:369)
at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:396)
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:481)
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:459)
at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:206)
at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:172)
at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1506)
at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1421)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:455)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:426)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:436)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:384)
at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:376)
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:393)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:72)
at org.glassfish.jersey.apache.connector.ApacheConnector.apply(ApacheConnector.java:486)
... 14 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:439)
at java.base/sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:306)
at java.base/sun.security.validator.Validator.validate(Validator.java:264)
at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231)
at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:132)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:638)
... 37 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:148)
at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:129)
at java.base/java.security.cert.CertPathBuilder.build(CertPathBuilder.java:297)
at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:434)
... 42 more
Para resolver isso temos que criar um arquivo JKS com o certificado que geramos, para que possamos estabelecer uma relação de confiança entre a conexão do código Java com o Load Balancer.
Um arquivo JKS (Java KeyStore) é um repositório binário protegido por senha, específico do Java, usado para armazenar certificados de segurança (públicos) e chaves privadas. Ele é amplamente utilizado em ambientes Java para garantir a autenticidade e a criptografia SSL. Neste exemplo, o JKS será usado como truststore, armazenando o certificado público confiável do listener.
Para criar o arquivo JKS e importar o certificado que geramos para o Listener do Load Balancer, execute o comando:
keytool -importcert \
-noprompt \
-alias labStreaming \
-file certificado.crt \
-keystore truststore.jks \
-storepass changeit
Vamos executar a produção de mensagens, mudando os atributos conforme segue:
- trustStorePath: para o path que está o seu arquivo jks criado no passo anterior;
- usarJks: alterar para
true, para o código utilizar o arquivo JKS criado.
As mensagens serão publicadas com sucesso.
Caso seja necessário consumir mensagens via HTTPS com certificado autoassinado, implemente no Consumer a mesma configuração de SSLContext e truststore usada no Producer.
Neste artigo, mostramos que é possível expor um OCI Streaming privado por meio de um Load Balancer Layer 7, usando a SDK da OCI sobre HTTPS/443, sem depender do protocolo nativo do Kafka. Também vimos que, embora o listener possa receber requisições HTTP ou HTTPS, a comunicação com o backend precisa respeitar o protocolo real do serviço de destino.
O principal aprendizado deste cenário é que, quando o backend utiliza HTTPS, não basta apenas publicar o endpoint no Load Balancer: é necessário configurar corretamente a relação de confiança entre o Load Balancer e o serviço privado, incluindo a importação dos certificados exigidos pelo backend. Foi justamente esse ajuste que eliminou o erro 502 Bad Gateway e permitiu a publicação das mensagens com sucesso.
Também apresentamos um exemplo de como configurar o Listener do Load Balancer com um certificado autoassinado e como ajustar o código Java para utilizar um arquivo JKS, mantendo a comunicação funcionando.
Em ambientes reais, esse padrão pode ser útil quando há exigências de isolamento de rede, controle de exposição e adoção de serviços adicionais de segurança, como WAF, observabilidade e políticas mais rígidas de acesso.
- OCI SDK Authentication Methods
- Streaming
- Código Java de exemplo para consumir e produzir mensagens via OCI SDK
- Como criar um Stream Pool
- Protect on-premises Web Applications with Oracle Cloud Infrastructure Load Balancer and Regional Web Application Firewall
- Rodrigo Chafik Choueiri - Oracle LAD A-Team Solution Engineer
- Rodrigo Pace de Barros - Oracle LAD A-Team Security Specialist


























