Dubbo异步调用与主线程同步完全指南:告别阻塞,掌控并发

揭秘Dubbo如何在高并发异步世界中实现精准的同步控制

文章目录

    • 引言:异步时代的同步难题
    • [一、为什么需要异步调用与主线程同步? 🤔](#一、为什么需要异步调用与主线程同步? 🤔)
      • [1.1 同步调用的性能瓶颈](#1.1 同步调用的性能瓶颈)
      • [1.2 异步调用的优势与挑战](#1.2 异步调用的优势与挑战)
      • [1.3 Dubbo的异步调用模型](#1.3 Dubbo的异步调用模型)
    • [二、Dubbo异步调用同步机制全景图 🗺️](#二、Dubbo异步调用同步机制全景图 🗺️)
      • [2.1 同步 vs 异步 vs 单向调用](#2.1 同步 vs 异步 vs 单向调用)
      • [2.2 Dubbo中的线程模型与派发策略](#2.2 Dubbo中的线程模型与派发策略)
    • [三、实战:五种同步机制详解与代码示例 💻](#三、实战:五种同步机制详解与代码示例 💻)
      • [3.1 方式一:基于RpcContext和Future的阻塞等待](#3.1 方式一:基于RpcContext和Future的阻塞等待)
        • [3.1.1 配置异步调用](#3.1.1 配置异步调用)
        • [3.1.2 调用与同步等待](#3.1.2 调用与同步等待)
      • [3.2 方式二:基于RpcContext.asyncCall的链式调用](#3.2 方式二:基于RpcContext.asyncCall的链式调用)
      • [3.3 方式三:基于CompletableFuture签名的接口](#3.3 方式三:基于CompletableFuture签名的接口)
        • [3.3.1 服务提供者实现](#3.3.1 服务提供者实现)
        • [3.3.2 服务消费者调用](#3.3.2 服务消费者调用)
      • [3.4 方式四:基于AsyncContext的服务端异步](#3.4 方式四:基于AsyncContext的服务端异步)
      • [3.5 方式五:基于事件通知的异步回调](#3.5 方式五:基于事件通知的异步回调)
        • [3.5.1 配置事件通知](#3.5.1 配置事件通知)
        • [3.5.2 实现通知回调](#3.5.2 实现通知回调)
    • [四、底层原理:DefaultFuture的等待-通知机制 ⚙️](#四、底层原理:DefaultFuture的等待-通知机制 ⚙️)
      • [4.1 DefaultFuture的核心结构](#4.1 DefaultFuture的核心结构)
      • [4.2 异步调用流程](#4.2 异步调用流程)
      • [4.3 同步与异步的线程协作](#4.3 同步与异步的线程协作)
    • [五、最佳实践与性能优化建议 🏆](#五、最佳实践与性能优化建议 🏆)
    • [六、总结 📚](#六、总结 📚)
      • [6.1 核心要点回顾](#6.1 核心要点回顾)
      • [6.2 架构思考](#6.2 架构思考)
      • [6.3 未来展望](#6.3 未来展望)
    • [参考资料 📖](#参考资料 📖)

引言:异步时代的同步难题

在微服务架构中,性能响应性往往是一对矛盾体。想象一下,你的电商系统在"双十一"需要同时处理用户订单、库存扣减、支付请求和物流通知------如果所有调用都同步等待,用户可能需要盯着加载动画长达数秒!

这就是异步调用 的价值所在:它让主线程不会被远程调用的网络延迟所阻塞,可以继续处理其他任务。但异步也带来了新挑战:如何优雅地等待异步结果?如何在需要时让主线程与异步任务同步?

Dubbo提供了多种机制来解决这一难题,从简单的Future.get()阻塞等待,到基于CompletableFuture的回调通知,再到RpcContext的异步控制,让你既能享受异步的高性能,又能保持同步的简洁逻辑。

一、为什么需要异步调用与主线程同步? 🤔

1.1 同步调用的性能瓶颈

在传统的同步RPC调用中,整个调用链路是"线性阻塞"的:

java 复制代码
// 传统的同步调用 - 线程全程阻塞
public OrderResult createOrder(OrderRequest request) {
    // 1. 验证用户身份(调用用户服务)- 线程阻塞等待
    User user = userService.getUser(request.getUserId());
    
    // 2. 检查库存(调用库存服务)- 线程再次阻塞等待
    Stock stock = stockService.checkStock(request.getProductId());
    
    // 3. 创建订单(本地操作)
    Order order = buildOrder(request, user, stock);
    
    // 4. 调用支付服务 - 线程又一次阻塞等待
    PaymentResult payment = paymentService.pay(order);
    
    // 总耗时 = 所有远程调用耗时之和
    return buildOrderResult(order, payment);
}

这种模式的问题很明显:

  • 资源浪费:线程在等待网络响应时什么也做不了
  • 响应延迟:总耗时是所有远程服务调用的耗时累加
  • 吞吐量限制:并发请求数受限于线程池大小

1.2 异步调用的优势与挑战

异步调用将"请求发出"与"结果处理"解耦:

java 复制代码
// 异步调用 - 并行发起请求
public CompletableFuture<OrderResult> createOrderAsync(OrderRequest request) {
    // 并行发起所有远程调用
    CompletableFuture<User> userFuture = userService.getUserAsync(request.getUserId());
    CompletableFuture<Stock> stockFuture = stockService.checkStockAsync(request.getProductId());
    
    // 异步组合结果
    return userFuture.thenCombine(stockFuture, (user, stock) -> {
        Order order = buildOrder(request, user, stock);
        return paymentService.payAsync(order)
            .thenApply(payment -> buildOrderResult(order, payment));
    }).thenCompose(Function.identity());
}

优势

  • 并行处理:多个远程调用同时进行
  • 资源高效:线程在等待时可处理其他任务
  • 响应更快:总耗时约等于最慢的远程调用

挑战

  • 代码复杂度:回调地狱(Callback Hell)
  • 结果同步:如何等待所有异步任务完成?
  • 异常处理:异步场景下的错误传播

1.3 Dubbo的异步调用模型

Dubbo的异步调用基于事件驱动架构,涉及多种线程协作:

  • Biz~线程:业务逻辑线程(如Tomcat的HTTP线程)
  • IO~线程:网络I/O线程(Netty的EventLoop)
  • 业务线程池:处理实际业务逻辑的线程池

一次完整的RPC调用涉及4次线程切换:

  1. 客户端业务线程 → IO线程(请求发出)
  2. 服务端IO线程 → 业务线程(请求处理)
  3. 服务端业务线程 → IO线程(响应写出)
  4. 客户端IO线程 → 业务线程(响应处理)

理解这一点至关重要 :Dubbo的"同步"API实际上是在异步基础上,通过DefaultFuture的等待-通知机制实现的。

二、Dubbo异步调用同步机制全景图 🗺️

Dubbo提供了多层次、多维度的同步控制机制,可以满足不同场景的需求。

2.1 同步 vs 异步 vs 单向调用

为了清晰地对比Dubbo中几种调用方式的特点与适用场景,以下是详细的对比分析:

同步调用 (Synchronous)

  • 控制参数isAsync=false (默认)
  • 线程行为:调用线程阻塞等待结果返回
  • 返回值:直接返回业务结果
  • 适用场景:需要立即结果的场景、简单逻辑、高性能服务
  • 性能影响:线程资源占用高,吞吐量相对较低

异步调用有返回值 (Async with Callback)

  • 控制参数isAsync=true
  • 线程行为 :立即返回FutureCompletableFuture,结果后续获取
  • 返回值 :返回Future/CompletableFuture
  • 适用场景:并行调用多个服务、不立即需要结果的场景
  • 性能影响:线程利用率高,吞吐量更高

异步调用无返回值 (Oneway)

  • 控制参数isOneway=true
  • 线程行为:立即返回,不关心结果
  • 返回值null或空结果
  • 适用场景:日志记录、审计跟踪、通知类操作
  • 性能影响:性能最好,但无法保证可靠性

2.2 Dubbo中的线程模型与派发策略

理解Dubbo的线程模型对掌握异步同步至关重要:

派发策略 (Dispatcher)

  • all:所有消息都派发到线程池
  • direct:所有消息都在IO线程直接执行
  • message:只有请求/响应消息派发到线程池
  • execution:只有请求消息派发到线程池
  • connection:连接事件放入队列顺序执行

线程池类型 (ThreadPool)

  • fixed:固定大小线程池(默认)
  • cached:缓存线程池,空闲回收
  • limited:可增长但不会收缩的线程池
  • eager:优先创建Worker线程的线程池

正确的线程模型配置可以显著影响异步调用的性能表现。

三、实战:五种同步机制详解与代码示例 💻

3.1 方式一:基于RpcContext和Future的阻塞等待

这是Dubbo最经典的异步转同步方式,适用于Dubbo 2.6.x及以上版本。

3.1.1 配置异步调用

XML配置方式

xml 复制代码
<dubbo:reference id="userService" interface="com.example.UserService">
    <dubbo:method name="getUserById" async="true" />
</dubbo:reference>

注解配置方式

java 复制代码
@Reference(interfaceClass = UserService.class,
           methods = @Method(name = "getUserById", async = true))
private UserService userService;
3.1.2 调用与同步等待
java 复制代码
public class OrderService {
    
    @Reference(interfaceClass = UserService.class,
               methods = @Method(name = "getUserById", async = true))
    private UserService userService;
    
    /**
     * 方式1:使用Future.get()阻塞等待
     */
    public User getUserWithBlockingWait(Long userId) throws Exception {
        // 异步调用,立即返回null
        User immediateResult = userService.getUserById(userId);
        System.out.println("立即返回: " + immediateResult); // null
        
        // 获取Future对象
        Future<User> future = RpcContext.getContext().getFuture();
        
        // 主线程可以继续处理其他任务
        doOtherWork();
        
        // 当需要结果时,阻塞等待
        User user = future.get(3000, TimeUnit.MILLISECONDS); // 超时3秒
        
        return user;
    }
    
    /**
     * 方式2:使用CompletableFuture(推荐)
     */
    public CompletableFuture<User> getUserWithCompletableFuture(Long userId) {
        // 异步调用
        userService.getUserById(userId);
        
        // 获取CompletableFuture
        CompletableFuture<User> future = RpcContext.getContext().getCompletableFuture();
        
        return future;
    }
    
    private void doOtherWork() {
        System.out.println("主线程处理其他任务...");
        // 模拟其他工作
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

3.2 方式二:基于RpcContext.asyncCall的链式调用

Dubbo 2.7.0+引入了更简洁的异步调用API。

java 复制代码
public class OrderService {
    
    @Reference
    private UserService userService;
    
    @Reference
    private ProductService productService;
    
    /**
     * 使用asyncCall进行异步调用
     */
    public CompletableFuture<Order> createOrderAsync(Long userId, Long productId) {
        // 同时发起多个异步调用
        CompletableFuture<User> userFuture = RpcContext.getContext()
            .asyncCall(() -> userService.getUserById(userId));
            
        CompletableFuture<Product> productFuture = RpcContext.getContext()
            .asyncCall(() -> productService.getProductById(productId));
        
        // 异步组合结果
        return userFuture.thenCombine(productFuture, (user, product) -> {
            // 当两个调用都完成后,执行创建订单逻辑
            return createOrder(user, product);
        });
    }
    
    /**
     * 单向调用(不关心结果)
     */
    public void logUserAction(Long userId, String action) {
        RpcContext.getContext().asyncCall(() -> {
            // 记录用户行为日志,不需要等待结果
            userService.logAction(userId, action);
            return null;
        });
        
        // 立即继续执行,不等待日志记录完成
        System.out.println("用户行为日志已异步记录");
    }
    
    private Order createOrder(User user, Product product) {
        // 创建订单逻辑
        return new Order(user, product);
    }
}

3.3 方式三:基于CompletableFuture签名的接口

这是最优雅的异步编程方式,需要服务提供者和消费者共同配合。

3.3.1 服务提供者实现
java 复制代码
public interface UserService {
    /**
     * 基于CompletableFuture签名的异步接口
     */
    CompletableFuture<User> getUserById(Long userId);
}

@Service
public class UserServiceImpl implements UserService {
    
    @Override
    public CompletableFuture<User> getUserById(Long userId) {
        // 使用自定义线程池,避免占用Dubbo线程池
        return CompletableFuture.supplyAsync(() -> {
            // 模拟耗时操作
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            // 查询数据库获取用户信息
            User user = userRepository.findById(userId);
            
            // 可以在这里处理上下文信息
            RpcContext savedContext = RpcContext.getContext();
            String consumerKey = savedContext.getAttachment("consumer-key1");
            System.out.println("获取到消费者传递的参数: " + consumerKey);
            
            return user;
        }, customExecutor); // 使用自定义线程池
    }
}
3.3.2 服务消费者调用
java 复制代码
public class OrderService {
    
    @Reference
    private UserService userService;
    
    /**
     * 直接使用CompletableFuture,无需RpcContext
     */
    public void processUserOrder(Long userId) {
        // 异步调用,立即返回CompletableFuture
        CompletableFuture<User> userFuture = userService.getUserById(userId);
        
        // 非阻塞回调
        userFuture.whenComplete((user, exception) -> {
            if (exception != null) {
                // 异常处理
                System.err.println("获取用户失败: " + exception.getMessage());
            } else {
                // 成功处理
                System.out.println("获取到用户: " + user.getName());
                createOrderForUser(user);
            }
        });
        
        // 主线程继续执行
        System.out.println("已发起用户查询请求,继续处理其他逻辑...");
    }
    
    /**
     * 需要同步等待的场景
     */
    public User getUserSync(Long userId) throws Exception {
        CompletableFuture<User> future = userService.getUserById(userId);
        
        // 方法1:阻塞等待(简单但会阻塞线程)
        // return future.get(2000, TimeUnit.MILLISECONDS);
        
        // 方法2:轮询检查(非阻塞)
        while (!future.isDone()) {
            // 处理其他任务
            doOtherWork();
            
            // 检查是否完成(非阻塞)
            if (future.isDone()) {
                break;
            }
            
            // 短暂等待避免CPU忙等
            Thread.sleep(10);
        }
        
        return future.get(); // 此时已完成,立即返回
    }
    
    private void createOrderForUser(User user) {
        // 创建订单逻辑
    }
}

3.4 方式四:基于AsyncContext的服务端异步

对于服务提供者,如果接口没有使用CompletableFuture签名,可以使用AsyncContext实现异步处理。

java 复制代码
public class UserServiceImpl implements UserService {
    
    @Override
    public String getUserInfo(Long userId) {
        // 启动异步上下文
        final AsyncContext asyncContext = RpcContext.startAsync();
        
        // 在新线程中处理耗时操作
        new Thread(() -> {
            // 必须首先执行,才能使用RPC上下文
            asyncContext.signalContextSwitch();
            
            try {
                // 模拟耗时操作
                Thread.sleep(1000);
                
                // 查询数据库
                User user = userRepository.findById(userId);
                
                // 异步写回响应
                asyncContext.write("User: " + user.getName() + ", Email: " + user.getEmail());
                
            } catch (Exception e) {
                // 异常处理
                asyncContext.write("Error: " + e.getMessage());
            }
        }).start();
        
        // 立即返回null,响应将通过asyncContext.write异步返回
        return null;
    }
}

3.5 方式五:基于事件通知的异步回调

Dubbo提供了事件通知机制,可以在调用前、正常返回后或异常时触发回调。

3.5.1 配置事件通知
xml 复制代码
<bean id="userNotify" class="com.example.UserNotify" />

<dubbo:reference id="userService" interface="com.example.UserService">
    <dubbo:method name="getUserById" 
                  onreturn="userNotify.onreturn"
                  onthrow="userNotify.onthrow" />
</dubbo:reference>
3.5.2 实现通知回调
java 复制代码
public class UserNotify {
    
    private Map<Long, User> userCache = new ConcurrentHashMap<>();
    
    /**
     * 正常返回回调
     * 参数规则:第一个参数为返回值,其余为调用参数
     */
    public void onreturn(User user, Long userId) {
        System.out.println("异步回调:获取到用户 " + user.getName());
        
        // 缓存用户信息
        userCache.put(userId, user);
        
        // 触发后续处理
        processUserData(user);
    }
    
    /**
     * 异常回调
     * 参数规则:第一个参数为异常,其余为调用参数
     */
    public void onthrow(Throwable ex, Long userId) {
        System.err.println("异步调用异常,用户ID: " + userId + ", 错误: " + ex.getMessage());
        
        // 异常处理,如降级策略
        User fallbackUser = getFallbackUser(userId);
        userCache.put(userId, fallbackUser);
    }
    
    private void processUserData(User user) {
        // 处理用户数据
    }
    
    private User getFallbackUser(Long userId) {
        // 返回降级数据
        User user = new User();
        user.setId(userId);
        user.setName("默认用户");
        return user;
    }
}

四、底层原理:DefaultFuture的等待-通知机制 ⚙️

理解Dubbo异步转同步的底层实现,有助于更好地使用和调试。

4.1 DefaultFuture的核心结构

DefaultFuture是Dubbo实现异步转同步的核心类:

java 复制代码
public class DefaultFuture implements ResponseFuture {
    
    // 同步控制
    private final Lock lock = new ReentrantLock();
    private final Condition done = lock.newCondition();
    
    // 响应结果
    private volatile Response response;
    
    // 回调函数
    private volatile Callback callback;
    
    // 存储所有未完成的Future
    private static final Map<Long, DefaultFuture> FUTURES = new ConcurrentHashMap<>();
    
    /**
     * 阻塞等待结果
     */
    @Override
    public Object get(int timeout) throws RemotingException {
        if (timeout <= 0) {
            timeout = Constants.DEFAULT_TIMEOUT;
        }
        
        // 如果尚未完成
        if (!isDone()) {
            long start = System.currentTimeMillis();
            lock.lock();
            try {
                // 循环等待,避免虚假唤醒
                while (!isDone()) {
                    done.await(timeout, TimeUnit.MILLISECONDS);
                    
                    // 检查是否完成或超时
                    if (isDone() || System.currentTimeMillis() - start > timeout) {
                        break;
                    }
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                lock.unlock();
            }
        }
        
        // 超时检查
        if (!isDone()) {
            throw new TimeoutException(/* 超时信息 */);
        }
        
        // 返回响应结果
        return returnFromResponse();
    }
    
    /**
     * 接收响应时被调用
     */
    private void doReceived(Response res) {
        lock.lock();
        try {
            // 设置响应
            response = res;
            
            // 唤醒等待的线程
            if (done != null) {
                done.signalAll();
            }
        } finally {
            lock.unlock();
        }
        
        // 如果有回调函数,执行回调
        if (callback != null) {
            invokeCallback(callback);
        }
    }
}

4.2 异步调用流程

以下是Dubbo异步调用与同步等待的完整流程图:

4.3 同步与异步的线程协作

理解不同调用模式下的线程协作非常重要:

同步调用线程协作

  • 主线程调用future.get()进入阻塞
  • IO线程收到响应后调用doReceived()
  • doReceived()唤醒主线程
  • 主线程从get()方法返回

异步回调线程协作

  • 主线程发起调用后立即返回
  • IO线程收到响应后调用回调函数
  • 回调在IO线程或指定线程池执行

五、最佳实践与性能优化建议 🏆

5.1 同步机制选型指南

根据不同的业务场景,选择合适的同步机制:

简单阻塞等待场景

  • 推荐机制Future.get()CompletableFuture.get()
  • 适用情况:逻辑简单、需要立即结果、调用链短
  • 优点:编程简单、直观
  • 缺点:线程阻塞、资源利用率低

复杂异步编排场景

  • 推荐机制CompletableFuture组合操作
  • 适用情况:多个异步调用并行、结果需要组合处理
  • 优点:高效利用资源、代码表达力强
  • 缺点:学习曲线较陡、调试困难

事件驱动场景

  • 推荐机制:事件通知回调
  • 适用情况:结果处理与调用分离、需要事件触发
  • 优点:解耦彻底、扩展性好
  • 缺点:流程跟踪困难、异常处理复杂

高吞吐量场景

  • 推荐机制 :服务端AsyncContextCompletableFuture签名
  • 适用情况:服务端处理耗时、需要释放Dubbo线程
  • 优点:避免线程池阻塞、提高吞吐量
  • 缺点:实现稍复杂、需要线程池管理

5.2 性能优化配置建议

yaml 复制代码
# application.yml 优化配置示例
dubbo:
  protocol:
    name: dubbo
    # 线程池配置
    dispatcher: message  # 根据场景选择
    threadpool: fixed
    threads: 200         # 根据实际情况调整
    queues: 0           # 队列大小,0表示无界
    
  consumer:
    # 异步调用配置
    async: false        # 默认同步,需要时再开启异步
    
  provider:
    # 服务端线程配置
    threads: 500        # 服务端线程数
    
  # 全局超时配置
  reference:
    timeout: 3000       # 默认3秒超时
    retries: 2          # 重试次数

5.3 常见问题与解决方案

问题1:Future.get()导致线程长时间阻塞

现象:应用线程池耗尽,请求排队

解决方案

java 复制代码
// 设置合理的超时时间
future.get(2000, TimeUnit.MILLISECONDS);

// 或者使用带超时的CompletableFuture操作
completableFuture
    .completeOnTimeout(defaultValue, 2000, TimeUnit.MILLISECONDS)
    .thenAccept(result -> processResult(result));
问题2:回调函数中执行阻塞操作

现象:IO线程被阻塞,影响网络处理能力

解决方案

java 复制代码
// 错误:在回调中执行阻塞操作
future.thenAccept(result -> {
    // 阻塞的数据库查询
    UserDetail detail = userDao.getDetail(result.getId()); 
});

// 正确:将阻塞操作提交到线程池
future.thenAcceptAsync(result -> {
    UserDetail detail = userDao.getDetail(result.getId());
}, executorService); // 指定线程池
问题3:异步调用异常丢失

现象:异步调用失败但主线程不知道

解决方案

java 复制代码
CompletableFuture<User> future = userService.getUserById(userId);

// 总是处理异常情况
future.exceptionally(throwable -> {
    log.error("获取用户失败: {}", userId, throwable);
    return getFallbackUser(userId); // 提供降级数据
}).thenAccept(user -> {
    // 正常处理
    processUser(user);
});
问题4:上下文信息丢失

现象:异步线程中获取不到RPC上下文

解决方案

java 复制代码
// 保存上下文
RpcContext savedContext = RpcContext.getContext().copy();

CompletableFuture.supplyAsync(() -> {
    // 恢复上下文
    RpcContext.restoreContext(savedContext);
    
    // 现在可以访问上下文信息
    String attachment = RpcContext.getContext().getAttachment("key");
    
    // 业务逻辑
    return processData();
});

六、总结 📚

通过本文的全面探讨,我们深入理解了Dubbo异步调用与主线程同步的多种机制:

6.1 核心要点回顾

五大同步机制Future.get()阻塞、CompletableFuture回调、RpcContext控制、AsyncContext服务端异步、事件通知

底层原理DefaultFuture的等待-通知机制,基于条件变量的线程协作

配置方式 :XML配置、注解配置、API编程多种方式

性能优化 :合理的线程模型配置、超时设置、异常处理

适用场景:不同业务场景下的同步机制选型指南

6.2 架构思考

异步调用与同步等待不是对立关系,而是互补协作的关系:

异步是手段,同步是需求。Dubbo通过灵活的同步控制机制,让我们能够根据业务需求,在"完全异步"和"完全同步"之间找到最佳的平衡点。

真正的架构艺术在于:

  • 识别阻塞点:找出真正需要同步等待的关键路径
  • 合理并行化:将无依赖的调用并行执行
  • 优雅降级:在超时或失败时有备选方案
  • 资源控制:避免过度并发导致系统过载

6.3 未来展望

随着响应式编程和协程技术的发展,Dubbo的异步编程模型也在不断演进:

  • 响应式集成:更好的Reactive Streams支持
  • 协程支持:基于Project Loom的轻量级线程
  • 更智能的流量控制:基于响应时间的自适应并发控制

无论技术如何发展,理解业务需求、合理使用异步同步机制、保证系统稳定可靠的原则永远不会过时。


参考资料 📖

  1. Apache Dubbo官方文档 - 异步执行
  2. Dubbo客户端异步接口的实现背景和实践
  3. Dubbo源码解析---网络调用
  4. Dubbo线程模型

架构师建议:异步调用是一把双刃剑,用好了可以大幅提升系统性能,用不好会导致复杂度剧增和难以调试。建议从简单场景开始,逐步引入异步模式,并建立完善的监控和调试机制。记住:"先确保正确性,再优化性能"。


标签 : Dubbo 异步调用 同步等待 CompletableFuture RpcContext 线程模型 性能优化

相关推荐
2***b8843 分钟前
【语义分割】12个主流算法架构介绍、数据集推荐、总结、挑战和未来发展
算法·架构
小坏讲微服务1 小时前
K8S 部署 Spring Cloud Alibaba 微服务企业实战完整使用
spring cloud·docker·微服务·云原生·容器·kubernetes·k8s
java水泥工1 小时前
基于Echarts+HTML5可视化数据大屏展示-监管系统
前端·echarts·html5·可视化大屏·大屏展示
灵犀坠1 小时前
前端高频知识点汇总:从手写实现到工程化实践(面试&开发双视角)
开发语言·前端·javascript·tcp/ip·http·面试·职场和发展
yihuiComeOn1 小时前
【大数据高并发核心场景实战】 - 设计秒杀架构必知必会的那些事
java·后端·微服务·架构
Q_Q5110082851 小时前
python+django/flask+vue基于web的产品管理系统
前端·spring boot·python·django·flask·node.js
无奈何杨1 小时前
业务如何对接风控决策,实时/异步,结果同步
前端·后端
mobº1 小时前
K8s 集群部署微服务 - DevOps(一)
微服务·kubernetes·devops
axihaihai1 小时前
jenkins下微服务的cicd流程
运维·微服务·jenkins