kafka初识

本文详细介绍了在Ubuntu 18.04环境下安装Kafka 0.10.0.1版本,配置server.properties和zookeeper.properties,创建、删除topic,以及使用命令行工具发送和消费消息的过程。还展示了Go语言实现的生产者和消费者的简单示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

kafka中文文档 本文环境:ubuntu:18.04

kafka安装、配置与基本使用(单节点)

安装kafka

下载 0.10.0.1版本并解压缩
在这里插入图片描述

> tar -xzf kafka_2.11-0.10.0.1.tgz
> cd kafka_2.11-0.10.0.1.tgz

kafka简单配置

> vi config/server.properties

主要注意三个地方:
	broker.id:			标识本机
	log.dirs:			是kafka接收消息存放路径
	zookeeper.connect:	指定连接的zookeeper集群地址

在这里插入图片描述

启动服务器

启动ZooKeeper服务器:
如果没有ZooKeeper服务器,可以通过与kafka打包在一起的便捷脚本来创建一个单节点ZooKeeper实例:

> bin/zookeeper-server-start.sh config/zookeeper.properties
> #后台启动: bin/zookeeper-server-start.sh -daemon config/zookeeper.properties
[2021-02-22 15:01:37,495] INFO Reading configuration from: config/zookeeper.properties (org.apache.zookeeper.server.quorum.QuorumPeerConfig)
...

启动Kafka服务器:

> bin/kafka-server-start.sh config/server.properties
> #后台启动: bin/kafka-server-start.sh -daemon config/server.properties
[2021-02-22 15:01:47,028] INFO Verifying properties (kafka.utils.VerifiableProperties)
[2021-02-22 15:01:47,051] INFO Property socket.send.buffer.bytes is overridden to 1048576 (kafka.utils.VerifiableProperties)
...

创建一个 topic

创建一个名为“test”的topic,它有一个分区和一个副本:

> bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test

查看所有 topic列表:

> bin/kafka-topics.sh --list --zookeeper localhost:2181
test

删除一个 topic (标记):

> bin/kafka-topics.sh --delete --zookeeper localhost:2181 --topic test

发送一些消息

Kafka自带一个命令行客户端,它从文件或标准输入中获取输入,并将其作为message(消息)发送到Kafka集群。默认情况下,每行将作为单独的message发送。
运行 producer,然后在控制台输入一些消息以发送到服务器。

> bin/kafka-console-producer.sh --broker-list localhost:9092 --topic test
This is a message
This is another message

启动一个 consumer

Kafka 还有一个命令行consumer(消费者),将消息转储到标准输出。

> bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test --from-beginning
This is a message
This is another message

查看消费组

查看所有消费组

> bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --list --new-consumer

查看单个消费组的消费详情

> bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --describe --group test(消费组name) --new-consumer

发布-订阅模式

Topic:

  • Kafka中的Topics总是多订阅者模式,一个topic可以拥有一个或者多个消费者来订阅它的数据

  • 对于每一个topic, Kafka集群都会维持一个分区日志,每个分区都是有序且顺序不可变的记录集,并且不断地追加到结构化的commitlog文件

  • 分区中的每一个记录都会分配一个id号来表示顺序,我们称之为 offset,offset用来唯一的标识分区中每一条记录

  • Kafka 集群保留所有发布的记录—无论他们是否已被消费—并通过一个可配置的参数——保留期限来控制.

  • 每一个消费者中唯一保存的元数据是offset(偏移量)即消费在log中的位置.

偏移量由消费者所控制:通常读取记录后,消费者会以线性的方式增加偏移量,但是实际上,由于这个位置由消费者控制,所以消费者可以采用任何顺序来消费记录.

生产者

生产者可以将数据发布到所选择的topic(主题)中

消费者

  • 消费者使用一个 消费组 名称来进行标识,发布到topic中的每条记录被分配给 订阅消费组 中的一个消费者实例.

  • 如果所有的消费者实例在同一消费组中,消息记录会负载平衡到每一个消费者实例

  • 如果所有的消费者实例在不同的消费组中,每条消息记录会广播到所有的消费者进程

消费者消费是以消费组为单位,消费组之间数据互不影响,组内数据均分

Go实现(Go 1.15)

kafka_p.go

package kafka_p

import (
	"github.com/Shopify/sarama"
	"log"
	"time"
)

// 定义Kafka生产者对象
type KafkaProducer struct {
	Config  *sarama.Config
	Address []string
	Topic   string
}

// 定义生产者接口
type Producer interface {
	MsgContent() []byte
}

//实例化sarama: Config
func (kP *KafkaProducer) ProducerConfigInit() {
	config := sarama.NewConfig()
	//是否开启消息发送成功后通知 successes channel
	config.Producer.Return.Successes = true
	//重试次数
	config.Producer.Retry.Max = 3
	//失败后再次尝试的间隔时间
	config.Producer.Retry.Backoff = 1 * time.Second
	//指定kafka版本,不指定,使用最小版本,高版本的新功能可能无法正常使用.
	config.Version = sarama.V0_10_0_1
	kP.Config = config
}

//同步消息模式
func (kP *KafkaProducer) SyncProducer(p Producer) error {
	//初始化客户端
	producer, err := sarama.NewSyncProducer(kP.Address, kP.Config)
	if err != nil {
		log.Printf("sarama.NewSyncProducer err, message=%s \n", err)
		return err
	}
	defer producer.Close()
	//发送消息
	msg := &sarama.ProducerMessage{
		Topic: kP.Topic,
		Value: sarama.ByteEncoder(p.MsgContent()),
	}
	part, offset, err := producer.SendMessage(msg)
	if err != nil {
		log.Printf("send message(%s) err=%s \n", p.MsgContent(), err)
		return err
	} else {
		log.Printf("发送成功,partition=%d, offset=%d \n", part, offset)
		return nil
	}
}

// 启动Kafka生产者
func (kP *KafkaProducer) StartP(p Producer) error {
	kP.ProducerConfigInit()
	return kP.SyncProducer(p)
}

kafka_c.go

package kafka_c

import (
	"github.com/Shopify/sarama"
	cluster "github.com/bsm/sarama-cluster"
	"log"
	"time"
)

// 定义Kafka消费者对象
type KafkaConsumer struct {
	Config  *cluster.Config
	Address []string
	Topics  []string
	GroupId string
}

// 定义消费者接口
type Consumer interface {
	Consumer([]byte) error
}

//实例化sarama: Config
func (kC *KafkaConsumer) ConsumerConfigInit() {
	config := cluster.NewConfig()
	//接收失败通知
	config.Consumer.Return.Errors = true
	//设置使用的kafka版本,如果低于V0_10_0_0版本,消息中的timestrap没有作用.需要消费和生产同时配置
	config.Version = sarama.V0_10_0_1
	//初始从最新的offset开始
	config.Consumer.Offsets.Initial = sarama.OffsetNewest
	kC.Config = config
}

//cluster消费组 消费
func (kC *KafkaConsumer) ClusterConsumer(c Consumer) error {
	//初始化客户端
	consumer, err := cluster.NewConsumer(kC.Address, kC.GroupId, kC.Topics, kC.Config)
	if err != nil {
		log.Printf("Failed open consumer: %s \n", err)
		return err
	}
	defer consumer.Close()
	go func() {
		for err := range consumer.Errors() {
			log.Printf("consumer err: %s \n", err)
		}
	}()
	go func() {
		for note := range consumer.Notifications() {
			log.Println("Rebalanced: ", note)
		}
	}()
	//接收消息
	for msg := range consumer.Messages() {
		if err = c.Consumer(msg.Value); err != nil {
			return nil
		}else {
			// MarkOffset 并不是实时写入kafka,有可能在程序crash时丢掉未提交的offset
			consumer.MarkOffset(msg, "")
			time.Sleep(1 * time.Second)
		}
	}
	return nil
}

// 启动Kafka消费者
func (kC *KafkaConsumer) StartC(c Consumer) error {
	kC.ConsumerConfigInit()
	return kC.ClusterConsumer(c)
}

配置kafka_config.go

package kafka_config

import "fmt"

// Address
var Address = []string{"IP:9092"}

var Topic = "test"            // 生产者topic
var Topics = []string{"test"} // 消费者topics
var GroupId = "test-group-1"  // 消费组id

//发送者
type TestP struct {
	MsgData []byte
}

// 实现发送者
func (t *TestP) MsgContent() []byte {
	fmt.Println(string(t.MsgData))
	return t.MsgData
}

//接收者
type TestC struct {
	MsgData string
}

// 实现接收者
func (t *TestC) Consumer(dataByte []byte) error {
	fmt.Println(string(dataByte))
	return nil
}

type KafkaMessage struct {
	FileDir     string `json:"dir"`
	FileName    string `json:"file"`
	OperateType string `json:"operation"`
	OldData     string `json:"old_data"`
	NewData     string `json:"new_data"`
}

type KafkaMessageP struct {
	UserName string         `json:"user_name"`
	MsgId    string         `json:"msg_id"`
	Messages []KafkaMessage `json:"msg"`
}

消费者main.go

package main

import (
	"golong/kafka_c"
	"golong/kafka_config"
)

func main() {
	//消费者
	c := &kafka_config.TestC{}
	kC := &kafka_c.KafkaConsumer{
		Address: kafka_config.Address,
		Topics:  kafka_config.Topics,
		GroupId: kafka_config.GroupId,
	}
	_ = kC.StartC(c)
}

生产者main.go

package main

import (
	"encoding/json"
	"fmt"
	"golong/kafka_config"
	"golong/kafka_p"
)

func main() {
	//生产者
	msgKp := &kafka_config.KafkaMessageP{}
	msgKp.UserName = "fxm"
	msgKpBytes, _ := json.Marshal(msgKp)
	p := &kafka_config.TestP{
		MsgData: msgKpBytes,
	}
	kP := &kafka_p.KafkaProducer{
		Address: kafka_config.Address,
		Topic:   kafka_config.Topic,
	}
	err := kP.StartP(p)
	if err != nil {
		fmt.Println("添加异常 !!!")
	}
}

panic: non-positive interval for NewTicker 问题处理

//处理1: 
	找到这个consumer.go源码位置,上面的第二个报错有标注位置
	github.com/bsm/sarama-cluster.(*Consumer).cmLoop(0xc000212000, 0xc0002ba1e0)
	D:/work/mygo/pkg/mod/github.com/bsm/sarama-cluster@v2.1.15+incompatible/consumer.go:452 +0x61
	 
	// 修改452行,
		//	ticker := time.NewTicker(c.client.config.Consumer.Offsets.CommitInterval)
		ticker := time.NewTicker(c.client.config.Consumer.Offsets.AutoCommit.Interval)
	// 保存重新build即可

//处理2:
	把 sarama 版本改成 从 v1.26.1 --> v1.24.1 就可以用啦 github.com/Shopify/sarama v1.24.1
	
	gomod 的配置改下版本号就可以
	github.com/Shopify/sarama v1.24.1
		github.com/bsm/sarama-cluster v2.1.15+incompatible
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值