Java 与卡夫卡消费记录并行流

Java 与卡夫卡消费记录并行流,java,apache-kafka,kafka-consumer-api,Java,Apache Kafka,Kafka Consumer Api,我有卡夫卡的记录: ConsumerRecords<String, Events> records = kafkaConsumer.poll(POLL_TIMEOUT); 我尝试使用mlutithreading,但我想尝试parallelstream: for (ConsumerRecord<String, Event> record : records) { executor.execute(new Runnable()

我有卡夫卡的记录:

ConsumerRecords<String, Events> records = kafkaConsumer.poll(POLL_TIMEOUT);
我尝试使用mlutithreading,但我想尝试parallelstream:

for (ConsumerRecord<String, Event> record : records) {
                        executor.execute(new Runnable() {
                            @Override
                            public void run() {

                                        HTTPSend.send(Event);

                            }
                        });

                    }
HTTPSend.send()是:

long sizeSend=0;
SSLContext sc=null;
试一试{
sc=SSLContext.getInstance(“TLS”);
sc.init(空,信任所有证书,新SecureRandom());
}catch(nosuchagorithmexception | KeyManagementException e){
LOGGER.error(“未能创建SSL上下文”,e);
}
//忽略给定主机名和证书主机名之间的差异
HostnameVerifier hv=(主机名,会话)->true;
//创建REST客户机并将其配置为连接元数据
Client Client=ClientBuilder.newBuilder()
.主机名验证程序(hv)
.sslContext(sc.build();
WebTarget baseTarget=client.target(getURL()).path(HTTP\u path);
Response jsonResponse=null;
试一试{
StringBuilder eventsBatchString=新建StringBuilder();
append(this.getEvent(event));
Entity Entity=Entity.Entity(eventsBatchString.toString(),MediaType.APPLICATION\u JSON\u TYPE);
builder=baseTarget.request();
debug(“即将发送事件{}和URL{}”,实体,getURL());
jsonResponse=builder.header(HTTP\u ACK\u CHANNEL,guid.toString())
.header(“内容类型”,MediaType.APPLICATION_JSON)
.header(“授权”,String.format(“元%s”,eventsModuleConfig.getSecretKey()))
.员额(实体);

我知道你想做什么,但我不确定这是不是最好的主意(我也不确定这不是)

卡夫卡的
轮询
/
提交
模型允许在崩溃时对最后处理的项目进行简单的背压和保留。通过“立即”返回轮询循环,您告诉卡夫卡“我准备好接受更多”,并提交偏移量(手动或自动)告诉卡夫卡你已经成功地读到了这一点

您似乎想做的是尽快读取卡夫卡,提交偏移量,然后将卡夫卡记录放入执行器队列,然后平衡每秒的请求等

我不是100%确定这是一个好主意:如果你的应用程序崩溃了会发生什么?你可能提交了一些卡夫卡消息,但实际上没有上行。如果你真的想这样做,我建议手动提交偏移量(通过
commitSync
)在完成
可运行时
,而不是让高级消费者为您执行

为什么要使用线程执行器:我认为这些也可以通过Kafka实现

您可能希望同时向web服务器发布多条消息。一个分区良好的Kafka主题将允许多个使用者/使用者组使用多个分区,因此(假设HTTP服务器具有完美的可扩展性)将允许您并行地向服务器发布消息。是的,基于进程的并发

可能web服务器不是完全可伸缩的,或者对于此请求来说速度较慢(假设每个请求需要1秒):您需要限制web服务器每秒的请求数,如果您有一个队列,则在不备份Kafka的情况下可能会有几个线程发布

在这种情况下,您可以设置web服务器所需的可伸缩值。可能还有更好的方法来实现这一点,尽管目前我还不清楚

如果您的web服务器需要很长时间来响应,您可能会收到与心跳失败相关的错误。在这种情况下,我会指示您


我不会使用线程执行器,从而使同步HTTP请求看起来是异步的,我会使用类似事件HTTP客户端的客户端,从而在没有基于线程的并发的情况下实现并行性。

实际上,我面临着HTTP.send与多线程(即使线程池为1个线程)的问题。我“原因:sun.security.validator.validator异常:PKIX路径生成失败:sun.security.provider.certpath.SunCertPathBuilderException:找不到请求目标的有效证书路径“。这是一个通过https的请求。此错误仅在第一次发出请求时出现。之后,异常消失。poof!使用阻塞队列和…int threadCOunt=1;阻塞队列队列=new ArrayBlockingQueue(threadCOunt,true);RejectedExecutionHandler处理程序=新的ThreadPoolExecutor.CallerRunPolicy();ExecutorService执行程序=新的ThreadPoolExecutor(threadCOunt,threadCOunt,0L,TimeUnit.毫秒,队列,处理程序);我打赌你可以从Kafka程序中提取帖子,它会给出相同的错误。我会尝试将这两件事分开来调试这个问题:“它会在连接服务器时抛出错误!?”和“我如何让Kafka做我认为我应该做的事?”我对问题进行了编辑。kafka中的多线程是为了提高性能,但后来我开始得到PKIX异常
for (ConsumerRecord<String, Event> record : records) {
                        executor.execute(new Runnable() {
                            @Override
                            public void run() {

                                        HTTPSend.send(Event);

                            }
                        });

                    }
int threadCOunt=1;
                BlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(threadCOunt, true);
                RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();
                ExecutorService executor = new ThreadPoolExecutor(threadCOunt, threadCOunt, 0L, TimeUnit.MILLISECONDS, queue, handler);
long sizeSend = 0;
    SSLContext sc = null;

    try {
        sc = SSLContext.getInstance("TLS");
        sc.init(null, TRUST_ALL_CERTS, new SecureRandom());
    } catch (NoSuchAlgorithmException | KeyManagementException e) {
        LOGGER.error("Failed to create SSL context", e);
    }

    // Ignore differences between given hostname and certificate hostname
    HostnameVerifier hv = (hostname, session) -> true;

    // Create the REST client and configure it to connect meta
    Client client = ClientBuilder.newBuilder()
            .hostnameVerifier(hv)
            .sslContext(sc).build();

    WebTarget baseTarget = client.target(getURL()).path(HTTP_PATH);
    Response jsonResponse = null;

    try {
        StringBuilder eventsBatchString = new StringBuilder();
        eventsBatchString.append(this.getEvent(event));
        Entity<String> entity = Entity.entity(eventsBatchString.toString(), MediaType.APPLICATION_JSON_TYPE);
        builder = baseTarget.request();
        LOGGER.debug("about to send the event {} and URL {}", entity, getURL());
        jsonResponse = builder.header(HTTP_ACK_CHANNEL, guid.toString())
                .header("Content-type", MediaType.APPLICATION_JSON)
                .header("Authorization", String.format("Meta %s", eventsModuleConfig.getSecretKey()))
                .post(entity);