1
2
3
|
// 客户端代码会创建kafka.javaapi.producer.Producer, 而此porducer在初始化的时候,
// 创建kafka.producer.Produce
def
this
(config
:
ProducerConfig)
=
this
(
new
kafka.producer.Producer[K,V](config))
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
class
Producer[K,V](
val
config
:
ProducerConfig,
private
val
eventHandler
:
EventHandler[K,V])
// only for unit testing
extends
Logging {
private
val
queue
=
new
LinkedBlockingQueue[KeyedMessage[K,V]](config.queueBufferingMaxMessages)
private
var
producerSendThread
:
ProducerSendThread[K,V]
=
null
config.producerType
match
{
case
"sync"
=
>
case
"async"
=
>
sync
=
false
//创建一个send线程,并启动它
producerSendThread
=
new
ProducerSendThread[K,V](
"ProducerSendThread-"
+ config.clientId,
queue,
eventHandler,
config.queueBufferingMaxMs,
config.batchNumMessages,
config.clientId)
producerSendThread.start()
}
//创建实际的handler 对象,后面调用send,实际上就是调用DefaultEventHandler的handle方法
def
this
(config
:
ProducerConfig)
=
this
(config,
new
DefaultEventHandler[K,V](config,
Utils.createObject[Partitioner](config.partitionerClass, config.props),
Utils.createObject[Encoder[V]](config.serializerClass, config.props),
Utils.createObject[Encoder[K]](config.keySerializerClass, config.props),
new
ProducerPool(config)))
}
|
1
2
3
4
5
6
7
8
9
10
11
12
|
def
send(messages
:
KeyedMessage[K,V]*) {
lock synchronized {
if
(hasShutdown.get)
throw
new
ProducerClosedException
recordStats(messages)
sync
match
{
//此处会进行选择,默认的情况下,为true,也就是走handle流程
case
true
=
> eventHandler.handle(messages)
case
false
=
> asyncSend(messages)
}
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
class
ProducerSendThread[K,V](... ... )
extends
Thread(threadName)
with
Logging
with
KafkaMetricsGroup {
... ....
//在此send线程中,主体动作是调用processEvents
private
def
processEvents() {
... ...
// drain the queue until you get a shutdown command
//从queue队列中取出一个消息。用户在使用producer.send()时,消息将会被放入到queue队列中
Stream.continually(queue.poll(scala.math.max(
0
, (lastSend + queueTime) - SystemTime.milliseconds), TimeUnit.MILLISECONDS))
.takeWhile(item
=
>
if
(item !
=
null
) item ne shutdownCommand
else
true
).foreach {
... ...
if
(currentQueueItem !
=
null
) {
//将取出来的消息赋给event
events +
=
currentQueueItem
}
... ....
// send the last batch of events
//调用tryToHandle来处理这个消息
tryToHandle(events)
}
def
tryToHandle(events
:
Seq[KeyedMessage[K,V]]) {
... ...
//调用DefaultEventHandler中的handle函数来处理消息
handler.handle(events)
... ...
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
def
handle(events
:
Seq[KeyedMessage[K,V]]) {
//将该消息序列化
val
serializedData
=
serialize(events)
... ...
//然后会根据传入的broker信息、topic信息,去取最新的该topic的metadata信息
//此处还不是太清楚
Utils.swallowError(brokerPartitionInfo.updateInfo(topicMetadataToRefresh.toSet, correlationId.getAndIncrement))
... ...
//开始发送消息了
outstandingProduceRequests
=
dispatchSerializedData(outstandingProduceRequests)
... ...
}
|
1
2
3
4
5
6
7
8
|
private
def
dispatchSerializedData(messages
:
Seq[KeyedMessage[K,Message]])
:
Seq[KeyedMessage[K, Message]]
=
{
... ....
//此处就开始发送消息了。
//很奇怪的是,使用debug模式调式,总是跳过它。加上日志可以看清楚
val
failedTopicPartitions
=
send(brokerid, messageSetPerBroker)
... ...
}
|
1
2
3
4
5
6
7
8
9
|
private
def
send(brokerId
:
Int, messagesPerTopic
:
collection.mutable.Map[TopicAndPartition, ByteBufferMessageSet])
=
{
... ...
//首先根据brokerId,找到对应的producer句柄,这个producerPool是事先初始化好的
val
syncProducer
=
producerPool.getProducer(brokerId)
... ...
//找到后,开始调用send命令
val
response
=
syncProducer.send(producerRequest)
... ...
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
private
def
doSend(request
:
RequestOrResponse, readResponse
:
Boolean
=
true
)
:
Receive
=
{
lock synchronized {
//首先校验消息是否合法
verifyRequest(request)
//获取与broken的连接。如我的broker 0是hadoop221:9092,客户端就会与9092这个端口连接
//只有在首次的时候会连接,连接后,会持有此连
getOrMakeConnection()
var
response
:
Receive
=
null
try
{
//将消息通过tcp连接发送过去
blockingChannel.send(request)
if
(readResponse)
//收到回复消息
response
=
blockingChannel.receive()
}
... ...
}
|
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
def
connect()
=
lock synchronized {
if
(!connected) {
try
{
channel
=
SocketChannel.open()
//阻塞式连接
channel.configureBlocking(
true
)
channel.socket.setSoTimeout(readTimeoutMs)
channel.socket.setKeepAlive(
true
)
channel.socket.setTcpNoDelay(
true
)
channel.socket.connect(
new
InetSocketAddress(host, port), connectTimeoutMs)
//writeChannel 用于写数据
writeChannel
=
channel
//而readChannel是获取inputstream流
readChannel
=
Channels.newChannel(channel.socket().getInputStream)
connected
=
true
... ...
}
}
|
1
2
3
4
5
6
7
|
def send(request: RequestOrResponse):Int = {
.. ...
//在send的时候,会创建一个ByteBufferSend对易用
val send =
new
BoundedByteBufferSend(request)
send.writeCompletely(writeChannel)
}
|
1
2
3
4
5
6
7
8
9
|
def
this
(request: RequestOrResponse) = {
//初始化bytebuffer的大小
this
(request.sizeInBytes + (
if
(request.requestId != None)
2
else
0
))
request.requestId match {
case
Some(requestId) =>
//写入requestId,其值val ProduceKey: Short = 0,也就是第一个值就是requestId
buffer.putShort(requestId)
case
None =>
}
|