Kafka specifies the partition rule of the message

Keywords: kafka Java socket JSON

Note: the number of partitions num.partitions is specified in the configuration file server.properties. This refers to the sum of the number of partitions of multiple single topic s. If there are multiple brokers, the partition may be distributed on different nodes, then the total number of all partitions of multiple brokers is num.partitions

Several items of producer configuration in 0.7 are mutually exclusive. If one of them is set, the other cannot be set
For example:
broker.list and zk.connect cannot be set at the same time
broker.list and partitioner.class cannot be set at the same time
If you do this, it doesn't matter at compile time. The runtime throws exceptions

1. Specify the broker

props.put("broker.list", "0:10.10.10.10:9092"); / / directly connect to kafka
After setting this item, you can't set partitioner.class. However, when I run it, I found that all data is sent to the four partitions of 10.10.10.10, not only one partition. It's useless for me to change the send (topic, partitioned, list) in syncproducer.

2. Specify partition
props.put("partitioner.class","com.kafka.myparitioner.CidPartitioner");
props.put("zk.connect", "10.10.10.10:2181"); / / connect zk

The above com.kafka.myparitioner.CidPartitioner is a self implemented class. Please implement the complete package name yourself
The CidPartitioner inherits the Partitioner class, where the partition method implemented specifies the method to calculate the partition through the key

 

package com.kafka.myparitioner;

import kafka.producer.Partitioner;
import kafka.utils.VerifiableProperties;

//Set the rule of which partition to send the current message according to the key
public class CidPartitioner implements Partitioner {
    public CidPartitioner(VerifiableProperties props) {  
          //Note: there is nothing in the function body of the constructor, but there can be no constructor          
    }  
    
    @Override
    public int partition(Object key, int numPartitions) {
        try {            
            long partitionNum = Long.parseLong((String) key);
            return (int) Math.abs(partitionNum % numPartitions);
        } catch (Exception e) {
            return Math.abs(key.hashCode() % numPartitions);
        }
    }
}

 

 

To allocate partition based on key, you need to specify key when sending messages.  

 

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Properties;
import java.util.regex.Pattern;

import kafka.producer.KeyedMessage;
import kafka.producer.ProducerConfig;

//The difference between KafkaReceiverLTELogSocket and kafkareceivertlelogsocket is that the partition allocation rules of messages are specified
public class KafkaReceiveLTELogSocketPartition extends Thread{
    //Sending LTE signaling data at a certain time interval
    String regEx ="[^0-9.\\+\\-\\s+\\,E]"; 
    Pattern p = Pattern.compile(regEx); 
        
    //The first type represents the type of key, and the second represents the type of message
    private final kafka.javaapi.producer.Producer<String, String> producer;
    private final String topic;
    private final Properties props = new Properties();
    
    private final int port = 12345; 
    
    public KafkaReceiveLTELogSocketPartition(String topic) {
        props.put("serializer.class", "kafka.serializer.StringEncoder");
        props.put("metadata.broker.list", "192.168.1.164:9093"); // Configure kafka port        
        props.put("partitioner.class","com.kafka.myparitioner.CidPartitioner");
        //props.put("zk.connect", "192.168.1.164:2181"); / / connect zk. The new version seems to be unnecessary
        
        producer = new kafka.javaapi.producer.Producer<String, String>(new ProducerConfig(props));
        this.topic = topic;
    }
    
    public void receiveAndWrite2(String outputFileName , int port) throws IOException{
        ServerSocket serverSocket = new ServerSocket(port);
        Socket socket = serverSocket.accept();
        StringBuilder sb = new StringBuilder();
        try{
            while(true){                
                InputStream istream = socket.getInputStream();
                int count = 0;
                while (count == 0) {
                    count = istream.available();
                }
                byte[] b = new byte[count];
                istream.read(b);
                for(int i = 0 ; i < count ; i ++){
                    if(b[i]=='\n'){ //When a line break in the stream is encountered, it indicates that a complete message has been obtained and sent        
                        String str = sb.toString();
                        
                        //Get key CID str
                        String key_cid_str = str.substring(str.indexOf(":")+1, str.indexOf(","));
                        
                        System.out.println("Receiving length:"+str.length());
                        System.out.println(str);
                        //The first parameter represents the type of key, and the second parameter represents the type of message
                        producer.send(new KeyedMessage<String, String>(topic,key_cid_str,str));
                        
                        sb = new StringBuilder();
                    }else{        
                        sb.append(Character.toChars(b[i]));
                    }
                }
            }
            
        }finally{
            // Close socket, do not close in while, otherwise the sender will rebuild the connection every time
            socket.close();
            serverSocket.close();
        }
    }
    
    @Override
    public void run() {
        String filename = "JSON1_Yanming_DriveTesting_09-04.16-17.16-27_TIME.json";
        String outputFileName  = ""+filename;
        
        try {
            receiveAndWrite2(outputFileName,port);
        } catch (IOException e) {    
            e.printStackTrace();
        }        
    }    
    public static void main(String[] args) {
        String topic = "kafka_flume_topic";
        new KafkaReceiveLTELogSocketPartition(topic).start();
    }
}

 

Posted by rejoice on Wed, 20 Nov 2019 13:22:10 -0800