初始化
commit
3894f18c54
|
@ -0,0 +1,38 @@
|
||||||
|
target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
!**/src/main/**/target/
|
||||||
|
!**/src/test/**/target/
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea/modules.xml
|
||||||
|
.idea/jarRepositories.xml
|
||||||
|
.idea/compiler.xml
|
||||||
|
.idea/libraries/
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### Eclipse ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
build/
|
||||||
|
!**/src/main/**/build/
|
||||||
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
### Mac OS ###
|
||||||
|
.DS_Store
|
|
@ -0,0 +1,8 @@
|
||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding">
|
||||||
|
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||||
|
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
|
<component name="MavenProjectsManager">
|
||||||
|
<option name="originalFiles">
|
||||||
|
<list>
|
||||||
|
<option value="$PROJECT_DIR$/pom.xml" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
|
||||||
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,124 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Palette2">
|
||||||
|
<group name="Swing">
|
||||||
|
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||||
|
<initial-values>
|
||||||
|
<property name="text" value="Button" />
|
||||||
|
</initial-values>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||||
|
<initial-values>
|
||||||
|
<property name="text" value="RadioButton" />
|
||||||
|
</initial-values>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||||
|
<initial-values>
|
||||||
|
<property name="text" value="CheckBox" />
|
||||||
|
</initial-values>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||||
|
<initial-values>
|
||||||
|
<property name="text" value="Label" />
|
||||||
|
</initial-values>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||||
|
<preferred-size width="150" height="-1" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||||
|
<preferred-size width="150" height="-1" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||||
|
<preferred-size width="150" height="-1" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||||
|
<preferred-size width="200" height="200" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||||
|
<preferred-size width="200" height="200" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||||
|
<preferred-size width="-1" height="20" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||||
|
</item>
|
||||||
|
</group>
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,17 @@
|
||||||
|
# 基础镜像
|
||||||
|
FROM anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/openjdk:17-8.6
|
||||||
|
|
||||||
|
#暴露端口位置
|
||||||
|
EXPOSE 9999
|
||||||
|
|
||||||
|
# 挂载目录
|
||||||
|
VOLUME /home/logs/god-data-server
|
||||||
|
|
||||||
|
# 复制jar文件到docker内部
|
||||||
|
COPY /target/mqtt-redis-demo-1.0-SNAPSHOT.jar /home/app.jar
|
||||||
|
|
||||||
|
#工作目录 exec -it 进来默认就是这个目
|
||||||
|
WORKDIR /home
|
||||||
|
|
||||||
|
# 启动java程序
|
||||||
|
ENTRYPOINT ["java","-Dfile.encoding=UTF-8","-jar","/home/app.jar"]
|
|
@ -0,0 +1,76 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.god</groupId>
|
||||||
|
<artifactId>mqtt-kafkademo</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
|
<maven.compiler.target>17</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>2.7.7</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>menghang-public</id>
|
||||||
|
<name>梦航-public</name>
|
||||||
|
<url>http://10.100.1.6:8081/repository/maven-public/</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<distributionManagement>
|
||||||
|
<repository>
|
||||||
|
<id>menghang-releases</id>
|
||||||
|
<name>梦航-releases</name>
|
||||||
|
<url>http://10.100.1.6:8081/repository/maven-releases/</url>
|
||||||
|
</repository>
|
||||||
|
</distributionManagement>
|
||||||
|
|
||||||
|
<!-- kafka-->
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.kafka</groupId>
|
||||||
|
<artifactId>kafka-clients</artifactId>
|
||||||
|
<version>3.3.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.kafka</groupId>
|
||||||
|
<artifactId>spring-kafka</artifactId>
|
||||||
|
<version>2.8.11</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>fastjson</artifactId>
|
||||||
|
<version>1.2.83</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>1.18.28</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.paho</groupId>
|
||||||
|
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
|
||||||
|
<version>1.2.5</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.god;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class MqttRedisApplication {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(MqttRedisApplication.class);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
package com.god.kafka.config;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.apache.kafka.clients.producer.KafkaProducer;
|
||||||
|
import org.apache.kafka.clients.producer.ProducerConfig;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.boot.SpringBootConfiguration;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.kafka.support.serializer.JsonSerializer;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kafka 消息的提供者 配置类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@Configuration
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@ConfigurationProperties(prefix = "spring.kafka.producer")
|
||||||
|
public class KafkaProviderConfig {
|
||||||
|
|
||||||
|
private String bootstrapServers;
|
||||||
|
|
||||||
|
private String transactionIdPrefix;
|
||||||
|
|
||||||
|
private String acks;
|
||||||
|
|
||||||
|
private String retries;
|
||||||
|
|
||||||
|
private String batchSize;
|
||||||
|
|
||||||
|
private String bufferMemory;
|
||||||
|
|
||||||
|
private String keySerializer;
|
||||||
|
|
||||||
|
private String valueSerializer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建了 Map 存放了 Kafka 生产者的 配置信息
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public KafkaProducer<String, String> producerConfigs() {
|
||||||
|
Properties props = new Properties();
|
||||||
|
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
|
||||||
|
//acks=0 : 生产者在成功写入消息之前不会等待任何来自服务器的响应。
|
||||||
|
//acks=1 : 只要集群的首领节点收到消息,生产者就会收到一个来自服务器成功响应。
|
||||||
|
//acks=all :只有当所有参与复制的节点全部收到消息时,生产者才会收到一个来自服务器的成功响应。
|
||||||
|
//开启事务必须设为all
|
||||||
|
props.put(ProducerConfig.ACKS_CONFIG, acks);
|
||||||
|
//发生错误后,消息重发的次数,开启事务必须大于0
|
||||||
|
props.put(ProducerConfig.RETRIES_CONFIG, retries);
|
||||||
|
//当多个消息发送到相同分区时,生产者会将消息打包到一起,以减少请求交互. 而不是一条条发送
|
||||||
|
//批次的大小可以通过batch.size 参数设置.默认是16KB
|
||||||
|
//较小的批次大小有可能降低吞吐量(批次大小为0则完全禁用批处理)。
|
||||||
|
//比如说,kafka里的消息5秒钟Batch才凑满了16KB,才能发送出去。那这些消息的延迟就是5秒钟
|
||||||
|
//实测batchSize这个参数没有用
|
||||||
|
props.put(ProducerConfig.BATCH_SIZE_CONFIG, batchSize);
|
||||||
|
//有的时刻消息比较少,过了很久,比如5min也没有凑够16KB,这样延时就很大,所以需要一个参数. 再设置一个时间,到了这个时间,
|
||||||
|
//即使数据没达到16KB,也将这个批次发送出去
|
||||||
|
props.put(ProducerConfig.LINGER_MS_CONFIG, "5000");
|
||||||
|
//生产者内存缓冲区的大小
|
||||||
|
props.put(ProducerConfig.BUFFER_MEMORY_CONFIG, bufferMemory);
|
||||||
|
//反序列化,和生产者的序列化方式对应
|
||||||
|
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, keySerializer);
|
||||||
|
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, valueSerializer);
|
||||||
|
props.put("partitioner.class", "com.god.kafka.partitioner.MyPartitioner");
|
||||||
|
return new KafkaProducer<>(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.god.kafka.contents;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author DongZl
|
||||||
|
* @description: kafka常量类
|
||||||
|
* @Date 2023/8/25 18:47
|
||||||
|
*/
|
||||||
|
public class KafkaContent {
|
||||||
|
|
||||||
|
public static final String TOPIC = "top";
|
||||||
|
|
||||||
|
public static final String KAFKA_CON = "117.72.43.22:9092";
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.god.kafka.partitioner;
|
||||||
|
|
||||||
|
import org.apache.kafka.clients.producer.Partitioner;
|
||||||
|
import org.apache.kafka.common.Cluster;
|
||||||
|
import org.apache.kafka.common.PartitionInfo;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author:fst
|
||||||
|
* @date:2023/11/25
|
||||||
|
* @aim:自定义分区器
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class MyPartitioner implements Partitioner {
|
||||||
|
/**
|
||||||
|
* 自定义kafka分区主要解决用户分区数据倾斜问题 提高并发效率(假设 3 分区)
|
||||||
|
* @param topic 消息队列名
|
||||||
|
* @param key 用户传入key
|
||||||
|
* @param keyBytes key字节数组
|
||||||
|
* @param value 用户传入value
|
||||||
|
* @param valueBytes value字节数组
|
||||||
|
* @param cluster 当前kafka节点数
|
||||||
|
* @return 如果3个分区,返回 0 1 2
|
||||||
|
*/
|
||||||
|
public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {
|
||||||
|
//获取topic的partitions信息
|
||||||
|
List<PartitionInfo> partitionInfos = cluster.partitionsForTopic(topic);
|
||||||
|
int partitionsNum = partitionInfos.size();
|
||||||
|
// 这里以 key 的哈希值作为分区选择依据
|
||||||
|
System.out.println("================================");
|
||||||
|
System.out.println(Math.abs(key.hashCode()) % partitionsNum);
|
||||||
|
return Math.abs(key.hashCode()) % partitionsNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void configure(Map<String, ?> map) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
package com.god.kafka.producer;
|
||||||
|
|
||||||
|
import org.apache.kafka.clients.producer.KafkaProducer;
|
||||||
|
import org.apache.kafka.clients.producer.Producer;
|
||||||
|
import org.apache.kafka.clients.producer.ProducerRecord;
|
||||||
|
import org.apache.kafka.clients.producer.RecordMetadata;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
|
import static com.god.kafka.contents.KafkaContent.KAFKA_CON;
|
||||||
|
import static com.god.kafka.contents.KafkaContent.TOPIC;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author DongZl
|
||||||
|
* @description: 生产者测试
|
||||||
|
* @Date 2023/8/25 18:50
|
||||||
|
*/
|
||||||
|
public class ProducerTest {
|
||||||
|
private static Producer<String, String> producer;
|
||||||
|
|
||||||
|
public static void KfkProducer() {
|
||||||
|
Properties props = new Properties();
|
||||||
|
props.put("bootstrap.servers", KAFKA_CON);
|
||||||
|
// props.put("linger.ms", 1);
|
||||||
|
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
|
||||||
|
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
|
||||||
|
producer = new KafkaProducer<>(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void close() {
|
||||||
|
producer.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RecordMetadata send(String topic, String key, String value) {
|
||||||
|
Future<RecordMetadata> result = producer.send(new ProducerRecord<>(topic, key, value));
|
||||||
|
RecordMetadata meta = null;
|
||||||
|
try {
|
||||||
|
meta = result.get();
|
||||||
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main (String[] args) {
|
||||||
|
KfkProducer();
|
||||||
|
|
||||||
|
new Thread(() -> {
|
||||||
|
int i = 0;
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
String format = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
send(TOPIC, UUID.randomUUID().toString(), format);
|
||||||
|
}while (i++ < 1000);
|
||||||
|
close();
|
||||||
|
}).start();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.god.kafka.service;
|
||||||
|
|
||||||
|
import org.apache.kafka.clients.producer.Producer;
|
||||||
|
import org.apache.kafka.clients.producer.ProducerRecord;
|
||||||
|
import org.apache.kafka.clients.producer.RecordMetadata;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 卡芙卡生产者服务
|
||||||
|
* @Author fst
|
||||||
|
* @date 2023/11/26 15:06
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class KafkaProducerService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private Producer<String, String> producer;
|
||||||
|
|
||||||
|
public RecordMetadata send(String topic, String key, String value) {
|
||||||
|
Future<RecordMetadata> result = producer.send(new ProducerRecord<>(topic, key, value));
|
||||||
|
RecordMetadata meta = null;
|
||||||
|
try {
|
||||||
|
meta = result.get();
|
||||||
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return meta;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.god.mqtt.config;
|
||||||
|
|
||||||
|
import com.god.mqtt.service.MqttService;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttClient;
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
|
||||||
|
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author DongZl
|
||||||
|
* @description: Mqtt配置
|
||||||
|
* @Date 2023-11-24 下午 02:06
|
||||||
|
*/
|
||||||
|
@Log4j2
|
||||||
|
@Configuration
|
||||||
|
public class MqttConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public MqttClient initClient(MqttProper mqttProper, MqttService mqttService){
|
||||||
|
try {
|
||||||
|
log.info("mqtt服务器初始化开始");
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
MqttClient client = new MqttClient(mqttProper.getBroker(),
|
||||||
|
UUID.randomUUID().toString(),
|
||||||
|
new MemoryPersistence());
|
||||||
|
MemoryPersistence memoryPersistence = new MemoryPersistence();
|
||||||
|
// 连接参数
|
||||||
|
MqttConnectOptions options = new MqttConnectOptions();
|
||||||
|
options.setConnectionTimeout(60);
|
||||||
|
options.setKeepAliveInterval(60);
|
||||||
|
log.info("mqtt服务器初始化结束, 耗时:[{}MS]", System.currentTimeMillis() - startTime);
|
||||||
|
client.connect(options);
|
||||||
|
client.setCallback(mqttService);
|
||||||
|
client.subscribe(mqttProper.getTopic(), 0);
|
||||||
|
return client;
|
||||||
|
}catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.god.mqtt.config;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author DongZl
|
||||||
|
* @description: mqtt配置
|
||||||
|
* @Date 2023-11-24 下午 02:04
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@Configuration
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@ConfigurationProperties(prefix = "mqtt.config")
|
||||||
|
public class MqttProper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点
|
||||||
|
*/
|
||||||
|
private String broker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主题
|
||||||
|
*/
|
||||||
|
private String topic;
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package com.god.mqtt.service;
|
||||||
|
|
||||||
|
|
||||||
|
import com.god.kafka.contents.KafkaContent;
|
||||||
|
import com.god.kafka.service.KafkaProducerService;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.apache.kafka.clients.producer.Producer;
|
||||||
|
import org.apache.kafka.clients.producer.ProducerRecord;
|
||||||
|
import org.apache.kafka.clients.producer.RecordMetadata;
|
||||||
|
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttCallback;
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author DongZl
|
||||||
|
* @description: Mqtt消费者
|
||||||
|
* @Date 2023-11-24 下午 02:10
|
||||||
|
*/
|
||||||
|
@Log4j2
|
||||||
|
@Service
|
||||||
|
public class MqttService implements MqttCallback {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private KafkaProducerService kafkaProducerService;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called when the connection to the server is lost.
|
||||||
|
*
|
||||||
|
* @param cause the reason behind the loss of connection.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void connectionLost (Throwable cause) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mqtt监听消息发送给kafka
|
||||||
|
* @param topic
|
||||||
|
* @param message
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void messageArrived(String topic, MqttMessage message) throws Exception {
|
||||||
|
String msg = new String(message.getPayload());
|
||||||
|
log.info("topic: [{}], Qos: [{}], message content: [{}]", topic, message.getQos(), msg);
|
||||||
|
kafkaProducerService.send(KafkaContent.TOPIC, String.valueOf(msg.hashCode()), msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
mqtt:
|
||||||
|
config:
|
||||||
|
broker: tcp://47.115.225.229:1883
|
||||||
|
topic: test
|
||||||
|
|
||||||
|
# Tomcat
|
||||||
|
server:
|
||||||
|
port: 9999
|
||||||
|
|
||||||
|
# Spring
|
||||||
|
spring:
|
||||||
|
application:
|
||||||
|
# 应用名称
|
||||||
|
name: mqtt-kafka
|
||||||
|
profiles:
|
||||||
|
# 环境配置
|
||||||
|
active: dev
|
||||||
|
# kafka
|
||||||
|
kafka:
|
||||||
|
producer:
|
||||||
|
# Kafka生产者服务器
|
||||||
|
bootstrap-servers: 10.100.1.8:9092
|
||||||
|
transaction-id-prefix: kafkaTx-
|
||||||
|
retries: 3
|
||||||
|
|
||||||
|
# acks=0 : 生产者成功写入消息不会等待任何来自服务器的相应
|
||||||
|
# acks=1 : 只要集群的master收到消息,生产者就会收到一个来自服务器的响应。
|
||||||
|
# acks=all : 只有当所有参与者的复制节点全部收到消息时,生产者才会收到一个来自服务器的响应
|
||||||
|
# 开启事务时 必须设置为all
|
||||||
|
acks: all
|
||||||
|
# 当有多个消息需要被发送到同一分区时,生产者会把他们放在同一批次里。
|
||||||
|
batch-size: 16384
|
||||||
|
# 生产者内存缓冲区的大小
|
||||||
|
buffer-memory: 1024000
|
||||||
|
# 键的序列化方式
|
||||||
|
key-serializer: org.apache.kafka.common.serialization.StringSerializer
|
||||||
|
# 值的序列化方式
|
||||||
|
value-serializer: org.apache.kafka.common.serialization.StringSerializer
|
||||||
|
properties:
|
||||||
|
# 两次poll之间的最大间隔,默认值为5分钟。如果超过这个间隔会触发reBalance
|
||||||
|
max:
|
||||||
|
poll:
|
||||||
|
interval:
|
||||||
|
ms: 600000
|
||||||
|
# 当broker多久没有收到consumer的心跳请求后就出发reBalance,默认值是10s
|
||||||
|
session:
|
||||||
|
timeout:
|
||||||
|
ms: 10000
|
||||||
|
listener:
|
||||||
|
# 在侦听器容器中运行的线程数,一般设置为 机器数*分区数
|
||||||
|
concurrency: 4
|
||||||
|
# 自动提交关闭,需要设置手动消息确认
|
||||||
|
ack-mode: manual_immediate
|
||||||
|
# 消费监听接口监听的主题不存在时,默认会报错,所以设置为false忽略报错
|
||||||
|
missing-topics-fatal: false
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue