IDEA中Quarkus框架(3.13版本)容器编排、压测与调优、注意事项等

Quarkus框架学习的第一部分,请访问:

IDEA中Quarkus框架(3.13版本)开发、调试、部署、打包等

五、docker-compose容器编排

1、创建编排文件

复制代码
    cd quarkus-helloworld
    vi docker-compose.yml

docker-compose.yml内容如下:

复制代码
# yaml 配置实例
version: '3'
services:
  quarkus-hello-world:
    image: quarkus/code-with-quarkus:latest # docker中已存在的镜像名+版本名
    ports:
      - "8080:8080"    # 主机Port: 容器暴露Port
    environment:
      TZ: Asia/Shanghai  
    deploy:
      replicas: 2
      update_config:
        parallelism: 2
        delay: 1s
      restart_policy:
        condition: on-failure

volumes:
  logvolume01: {}

2 docker-compose启动(单实例):

复制代码
cd quarkus-helloworld
docker-compose up -d

如果启动有问题(端口占用等)则可停止(会杀死容器实例)

复制代码
docker-compose down

3、 docker-compose启动(多实例,弹性伸缩、负载均衡):

docker-compose.yml 文件内容调整为:

复制代码
# yaml 配置实例
version: '3'
services:
  quarkus-hello-world:
    image: registry.cn-hangzhou.aliyuncs.com/lizhou828/code-with-quarkus:1.0.0-SNAPSHOT # docker中已存在的镜像名+版本名
    ports:
      - "8080" #  将容器内部的多个端口映射到宿主机的端口上
    restart: always
    environment:
      TZ: Asia/Shanghai

  nginx:
    image: nginx:latest
    volumes:
      - type: bind
        source: /run/desktop/mnt/host/d/xxxx/quarkus-helloworld/nginx.conf  # /run/desktop/mnt/host/ 前缀来表示 WSL 中访问 Windows 主机文件系统的路径映射  /d/xxxx/quarkus-helloworld/nginx.conf 是windows文件路径在linux系统的表示方式
        target: /etc/nginx/nginx.conf  # 容器中的路径
    depends_on:
      - quarkus-hello-world
    ports:
      - "81:81"

volumes:
  logvolume01: {}

新增 nginx.conf文件

复制代码
cd quarkus-helloworld
vi nginx.conf

nginx.conf 文件内容如下:

asciidoc 复制代码
user  nginx;
events {
    worker_connections   1000;
}
http {
        server {
              listen 81;
              location / {
                proxy_pass http://quarkus-hello-world:8080;
              }
        }
}

执行启动命令(2个实例):

复制代码
docker-compose up  -d --scale quarkus-hello-world=2


六、压测与调优

1、启动参数未加 任何 参数,且docker-compose.yaml未限制CPU与内存资源 情况下:

复制代码
在不停的访问 http://localhost:9000/hello/testData 接口时,内存占用情况从启动时的21M一直升到50M(单实例):

2、启动增加参数 -Xmx32m 参数,且 docker-compose.yaml限制了CPU与内存资源 情况下(两个实例,1个并发,测试接口访问10000次):

复制代码
使用工具压测 http://localhost:81/hello/testData 接口时,测试访问10000+次,内存占用情况非常平稳:

3、启动增加参数 -Xmx32m 参数,且 docker-compose.yaml限制了CPU与内存资源 情况下(10个实例、1000个并发):

复制代码
使用工具压测 http://localhost:81/hello/testData 接口时,启动10个实例、1000个并发,内存占用情况也非常平稳(在预热期间,CPU在短时间内有个峰值):

第一轮测试情况:


复制代码
第二轮测试情况:



七、参考文档

7.1、官方文档

quarkus最新指南

quarkus-quickstarts

Quarkus实战:专为Kubernetes而优化的Java解决方案.pdf

quarkus-quickstarts

7.2、开发、部署、调试

日志文件的日志是正常,但控制台打印日志中文乱码的问题

IDEA中Quarkus框架(3.13版本)开发、调试、部署、打包等

quarkus实战之四:远程热部署

7.3、Web层

Quarkus的JAX-RS采用Resteasy的实现,可以实现各类Web操作:上传、下载、导入、导出等
Resteasy官方文档

Related guide section...

quarkus数据库篇之三:单应用同时操作多个数据库(有链接要改)

quarkus+saas 多租户动态数据源切换实现简单完美

7.4、持久层ORM

hibernate-orm-panache 单表操作 的 官方文档

JPA SQL 查询、结果集映射(@NamedNativeQuery、@ColumnResult注解说明)

JPA EntityManager采用原生SQL语句执行后,返回LIst自定义对象的方法

hibernate使用createNativeQuery做原始的字段映射处理

EntityManager使用原生查询createNativeQuery并把值映射到自定义实体

JPA Repository: 自定义SQL的2种方法

JPA原生SQL(单表自定义SQL)分页查询逻辑

完美的 jpa 多表 原生sql 分页查询
JPA使用原生SQL实现分页查询、排序

DB操作 Hibernate Panache

Quarkus使用了Panache来简化数据库操作

在quarkus上使用panache执行自定义JPQL查询

Quarkus - Using MyBatis

hibernate-orm#multitenancy

quarkus+saas 多租户动态数据源切换实现简单完美

quarkus-mybatis

quarkus-mybatis-plus

7.5、原生应用

quarkus官方关于原生应用的提示

原生包中使用反射,GraalVM 提供了一些解决方案

GraalVM如何支持原生包中的反射、JNI、proxy?

Graalvm构建原生镜像时,如何嵌入配置文件(静态文件、反射、动态代理、序列化等)

quarkus云原生构建的配置,官方文档

编写quarkus原生应用程序的提示

在云原生镜像中如何自动识别反射、动态代理、序列化等、静态资源、JNI、URL协议等所用到的类和方法的说明

quarkus原生应用,一直刷接口,内存一直在升高?

quarkus原生应用,一直刷接口,内存从21M上升到50M,内存没有回收?

复制代码
解决方式一:启动命令增加参数:   -Xmx64m

解决方式二:
构建原生镜像时,添加参数: -Dquarkus.native.native-image-xmx=64M

https://docs.redhat.com/en/documentation/red_hat_build_of_quarkus/2.13/html-single/compiling_your_quarkus_applications_to_native_executables/index#proc_native-memory-configuration_quarkus-building-native-executable

7.6、容器化

docker compose 命令自定义参数 docker-compose使用

谁说docker-compose不能水平扩展容器、服务多实例?

Docker-desktop启用k8s挂载hostpath类型的pv时挂载不到windows磁盘的问题

7.7、单元测试

Test a Quarkus application with Junit5, Mockito and H2 Database

quarkus-testing-restassured

REST Assured 实践:断言实现

h2database

7.8、RBAC 基于角色的权限访问控制

Quarkus中基于角色的权限访问控制教程

7.9、quarkus 微服务( rest-api)

quarkus-microservice

Quarkus集成Dubbo Rpc远程通讯框架(8)

Quarkus集成Dubbo框架扩展开源了(23)

quarkus-dubbo-rpc

Dubbo 一款云原生微服务开发框架 官网

How quarkus/helidon/micronaut support Apache Dubbo Component ?

7.10、quarkus的扩展(二方包、三方包)

quarkus编写您自己的扩展

quarkus-building-my-first-extension

quarkus编写扩展的常见问题

quarkus官方依赖的源码库 Quarkiverse Hub

quarkus框架的所有配置项

7.11、国内博主专栏

程序员欣宸的博客 CSDN专栏 java 云原生

程序员欣宸的博客 知乎专栏 quarkus

kl博主 在腾讯云开发者社区的专栏 quarkus

CSDN博客专家程序员欣宸的github,这里有六百多篇原创文章的详细分类和汇总,以及对应的源码,内容涉及Java、Docker、Kubernetes、DevOPS等方面

软件开发记录---是我冒饭了

quarkus框架开发的个人博客项目

八、编码注意事项

复制代码
明确调用自己类的实例方法(this),还是调用父类的方法( super) 
子类通过super调用了父类的方法, 父类里面的该方法内部不能再有调用链,否则报错
quarkus框架中,尽量避免使用 this 调用其他方法,而是通过 静态方法 或 工具类 来实现逻辑。也尽可能少使用:动态代理、反射等特性
hibernate-orm 执行原生SQL时,映射结果集的类MnItemVo 会被反射调用构造器,如果需要打原生包运行本应用的话,MnItemVo类必须要大打上@RegisterForReflection 注解
hibernate-orm 执行原生SQL时,要映射的结果集的类,每个字段的类型必须准确,否则报错 : argument type mismatch ,或者使用project() 投影 VO类

九 、spring框架的对比

1. 代理类生成机制的不同

复制代码
   Spring 的代理机制
       默认使用 JDK 动态代理或 CGLIB:Spring 使用 JDK 动态代理(接口代理)或 CGLIB(基于子类的字节码生成)。
       AOP 和代理行为透明:Spring 会尽可能保留类的原始逻辑,super 调用通常不会被代理拦截,因为 Spring 的代理层对父类方法并没有特殊处理。

   Quarkus 的代理机制
       基于字节码增强:Quarkus 不使用传统的动态代理(如 JDK 或 CGLIB)。取而代之,Quarkus 在构建时通过字节码增强(Bytecode Enhancement)生成代理类。
       代理类替换原始类:Quarkus 的代理机制更偏向运行时性能优化,使用的是增强后的类作为代理。增强后的类可能不会直接调用原始父类的逻辑,而是将方法调用委托给特定的拦截器。
       
   导致问题 :
   在 Quarkus 中,super 的调用通常会绕过代理类的增强逻辑。如果代理类对父类方法有特殊的增强逻辑(例如注解解析、事务管理等),直接调用 super 会导致增强逻辑无法生效。这与 Spring 的行为不同,因为 Spring 的代理机制通常不会破坏方法调用链。

2. CDI 和 AOP 实现的差异

复制代码
   Spring 的 AOP
   Spring 的 AOP 基于 AspectJ 或代理机制,支持拦截方法调用,包括子类方法调用。
   如果子类调用父类的 super 方法,Spring 不会主动拦截,因为代理通常只针对接口或类的公开方法。

   Quarkus 的 CDI
   Quarkus 使用的是 Jakarta CDI(Context and Dependency Injection)的实现,它更加严格地依赖注解元数据和代理类增强。
   父类方法在 Quarkus 的代理中可能不会自动包含注解元数据(如 @Path、@Transactional 等)。因此,当子类调用 super 方法时,代理无法处理注解解析,导致 NullPointerException
   Quarkus 的 CDI 机制支持懒加载,这意味着某些方法调用可能会被代理类拦截,从而导致方法调用链被破坏。
   Quarkus 在构建时会对字节码进行增强,以优化性能和减少内存占用。这种增强可能会影响类的继承结构,导致父类方法调用出现问题。

3. 生命周期和上下文的处理差异

复制代码
   Spring 的 Bean 生命周期
   Spring 的 Bean 生命周期在运行时动态管理,Spring 的代理类是在运行时加载和初始化时生成的。
   因为代理的目标是增强现有的 Bean,父类方法调用通常不会受到代理逻辑的影响。

   Quarkus 的 Bean 生命周期
   Quarkus 的 Bean 生命周期通过构建时分析生成字节码进行优化,代理类和增强逻辑在编译时就已经被固定。
   如果子类调用父类的 super 方法时,增强逻辑或注解处理需要运行时动态解析,Quarkus 可能无法支持这种行为,因为代理类与父类的注解处理是分离的。

十、常见的第三方依赖的扩展包

复制代码
已有的扩展:
    redis、kafka、mongoDB、ES、microsoft-server-sql、quarkus-scheduler、itext、zookeeper、flyway、hibernate、JDBC

没有的扩展:
    nacos、aliyun-sdk-oss、xxl-job
相关推荐
程序员阿鹏2 分钟前
实现SpringBoot底层机制【Tomcat启动分析+Spring容器初始化+Tomcat 如何关联 Spring容器】
java·spring boot·后端·spring·docker·tomcat·intellij-idea
掘金-我是哪吒32 分钟前
分布式微服务系统架构第118集:Future池管理容器-CompletableFuture
分布式·微服务·云原生·架构·系统架构
学Java的小半2 小时前
用键盘实现控制小球上下移动——java的事件控制
java·开发语言·算法·intellij-idea·gui·事件监听
爱的叹息2 小时前
本地(NAS/服务器)与云端(Docker/Kubernetes)部署详解与对比
服务器·docker·kubernetes
itachi-uchiha3 小时前
Docker配置带证书的远程访问监听
docker·容器·tls
八股文领域大手子4 小时前
IDEA热加载
java·ide·intellij-idea
云闲不收5 小时前
CAP原理,zookeeper是强一致性么?为什么zookeeper不满足线性一致性依然可以实现分布式锁?
分布式·zookeeper·云原生
bst@微胖子5 小时前
K8S探针的应用
云原生·容器·kubernetes