在调用 borrowObject 方法时,Apache Commons Pool 会根据连接池的配置触发一系列相关的方法

news2025/1/8 11:22:05

在调用 borrowObject 方法时,Apache Commons Pool 会根据连接池的配置触发一系列相关的方法

1. GrpcChannel 的概念

GrpcChannelgRPC 客户端与服务器之间通信的核心组件。它是基于 HTTP/2 的连接,支持多路复用,即通过单个通道可以发送多个请求。

特点

  • 高消耗:创建 gRPC 通道可能涉及 DNS 解析、SSL 握手、连接认证等,耗时较高。
  • 长连接:gRPC 通道是长连接,在生命周期内可以复用。
  • 线程安全:gRPC 通道是线程安全的,多个线程可以共享一个通道发送请求。

2. 为什么需要 GrpcChannelPool

在高并发场景中,如果每个请求都创建一个新的 GrpcChannel,会导致以下问题:

  1. 资源消耗大:频繁创建和销毁通道会增加系统开销(如网络连接、CPU 和内存使用)。
  2. 性能瓶颈:SSL 握手、认证等操作可能导致响应时间变长。
  3. 连接浪费:大多数情况下,一个 gRPC 通道可以复用多个请求。

为了解决上述问题,引入连接池管理 GrpcChannel,实现通道的复用。


3. GrpcChannelPool 的作用

GrpcChannelPool 的主要功能是:

  1. 通道复用:通过复用 GrpcChannel,减少创建和销毁的开销。
  2. 资源管理:限制活跃和空闲连接的数量,避免资源耗尽。
  3. 性能优化:通过预热和连接验证机制,确保请求的响应速度和可靠性。

4. GrpcChannelPool 的实现

实现方式

GrpcChannelPool 通常基于 Apache Commons Pool,使用 GenericObjectPool 来管理连接池。以下是主要组件:

  1. GrpcChannelFactory:

    • 实现 PooledObjectFactory<GrpcChannel> 接口。
    • 负责创建、销毁和验证 GrpcChannel
  2. GenericObjectPool:

    • 提供连接池的核心功能,包括对象的借用(borrowObject)、归还(returnObject)、空闲检测等。

代码示例

1. 定义 GrpcChannelFactory
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;

public class GrpcChannelFactory implements PooledObjectFactory<ManagedChannel> {
    private final String target;

    public GrpcChannelFactory(String target) {
        this.target = target;
    }

    @Override
    public PooledObject<ManagedChannel> makeObject() {
        ManagedChannel channel = ManagedChannelBuilder.forTarget(target).usePlaintext().build();
        return new DefaultPooledObject<>(channel);
    }

    @Override
    public void destroyObject(PooledObject<ManagedChannel> p) {
        ManagedChannel channel = p.getObject();
        channel.shutdown();
    }

    @Override
    public boolean validateObject(PooledObject<ManagedChannel> p) {
        ManagedChannel channel = p.getObject();
        return !channel.isShutdown() && !channel.isTerminated();
    }

    @Override
    public void activateObject(PooledObject<ManagedChannel> p) {
        // 可选的激活逻辑
    }

    @Override
    public void passivateObject(PooledObject<ManagedChannel> p) {
        // 可选的钝化逻辑
    }
}
2. 配置 GrpcChannelPool
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

public class GrpcChannelPool {
    private final GenericObjectPool<ManagedChannel> pool;

    public GrpcChannelPool(String target) {
        GrpcChannelFactory factory = new GrpcChannelFactory(target);
        GenericObjectPoolConfig<ManagedChannel> config = new GenericObjectPoolConfig<>();
        config.setMaxTotal(50);          // 最大活跃连接数
        config.setMinIdle(5);           // 最小空闲连接数
        config.setMaxIdle(10);          // 最大空闲连接数
        config.setTimeBetweenEvictionRunsMillis(30000); // 空闲检测周期
        config.setTestOnBorrow(true);  // 借用时验证
        config.setTestWhileIdle(true); // 空闲时验证
        pool = new GenericObjectPool<>(factory, config);
    }

    public ManagedChannel borrowChannel() throws Exception {
        return pool.borrowObject();
    }

    public void returnChannel(ManagedChannel channel) {
        pool.returnObject(channel);
    }
}
3. 使用 GrpcChannelPool
public class GrpcClient {
    public static void main(String[] args) throws Exception {
        GrpcChannelPool channelPool = new GrpcChannelPool("localhost:50051");

        // 借用一个通道
        ManagedChannel channel = channelPool.borrowChannel();

        // 使用通道发送 gRPC 请求
        // 示例代码:
        // MyGrpcServiceGrpc.MyGrpcServiceBlockingStub stub = MyGrpcServiceGrpc.newBlockingStub(channel);
        // stub.myRpcMethod();

        // 归还通道
        channelPool.returnChannel(channel);
    }
}

5. GrpcChannelPool 的参数配置

  • maxTotal:最大活跃连接数,限制并发连接的数量。
  • minIdle:最小空闲连接数,确保有预热的连接可以立即使用。
  • maxIdle:最大空闲连接数,避免空闲连接占用过多资源。
  • timeBetweenEvictionRunsMillis:空闲检测周期,定期清理无效连接。
  • testOnBorrow:借用连接时验证有效性,避免借用无效连接。
  • testWhileIdle:空闲检测时验证连接有效性,确保空闲连接的健康状态。

6. GrpcChannelPool 的优点

  1. 提高性能

    • 减少频繁创建和销毁 gRPC 通道的开销。
    • 确保在高并发场景下能够快速响应。
  2. 降低资源消耗

    • 通过复用通道和限制连接数量,避免资源浪费。
  3. 增强可靠性

    • 通过验证和检测机制,确保连接池中的通道始终处于健康状态。
  4. 支持动态调整

    • 根据负载情况灵活调整池的大小,满足不同场景需求。

7. GrpcChannelPool 在调用 borrowObject 时触发的方法

在调用 borrowObject 方法时,可能触发以下方法:

A. makeObject

  • 触发条件
    • 当池中没有空闲对象,且当前活跃对象数小于 maxTotal 时,会调用此方法创建新对象。
  • 作用
    • 创建并包装一个新的 GrpcChannel 对象。
  • 示例
    @Override
    public PooledObject<ManagedChannel> makeObject() {
        ManagedChannel channel = ManagedChannelBuilder.forTarget(target).usePlaintext().build();
        return new DefaultPooledObject<>(channel);
    }
    

B. validateObject

  • 触发条件
    • testOnBorrow 设置为 true 时,每次调用 borrowObject 都会触发此方法。
  • 作用
    • 验证对象是否处于健康状态,例如 GrpcChannel 是否已关闭或异常。
    • 如果验证失败,该对象会被销毁。
  • 示例
    @Override
    public boolean validateObject(PooledObject<ManagedChannel> p) {
        ManagedChannel channel = p.getObject();
        return !channel.isShutdown() && !channel.isTerminated();
    }
    

C. activateObject

  • 触发条件
    • 在对象被借出时会调用此方法(如果需要)。
  • 作用
    • 激活对象,例如初始化某些状态或设置上下文信息。
  • 示例
    @Override
    public void activateObject(PooledObject<ManagedChannel> p) {
        System.out.println("Activating gRPC Channel: " + p.getObject());
    }
    

D. passivateObject

  • 作用
    • 当对象被归还到池中时,passivateObject 方法会被触发,用于将对象的状态重置为初始状态。

8. 调用流程总结

  1. 检查空闲对象是否可用:如果池中有空闲对象,尝试直接获取。
  2. 验证对象有效性:通过 validateObject 检查对象状态(取决于配置)。
  3. 激活对象:调用 activateObject 进行状态初始化(如果需要)。
  4. 创建新对象:如果没有可用对象且未达 maxTotal,调用 makeObject 创建新对象。

通过合理配置参数和优化对象工厂逻辑,可以有效提高 borrowObject 的性能和可靠性。


GrpcChannelPool 方法耗时分析及优化

1. 可能耗时的方法

A. makeObject(创建对象)

  • 耗时原因

    • 创建 GrpcChannel 涉及:
      1. DNS 解析:在创建连接时需要解析目标服务器地址。
      2. 网络连接:与服务器建立 HTTP/2 连接。
      3. SSL/TLS 握手(如果启用加密):握手过程会增加额外的网络延迟。
      4. 认证过程(可选):如果使用身份验证机制(如 JWT、OAuth),会增加初始化时间。
    • 通常,这个步骤是最耗时的,特别是当目标服务延迟较高或网络不稳定时。
  • 优化建议

    1. 启用预热机制
      • 设置 minIdletimeBetweenEvictionRunsMillis,在负载高峰前预先创建连接。
    2. 优化网络环境
      • 使用快速 DNS 服务和低延迟网络。
    3. 连接复用
      • 尽量通过池化减少新连接的创建频率。

B. validateObject(验证对象)

  • 耗时原因

    • 验证逻辑可能会检查连接是否存活,通常包括:
      1. 检查连接是否已关闭或终止(通常较快)。
      2. 测试连接是否有效(如发送心跳或小数据包),如果涉及网络交互则可能增加延迟。
      3. 外部资源状态检查(例如,验证服务器响应状态)。
    • 如果验证逻辑涉及网络请求(如 Ping 服务器),会导致验证时间延长。
  • 优化建议

    1. 本地快速验证
      • 首选本地状态检查(如 !channel.isShutdown()),尽量避免网络交互。
    2. 设置合理的验证频率
      • 仅在必要时启用 testOnBorrowtestWhileIdle

C. activateObject(激活对象)

  • 耗时原因

    • 激活逻辑通常较快,但如果涉及复杂的状态初始化或外部资源调用,可能会增加耗时。
    • 示例耗时操作:
      • 加载上下文信息。
      • 注册监控事件。
      • 清理历史状态。
  • 优化建议

    1. 简化激活逻辑,尽量避免耗时操作。
    2. 将部分激活工作移至 makeObject,减少借用时的开销。

2. 哪些方法通常较快

A. passivateObject(钝化对象)

  • 用于在对象归还时重置状态,通常仅涉及本地操作,例如清除缓存或重置标志位,通常耗时极低。

B. destroyObject(销毁对象)

  • 销毁对象时通常调用 ManagedChannel.shutdown(),异步关闭连接,对借用方的延迟影响较小。

3. 可能耗时的场景与应对策略

场景耗时操作应对策略
创建新连接DNS 解析、网络连接、SSL 握手、身份验证启用预热机制,提前创建连接,减少高峰期负载压力
验证连接有效性网络交互(如心跳)、服务器状态检查优化验证逻辑,仅在必要时进行全面检查
激活对象(初始化)初始化上下文、注册事件、状态清理尽量简化激活逻辑,避免复杂耗时操作
网络不稳定或服务延迟问题依赖外部服务的操作会增加时间增强网络稳定性,确保服务响应快速可靠

4. 性能优化总结

  1. 减少创建连接频率

    • 通过连接池复用 GrpcChannel,减少 makeObject 的调用次数。
  2. 优化验证逻辑

    • validateObject 中优先使用本地检查,避免不必要的网络交互。
  3. 提前创建和预热连接

    • 设置 minIdletimeBetweenEvictionRunsMillis,在负载高峰前确保足够的空闲连接。
  4. 监控与调试

    • 记录各方法的执行时间,识别性能瓶颈并优化耗时操作。

通过以上优化,可以显著降低 borrowObject 方法的延迟,提高 GrpcChannelPool 的性能和可靠性。


makeObject(创建对象)耗时分析及优化

1. 影响 makeObject 耗时的主要因素

A. DNS 解析时间

  • 在创建 GrpcChannel 时,如果目标地址需要解析 DNS,耗时取决于 DNS 服务的响应时间。
  • 一般耗时
    • 通常在 10-50ms
    • 如果缓存了 DNS 解析结果,可以进一步减少时间。

B. 网络连接时间

  • 创建 GrpcChannel 需要与服务器建立 TCP 连接,这个过程受以下因素影响:
    1. 服务器响应速度
    2. 网络延迟(RTT,往返时间)。
  • 一般耗时
    • 本地网络环境(LAN):通常在 5-30ms
    • 跨区域(WAN):可能达到 50-150ms,视网络质量而定。

C. SSL/TLS 握手时间

  • 如果 GrpcChannel 使用了加密连接(useTransportSecurity),握手会增加额外的耗时,包括:
    1. 公私钥交换。
    2. 加密算法协商。
    3. 服务端证书验证。
  • 一般耗时
    • 通常在 50-200ms,具体取决于服务器和客户端的计算能力以及网络环境。

D. 自定义逻辑

  • 如果 makeObject 中包含其他初始化逻辑,例如身份认证、加载配置或依赖外部资源,可能进一步增加时间。
  • 一般耗时:不固定,完全取决于实现。

2. 实际测量方法

为了测量 makeObject 的平均耗时,可以在代码中记录开始和结束时间,例如:

代码示例
import java.time.Duration;
import java.time.Instant;
import org.apache.commons.pool2.impl.DefaultPooledObject;

public class GrpcChannelFactory implements PooledObjectFactory<ManagedChannel> {
    private final String target;

    public GrpcChannelFactory(String target) {
        this.target = target;
    }

    @Override
    public PooledObject<ManagedChannel> makeObject() {
        Instant start = Instant.now(); // 开始计时

        ManagedChannel channel = ManagedChannelBuilder.forTarget(target)
                .usePlaintext() // 或者使用 .useTransportSecurity()
                .build();

        Instant end = Instant.now(); // 结束计时
        System.out.println("makeObject 耗时: " + Duration.between(start, end).toMillis() + " ms");

        return new DefaultPooledObject<>(channel);
    }

    // 其他方法省略...
}

3. 平均耗时的估算

在不同场景下,makeObject 的平均耗时可能如下:

场景环境平均耗时主要原因
本地开发(无加密)本地服务器/LAN5-20msTCP 连接快速,且无额外开销。
生产环境(加密连接)云服务器/WAN50-150msSSL 握手和网络延迟导致耗时增加。
复杂认证或初始化逻辑使用外部身份认证服务200ms 或更高认证请求和外部依赖增加了耗时。

4. 如何优化 makeObject 的耗时

A. 减少 DNS 解析时间

  • 方法
    1. 在客户端启用 DNS 缓存(Java 默认启用,缓存时间可配置)。
    2. 使用 IP 地址直连,跳过 DNS 解析。

B. 提高网络连接速度

  • 方法
    1. 部署 gRPC 服务器和客户端在同一网络区域,降低网络延迟。
    2. 使用快速网络,如低延迟的专用通道或优化路由。

C. 减少 SSL 握手时间

  • 方法
    1. 使用更高效的加密算法(如 TLS 1.3)。
    2. 启用会话复用(Session Resumption),避免每次都重新握手。

D. 简化初始化逻辑

  • 方法
    1. 尽量减少 makeObject 中的额外逻辑,将复杂任务移到其他阶段。
    2. 在对象池中预热连接,减少实际使用时的初始化开销。

5. 总结

  • 本地开发环境:平均耗时 5-20ms
  • 生产环境(加密连接、跨区域):平均耗时 50-150ms,高延迟网络可能更高。
  • 复杂认证场景:如果涉及外部依赖,可能超过 200ms

通过优化网络环境、减少初始化逻辑和启用预热机制,可以有效降低 makeObject 的平均耗时,从而提高系统性能。


makeObject(创建对象)与等待线程数的耗时比较

1. 两者耗时的核心区别

A. makeObject(创建对象)耗时

makeObject 的耗时是主动操作的结果,受以下因素影响:

  1. 创建过程中的外部依赖
    • DNS 解析、网络连接、SSL/TLS 握手、外部服务验证等。
    • 这些操作通常是固定的,对于每个新对象的创建,耗时是线性增加的。
  2. 无法完全避免
    • 如果连接池中没有足够的空闲对象,且活跃对象数已接近 maxTotalmakeObject 是必需的耗时操作。

典型耗时范围

  • 无加密/本地连接:5-30ms。
  • 加密连接/复杂验证:50-200ms,甚至更高。

B. 等待执行的线程数

等待线程数的耗时是被动等待的结果,受以下因素影响:

  1. 线程排队机制
    • borrowObject 被调用时,如果没有空闲对象且活跃对象数已达 maxTotal,新的线程会进入等待状态。
  2. 最大等待时间限制
    • 配置了 maxWaitMillis 时,线程会阻塞至超时或有对象归还/创建完成。
  3. 竞争关系
    • 如果线程数较多,等待时间可能呈指数级增长,因为所有线程需要依次获取锁或等待资源。

典型耗时范围

  • 低竞争场景:几十毫秒到几百毫秒,取决于资源释放速度。
  • 高竞争场景:可能超时(抛出 NoSuchElementExceptionTimeoutException),视配置而定。

2. 哪种操作更耗时?

场景 1:连接池有足够的资源

  • makeObject 更耗时
    • 如果连接池中有空闲对象,即使有线程排队,借用操作会立即完成,线程等待耗时较短。
    • 新对象的创建仍需要进行网络连接等耗时操作,因此 makeObject 更耗时。

场景 2:连接池资源耗尽

  • 等待线程数更耗时
    • 当所有对象都被借出,且线程需要等待时,线程排队时间可能无限增长(取决于资源归还速度)。
    • 特别是高并发场景中,线程数较多时,每个线程的等待时间会显著增加。

场景 3:高并发 + 对象创建较慢

  • 两者均耗时
    • 在高并发场景中,如果 makeObject 创建对象较慢,线程等待时间会与 makeObject 的耗时叠加。
    • 如果等待线程数远多于可用资源,线程的等待时间可能最终成为主要瓶颈。

3. 优化策略

A. 优化 makeObject 的耗时

  1. 启用预热机制
    • 配置 minIdletimeBetweenEvictionRunsMillis,确保在高并发到来前提前创建连接。
  2. 简化创建逻辑
    • 优化 DNS 解析、网络连接和认证流程,减少创建对象的固定开销。
  3. 分布式连接池
    • 在高并发场景下,使用多个连接池分散负载,降低单个池的压力。

B. 优化等待线程数

  1. 增加连接池容量
    • 调整 maxTotalmaxIdle,确保池中有足够的资源处理高峰流量。
  2. 动态调配资源
    • 根据请求量动态调整池的大小,避免长时间的线程排队。
  3. 合理设置超时
    • 配置 maxWaitMillis,限制线程的最大等待时间,避免因过长的阻塞导致系统雪崩。

4. 综合判断:耗时比较

条件耗时较高的操作原因
空闲连接充足makeObject需要进行创建过程,涉及网络连接、加密握手等。
资源完全耗尽等待线程数线程阻塞时间可能超过资源创建时间,取决于资源归还速度和线程数。
高并发 + 低资源归还速率两者均耗时新对象创建缓慢导致线程长时间排队,线程排队又进一步增加系统压力。

5. 示例优化配置

以下是一个优化配置的示例,平衡 makeObject 和等待线程数的耗时问题:

GenericObjectPoolConfig<ManagedChannel> config = new GenericObjectPoolConfig<>();
config.setMaxTotal(50);                      // 增加池的容量,减少线程等待
config.setMinIdle(10);                       // 启用预热机制,提前创建连接
config.setTimeBetweenEvictionRunsMillis(10000); // 每 10 秒检测空闲连接
config.setMaxWaitMillis(500);                // 限制线程的最大等待时间
config.setTestOnBorrow(true);                // 借用时验证连接是否有效

6. 结论

  • 小规模并发(空闲资源充足)makeObject 通常更耗时。
  • 高并发 + 资源耗尽:线程等待时间更耗时。
  • 综合优化:通过预热机制、动态资源调配和合理配置参数,可以有效降低两者的耗时,提升系统性能。

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

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

相关文章

HDFS异构存储和存储策略

一、HDFS异构存储类型 1.1 冷、热、温、冻数据 通常&#xff0c;公司或者组织总是有相当多的历史数据占用昂贵的存储空间。典型的数据使用模式是新传入的数据被应用程序大量使用&#xff0c;从而该数据被标记为"热"数据。随着时间的推移&#xff0c;存储的数据每周…

【51单片机】02LED流水灯实验

点亮你的LED 一、点亮第一个LED1.GPIO介绍2.P1、P2、P3端口 二、LED实验2.尝试点亮LED3.LED流水灯 一、点亮第一个LED 1.GPIO介绍 这块内容这里可以做简单的了解&#xff0c;与数电知识强相关。后续可以再回过头来学习 GPIO (general purpose input output) 通用输入输出端口…

springboot 集成 etcd

springboot 集成 etcd 往期内容 ETCD 简介docker部署ETCD 前言 好久不见各位小伙伴们&#xff0c;上两期内容中&#xff0c;我们对于分布式kv存储中间件有了简单的认识&#xff0c;完成了docker-compose 部署etcd集群以及可视化工具 etcd Keeper&#xff0c;既然有了认识&a…

云安全相关博客阅读(一)

2024-03-04 Cloudflare announces Firewall for AI 关注问题&#xff1a; 传统的WAF功能能够保护web和api安全&#xff0c;但是随着LLM等AI模型等出现&#xff0c;保护这些AI相关应用等安全是一个新出现的问题虽然AI应用是新的场景&#xff0c;但是以往的攻击方法也能够直接用…

2025年01月07日Github流行趋势

项目名称&#xff1a;khoj 项目地址url&#xff1a;https://github.com/khoj-ai/khoj项目语言&#xff1a;Python历史star数&#xff1a;20105今日star数&#xff1a;363项目维护者&#xff1a;debanjum, sabaimran, MythicalCow, aam-at, shantanuSakpal项目简介&#xff1a;你…

从零手写线性回归模型:PyTorch 实现深度学习入门教程

系列文章目录 01-PyTorch新手必看&#xff1a;张量是什么&#xff1f;5 分钟教你快速创建张量&#xff01; 02-张量运算真简单&#xff01;PyTorch 数值计算操作完全指南 03-Numpy 还是 PyTorch&#xff1f;张量与 Numpy 的神奇转换技巧 04-揭秘数据处理神器&#xff1a;PyTor…

【python】matplotlib(radar chart)

文章目录 1、功能描述和原理介绍2、代码实现3、效果展示4、完整代码5、多个雷达图绘制在一张图上6、参考 1、功能描述和原理介绍 基于 matplotlib 实现雷达图的绘制 一、雷达图的基本概念 雷达图&#xff08;Radar Chart&#xff09;&#xff0c;也被称为蛛网图或星型图&…

数据库环境安装(day1)

网址&#xff1a;MySQL 下载&#xff08;环境准备&#xff09;&#xff1a; &#xff08;2-5点击此处&#xff0c;然后选择合适的版本&#xff09; 1.linux在线YUM仓库 下载/安装: wget https://repo.mysql.com//mysql84-community-release-el9-1.noarch.rpm rpm -i https://r…

Fabric链码部署测试

参考链接&#xff1a;运行 Fabric 应用程序 — Hyperledger Fabric Docs 主文档 (hyperledger-fabric.readthedocs.io) &#xff08;2&#xff09;fabric2.4.3部署运行自己的链码 - 知乎 (zhihu.com) Fabric2.0测试网络部署链码 - 辉哥哥~ - 博客园 (cnblogs.com) 1.启动测试…

数据结构与算法之二叉树: LeetCode 107. 二叉树的层序遍历 II (Ts版)

二叉树的层序遍历 II https://leetcode.cn/problems/binary-tree-level-order-traversal-ii/description/ 描述 给你二叉树的根节点 root &#xff0c;返回其节点值 自底向上的层序遍历 。 &#xff08;即按从叶子节点所在层到根节点所在的层&#xff0c;逐层从左向右遍历&a…

Python插件化开发实战:开发个图片浏览器

在本篇教程中&#xff0c;我将详细介绍如何使用Python开发一个基于插件架构的图片浏览器。这个项目将展示如何实现插件系统、如何处理图片显示,以及如何使用wxPython构建GUI界面。 “C:\pythoncode\pythonplugin\your_project\main_app.py” 项目概述 我们将开发一个具有以下…

根据python代码自动生成类图的实现方法[附带python源码]

概述 利用python库抽象语法树(AST)和类图描述语言(PlantUML),实现自动将python代码生成类图的目的。 环境 windowsvscodepythonplantuml ✒️网上好像大部分都是用Pyreverse库来实现的&#xff0c;但是我实际测试发现只能在一个文件中才能行&#xff0c;当然应该有解决方法…

下载b站高清视频

需要使用的edge上的一个扩展插件&#xff0c;所以选择使用edge浏览器。 1、在edge浏览器上下载 强力视频下载合并 扩展插件 2、在edge上打开b站&#xff0c;登录自己账号&#xff08;登录后才能下载到高清&#xff01;&#xff01;&#xff09;。打开一个视频&#xff0c;选择自…

flutter 专题二十四 Flutter性能优化在携程酒店的实践

Flutter性能优化在携程酒店的实践 一 、前言 携程酒店业务使用Flutter技术开发的时间快接近两年&#xff0c;这期间有列表页、详情页、相册页等页面使用了Flutter技术栈进行了跨平台整合&#xff0c;大大提高了研发效率。在开发过程中&#xff0c;也遇到了一些性能相关问题和…

UE5 打包要点

------------------------- 1、需要环境 win sdk &#xff0c;大约3G VS&#xff0c;大约10G 不安装就无法打包&#xff0c;就是这么简单。 ----------------------- 2、打包设置 编译类型&#xff0c;开发、调试、发行 项目设置-地图和模式&#xff0c;默认地图 项目…

vulnhub靶场【DC系列】之5

前言 靶机&#xff1a;DC-5&#xff0c;IP地址为192.168.10.4 攻击&#xff1a;kali&#xff0c;IP地址为192.168.10.2 都采用VMWare&#xff0c;网卡为桥接模式 对于文章中涉及到的靶场以及工具&#xff0c;我放置网盘中https://pan.quark.cn/s/2fcf53ade985 主机发现 使用…

双模态视觉特征流用于医学报告生成|文献速递-视觉大模型医疗图像应用

Title 题目 Dual-modality visual feature flow for medical report generation 双模态视觉特征流用于医学报告生成 01 文献速递介绍 医学报告生成是一项新兴的跨模态文本生成任务&#xff08;X. Zeng et al., 2020&#xff1b;Najdenkoska et al., 2022&#xff1b;Li et…

基于Fluent和深度学习算法驱动的流体力学计算与应用

物理模型与深度学习的融合&#xff1a;研究如何将传统的物理模型与深度学习算法相结合&#xff0c;以提高流体力学问题的预测准确性和计算效率。复杂流动模拟&#xff1a;利用深度学习技术对复杂流动现象进行模拟和分析&#xff0c;包括湍流、多相流、非牛顿流体等&#xff0c;…

记PasteSpider部署工具的Windows.IIS版本开发过程之草稿-动态表单(2)

接1的内容&#xff0c;那么有这么一个需求&#xff01; 需求分析 需要修改某一个配置的时候 1.从对应的api中读取消息&#xff0c;消息内容为Json格式的 2.基于当前的Json渲染成表单提供给管理端的客户呈现 3.管理端的用户可以基于这个表单的内容进行修改&#xff0c;然后提交…

pycharm-pyspark 环境安装

1、环境准备&#xff1a;java、scala、pyspark、python-anaconda、pycharm vi ~/.bash_profile export SCALA_HOME/Users/xunyongsun/Documents/scala-2.13.0 export PATH P A T H : PATH: PATH:SCALA_HOME/bin export SPARK_HOME/Users/xunyongsun/Documents/spark-3.5.4-bin…