Kafka 生产实战调优 生产者<------>消费者

Talk is cheap,Show me the code
生产者

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Primary;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.SendResult;
import org.springframework.stereotype.Component;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;

import javax.annotation.Resource;


/**
 * @ClassName: KafkaProducer
 * @Author: Guoxin
 * @Description: kafka生产类
 * @Date: 2021/7/16 10:21 上午
 */
@Component
@Slf4j
@Primary
public class KafkaProducer{

    @Resource
    private KafkaTemplate kafkaTemplate;

    public void send(String topic,Object obj) {
        String obj2String = JSONObject.toJSONString(obj);
        //发送消息
        ListenableFuture> future = kafkaTemplate.send(topic, obj2String);
        future.addCallback(new ListenableFutureCallback>() {
            @Override
            public void onFailure(Throwable throwable) {
                //发送失败的处理
                log.error(topic + " - 生产者 发送消息失败:{}" ,throwable);
            }

            @Override
            public void onSuccess(SendResult stringObjectSendResult) {
                //成功的处理
                //log.info(topic + " - 生产者 发送消息成功:{}" ,stringObjectSendResult.getProducerRecord().value());
            }
        });
    }
}

调优参数:
#指定发送延迟
# 这个参数用来指定生产者发送 ProducerBatch 之前等待更多消息(ProducerRecord)加入ProducerBatch 的时间,默认值为 0。生产者客户端会在 ProducerBatch 被填满或等待时间超过linger.ms 值时发送出去。增大这个参数的值会增加消息的延迟,但是同时能提升一定的吞吐量。这个linger.ms参数与TCP协议中的Nagle算法有异曲同工之妙。
spring.kafka.properties.linger.ms = 50
# 服务端地址 多个用,隔开   其实写一个就行。但是最好都写好 防止一个挂掉 找不到其他的集群节点
spring.kafka.bootstrap-servers = localhost:9092
# retries参数用来配置生产者重试的次数,默认值为0,即在发生异常的时候不进行任何重试动作。消息在从生产者发出到成功写入服务器之前可能发生一些临时性的异常,比如网络抖动、leader副本的选举等,这种异常往往是可以自行恢复的,生产者可以通过配置retries大于0的值,以此通过内部重试来恢复而不是一味地将异常抛给生产者的应用程序。如果重试达到设定的次数,那么生产者就会放弃重试并返回异常。不过并不是所有的异常都是可以通过重试来解决的,比如消息太大,超过max.request.size参数配置的值时,这种方式就不可行了。
spring.kafka.producer.retries = 1
# 它主要用来实现ByteBuffer的复用,以实现缓存的高效利用。不过BufferPool只针对特定大小的ByteBuffer进行管理,而其他大小的ByteBuffer不会缓存进BufferPool中,这个特定的大小由batch.size参数来指定,默认值为16384B,即16KB。我们可以适当地调大batch.size参数以便多缓存一些消息
spring.kafka.producer.batch-size = 512000
# producer可以使用的最大内存来缓存等待发送到server端的消息. 如果消息速度大于producer交付到server端的阻塞时间max.block.ms, 将会抛出异常. 默认值33554432 byte (32m). 这个设置不是一个严格的边界, 因为producer除了用来缓存消息, 还要用来进行压缩.
spring.kafka.producer.buffer-memory = 104857600
# key 序列化
spring.kafka.producer.key-serializer = org.apache.kafka.common.serialization.StringSerializer
# value 序列化
spring.kafka.producer.value-serializer = org.apache.kafka.common.serialization.StringSerializer
#这个参数用来指定分区中必须要有多少个副本收到这条消息,之后生产者才会认为这条消息是成功写入的。acks 是生产者客户端中一个非常重要的参数,它涉及消息的可靠性和吞吐量之间的权衡
spring.kafka.producer.acks = 1
消费者

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.support.Acknowledgment;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Optional;

/**
 * @ClassName: KafkaConsumer
 * @Author: Guoxin
 * @Description: kafka消费端
 * @Date: 2021/7/16 3:04 下午
 */

@Component
@Slf4j
public class LogKafkaConsumer {

    @KafkaListener(topics = {"${engine.prd.save.topic:risk-api-prd-save}", "${engine.pre.save.topic:risk-api-pre-save}"}, groupId = "log")
    public void prdListen(List> list, Acknowledgment ack) {
        handlerRecord(list, ack);
    }


    private void handlerRecord(List> list, Acknowledgment ack) {
        list.forEach(consumerRecord -> Optional.ofNullable(consumerRecord.value()).map(message -> {
            String msg = message.toString();
            ack.acknowledge();
            log.info("topic_test 消费了: requestId:{}", msg);
            return true;
        }).isPresent());

    }


}


调优参数

kafka consume start###

#earliest 当各分区下有已提交的offset时,从提交的offset开始消费;无提 交offset时,从头开始消费
#atest
当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,消费新产生的该分区下的数据
#none topic各分区都存在已提交的offset时,从offset后开始消费;只要有一个分区不存在已提交的offset,则抛出异常
spring.kafka.consumer.auto-offset-reset = earliest
#不自动提交
spring.kafka.consumer.enable-auto-commit = false
#key序列化
spring.kafka.consumer.key-deserializer = org.apache.kafka.common.serialization.StringDeserializer
#value序列化
spring.kafka.consumer.value-deserializer = org.apache.kafka.common.serialization.StringDeserializer
#listener 中线程数量
spring.kafka.listener.concurrency = 5
#listener 手动立即提交
spring.kafka.listener.ack-mode = manual_immediate
#如果监听的topic不存在是否报错
spring.kafka.listener.missing-topics-fatal = false

kafka consume end

你可能感兴趣的:(kafka,spring-boot,kafka)