TechBits | Docker 部署(Bitnami镜像) Kafak-Kraft 模式配合Sasl加密认证

前言

最近在玩弄Kafa,没想到自己才是被玩弄那个一个。本来,我只想搞一个简简单单的Kafka-Kraft(为什么使用Kraft,理由就是部署简单方便,配置文件简洁干净明了)外加Sasl加密配置。网上动不动就是推荐Zookeeper模式进行Sasl认证(🙏,这也太麻烦了吧,即使使用docker来帮忙简化的操作也多简单...吐槽一下)。话说回来,Kafka2.8.0 版之后就可以使用Kraft模式,极大简化了部署的难度。Bitnami家的 Kafa 官方文档还不推荐使用Kafka-Kraft+Sasl,文档写稍微有点模糊,不过认真看还是能文档够依靠文档部署成功。但是,你要是不熟悉Docker-composeKafa的配置那么将会让你痛不欲生。至少,我体会到了。嗯,我承认我是菜逼,😭。

我在网上查阅了大部分文字,很少能够十分简单的部署,并且拿来即用的。大部分部署有点繁琐例如:

  • 我只是想配置一个Sasl有一些文章会直接使用官方文档配置和文件。但是,它有添加其他的配置,其实我并不需要。(当然,因人而异可能那些文章对其他可能就有帮助了。但是,我想要部署一个极简的,那么这些文章就会混淆我的视线)
  • zookeeper你罪大恶极😭(开玩笑的。我并不讨厌什么技术,只不过我想本地玩玩,那就想简单部署一下)。这几天网上上推荐部署的文章绝对多数都是zookeeper,看得我头大,我就不想使用zookeeper。(当然,Kafak + zookeeper 的组合在生成部署比较合适,一来文章多,遇到问题好解决,二来,稳定)

我想要的是极简的部署,不要什么额外操作,添加一些什么配置文件。这让我觉得部署十分的繁琐。有更简单的方式,我会更倾向简单的办法来解决。🆗,长话短说。我这篇文章也许并不能帮助你们部署一个稳定的kafka,但是一定能让大家快速体验一下 Kafka ,现在最新版 3.5.3 之后推出了脱离zookeeper模式的Kraft模式。接下来就看看什么叫做方便,真的拿来即用。妈妈再也不用为了kafka繁琐的环境而烦恼辣🙂

部署

Kraft模式

我是在Linux虚拟机中进行操作的我们使用docker-compose来帮助我们完成docker容器的下载和Kafka环境的配置

  • docker-compose命令
bash 复制代码
curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
​
chmod +x /usr/local/bin/docker-compose
​
docker-compose --version

上面命令可能会出现下载失败的问题可能是openssl导致的,那么可以更新一下openssl。并不推荐直接更新yum(sudo yum update)

复制代码
sudo yum install openssl

接着,我们需要创建一个docker-compose.yml文件(这是一个十分简单的kafka Kraft模式的配置文件):

ini 复制代码
version: "2"
​
services:
  kafka:
    image: 'bitnami/kafka:latest'
    hostname: kafka_one
    ports:
      - "9092:9092"
    volumes:
      - "kafka_data:/bitnami"
    networks:
      - kafka_net
    environment:
      # KRaft settings
      - KAFKA_CFG_NODE_ID=0
      - KAFKA_CFG_PROCESS_ROLES=controller,broker
      - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@kafka:9093
      # Listeners
      - KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093
      - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://192.168.249.128:9092
      - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
      - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
      - KAFKA_CFG_INTER_BROKER_LISTENER_NAME=PLAINTEXT
​
volumes:
  kafka_data:
    driver: local
​
networks:
  kafka_net:
    driver: bridge

注意: 这里有一些知识我们要需要了解一下。

ini 复制代码
    # KRaft settings
    - KAFKA_CFG_NODE_ID=0
    - KAFKA_CFG_PROCESS_ROLES=controller,broker
    - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@kafka:9093

这些是KRaft的相关配置。使用上面配置我们就可以和zookeeper说byebye。(zookeeper我们不熟好吧!)

ini 复制代码
   - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://192.168.249.128:9092

这个我们192.168.249.128ip需要更好为你自己的虚拟机的ip,后续我们通过这个进行连接kakfa

yaml 复制代码
hostname: kafka_one
networks:
kafka_net:
  driver: bridge

Docker Compose 会根据你的配置自动创建这个网络,无需在外部手动创建它。

那么,关键点说了,在大致说说其他内容吧:

go 复制代码
1. `version: "2"`:这是 Docker Compose 配置文件的版本,指定了使用的 Docker Compose 版本。
2. `services:`:这是一个服务定义的部分,下面将列出要启动的服务。
3. `kafka:`:这是定义 Kafka 服务的名称。你将在下面的部分中配置有关 Kafka 服务的详细信息。
4. `image: 'bitnami/kafka:latest'`:指定要使用的 Kafka 镜像。这里使用 Bitnami 提供的 Kafka 镜像,并将其标签设置为 "latest",表示使用最新版本。
5. `hostname: kafka_one`:为 Kafka 容器设置主机名为 "kafka_one"。
6. `ports:`:定义要映射的端口。
  - `"9092:9092"`:将主机的端口 9092 映射到 Kafka 容器的端口 9092。这允许从主机上访问 Kafka 服务。
7. `volumes:`:定义数据卷,用于持久化存储 Kafka 数据。
  - `"kafka_data:/bitnami"`:创建一个名为 "kafka_data" 的数据卷,将其挂载到 Kafka 容器的 "/bitnami" 目录。这有助于保留 Kafka 数据,以便在容器重启后数据不会丢失。
8. `networks:`:定义网络配置。
  - `"kafka_net"`:创建一个名为 "kafka_net" 的自定义网络,用于连接 Kafka 容器和其他容器。
9. `environment:`:定义环境变量,配置 Kafka 服务的各种参数。
  - `KAFKA_CFG_NODE_ID=0`:设置 Kafka 节点的ID为 0,用于标识 Kafka 集群中的不同节点。
  - `KAFKA_CFG_PROCESS_ROLES=controller,broker`:定义 Kafka 节点的角色,这里将其配置为同时充当控制器和经纪人。
  - `KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@kafka:9093`:配置控制器选举所需的投票者。在这里,配置为只有一个投票者,其节点ID为 0,并监听端口 9093。
  - `KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093`:配置 Kafka 的监听器,包括 "PLAINTEXT" 和 "CONTROLLER"。这些监听器用于与客户端和控制器通信。
  - `KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://192.168.249.128:9092`:配置广告监听器,指定客户端应使用的地址和端口。
  - `KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT`:定义监听器的安全协议映射,这里指定 "PLAINTEXT" 安全协议。
  - `KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER`:定义控制器的监听器名称。
  - `KAFKA_CFG_INTER_BROKER_LISTENER_NAME=PLAINTEXT`:定义经纪人之间的通信监听器。

接下来,我们有了这个文件,剩下的敲几行命令外加网络的配合即可。

运行docker-compose 命令

复制代码
docker-compose -f docker-compose.yml up -d

注意: 一定要添加启动的配置文件。不然,你可以尝试一下会发送什么。🤭

解释一下命令: 根据docker-compose.yml 文件拉去镜像+后台启动docker容器

查看容器命令

arduino 复制代码
docker ps //查看docker 镜像

查看日志

bash 复制代码
docker logs -f 容器id

添加-f,可以帮助我们持续的打印日志

🆗,到这里为止,如果能够正常启动。那么我们kafka-Kraft模式就算部署好了。很简单,这个没有难度。其实,去bitnima 上面看一下就会懂了。这个倒不是让人头疼的。接下俩这个添加Sasl才是头疼的。

Kraft模式+Sasl认证

如果,你想要添加Sasl在官方稳定中它并不是很推荐,希望能够配合SSL之类的操作。不过,这个就不再本文之内,如果真的需要到生产的话,还有运维大大帮助我们部署。这些就不用太担心了。话说回来,为什么会痛苦的原因就是官网文档没有很明确的直接说明。却要你自己去梳理命令等等的操作。

那么,开始吧,其实也很简单。但是难的地方就在于这些命令要添加什么?

在上面的docker-compose.yml的配置基础上,我添加Sasl认证。

ini 复制代码
version: "3"

services:
  kafka:
    image: 'bitnami/kafka:latest'
    hostname: kafka_one
    ports:
      - "9092:9092"
    volumes:
      - kafka_data:/bitnami
    networks:
      - kafka_net
    environment:
      - KAFKA_CFG_NODE_ID=0
      - KAFKA_CFG_PROCESS_ROLES=controller,broker
      - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@kafka:9093
      - KAFKA_CFG_LISTENERS=SASL_PLAINTEXT://:9092,CONTROLLER://:9093
      - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,SASL_PLAINTEXT:SASL_PLAINTEXT
      - KAFKA_CFG_ADVERTISED_LISTENERS=SASL_PLAINTEXT://192.168.249.128:9092
      
      - KAFKA_CLIENT_USERS=admin
      - KAFKA_CLIENT_PASSWORDS=123456
      
      - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
      - KAFKA_CFG_SASL_MECHANISM_CONTROLLER_PROTOCOL=PLAIN
      - KAFKA_CONTROLLER_USER=admin
      - KAFKA_CONTROLLER_PASSWORD=123456
      
      - KAFKA_CFG_INTER_BROKER_LISTENER_NAME=SASL_PLAINTEXT
      - KAFKA_CFG_SASL_MECHANISM_INTER_BROKER_PROTOCOL=PLAIN
      - KAFKA_INTER_BROKER_USER=admin
      - KAFKA_INTER_BROKER_PASSWORD=123456

volumes:
  kafka_data:
    driver: local

networks:
  kafka_net:
    driver: bridge

注意:

在这里,我们修改和添加了一些内容

ini 复制代码
     - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,SASL_PLAINTEXT:SASL_PLAINTEXT

     - KAFKA_CLIENT_USERS=admin
     - KAFKA_CLIENT_PASSWORDS=123456

     - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
     - KAFKA_CFG_SASL_MECHANISM_CONTROLLER_PROTOCOL=PLAIN
     - KAFKA_CONTROLLER_USER=admin
     - KAFKA_CONTROLLER_PASSWORD=123456

     - KAFKA_CFG_INTER_BROKER_LISTENER_NAME=SASL_PLAINTEXT
     - KAFKA_CFG_SASL_MECHANISM_INTER_BROKER_PROTOCOL=PLAIN
     - KAFKA_INTER_BROKER_USER=admin
     - KAFKA_INTER_BROKER_PASSWORD=123456
  1. KAFKA_CFG_LISTENERSKAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP 的值变为了 SASL_PLAINTEXT,表示使用 SASL_PLAINTEXT 安全协议。在先前的配置中,它们的值是 PLAINTEXT,表示使用普通文本协议。这意味着你正在配置 Kafka 以使用 SASL(Simple Authentication and Security Layer)进行身份验证。
  2. KAFKA_CLIENT_USERSKAFKA_CLIENT_PASSWORDS 被设置为 admin123456,这是用于 SASL_PLAINTEXT 安全协议的客户端用户的用户名和密码。
  3. KAFKA_CFG_CONTROLLER_LISTENER_NAMES 设置为 CONTROLLER,定义了控制器的监听器名称。
  4. KAFKA_CFG_SASL_MECHANISM_CONTROLLER_PROTOCOL 设置为 PLAIN,这是控制器的 SASL 机制协议。
  5. KAFKA_CONTROLLER_USERKAFKA_CONTROLLER_PASSWORD 分别设置为 admin123456,用于控制器身份验证的用户名和密码。
  6. KAFKA_CFG_INTER_BROKER_LISTENER_NAME 设置为 SASL_PLAINTEXT,定义了经纪人之间的通信监听器,使用了 SASL_PLAINTEXT 安全协议。
  7. KAFKA_CFG_SASL_MECHANISM_INTER_BROKER_PROTOCOL 设置为 PLAIN,这是经纪人之间的 SASL 机制协议。
  8. KAFKA_INTER_BROKER_USERKAFKA_INTER_BROKER_PASSWORD 分别设置为 admin123456,用于经纪人之间的身份验证的用户名和密码。

我们需要添加一下内容,如果我们去看其他文章可能就会一头雾水。就跟着那些文字,我反复实验好几次了,心累。

总结一下:其实就是添加了CONTROLLER_PROTOCO controller的策略 + BROKER_PROTOCOL broker的策略 + CLIENT_USERS client 的用户和密码。到时候我们需要使用它们来连接

做到这里还是按照之前dokcer的启动方式启动即可。这篇文章,你可以直接拿来就用,需要改动的地方可能说是没有,大致就一个ip地址需要更换。其他的就复制粘贴运行命令即可。那么,我们来整合SpringBoot来进行相关的配置。

整合Springboot

springboot官网中,kafka 支持版本是这样滴。我这边使用spring boot 2.7.0,kafka使用最新的即可

Spring for Apache Kafka Version Spring Integration for Apache Kafka Version kafka-clients Spring Boot
3.1.x (pre-release) 6.2.x (pre-release) 3.6.0 3.2.x (pre-release)
3.0.x 6.0.x/6.1.x 3.3.2 to 3.6.0 3.0.x/3.1.x
2.9.x 5.5.x 3.2.3 to 3.6.0 2.7.x (not managed)

kraft模式的springboot整合

producer

yaml 复制代码
server:
  port: 8090

spring:
  datasource:
    driverClassName: com.mysql.cj.jdbc.Driver
    password: QWEasd123456!
    url: jdbc:mysql://127.0.0.1/code_test_platform?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&autoReconnect=true
    username: root
    hikari:
      connection-timeout: 600
      max-lifetime: 550


  kafka:
    producer:
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
#      value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
      value-serializer: org.apache.kafka.common.serialization.StringSerializer

    bootstrap-servers: 192.168.249.128:9092


  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher

mybatis:
  mapper-locations: classpath*:mapper/**/*Mapper.xml
  type-aliases-package: com.qiaose.entity.*

没有添加Sasl认真的话,springboot就很简单了。需要注意的是:

makefile 复制代码
bootstrap-servers: 192.168.249.128:9092

这个配置一定是在producer同级的,不然配置错误,就会出现连接失败。有一些旧的文章会将配置bootstrap-servers: 192.168.249.128:9092 放到producer同级的位置,导致出现如下错误:

ini 复制代码
2023-10-28 22:18:52.331  WARN 16320 --- [| adminclient-1] org.apache.kafka.clients.NetworkClient   : [AdminClient clientId=adminclient-1] Connection to node -1 (localhost/127.0.0.1:9092) could not be established. Broker may not be available.
2023-10-28 22:18:53.022  INFO 16320 --- [| adminclient-1] o.a.k.c.a.i.AdminMetadataManager         : [AdminClient clientId=adminclient-1] Metadata update failed

如果出现这个错误,绝大多数就是springboot配置文件出现了问题,想之前还那么相信那些文件的配置。干!😭,浪费老子的时间和生命。

consumer

yaml 复制代码
server:
  port: 8091

spring:
  datasource:
    driverClassName: com.mysql.cj.jdbc.Driver
    password: QWEasd123456!
    url: jdbc:mysql://127.0.0.1/kafak-template?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&autoReconnect=true
    username: root
    hikari:
      connection-timeout: 600
      max-lifetime: 550

  jpa:
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL8Dialect
        show_sql: true
        use_sql_comments: true
        format_sql: true
    hibernate:
      ddl-auto: update


  kafka:
    consumer:
      group-id: myGroup
      auto-offset-reset: earliest
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
#      value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
      properties:
        spring:
          json:
            trusted:
              packages: com.qiaose.entity.*
          value-deserializer: org.apache.kafka.common.serialization.StringDeserializer


    bootstrap-servers: 192.168.249.128:9092

  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher

mybatis:
  mapper-locations: classpath*:mapper/**/*Mapper.xml
  type-aliases-package: com.qiaose.entity.*

这里就没有什么好说的了,说一下这个

yaml 复制代码
properties:
   spring:
     json:
       trusted:
         packages: com.qiaose.entity.*

配置中,spring.json.trusted.packages 配置了 com.qiaose.entity.*,这表示任何来自 com.qiaose.entity 包以及其子包中的类都可以被用于 JSON 反序列化,而不会引发安全异常。

到这里,简单的Kafka-Kraft就配置完成了,启动springboot接口。更详细的代码可以从这里获取

springboot整合kraft-Sasl模式

这个会稍微会麻烦点,并且有一些文件配置需要注意:

producer

yaml 复制代码
server:
  port: 8180

spring:
  datasource:
    driverClassName: com.mysql.cj.jdbc.Driver
    password: QWEasd123456!
    url: jdbc:mysql://127.0.0.1/code_test_platform?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&autoReconnect=true
    username: root
    hikari:
      connection-timeout: 600
      max-lifetime: 550


  kafka:
    producer:
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
    topic:
      name: order_topics
    properties:
      security:
        protocol: SASL_PLAINTEXT
      sasl:
        mechanism: PLAIN
        jaas:
          config: 'org.apache.kafka.common.security.plain.PlainLoginModule required username="admin" password="123456";'
    bootstrap-servers: 192.168.249.128:9092



  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher

mybatis:
  mapper-locations: classpath*:mapper/**/*Mapper.xml
  type-aliases-package: com.qiaose.entity.*

这个配置文件最重要就是

yaml 复制代码
properties:
 security:
   protocol: SASL_PLAINTEXT
 sasl:
   mechanism: PLAIN
   jaas:
     config: 'org.apache.kafka.common.security.plain.PlainLoginModule required username="admin" password="123456";'

旧的版本的配置文件:

yaml 复制代码
spring:
kafka:
producer:
 bootstrap-servers: 0.0.0.0:9092,0.0.0.0:9092,0.0.0.0:9092
 key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
 value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
 properties:
   sasl.mechanism: PLAIN
   security.protocol: SASL_PLAINTEXT
   sasl.jaas.config: org.apache.kafka.common.security.scram.ScramLoginModule required username=${KAFKA-USER} password=${KAFKA-PASSWORD};
consumer:
 bootstrap-servers: 0.0.0.0:9092,0.0.0.0:9092,0.0.0.0:9092
 key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
 value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
 properties:
   sasl.mechanism: PLAIN
   security.protocol: SASL_PLAINTEXT
   sasl.jaas.config: org.apache.kafka.common.security.scram.ScramLoginModule required username=admin password=admin-secret;
 group-id: consumer_id:123
profiles:
active: dev

摘自某一篇文章的配置(害死人辣!!!😭) 。当然,这并不是意味着,这个配置就是错误的,那是说明在我们版本中使用这个配置就会有问题,需要注意一下:

yaml 复制代码
kafka:
producer:
 key-serializer: org.apache.kafka.common.serialization.StringDeserializer
 value-serializer: org.springframework.kafka.support.serializer.JsonDeserializer
 properties:
   security.protocol: SASL_PLAINTEXT
   sasl.mechanism: PLAIN
   sasl.jaas.config: org.apache.kafka.common.security.plain.PlainLoginModule required username="admin" password="123456";
bootstrap-servers: 192.168.249.128:9092

如果,使用了上面的配置就会出现这个问题,请求的策略错误,原因就是配置文件的问题,

less 复制代码
2023-10-28 22:37:09.274  INFO 25324 --- [| adminclient-1] org.apache.kafka.clients.NetworkClient   : [AdminClient clientId=adminclient-1] Node -1 disconnected.
2023-10-28 22:37:09.274  INFO 25324 --- [| adminclient-1] org.apache.kafka.clients.NetworkClient   : [AdminClient clientId=adminclient-1] Cancelled in-flight METADATA request with correlation id 17 due to node -1 being disconnected (elapsed time since creation: 302ms, elapsed time since send: 302ms, request timeout: 26357ms)

在控制台打印的信息来看,它采用的是GSSAPI,而不是PLAIN也就意味着配置文件没有生效。应该这个地方也需要注意一下。

ini 复制代码
	sasl.login.refresh.window.jitter = 0.05
	sasl.login.retry.backoff.max.ms = 10000
	sasl.login.retry.backoff.ms = 100
	sasl.mechanism = GSSAPI
	sasl.oauthbearer.clock.skew.seconds = 30
	sasl.oauthbearer.expected.audience = null
	sasl.oauthbearer.expected.issuer = null
	sasl.oauthbearer.jwks.endpoint.refresh.ms = 3600000

consumer

yaml 复制代码
server:
  port: 8182

spring:
  datasource:
    driverClassName: com.mysql.cj.jdbc.Driver
    password: QWEasd123456!
    url: jdbc:mysql://127.0.0.1/code_test_platform?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&autoReconnect=true
    username: root
    hikari:
      connection-timeout: 600
      max-lifetime: 550


  kafka:
    consumer:
      group-id: email
      auto-offset-reset: earliest
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
    topic:
      name: order_topics
    properties:
      spring:
        json:
          trusted:
            packages: com.qiaose.entity.*
      security:
        protocol: SASL_PLAINTEXT
      sasl:
        mechanism: PLAIN
        jaas:
          config: 'org.apache.kafka.common.security.plain.PlainLoginModule required username="admin" password="123456";'
    bootstrap-servers: 192.168.249.128:9092


mvc:
  pathmatch:
    matching-strategy: ant_path_matcher

mybatis:
  mapper-locations: classpath*:mapper/**/*Mapper.xml
  type-aliases-package: com.qiaose.entity.*

这样就配置完成了,如果,这篇文章对你有所帮助的话。还请不要吝啬点赞哇😭。希望,能帮到大家。😊

详细kafka代码可以从这里获取

相关推荐
阿在在39 分钟前
Spring 系列(三):Spring PostProcessor 顶级扩展接口全解析
java·后端·spring
祈安_1 小时前
深入理解指针(三)
c语言·后端
听风者就是我1 小时前
(LLM系列)文档切分策略详解:Chunk Size 如何决定 RAG 系统的检索天花板
后端
野犬寒鸦1 小时前
ArrayList扩容机制深度解析(附时序图详细讲解)
java·服务器·数据结构·数据库·windows·后端
逆境不可逃2 小时前
【从零入门23种设计模式03】创建型之建造者模式(简易版与导演版)
java·后端·学习·设计模式·职场和发展·建造者模式
汤姆yu2 小时前
基于springboot的健身爱好者打卡与互动交流系统
java·spring boot·后端
学到头秃的suhian3 小时前
Docker基础扫盲
运维·docker·容器
百锦再3 小时前
Java Map常用方法和实现类深度详解
java·开发语言·spring boot·struts·kafka·tomcat·maven
袁袁袁袁满3 小时前
Docker后台日志和容器日志怎么查看?
linux·运维·服务器·docker·容器
计算机毕设VX:Fegn08954 小时前
计算机毕业设计|基于springboot + vue连锁门店管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计