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代码可以从这里获取

相关推荐
2401_857439691 小时前
Spring Boot新闻推荐系统:用户体验优化
spring boot·后端·ux
进击的女IT2 小时前
SpringBoot上传图片实现本地存储以及实现直接上传阿里云OSS
java·spring boot·后端
一 乐3 小时前
学籍管理平台|在线学籍管理平台系统|基于Springboot+VUE的在线学籍管理平台系统设计与实现(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·学习
CopyLower5 小时前
Kafka 消费者状态及高水位(High Watermark)详解
分布式·kafka
艾伦~耶格尔6 小时前
Spring Boot 三层架构开发模式入门
java·spring boot·后端·架构·三层架构
man20176 小时前
基于spring boot的篮球论坛系统
java·spring boot·后端
wusam7 小时前
螺蛳壳里做道场:老破机搭建的私人数据中心---Centos下Docker学习04(环境准备)
学习·docker·centos
攸攸太上7 小时前
Spring Gateway学习
java·后端·学习·spring·微服务·gateway
罗曼蒂克在消亡7 小时前
graphql--快速了解graphql特点
后端·graphql
潘多编程7 小时前
Spring Boot与GraphQL:现代化API设计
spring boot·后端·graphql