python 中使用Kafka模块进行鉴权数据推送和消费

最近刚好要用到kafka进行数据传输,又要鉴权,就研究了一下kafka的鉴权推送和消费,现在将代码放出来,有兴趣的可以看一下,鉴权的加密方式各有不同,所以需要注意哦!

一、生产者

生产者采用的是异步推送的形式,另外加入了计数模块,担心因为脚本推送后未回调但是脚本就停止的情况。

import datetime
from loguru import logger
import time
import random
import json
import gc
from kafka import KafkaProducer
from kafka.errors import KafkaTimeoutError
import traceback


class KProducer:
    def __init__(self, bootstrap_servers, topic, sasl_plain_username, sasl_plain_password, retry_max_times=5, type=0):
        """
        kafka 生产者
        :param bootstrap_servers: 地址
        :param topic:  topic
        """
        self.producer = self.get_kafkaProduct(bootstrap_servers, sasl_plain_username, sasl_plain_password, type)
        self.topic = topic
        self.flage = True
        self.text = ''''''
        self.retry_max_times = retry_max_times
        self.error_max_cout = 1000
        self.error_cout = 0

        self.item_count = 0
        self.total_push_count = 0
        self.total_receive_s_count = 0
        self.total_receive_e_count = 0

        self.kafka_items = {}

    def get_kafkaProduct(self, bootstrap_servers, sasl_plain_username, sasl_plain_password, type=0):
        '''
       获取kafka 生产者实例
       :param bootstrap_servers:
       :return:
       '''
        producer = None
        for i in range(5):
            try:
                if type in [1, '1']: # 判断是否要进行鉴权
                    producer = KafkaProducer(
                        bootstrap_servers=bootstrap_servers,
                        key_serializer=lambda k: json.dumps(k).encode(),
                        value_serializer=lambda v: json.dumps(v).encode(),  # value值为 json 格式化发送的内容
                        acks='all',  # acks:kafka返回的模式,1为发送成功则返回成功,‘all’为kafka全流程保存成功才返回成功。否则返回连接超时
                        retries=5,  # 重试发送次数,有时候网络出现短暂的问题的时候,会自动重发消息,这个值是需要在acks=1或all时候才有效,并且后面的max_in_flight_requests_per_connection 需要设置成1
                        request_timeout_ms=10000,  # 默认超时时间是30000ms
                        max_in_flight_requests_per_connection=1,  # 每个发送数据的网络连接对并未接收到响应的消息的最大数。默认值是5
                        batch_size=1048576,
                        # linger_ms=100,

                        sasl_mechanism="SCRAM-SHA-256",  # PLAIN 数据加密方式
                        # ssl_context=context,
                        security_protocol='SASL_PLAINTEXT',  # SASL_SSL
                        api_version=(0, 10),
                        sasl_plain_username=sasl_plain_username, # 鉴权账号
                        sasl_plain_password=sasl_plain_password, # 鉴权账号密码
                    )
                else:
                    producer = KafkaProducer(
                        bootstrap_servers=bootstrap_servers,
                        key_serializer=lambda k: json.dumps(k).encode(),
                        value_serializer=lambda v: json.dumps(v).encode(),  # value值为 json 格式化发送的内容
                        acks='all',  # acks:kafka返回的模式,1为发送成功则返回成功,‘all’为kafka全流程保存成功才返回成功。否则返回连接超时
                        retries=5,  # 重试发送次数,有时候网络出现短暂的问题的时候,会自动重发消息, 这个值是需要在acks=1或all
                                    # 时候才有效,并且后面的max_in_flight_requests_per_connection 需要设置成1

                        request_timeout_ms=10000,  # 默认超时时间是30000ms
                        batch_size=1048576,
                        linger_ms=300,
                        max_in_flight_requests_per_connection=1,  # 每个发送数据的网络连接对并未接收到响应的消息的最大数。默认值是5
                    )

                break
            except Exception as e:
                logger.error(f'【kafka_error】{bootstrap_servers}  报错: {e} kafka连接断开,重连中!')
                time.sleep(5)

        return producer

    def asyn_producer_callback(self, data, key, now_time=1):
        """
        异步发送数据 + 发送状态处理
        :param data_list:
        :param data_li:发送数据
        :return:
        """
        # gc.disable()
        try:
            if self.producer:
                key_name = key[key.find('|', 1) + 1:key.rfind('|', 1)]
                now_num = self.kafka_items.setdefault(key_name, {'push_num': 0, 'callbakc_num': 0, 'error_num': 0})[
                              'push_num'] + 1
                self.kafka_items[key_name]['push_num'] = now_num

                res = self.producer.send(self.topic, value=data, key=key).add_callback(
                    self.send_success, key_name=key_name).add_errback(self.send_error, data=data, key=key, now_time=now_time, key_name=key_name)
                self.item_count += 1
                self.total_push_count += 1
            # res.get(timeout=5)  # producer默认是异步的 如果加了get就变成了同步,也就是说要等待get到服务端返回的结果后再往下执行
            # self.producer.flush()  # 批量提交

        except KafkaTimeoutError as err:
            if self.error_cout < self.error_max_cout:
                self.error_cout += 1
                logger.error(f'【Kafka】超时 {err}')

            if now_time <= self.retry_max_times:
                now_time += 1
                return self.asyn_producer_callback(data=data, key=key, now_time=now_time)

        except Exception as err:
            if self.error_cout < self.error_max_cout:
                self.error_cout += 1
                logger.error(f'【kafka_error】key: {key} => 异步发送错误: {err} ,重新发送。')

            if now_time <= self.retry_max_times:
                now_time += 1
                return self.asyn_producer_callback(data=data, key=key, now_time=now_time)

        return ''

    def send_success(self, *args, **kwargs):
        """异步发送成功回调函数"""
        if self.item_count > 0:
            self.item_count -= 1
        # print('send_success')
        key_name = kwargs['key_name']
        self.kafka_items[key_name]['callbakc_num'] += 1
        self.total_receive_s_count += 1
        return

    def send_error(self, excp=None, *args, **kwargs):
        """异步发送错误回调函数"""
        if self.item_count > 0:
            self.item_count -= 1

        self.total_receive_e_count += 1
        try:
            data = kwargs['data']
            key = kwargs['key']
            now_time = kwargs['now_time']
            key_name = kwargs['key_name']
            self.kafka_items[key_name]['error_num'] += 1

            if now_time <= self.retry_max_times:
                now_time += 1
                time.sleep(10)
                yield self.asyn_producer_callback(data, key, now_time)

        except KafkaTimeoutError as err:
            if self.error_cout < self.error_max_cout:
                self.error_cout += 1
                logger.error(f'【kafka_error】key: {key} => 异步发送错误: {err} ,重新发送。')

            if now_time <= self.retry_max_times:
                now_time += 1
                return self.asyn_producer_callback(data=data, key=key, now_time=now_time)

        except Exception as e:
            if self.error_cout < self.error_max_cout:
                self.error_cout += 1
                logger.info(f'异步发送错误回调函数错误: {excp} | {e} | {args} |------| {kwargs}')

            if now_time <= self.retry_max_times:
                now_time += 1
                return self.asyn_producer_callback(data=data, key=key, now_time=now_time)

    def close_producer(self):
        try:
            self.producer.close()
        except Exception as e:
            logger.error(f'【kafka_error】kafka 关闭失败 原因:{e}')
            


kafka_config = {
        "bootstrap_servers": [],
        "topic": "",
        "sasl_plain_username": "", # 鉴权账号
        "sasl_plain_password": "", # 鉴权账号密码
        "type": 1
    }

topic = kafka_config.get('topic', '')
kakfka_producer = KProducer(topic=kafka_config['topic'],
                            bootstrap_servers=kafka_config['bootstrap_servers'],
                            sasl_plain_username=kafka_config['sasl_plain_username'],
                            sasl_plain_password=kafka_config['sasl_plain_password'],
                            type=kafka_config['type'])
# 发送的内容               
item_new = {
    'database': '',
    'table': '',
    'data': 'msg'
}
# 定义kafka推送数据唯一标识
keys = '|'.join([item_new['database'], item_new['table'], str(int(time.time() * 1000))])
kakfka_producer.asyn_producer_callback(item_new, key=keys)

二、消费者

消费者的代码就比较简单,只需要加入鉴权的账号密码以及加密方式即可。

from kafka import KafkaProducer, KafkaConsumer
from kafka.errors import kafka_errors
import traceback
import json
import datetime
import time

def consumer_demo():
    config = {
        "bootstrap_servers": [""],
        "topic": "",
        "sasl_plain_username": "",
        "sasl_plain_password": "",
        "type": 1
    }

    consumer = KafkaConsumer(
        config['topic'],
        bootstrap_servers=config['bootstrap_servers'],
        sasl_mechanism="SCRAM-SHA-256",  # PLAIN
        # ssl_context=context,
        security_protocol='SASL_PLAINTEXT',  # SASL_SSL
        api_version=(0, 10),
        sasl_plain_username=config['sasl_plain_username'],
        sasl_plain_password=config['sasl_plain_password'],

    )
    
    print('等待接收....', config)
    for message in consumer:
        # if 'gzzfcj_collection_monitor' in message.key.decode():
        print("receive, key: {}, value: {}".format(
            json.loads(message.key.decode()),
            json.loads(message.value.decode())
        )
        )

if __name__ == '__main__':
    consumer_demo()

以上就是全部代码,有兴趣的可以了解一下,我也当做记录。

<think>嗯,用户想应聘Java工程师,需要在简历上添加一个关于购物网站用户行为分析商品推荐的项目。我得先理解他的需求。他提到用户有浏览、收藏、购买等交互数据,然后基于这些用模型预测兴趣商品,推送结果,并记录到MySQL。 首先,可能需要确定项目的整体架构。常见的是分层结构,比如数据采集、数据处理、模型训练、推荐服务、数据存储。数据采集部分,用户行为数据怎么收集?可能用前端埋点,或者后端日志。前端埋点的话,可以用JavaScript发送事件到后端API,或者用日志收集框架如Flume、Kafka。 然后数据处理,可能需要实时或离线处理。实时的话可以用Flink或Spark Streaming,离线用Hadoop或Spark。然后特征工程,提取用户商品的特征,比如用户偏好、商品类别、点击率等。模型方面,协同过滤是基础,但可能也需要更复杂的算法,比如矩阵分解、深度学习模型如Wide & Deep。不过用户是Java工程师,可能需要用Java相关的机器学习库,比如Weka或者DL4J,但实际中可能更多用Python,这里可能需要结合,比如用Python训练模型,Java调用API。 推荐服务部分,需要设计一个RESTful API,用Spring Boot实现,接收用户ID,返回推荐列表。推送的话,可能用消息队列如Kafka,或者定时任务,比如每天推送数据存储到MySQL,需要设计表结构,比如用户行为表、推荐结果表、商品表等。 安全性方面,JWT权,防止恶意请求。性能优化,Redis缓存推荐结果,减少数据库压力。高可用的话,服务可能部署在云上,用Nginx做负载均衡,集群部署。 技术栈要写清楚,比如Spring Boot、MyBatis、MySQL、Redis、Kafka、Flink、Spark MLlib或者TensorFlow。不过用户是Java工程师,可能更侧重Java相关的技术,比如Spring生态,数据处理部分如果用Flink或Spark,可能用Java或Scala,但需要看用户是否熟悉。 项目难点可能包括实时数据处理、模型效果优化、系统性能。解决方案如Flink实时计算,A/B测试调优模型,缓存分库分表优化数据库。 需要确保技术细节足够,让简历有亮点,同时用户能解释清楚。可能还要考虑项目规模,比如数据量,是否分布式处理,有没有用到云计算服务等。总之,要突出Java技术栈,数据处理系统设计能力,以及模型集成方面的经验。</think>我将从技术选型、架构设计、核心模块实现三个层面为您梳理简历项目方案,并提供技术亮点包装建议: 一、技术栈增强方案(简历可呈现) 1. 数据采集层 - 埋点采集:Spring Boot + Apache Kafka实时收集用户行为事件 - 日志处理:Logstash + Elasticsearch实现行为日志结构化存储 - 流量控制:Guava RateLimiter实现API限流保护 2. 特征工程层 - 特征存储:Redis HyperLogLog统计商品UV,ZSET实现热度排行 - 特征计算:Apache Flink实时计算用户行为时间窗口统计量 - 特征编码:Alibaba FastJSON实现行为序列的Embedding编码 3. 模型服务层 - 离线训练:PyTorch实现Wide&Deep双塔推荐模型(Java通过JNI调用) - 在线服务:Spring Cloud Alibaba + gRPC构建模型推理微服务 - 缓存优化:Caffeine本地缓存+Redis分布式缓存二级缓存架构 4. 数据存储层 - 分库分表:ShardingSphere实现MySQL水平分片 - 数据同步:Canal监听MySQL binlog同步到Elasticsearch - 数据治理:Druid连接池+Prometheus监控慢查询 二、核心模块设计(面试重点) 1. 实时特征处理流水线 ```java // Flink实时处理示例 DataStream<UserBehavior> stream = env .addSource(new KafkaSource<>()) .keyBy(behavior -> behavior.userId) .window(TumblingEventTimeWindows.of(Time.minutes(5))) .process(new ProcessWindowFunction<>() { @Override public void process(String key, Context ctx, Iterable<UserBehavior> elements, Collector<UserFeature> out) { // 计算5分钟内点击/收藏/购买次数 FeatureBuilder feature = new FeatureBuilder(); elements.forEach(behavior -> { switch(behavior.type) { case CLICK: feature.clickCount++; break; case COLLECT: feature.collectCount++; break; case PURCHASE: feature.purchaseCount++; break; } }); out.collect(feature.build()); } }); ``` 2. 混合推荐策略设计 ```mermaid graph TD A[新用户] --> B[基于内容推荐] A --> C[热门商品兜底] D[老用户] --> E[协同过滤推荐] D --> F[深度学习模型] E --> G[多策略融合] F --> G G --> H[业务规则过滤] ``` 三、系统优化亮点(简历加分项) 1. 性能优化: - 通过BloomFilter实现曝光去重,QPS提升40% - 使用JDK16 Vector API加速特征向量计算 - 基于Zipkin实现全链路追踪,95%请求延迟<200ms 2. 架构设计: - 搭建ABTest平台实现多版本模型对比验证 - 设计降级策略:当模型服务不可用时自动切换规则引擎 - 采用Hystrix实现服务熔断,故障恢复时间<30s 四、MySQL表结构设计示例 ```sql CREATE TABLE user_behavior ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL COMMENT '用户ID', item_id INT NOT NULL COMMENT '商品ID', behavior_type TINYINT COMMENT '1-浏览 2-收藏 3-加购 4-购买', event_time DATETIME DEFAULT CURRENT_TIMESTAMP, INDEX idx_user_item (user_id, item_id), INDEX idx_time (event_time) ) ENGINE=InnoDB PARTITION BY RANGE (YEAR(event_time)) ( PARTITION p2023 VALUES LESS THAN (2024), PARTITION p2024 VALUES LESS THAN (2025) ); ``` 简历呈现建议: 1. 项目描述:"构建千万级用户规模的实时推荐系统,实现从数据采集、特征工程、模型服务到效果分析的完整闭环" 2. 技术亮点突出: - 实现Flink+Redis的实时特征计算框架,延迟<1s - 搭建混合推荐系统,CTR提升18.7% - 设计分级缓存架构,推荐服务TP99<50ms 3. 成果量化: - 日均处理20亿+用户行为事件 - 推荐转化率提升23% - 支持5000+ TPS并发请求 建议准备延伸问题: 1. 如何处理冷启动问题? 2. 模型特征如何进行版本管理? 3. 推荐结果如何避免重复曝光? 4. 怎样验证推荐效果的有效性?
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值