Apache Kafka概念入门

介绍

Apache Kafka® 是 一个分布式流处理平台

开发步骤

  • 添加依赖
<dependency>
    <groupId>org.springframework.kafka</groupId>
    <artifactId>spring-kafka</artifactId>
    <version>2.2.4.RELEASE</version>
</dependency>
  • 生产者配置
#kafka producer
spring.kafka.bootstrap-servers=IP1:9092,IP2:9092,IP3:9092
spring.kafka.producer.acks=1
spring.kafka.producer.batch-size=16384
spring.kafka.producer.retries=0
spring.kafka.producer.buffer-memory=33554432
spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer
spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer

生产消息,异步发送

异步发送速度快,可能会推送重复数据,可能记录还没删除掉,查询又查了一次,导致重复推送数据(异步发完就不管了,设置监听器里的处理不具有有序性

@Autowired
private KafkaTemplate<String, Object> kafkaTemplate;

for (OrderDetail orderDetail : list) {
    final boolean[] lowFlag = {false};
    final boolean[] ownerFlag = {false};

    // 清洗级别为 OCR更新 时才发送kafka
    if (Objects.equals(orderDetail.getCleanPrecision(), CleanPrecisionEnum.OCR_UPDATE.getCode())) {
        //异步发送给自己的kafka
        ListenableFuture<SendResult<String, Object>> ownerFuture = kafkaTemplate.send(OrderConstants.OWNER_ORDER_TOPIC, JsonUtil.toJson(orderDetail));
        ownerFuture.addCallback(new ListenableFutureCallback<SendResult<String, Object>>() {
            @Override
            public void onSuccess(SendResult<String, Object> result) {
                ownerFlag[0] = true;
                log.error("ownerFuture发送kafka成功,数据为:" + result.getProducerRecord().value());

                //两个topic都发送成功后,删除数据
                if (lowFlag[0] && ownerFlag[0]) {
                    int num = nabsOrderDetailService.deleteOrderDetail(orderDetail, dSource);
                    log.error("ownerFuture删除成功数:" + num);
                }
            }

            @Override
            public void onFailure(Throwable throwable) {
                ownerFlag[0] = false;
                log.error("ownerFuture发送kafka失败", throwable);
            }
        });

    } else {
        ownerFlag[0] = true;
    }


    //异步发送给下游的kafka
    OrderDetailDto dto = BeanUtil.copy(orderDetail, OrderDetailDto.class);
    ListenableFuture<SendResult<String, Object>> lowFuture = kafkaTemplate.send(OrderConstants.LOWER_REACHES_ORDER_TOPIC, JsonUtil.toJson(dto));
    lowFuture.addCallback(new ListenableFutureCallback<SendResult<String, Object>>() {
        @Override
        public void onSuccess(SendResult<String, Object> result) {
            lowFlag[0] = true;
            log.error("lowFuture发送kafka成功,数据为:" + result.getProducerRecord().value());

            //两个topic都发送成功后,删除数据
            if (lowFlag[0] && ownerFlag[0]) {
                int num = nabsOrderDetailService.deleteOrderDetail(orderDetail, dSource);
                log.error("lowFuture删除成功数:" + num);
            }
        }

        @Override
        public void onFailure(Throwable throwable) {
            lowFlag[0] = false;
            log.error("lowFuture发送kafka失败", throwable);
        }
    });


}

生产消息,同步发送

同步发送速度慢,等待发送返回结果,保证顺序执行

protected void handleData(String dSource, List<OrderDetail> list) {
     long startTime = System.currentTimeMillis();

     for (OrderDetail orderDetail : list) {
         boolean ownFlag = true;
         boolean lowFlag = true;

         try {
             // 清洗级别为 OCR更新 时才发送kafka
             if (Objects.equals(orderDetail.getCleanPrecision(), CleanPrecisionEnum.OCR_UPDATE.getCode())) {
                 //同步发送给自己的kafka
                 SendResult<String, Object> ownSendResult = kafkaTemplate.send(OrderConstants.OWNER_ORDER_TOPIC, JsonUtil.toJson(orderDetail)).get();
                 log.error("ownSendResult发送kafka成功,数据为:" + ownSendResult.getProducerRecord().value());
             }
         } catch (Exception e) {
             ownFlag = false;
             log.error("ownSendResult发送kafka失败", e);
         }

         try {
             //同步发送给下游的kafka
             OrderDetailDto dto = BeanUtil.copy(orderDetail, OrderDetailDto.class);
             SendResult<String, Object> lowSendResult = kafkaTemplate.send(OrderConstants.LOWER_REACHES_ORDER_TOPIC, JsonUtil.toJson(dto)).get();
             log.error("lowSendResult发送kafka成功,数据为:" + lowSendResult.getProducerRecord().value());
         } catch (Exception e) {
             lowFlag = false;
             log.error("lowSendResult发送kafka失败", e);
         }

         if (ownFlag && lowFlag) {
             int num = nabsOrderDetailService.deleteOrderDetail(orderDetail, dSource);
             log.error("删除成功数:" + num);
         }


     }

     log.error("当前数据源【" + dSource + "】" + ",查询结果集大小:" + list.size() + ",耗时:" + (System.currentTimeMillis() - startTime) + " ms");

 }

  • 全局监听器
package cn.yto.kafka;

import cn.yto.nabs.common.entity.OrderDetail;
import cn.yto.nabs.common.util.JsonUtils;
import cn.yto.service.NabsOrderDetailService;
import cn.yto.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.clients.producer.RecordMetadata;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.support.ProducerListener;
import org.springframework.stereotype.Component;

/**
 * @Author yanyg
 * @Date 2020/7/17 13:41
 * @Descripetion admin
 */
@Component
@Slf4j
public class KafkaSendResultHandler implements ProducerListener {
    @Autowired
    private NabsOrderDetailService nabsOrderDetailService;

    @Override
    public void onSuccess(ProducerRecord producerRecord, RecordMetadata recordMetadata) {
        log.error("Message send success : " + producerRecord.toString());
        if (StringUtil.isBlank((String) producerRecord.value())) {
            return;
        }

        OrderDetail orderDetail = JsonUtils.json2Object((String) producerRecord.value(), OrderDetail.class);
        int num = nabsOrderDetailService.deleteOrderDetail(orderDetail);
        log.error("num==" + num);
    }

    @Override
    public void onError(ProducerRecord producerRecord, Exception exception) {
        log.error("Message send error : " + producerRecord.toString());
    }
}

  • 消费者配置
#kafka consumer
spring.kafka.bootstrap-servers=IP1:9092,IP2:9092,IP3:9092
#指定消息组
spring.kafka.consumer.group-id=owner-group
#指定消息被消费之后自动提交偏移量,以便下次继续消费
spring.kafka.consumer.enable-auto-commit=true
#指定从最近地方开始消费
spring.kafka.consumer.auto-offset-reset=latest
spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer
spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer

  • 消费消息
@Component
@Slf4j
public class KafkaMessageConsumer {

    @KafkaListener(topics = {"owner-topic"})
    public void listen(ConsumerRecord<String, String> record) {
        String data = record.value();
        Integer partition = record.partition();
        Long timestamp = record.timestamp();
        Long offset = record.offset();
        log.info("kafka consumer message:{};partition:{};offset:{};timestamp:{}", data, partition, offset, timestamp);
    }

}
资源下载链接为: https://pan.quark.cn/s/3d8e22c21839 随着 Web UI 框架(如 EasyUI、JqueryUI、Ext、DWZ 等)的不断发展与成熟,系统界面的统一化设计逐渐成为可能,同时代码生成器也能够生成符合统一规范的界面。在这种背景下,“代码生成 + 手工合并”的半智能开发模式正逐渐成为新的开发趋势。通过代码生成器,单表数据模型以及一对多数据模型的增删改查功能可以被直接生成并投入使用,这能够有效节省大约 80% 的开发工作量,从而显著提升开发效率。 JEECG(J2EE Code Generation)是一款基于代码生成器的智能开发平台。它引领了一种全新的开发模式,即从在线编码(Online Coding)到代码生成器生成代码,再到手工合并(Merge)的智能开发流程。该平台能够帮助开发者解决 Java 项目中大约 90% 的重复性工作,让开发者可以将更多的精力集中在业务逻辑的实现上。它不仅能够快速提高开发效率,帮助公司节省大量的人力成本,同时也保持了开发的灵活性。 JEECG 的核心宗旨是:对于简单的功能,可以通过在线编码配置来实现;对于复杂的功能,则利用代码生成器生成代码后,再进行手工合并;对于复杂的流程业务,采用表单自定义的方式进行处理,而业务流程则通过工作流来实现,并且可以扩展出任务接口,供开发者编写具体的业务逻辑。通过这种方式,JEECG 实现了流程任务节点和任务接口的灵活配置,既保证了开发的高效性,又兼顾了项目的灵活性和可扩展性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值