启动速度提升 10 倍:Apache Dubbo 静态化方案深入解析

作者:华钟明

文章摘要:

本文整理自有赞中间件技术专家、Apache Dubbo PMC 华钟明的分享。本篇内容主要分为五个部分:

-GraalVM 直面 Java 应用在云时代的挑战

-Dubbo 享受 AOT 带来的技术红利

-Dubbo Native Image 的实践和示例

-Dubbo 集成 Native Image 的原理和思考

-Dubbo 在 Native Image 技术的未来规划

GraalVM 直面 Java 应用在云时代的挑战

图片

云计算时代比较显著的特点包括:

  • 基于云计算的基础设施,我们的应用能够在云上快速、轻松且高效地做到弹性。尤其是无状态的应用,能够轻易地基于同一个镜像构建实例,当然也能轻易地收缩多余的实例,实现弹性伸缩容。
  • 基于容器化技术,系统资源被切分的更细,资源的利用也变得更优。
  • 基于云计算的开发平台,应用部署更加容易,应用开发更加敏捷。

那么在云计算时代,Java 应用存在哪些问题呢?

  • 冷启动速度较慢。 Java 应用启动需要经历包括 JVM 的初始化、类加载等过程,导致启动速度相较于其他语言来说是处于劣势的。
  • 应用预热时间过长,无法立即达到性能峰值。 比如如果没有对应用做一些预热机制,并且对 RT 又比较敏感的应用,会导致发布时有一定的接口超时情况。
  • 内存、CPU 等系统资源占用高。 当占用过高时,不得不为 Java 应用提供更高规格的实例,而切分大规格的实例,这也会导致切分后造成的碎片更大,从而导致资源的浪费。
  • Java 构建的应用程序繁重, 执行还需要具备 JDK 环境。

图片

在云计算的时代中,Java 应用存在劣势,最明显的就是在 Serverless 场景。因为 Serverless 除了能够简化应用的开发外,最关键的就是能够做到让开发者的应用服务做的秒级弹性扩容。除了容器调度和新的 Pod 创建的时间损耗以外,镜像下载耗时、应用冷启动耗时、以及应用服务预热所需的耗时,都是影响弹性扩容的因素。

上图是 Datadog 统计了 FaaS 产品 AWS lambda 在各语言的使用程度,可以看出来即使 Java 依旧是最流行的编程语言,Java 与 Node.js 和 Python 的差距还是非常明显。Java 语言虽然更流行,但相较于 Python 和 Node.js,它的占比还是比较低的。

图片

而面对 Java 语言的这些问题,GraalVM 也是应运而生。这里引用官网对 GraalVM 的介绍,GraalVM 能够提前将 Java 应用程序编译成独立的二进制文件。与在 Java 虚拟机上运行的应用程序相比,这些二进制文件更小,启动速度快 100 倍,在没有预热的情况下提供峰值性能,并且使用更少的内存和 CPU。是不是发现它解决的正是刚刚所提到的所有问题。包括冷启动速度问题、启动后需要预热、内存占用和 CPU 使用率也相对较高,甚至能够降低二进制文件的大小。二进制文件大小的降低更有利于容器镜像大小的缩减,减少镜像下载所需的时间。

GraalVM 可以理解为是 OpenJDK 的一个“超集”,它不但包含了完整的 JDK 发行版本,还包含 GraalVM Compiler、Native image、Truffle 等组件, 并且支持多语言混编等能力。这就意味着在使用这些新的能力的同时,Java 应用程序也能够按照原有的形式在 Graalvm 环境下正常的运行。

而在这个介绍中我们能够看到一个关键的的技术点,那就是 ahead of time,AOT 技术。传统的 Java 开发中,我们采用的都是 JIT,JIT 即为将我们编写的 Java 源代码编译为 .class 文件,并在运行期间将 JVM 认为是热点的字节码转化为机器码,加快程序运行速度。而 AOT 则是在编译期间就将字节码转化为了机器码,它将不再会有运行期还在持续将热点的字节码转化为机器码的操作。GraalVM 本身就包含了 JIT 和 AOT 这两部分。

图片

看左边的这张图,它就是一个标准的 Java 应用完整的生命周期。首先是 JVM 的启动初始化,然后到 Java main 函数的启动和调用,然后是应用预热的阶段,然后才是到达应用稳定运行的阶段,最后是应用销毁,至此整个 Java 应用的生命周期完结。可以看到在 Java 的整个生命周期中,如果是传统的 JIT 模式,从启动到达到应用平稳的阶段,需要经过 JVM 的初始化,类加载,解释器执行、即时编译、GC,并且即使到达了应用的稳定阶段,JIT、解释器依旧还在运行。

而对于 GraalVM 中的 AOT 技术而言,首先省去了 JVM 的启动,也就是红色区域的时间,第二是省去看解释器和编译器所占用的时间。那么既然 AOT 这么多优点,是否能替代 JIT,从目前来看还是没有办法替代的,右边这张图就说明了虽然现在 AOT 具备非常客观的启动速度提升,非常低的资源消耗,以及包的大小更小等优点,但是在吞吐量的峰值和最大延迟上还是 JIT 更优一些。

Dubbo 享受 AOT 带来的技术红利

1. 多产物形态

图片

当我们编写完程序的源代码后,需要对源码进行编译打包,生成能够启动 Dubbo 应用程序的目标产物,目前还是以第一种 Jar 包的形态居多。

而第二种则是引入 Spring Boot 后支持的产物形态,采用 Spring Boot 的插件,能够快速的生成容器镜像,而无需自己写比如 Docker file,手动把 Jar 打包到镜像中。方便了 Dubbo 应用的容器化部署。

而第三种则是 Dubbo 支持 GraalVM 后所新增的产物形态:Native Executable。

这三种产物的打包命令也有所区别,传统的 Jar 包形态,是最常见的 mvn clean package,第二种则是执行了 SpringBoot 的插件,第三种则是在编译阶段执行了 native 相关的插件。这种新的产物 Native Executable 能够做到无需安装 JDK 环境即可启动应用程序。

2. 启动耗时大幅降低

图片

Dubbo 框架发展有近十年,提供的能力也越来越强大,同时 Dubbo 应用的启动速度一直也是令我们比较头疼的事情,但是随着集成 GraalVM Native Image 后,这个问题也让我们看到了希望。

这上面展示了两张图,第一张图描述的是分别在 Native Executable 和 Jar package 的场景下,仅提供一个 Dubbo 服务的应用启动耗时对比。这里的数据都统计与 4c16g 的 macOS 系统下,并且每个场景都跑了 10 组数据。这里的启动耗时也将 JVM 启动耗时考虑进去,比如 Jar package 场景下的耗时计算的是从 java -jar 启动 Java 应用直到应用启动就绪,所需的耗时。

从对比图可以看出,Native Executable 比 Jar package 的启动耗时降低了 12.4 倍,也就是启动速度提升了 12.4 倍。第二张图则是仅存在一个 Dubbo 服务 Consumer 的应用启动耗时对比,从对比图可以看出,Native Executable 比 Jar package 的启动快了 11 倍。由此看出集成 GraalVM Native Image 后,Dubbo 应用真正的能够实现毫秒级启动。

3. 启动后立即达到性能峰值

图片

从统计图表上看,当 Consumer 和 Provider 都为 Native Executable 时,比他两都是 Jar package 的情况第一次调用的耗时足足减少了 6 倍。使 Dubbo 应用能够在启动后立即达到性能巅峰。启动耗时和启动即达到性能巅峰,这两个技术红利也让 Dubbo 有机会拓展在 Serverless 或者说是 Faas 技术场景的应用范围。

4. 内存损耗大幅降低

图片

在这里同样给出了 Provider 与 Consumer 应用在 Native Executable 与 Jar Package 两个场景下的内存对比统计图,拿第一张图,可以看到,Jar Package 启动后,所需的内存是 200 多兆,而 Native Executable 仅占了 60M 左右,在内存损耗上整整降低了 3.5 倍,在如今降本的大环境下,使得我们能够对 Java 应用降低内存使用,节省系统资源充满了更多的想象空间。

图片

除了以上四个技术红利以外,Dubbo 在集成 GraalVM Native Image 技术的同时,也在不断完善相关的内容。

首先是在易用性上得到了增强, 在 RPC 框架中,服务接口的定义是由业务决定的,而这些服务接口同样需要配置对应的可达性元数据,才能实现 RPC 调用,Dubbo 在注解和 XML 的配置方式中实现了自动生成可达性元数据,无需应用的开发者自行配置 Reachability Metadata 配置。

第二点是可维护性增强, 对于 Dubbo 的开发者和贡献者,也无需再有意识地维护这些 Dubbo 框架所需的Reachability Metadata 和Adaptive source code。举个例子,比如Dubbo 新增了一块新的功能,Dubbo 的贡献者新增了一个 SPI 接口,而他无需考虑在 native image 场景下生成 Adaptive source code。

第三点是对多平台的支持, 包括我们所熟知的 Linux、MacOS、Windows 操作系统。最后一个是 Dubbo 内的多种能力都能在 native image 场景下能够正常使用,比如 Dubbo 协议以及 Dubbo3.x 中的Triple协议。

##vDubbo Native Image 的实践和示例

图片

首先需要安装 Dubbo Native Image,这里就不过多介绍了,大家可以根据官方的文档进行下载。

然后安装插件,可以看到上图中有三个插件需要安装,但和 Dubbo 相关的只有一个,是 Dubbo Maven Plugin。

第一张图就是 Dubbo 新版本提供的用于适配 GraalVM Native Image 的 maven 插件。第二张图则是 SpringBoot 的 maven 插件,用于处理 Spring Boot 的 AOT 处理逻辑。如果采用的是 Dubbo 的 API 接入方式,则无需配置 SpringBoot 的 maven 插件。第三张图则是 GraalVM 官方提供的 maven 插件,它集成了打包编译 Native Executable 的逻辑。

图片

接下来是配置所需的依赖,Dubbo 集成 Native 还需要额外配置两个依赖,也就是 dubbo-native 和 dubbo-config-spring6,其中 dubbo-config-spring6 也与前面的 SpringBoot 插件一样,如果不采用 xml 或者注解的方式接入,则无需配置该依赖。它主要用于适配 Spring6,因为目前 Dubbo 还兼容着低版本的 Spring 和 Springboot,并且还兼容着 JDK8 和 JDK11,而 Springboot3.0 和 spring6 以上的版本将最低的 JDK 版本调整为了 JDK17,所以目前使用该模块来适配和兼容高版本的 Spring。

dubbo-native 中集成了 dubbo 所有的 source code 和 Reachability Metadata 生成的逻辑。以保证 Dubbo 应用能够正常被编译打包成 Native Executable,并用 Native Executable 形态正常运行。

图片

除此上述的配置以外,其他的使用方式都没有任何变化,开发者就可以把一个应用打包成 Native Executable。这里罗列了编译的命令,编译是需要 GraalVM 的环境和 native-image 工具,所以在编译前先检查环境是否正常。编译完后,在工程的根目录下就会出现一个 Native Executable,直接启动它,即可完成应用的启动。完整的示例代码在 dubbo-samples 下,感兴趣的朋友也可以自行去体验。

最下面是完整的代码示例,大家感兴趣的话,可以尝试一下编译打包,看一下执行的效果。

Dubbo 集成 Native Image 的原理和思考

图片

Dubbo 在 21 年 6 月份正式发布 Dubbo3.0,Dubbo 社区的成员初步调研了 GraalVM Native Image 技术,并在 3.0 的其中一个迭代版本中初步支持了 Native Image,但当时仅仅是以实验性 Demo 呈现,并没有过多的考虑生产环境的用户如何使用、Dubbo 的贡献者的维护成本等问题。初版的支持存在以下四个比较严重的问题:

1. Dubbo 核心仓库内需要维护 Adaptive Source code

当时应该是提供了一个生成 Adaptive Source code 的工具,提供给用户自行通过工具为 SPI 接口生成 Adaptive Source code。并且它会被直接生成在应用工程目前下,而并不是生成在 target 目录下,则对开发者应用程序源码有一定的侵入。

2. Dubbo 需要维护全量的 Reachability Metadata

如果 Dubbo 核心的仓库,举个例子,Dubbo 的注册中心支持 Zookeeper 和 Nacos,假如应用仅仅采用了 Zookeeper,没有用到 Nacos,但是因为 Dubbo 维护着全量的 Reachability Metadata,所以在打包时,也会把这些全部打包进入 Native Executable 中,导致可执行文件的大小膨胀,并且编译打包时间也变久了。除此之外,Dubbo 的贡献者如果新增了什么功能,也需要手动在对应的配置中维护 Reachability Metadata,如果忘记了,则会导致这块功能将无法在 native image 下使用,甚至可能导致打包编译的失败。

3. 仅仅支持 API 接入的方式,而不支持 XML 和注解的接入方式

我们知道,Dubbo 的大部分用户采用的还是 XML 和注解的接入方式,这就导致觉大多是的用户都无法使用该项能力。

4. dubbo-native-plugin 的内容过于聚焦

当时新增加了一个 dubbo-native-plugin 的 maven 插件,用于 native 相关的编译打包处理,这个插件的内容过于聚焦,后续将会导致 Dubbo 的用户每接入一个新的 Dubbo 功能,就需要接入一个新的插件,它并不利于后续 Dubbo maven plugin 的迭代和特性增强。并且会给 Dubbo 的用户带来使用和维护 Maven 插件的困扰。

随着这个实验性的 Native Image 技术支持后,在后续的 3.1 版本,也再没有更多的的更新迭代。

随着 2022 年 11 月份,Spring6 和 Spring boot 3.0 的发布,并伴随着 GraalVM Native Image 作为新版本一个非常具有亮点的特性亮相后,Dubbo 社区也意识到,Dubbo 集成 GraalVM Native Image 应该需要跨出一个新的阶段了。

我们会发现,人工去维护这些内容实在非常耗费精力,并且它给 code review 也带来了比较大的压力,需要提前判别出这部分改动可能会存在 Reachability Metadata。而经过几个版本的迭代,我们发现在 coding 和 code review 阶段遗漏了是普遍存在的。在 2023 年 4 月,发布的 3.2 版本中,我们重新思考并且重构了对 GraalVM Native Image 技术的支持,解决了之前实验性版本的问题:

  1. 编译阶段自动识别所需的 SPI 接口,并自动生成 Adaptive Source code。并且按照标准的 Java 编译产物目录结构,这些 Source Code 被生成在 target 目录下。并且这部分的 Source code 也不再 dubbo 核心仓库内维护,它是编译阶段动态生成的。

  2. 支持编译阶段自动生成 Dubbo 框架所需的 Reachability Metadata。同样无需开发者再维护这部分的配置信息。

  3. 除此之外,新增了 dubbo-maven-plugin,希望能够替代 dubbo-native-plugin。我们认为 dubbo-maven-plugin 应该作为 dubbo 框架对开发者输出的唯一一个 maven plugin,而所有需要借助 maven plugin 构建出来的新特性,都应该迁移到该 maven plugin 中。这样能够降低开发者的心智负担。

在 Dubbo 3.2 版本还有一个重要的迭代,那就是支持并且兼容了 Spring6 和 Spring Boot3,这也为 Dubbo 能够在 xml 和注解的接入姿势上提供 native image 能力打下了基础。在今年年底即将发布的 dubbo 3.3 版本中,将在支持 xml 和注解的接入方式上支持 native image。

图片

在前面的介绍中多次提到一个词,那就是 Reachability Metadata,Dubbo 在集成GraalVM Native Image 也主要是围绕着 Reachability Metadata 的处理。

那么它到底是什么?AOT 也存在自己的局限性,那就是它遵循封闭世界假设原则。也就是需要依赖于能够“看到全部的字节码”才能正确工作,这将导致 AOT 无法支持动态语言的功能,比如 JNI、Java 反射、动态代理、 ClassPath 资源的获取等能力。

在 Java  开发过程中,这些 Java 的动态能力被运用在各种场景中,它们早已经是 Java 开发者非常熟练的编码手段。所以 GraalVM 同样也考虑到了这个情况。在既不打破“封闭时间假设”原则的前提下,通过 Reachability Metadata 来解决这类问题。既然需要在编译器中能够确定所有的字节码和资源,那么就让开发者在编码阶段就确定这些元数据信息。

这张图中罗列了 Reachability Metadata 目前主要用到五种:分别是与JNI Metadata、Resource Metadata、Dynamic Proxy Metadata、Serialization Metadata、Reflection Metadata。官网上还有上还有第六种 Predefined Classes Metadata,因为它需要配置完整的类字节码 hash 值,它更多是配合 Tracing agent 配使用。对于开发者比较关心的问题就是,如何获取并提供这些 Reachability Metadata,从而达到 Native Executable 成功构建和执行的目的。

首先,GraalVM 提供了 Tracing Agent,来辅助开发者在运行时采集对应的Reachability Metadata。但是通过 Tracing Agent 采集的元数据并不能保障能够采集完整,原因是 Tracing Agent 只跟踪和采集执行的代码,而程序输入没有覆盖的代码路径,将无法采集到。GraalVM官网也建议采集后还需要手动 check 元数据。

第二个是 GraalVM 提供了 Reachability Metadata Repository,Java 发展这么多年,诞生出了非常多的组件库,业务开发可以非常轻松地使用这些组件来完成业务功能。纯粹的业务逻辑运用到 Java 动态语言特性的场景并不多,反而是这些组件库使用这些特性更加频繁,所以 GraalVM 提供了这 个Reachability Metadata Repository,吸纳来自不同的组件的 Reachability Metadata。

举个例子,Netty 是使用较为频繁的网络通信框架,Netty 内部用到了反射。而在这个仓库内,能够找到Netty的Reachability Metadata。那么这个仓库内的 Reachability Metadata 如何才能被应用使用,答案是使用 GraalVM 官方提供的 native-maven-plugin。

图片

了解了 Reachability Metadata,与 Dubbo 相关的 Reachability Metadata 有哪些?这张图列举了 Dubbo 对应的一些元数据场景,Dubbo 使用最多的就是反射。

第一个场景就是服务,Dubbo 是一个 RPC 框架,定义服务接口是最基本的需求,同时运行时通过反射获取接口的方法等操作非常频繁。这里区分了内外部的服务接口,原因是 Dubbo 框架内还有一些内建的服务,比如 MetricService、MetadataService 等。

第二个 SPI Extension 类和 Adaptive 类,我们知道 Dubbo 强大且灵活的扩展性得益于它自有的一套 SPI 机制,其中定义为 SPI 接口的实现类,以及 Adaptive 类都需要用到反射。当然这里的 SPI 扩展实现类,也包含业务自己实现的类,比如大家最熟悉和应用最广泛的 Dubbo 执行链中的 Filter,即使业务有自己的实现类,Dubbo aot 也能扫描到并且加载。

第三类是多实例的启动时候需要提前加载一些相关的类。

第四类是 Dubbo 核心的配置类,有通过 API 接入的方式使用经验的朋友应该清楚,比如 ServiceConfig、RegistryConfig 等。

最后是一些其他反射行为,这里包括的是 Dubbo 依赖的组件,存在一些反射行为,比如 ZK 中有反射。第二种是 Resource Metadata,Dubbo 相关的就以下四个资源文件,META-INF 下的这三个资源文件大家都比较熟悉,我们在使用 Dubbo 的 SPI 时,必须配置扩展实现的配置。才能保证 SPI 的实现被加载到。

第四个安全的资源文件, 包含了序列化所需的黑白名单。它能够防范一些序列化的 RCE 漏洞问题,这是 Dubbo3 版本新增的,为了加强服务的安全性。序列化相关的 Metadata。与 Dubbo 相关的主要是内外部服务方法的返回类型和请求参数类型。Dubbo 作为一个 RPC 框架,基本能力就是实现 RPC 调用。在调用过程中无论是请求还是响应,都需要被序列化和反序列化。

第四个就是到动态代理的元数据,在 Dubbo 中主要是在 Consumer 需要有生成动态代理类,用于代理远程的服务接口。屏蔽掉一些网络传输、序列化等行为的细节,让调用方能够像本地方法调用一样使用。而最后一个 JNI 目前 Dubbo 内还没有相关的元数据信息。

图片

这是 Dubbo 相关的 Reachability Metadata 总结和处理策略,我们把它分为了四类。

1. 规律性的内容: 是具备一定规律且需要被可生成的内容,比如刚刚提到的 Adaptive Source Code 的生成。

2. 确定性资源和行为: 确定的是 Dubbo 内自身在 Native 场景所需的的资源,比如 SPI 的配置文件等。

3. 不确定性的资源和行为: 是业务基于 Dubbo 的能力所添加的资源或行为,这部分被称为不确定性的资源和行为,比如业务自定义的 SPI 扩展实现以及定义的服务等。

4. 集成和依赖的组件: 比如刚刚提到 Zookeeper 等涉及到的元数据信息。

图片

Spring 和 Dubbo 都有自己的 AOT 处理逻辑,但是它们之间的处理又有些不同,这是 Spring Aot 的处理逻辑,可以看到从源码编译开始,Spring 会直接从 main 函数启动应用程序,并且会将 Spring bean 生成的 source code 生成,以及对应的 Reachability Metadata 生成。对于 Spring 而言,在启动和扫描过程已经能够完成所有 Metadata 的扫描。

下面这个就是通过 Spring AOT 生成的 Bean Source code,当我们简单的用一个 Spring 的 Service 注解时。这个 DemoService 的实现类就被定义为一个 Spring 内的 Bean,而经过 AOT 处理后,会生成右边这个与 DemoService 有个的 BeanDefinition 的提供类。用于在加载 Bean 时候获取相关的信息。

图片

而 Dubbo 的 AOT 则是在源码开始编译后,会启动一个扫描的进程,来完成刚刚列举的与 Dubbo 有关的 Reachability Metadata 和对应的 Source code。可以看到,我们将 Spring 的 Service 注解换成 Dubbo 的 DubboService 注解后,同样也会得到一个与 DemoService 有个的 BeanDefinition 的提供类,但是里面的内容是 Dubbo 提供的。包括拼接 interface 等参数。这里就是 Spring AOT 处理和 Dubbo AOT 的处理结果,可以看到分别在 spring-aot 和 dubbo-aot 下生成了 GraalVM 所需的 Reachability Metadata,以及他们各自的 Source code。

图片

上图是 Spring 本身提供的一个产物的内容以及 Dubbo 的 AOT 产物的内容。可以看到 Dubbo 下面是 Adaptive 的一些 source code。最后 Native 在执行的时候会读取到这里所有的配置。

图片

这是后续 Dubbo 在 AOT 演进上与 Spring AOT 的边界,首先在 API 接入的方式中,Dubbo 不依赖于 Spring,所以它能够完成所有的内容,包括所需的 Adaptive Source code 和 Reachability Metadata。其次因为 XML 和注解都依赖于 Spring,所以 Dubbo 内的 Bean 都将会依托于 Spring AOT 的能力来实现,包括 ServiceBean、ReferenceBean 以及 Dubbo 框架内的与 Spring Bean 有关的内容。除此之外,Spring 也会生成所需的 Reachability Metadata。

Dubbo 在 Native Image技术的未来规划

1. 提升开发者体验&开发效率

图片

第一点就是提升开发者体验和开发效率。Dubbo 在 3.0 之后提供了 CTL、脚手架、IDEA 插件,Dubbo Native Image 目前还在建设中,之后也会将 Native Image 加入其中。此外,还有关于一些 Dubbo Native 的文档建设也会逐步开展。

2. 性能优化与提升

图片

第二点是性能优化和提升。在 GraalVM 提供的能力上,我们还可以把一些类相关的可达性的配置加上去,产生作用之后能让最后打出来的二进制包更小,编译时间更短。

###v3. 覆盖更多的组件

图片

第三点则是覆盖更多的组件。因为目前很多组件都还不支持,所以我们现在的主要思路是把 Dubbo 主仓库的扩展性支持完成,然后再往 dubbo-spi-exntensions 的扩展上做相应的支持。另外,内核所需要的可达性的元数据,我们会把它推到 GraalVM 的可达性的元数据的仓库上面去,让业务开发能够正常使用 Dubbo 内核所需的元数据信息。

最后是我们覆盖更多组件的思路:我们会优先考虑 GraalVM 官方的支持,但是因为 GraalVM 发布周期不可控,推进的时间可能也会比较长,所以我们也会为一些通用且必要的组件优先支持元数据,让 Dubbo 用户能够提前享受到 Native Image 所带来的技术红利。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/107740.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

中国人口文化促进会社区文化推广工作委员会成立 暨2024社区春晚文艺活动新闻发布会在京成功举办

2023年10.13日,下午1点,在北京大红门国际会展中心召开了中国人口文化促进会社区文化推广工作委员会成立暨2024社区春晚文艺活动新闻发布会。来自政府相关部门、社会组织、新闻媒体和公益企业界的相关领导与代表齐聚一堂,共襄盛举。 本次大会由…

POI报表的入门

POI报表的入门 理解员工管理的的业务逻辑 能够说出Eureka和Feign的作用 理解报表的两种形式和POI的基本操作熟练使用POI完成Excel的导入导出操作 员工管理 需求分析 企业员工管理是人事资源管理系统中最重要的一个环节,分为对员工入职,转正&#x…

自动驾驶:控制算法概述

自动驾驶:控制算法概述 常见控制算法PID算法LQR算法MPC算法 自动驾驶控制算法横向控制纵向控制 参考文献 常见控制算法 PID算法 PID(Proportional-Integral-Derivative)控制是一种经典的反馈控制算法,通常用于稳定性和响应速度要…

ue5蓝图请求接口

安装与使用 1、在虚幻商城搜索 VaRest 插件 2、选择自己项目的对应版本安装 3、查看是否安装成功 4、进入项目后,分别启动VaRest、JSON Blueprint Utilities两个插件(勾选后会提示重启项目) 5、基本用法:打开关卡蓝图使用&#xf…

Android Studio SDK manager加载packages不全

打开Android Studio里的SDK manager,发现除了已安装的,其他的都不显示。 解决方法: 设置代理: 方便复制> http://mirrors.neusoft.edu.cn/ 重启Android Studio

【Java学习之道】TCPIP套接字编程实例

引言 网络编程是Java学习中不可或缺的一部分,而TCP/IP套接字编程又是网络编程的基础。那么,初学者如何才能快速掌握TCP/IP套接字编程呢?今天我们就来通过一个简单的实例,为你揭示TCP/IP套接字编程的奥秘! 一、什么是…

Sql Server 数据库中的所有已定义的唯一约束 (列名称 合并过了)

查询Sql Server Database中的唯一约束 with UniqueBasic as (SELECTtab.name AS TableName, -- 表名称idx.name AS UniqueName, -- 唯一约束的名称col.name AS UniqueFieldName -- 唯一约束的表字段FROMsys.indexes idxJOIN sys.index_columns idxColON (idx.object_id idxCo…

PyTorch 深度学习之循环神经网络(基础篇)Basic RNN(十一)

0.Revision: DNN dense 重义层 全连接 RNN处理带有序列的数据 1. What is RNNs? linear layer 1.1 What is RNN? tanh (-1, 1) 1.2 RNN Cell in PyTorch 1.3 How to use RNNCell *先把维度搞清楚 多了一个序列的维度 2. How to use RNN 2.1 How to use RNN - numLayers…

PC电脑 VMware安装的linux CentOs7如何扩容磁盘?

一、VM中进行扩容设置 必须要关闭当前CentOS,不然扩展按钮是灰色的。 输入值必须大于当前磁盘容量。然后点击扩展,等待扩展完成会提示一个弹框,点击确定,继续确定。 二、操作CentOS扩容——磁盘分区 第一步设置完成。那就启动 …

docker-compose部署elk(8.9.0)并开启ssl认证

docker部署elk并开启ssl认证 docker-compose部署elk部署所需yml文件 —— docker-compose-elk.yml部署配置elasticsearch和kibana并开启ssl配置基础数据认证配置elasticsearch和kibana开启https访问 配置logstash创建springboot项目进行测试kibana创建视图,查询日志…

微信小程序-3

一、交互 API - - - 界面 - - - 交互 功能&#xff1a;提示 是否删除 1.wx.showToast 显示消息提示框 <button type"primary" bindtapclickBtn>按钮</button> <input style"margin: 20rpx;height: 60rpx;background: gainsboro;" type&…

Docker逃逸---SYS_PTRACE浅析

一、产生原因 用户授予了容器SYS_PTRACE权限&#xff0c;并且与宿主机共享一个进程命名空间(--pidhost)&#xff0c;使得容器内可以查看到宿主机的进程&#xff0c;攻击者可以利用进程注入&#xff0c;反弹shell&#xff0c;从而实现逃逸 二、利用条件 1、容器有SYS_PTRACE权…

23基于MATLAB的小波降噪,默认阈值消噪,强制消噪,给定软阈值消噪方法,数据直接替换后就可以跑。

基于MATLAB的小波降噪&#xff0c;默认阈值消噪&#xff0c;强制消噪&#xff0c;给定软阈值消噪方法&#xff0c;数据直接替换后就可以跑。 https://www.xiaohongshu.com/explore/652d57c600000

elasticsearch配置

Elasticsearch version: 5.1.1 Windows Java安装 版本&#xff1a;jdk8 Java Archive | Oracle 中国 安装elasticsearch-rtf Elasticsearch-RTF是针对中文的一个发行版&#xff0c;即使用最新稳定的elasticsearch版本&#xff0c;并且帮你下载测试好对应的插件&#xff0c;…

ppt怎么压缩到10m以内?分享ppt缩小方法

在日常工作中&#xff0c;我们常常需要制作和分享PowerPoint演示文稿&#xff0c;然而&#xff0c;有时候文稿中的图片、视频等元素会导致文件过大&#xff0c;无法在电子邮件或其他平台上顺利传输。为了将PPT文件压缩到10M以内&#xff0c;我们可以使用一些专门的文件压缩工具…

性能超越 Clickhouse | 物联网场景中的毫秒级查询案例

1 物联网应用场景简介 物联网&#xff08;Internet of Things&#xff0c;简称 IoT&#xff09;是指通过各种信息传感、通信和 IT 技术来实时连接、采集、监管海量的传感设备&#xff0c;从而实现对现实世界的精确感知和快速响应&#xff0c;继而实现自动化、智能化管理。在查…

2-k8s-控制器介绍

文章目录 一、控制器类型二、Deployment控制器三、SatefulSet控制器四、Daemonset控制器五、Job控制器六、CronJob 控制器 一、控制器类型 Deployment&#xff1a;适合无状态的服务部署StatefullSet&#xff1a;适合有状态的服务部署DaemonSet&#xff1a;一次部署&#xff0c…

时间复杂度为 O(n^2) 的排序算法

大家好&#xff0c;我是 方圆。对于小规模数据&#xff0c;我们可以选用时间复杂度为 O(n2) 的排序算法&#xff0c;因为时间复杂度并不代表实际代码的执行时间&#xff0c;而且它也省去了低阶、系数和常数&#xff0c;仅代表的增长趋势&#xff0c;所以在小规模数据情况下&…

python:使用卷积神经网络(CNN)进行回归预测

作者:CSDN @ _养乐多_ 本文详细记录了从Excel或者csv中读取用于训练卷积神经网络(CNN)模型的数据,包括多个自变量和1个因变量数据,以供卷积神经网络模型的训练。随后,我们将测试数据集应用于该CNN模型,进行回归预测和分析。 该代码进一步修改可用于遥感影像回归模型. …

【广州华锐互动】人体血管器官3D动态展示为医学生提供哪些便利?

人体血管器官3D动态展示是一种采用先进的计算机图形技术和立体成像技术&#xff0c;对人体内部结构和功能进行三维可视化的教学方法。这种教学方式以其独特的优势&#xff0c;正在改变传统的解剖学教学模式&#xff0c;为医学教育带来了革新。 首先&#xff0c;3D动态演示能够提…