RPC 源码解析~Apache Dubbo
解析 RPC(远程过程调用)的源码可以帮助你深入理解其工作原理和实现细节。为了更好地进行源码解析,我们选择一个流行的 RPC 框架——Apache Dubbo 作为示例。Dubbo 是一个高性能、轻量级的开源 Java RPC 框架,广泛应用于企业级应用中。
Dubbo的优劣势
优势
-
高性能:
- Dubbo 使用 Netty 作为底层通信框架,支持高并发场景下的高效通信。
- 支持多种序列化方式(如 Hessian2, Kryo, FST 等),可以根据需要选择最合适的序列化方案以提升性能。
-
丰富的功能:
- 提供多种负载均衡策略(如 RandomLoadBalance, RoundRobinLoadBalance 等)。
- 内置了服务降级、熔断和限流机制,增强了系统的健壮性。
- 支持多协议(如 Dubbo 协议, HTTP 协议等),灵活适应不同的应用场景。
-
良好的生态系统:
- 拥有成熟的社区支持和丰富的文档资源。
- 可与 Spring Boot 和 Spring Cloud 等主流框架无缝集成,简化开发流程。
-
细粒度控制:
- 提供详细的配置选项,允许开发者对每个服务进行精细化管理。
- 支持服务分组、版本控制等功能,便于维护和升级。
-
强大的监控能力:
- 内置了监控中心,可以实时查看服务的调用情况和性能指标。
- 支持与其他监控系统(如 Prometheus, Grafana)集成,实现全面的监控解决方案。
劣势
-
依赖复杂:
- Dubbo 依赖较多,引入时可能需要额外配置多个组件(如注册中心、序列化库等)。
- 学习曲线相对陡峭,初学者需要一定时间掌握其复杂的配置和使用方法。
-
扩展性有限:
- 尽管 Dubbo 提供了插件机制,但相对于一些现代微服务框架(如 Spring Cloud),其扩展性和灵活性稍显不足。
- 对于某些特定需求,可能需要自行开发插件或中间件来满足。
-
生态整合难度:
- 虽然可以与 Spring Boot 和 Spring Cloud 集成,但在某些高级特性上可能存在兼容性问题。
- 相比 Spring Cloud 生态更为丰富和成熟,Dubbo 的第三方组件和支持程度略逊一筹。
-
社区活跃度:
- 虽然 Dubbo 社区活跃,但由于近年来 Spring Cloud 的崛起,部分开发者更倾向于使用后者。
- 新的功能更新速度相对较慢,不如 Spring Cloud 快速迭代。
解析目标
我们将逐步解析 Dubbo 的核心组件和流程,包括但不限于以下部分:
- 服务注册与发现:如何将服务注册到注册中心,并从注册中心发现可用的服务。
- 代理机制:客户端和服务端如何通过动态代理来透明地进行远程调用。
- 序列化:数据在网络传输过程中如何被序列化和反序列化。
- 负载均衡:客户端如何根据不同的策略选择合适的服务提供者。
- 通信协议:底层网络通信是如何实现的,包括 Netty 等网络框架的应用。
准备工作
在开始解析之前,请确保你已经具备以下条件:
- Java 开发环境:安装 JDK 8 或更高版本。
- Git 工具:用于克隆 Dubbo 源码仓库。
- IDE:推荐使用 IntelliJ IDEA 或 Eclipse。
- Maven:用于构建和管理依赖。
克隆 Dubbo 源码
首先,克隆 Dubbo 的 GitHub 仓库到本地:
bash
git clone https://github.com/apache/dubbo.git
cd dubbo
构建 Dubbo 源码
使用 Maven 构建 Dubbo 源码:
bash
mvn clean install -DskipTests=true
核心组件解析
1. 服务注册与发现
Dubbo 使用 ZooKeeper 作为默认的注册中心。以下是服务注册和发现的核心流程。
服务注册
当服务提供者启动时,会将其元数据注册到注册中心。主要涉及 RegistryProtocol 和 ZookeeperRegistry 类。
- RegistryProtocol: 负责处理服务注册和订阅逻辑。
- ZookeeperRegistry: 实现了具体的注册中心操作,如连接 ZooKeeper 并执行注册。
关键代码位置:
dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/RegistryProtocol.javadubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistry.java
核心方法:
export(Invoker<T> invoker): 导出服务并注册到注册中心。doRegister(URL url): 执行实际的注册操作。
示例代码:
java
@Override
public <T> Exporter<T> export(final Invoker<T> originInvoker) throws RpcException {URL registryUrl = getRegistryUrl(originInvoker);// 创建注册器实例Registry registry = getRegistry(registryUrl);final URL providerUrl = getProviderUrl(originInvoker, registryUrl);// 向注册中心注册服务final URL registeredProviderUrl = getRegisteredProviderUrl(providerUrl, registryUrl);ProviderModel providerModel = new ProviderModel(providerUrl.getServiceKey(), originInvoker, providerUrl);ApplicationModel.registerProvider(providerModel);registry.register(registeredProviderUrl);// 订阅 override 数据registry.subscribe(getSubscribedOverrideUrl(providerUrl), event -> {if (logger.isDebugEnabled()) {logger.debug("Notify urls for subscribe url " + event.getUrl() + ", urls: " + event.getUrls());}Map<String, String> notifiedUrls = new HashMap<>();if (CollectionUtils.isNotEmpty(event.getUrls())) {event.getUrls().forEach(url -> notifiedUrls.put(url.getServiceKey(), url.toFullString()));}refreshOverrideAndInvoker(providerUrl, notifiedUrls);});exporterMapLock.lock();try {ExporterChangeableWrapper<T> exporter = new ExporterChangeableWrapper<>(originInvoker, null);exporters.put(originInvoker, exporter);return exporter;} finally {exporterMapLock.unlock();}
}
服务发现
当服务消费者启动时,会从注册中心订阅服务提供者的地址列表。主要涉及 RegistryProtocol 和 ZookeeperRegistry 类。
- RegistryProtocol: 处理订阅逻辑,并生成服务代理。
- ZookeeperRegistry: 监听注册中心的变化,并通知消费者。
关键代码位置:
dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/RegistryProtocol.javadubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistry.java
核心方法:
refer(Class<T> type, URL url): 引用远程服务并创建代理对象。doSubscribe(URL url, NotifyListener listener): 执行实际的订阅操作。
示例代码:
java
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {URL subscribeUrl = new URL(Constants.CONSUMER_PROTOCOL, mapLocalHost(url.getParameter(Constants.REGISTER_IP_KEY, NetUtils.getLocalHost())), 0,type.getName(), url.getParameters());// 设置检查是否延迟暴露if (!Constants.YES_VALUE.equals(url.getParameter(Constants.LAZY_CONNECT_KEY))) {checkWhetherMetadataCenterExist(subscribeUrl);List<URL> urls = registryCache.get(subscribeUrl);if (urls != null && !urls.isEmpty()) {// 如果存在直接返回StaticDirectory<T> directory = new StaticDirectory<>(subscribeUrl, toInvokers(urls));doRefer(subscribeUrl, directory);return cluster.join(directory);}}// 创建动态目录DynamicDirectory<T> directory = new DynamicDirectory<>(subscribeUrl, registry, directoryFactory, false);directory.buildRouterChain(subscribeUrl);directory.setConsumerUrl(subscribeUrl);directoryList.add(directory);registry.subscribe(subscribeUrl, new CacheListener(directory, url));// 创建集群Invoker<T> clusterInvoker = cluster.join(directory);providersModel.setClusterInvoker(clusterInvoker);return clusterInvoker;
}
2. 代理机制
Dubbo 使用动态代理来简化远程调用的过程。主要涉及 ProxyFactory 和 JavassistProxyFactory 类。
- ProxyFactory: 定义了代理工厂接口。
- JavassistProxyFactory: 实现了具体的代理创建逻辑。
关键代码位置:
dubbo-common/src/main/java/org/apache/dubbo/common/proxy/ProxyFactory.javadubbo-proxy/dubbo-proxy-javassist/src/main/java/org/apache/dubbo/common/proxy/javassist/JavassistProxyFactory.java
核心方法:
getProxy(Invoker<?> invoker): 获取服务代理对象。getInvoker(T proxy, Class<T> type, URL url): 将代理对象转换为 Invoker。
示例代码:
java
@Override
public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
}@Override
public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {// TODO Wrapper cannot handle this scenario at this moment.throw new UnsupportedOperationException("Not supported.");
}
3. 序列化
Dubbo 支持多种序列化方式,如 Hessian2, Kryo, FST 等。主要涉及 Serialization 和具体序列化类。
- Serialization: 定义了序列化接口。
- Hessian2Serialization: 实现了 Hessian2 序列化的具体逻辑。
关键代码位置:
dubbo-common/src/main/java/org/apache/dubbo/common/serialize/Serialization.javadubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2Serialization.java
核心方法:
serialize(URL url, OutputStream output): 返回序列化对象。deserialize(URL url, InputStream input): 返回反序列化对象。
示例代码:
java
@Override
public ObjectOutput serialize(URL url, OutputStream out) throws IOException {Hessian2ObjectOutputStream hessian2os = new Hessian2ObjectOutputStream(out);com.caucho.hessian.io.SerializerFactory serializerFactory = getSerializerFactory(url);if (serializerFactory != null) {hessian2os.setSerializerFactory(serializerFactory);}return new CompatibleObjectOutput(hessian2os);
}@Override
public ObjectInput deserialize(URL url, InputStream is) throws IOException {Hessian2ObjectInputStream hessian2is = new Hessian2ObjectInputStream(is);com.caucho.hessian.io.DeserializerFactory deserializerFactory = getDeserializerFactory(url);if (deserializerFactory != null) {hessian2is.setDeserializerFactory(deserializerFactory);}return new CompatibleObjectInput(hessian2is);
}
4. 负载均衡
Dubbo 提供多种负载均衡策略,如 RandomLoadBalance, RoundRobinLoadBalance 等。主要涉及 LoadBalance 和具体策略类。
- LoadBalance: 定义了负载均衡接口。
- RandomLoadBalance: 实现了随机负载均衡的具体逻辑。
关键代码位置:
dubbo-cluster/src/main/java/org/apache/dubbo/rpc/loadbalance/LoadBalance.javadubbo-cluster/src/main/java/org/apache/dubbo/rpc/loadbalance/RandomLoadBalance.java
核心方法:
select(List<Invoker<T>> invokers, URL url, Invocation invocation): 选择合适的 Invoker。
示例代码:
java
@Override
protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {int length = invokers.size(); // Number of providersint totalWeight = 0; // The sum of weightsboolean sameWeight = true; // Every provider has the same weight?for (int i = 0; i < length; i++) {int weight = getWeight(invokers.get(i), invocation);totalWeight += weight; // Sumif (sameWeight && i > 0 && weight != getWeight(invokers.get(i - 1), invocation)) {sameWeight = false;}}if (totalWeight > 0 && !sameWeight) {// If (not every provider has the same weight & at least one provider's weight>0), select randomly based on totalWeight.int offset = ThreadLocalRandom.current().nextInt(totalWeight);// Return a invoker based on the random value.for (int i = 0; i < length; i++) {Invoker<T> invoker = invokers.get(i);offset -= getWeight(invoker, invocation);if (offset < 0) {return invoker;}}}// If all providers have the same weight value or totalWeight=0, return evenly.return invokers.get(ThreadLocalRandom.current().nextInt(length));
}
5. 通信协议
Dubbo 支持多种通信协议,如 Dubbo 协议, HTTP 协议等。主要涉及 Transporter 和具体协议类。
- Transporter: 定义了通信接口。
- NettyTransporter: 实现了基于 Netty 的通信逻辑。
关键代码位置:
dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Transporter.javadubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyTransporter.java
核心方法:
bind(URL url, ChannelHandler handler): 绑定服务器端口。connect(URL url, ChannelHandler handler): 连接到服务器。
示例代码:
@Override
public Server bind(URL url, ChannelHandler handler) throws RemotingException {return new NettyServer(url, handler);
}@Override
public Client connect(URL url, ChannelHandler handler) throws RemotingException {return new NettyClient(url, wrapChannelHandler(url, handler));
}
示例项目
为了更好地理解上述解析内容,我们可以创建一个简单的 Dubbo 示例项目,包含服务提供者和消费者。
1. 创建服务接口
定义一个简单的服务接口:
UserApi.java:
java
package com.example.dubbo.service;public interface UserApi {String sayHello(String name);
}
2. 实现服务提供者
实现服务接口并启动服务提供者:
UserServiceImpl.java:
java
package com.example.dubbo.provider;import com.example.dubbo.service.UserApi;
import org.apache.dubbo.config.annotation.DubboService;@DubboService(version = "1.0.0")
public class UserServiceImpl implements UserApi {@Overridepublic String sayHello(String name) {return "Hello, " + name;}
}
ProviderApplication.java:
java
package com.example.dubbo.provider;import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
@EnableDubbo(scanBasePackages = "com.example.dubbo.provider")
public class ProviderApplication {public static void main(String[] args) {SpringApplication.run(ProviderApplication.class, args);}
}
application.properties:
# Dubbo Application Info
dubbo.application.name=user-provider
dubbo.registry.address=zookeeper://localhost:2181
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
3. 实现服务消费者
创建服务消费者并调用远程服务:
ConsumerApplication.java:
java
package com.example.dubbo.consumer;import com.example.dubbo.service.UserApi;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class ConsumerApplication implements CommandLineRunner {@DubboReference(version = "1.0.0")private UserApi userApi;public static void main(String[] args) {SpringApplication.run(ConsumerApplication.class, args);}@Overridepublic void run(String... args) throws Exception {String result = userApi.sayHello("World");System.out.println(result); // Output: Hello, World}
}
application.properties:
# Dubbo Application Info
dubbo.application.name=user-consumer
dubbo.registry.address=zookeeper://localhost:2181
运行示例
-
启动 ZooKeeper: 确保 ZooKeeper 服务正在运行。如果没有安装,可以从 ZooKeeper 官网 下载并按照官方文档进行安装和启动。
-
启动服务提供者
bash
cd provider
mvn spring-boot:run
3.启动服务消费者
bash
cd consumer
mvn spring-boot:run
总结
通过对 Dubbo 源码的解析,我们深入了解了 RPC 框架的关键组成部分和工作原理,包括服务注册与发现、代理机制、序列化、负载均衡和通信协议。此外,我们还创建了一个简单的示例项目,展示了如何使用 Dubbo 进行服务开发和部署。
相关文章:
RPC 源码解析~Apache Dubbo
解析 RPC(远程过程调用)的源码可以帮助你深入理解其工作原理和实现细节。为了更好地进行源码解析,我们选择一个流行的 RPC 框架——Apache Dubbo 作为示例。Dubbo 是一个高性能、轻量级的开源 Java RPC 框架,广泛应用于企业级应用…...
VS Code--常用的插件
原文网址:VS Code--常用的插件_IT利刃出鞘的博客-CSDN博客 简介 本文介绍VS Code(Visual Studio Code)常用的插件。 插件的配置 默认情况下,插件会放到这里:C:\Users\xxx\.vscode\extensions 修改插件位置的方法 …...
深度学习 Pytorch 张量的索引、分片、合并以及维度调整
张量作为有序的序列,也是具备数值索引的功能,并且基本索引方法和python原生的列表、numpy中的数组基本一致。 不同的是,pytorch中还定义了一种采用函数来进行索引的方式。 作为pytorch中的基本数据类型,张量既具备了列表、数组的基…...
神州数码--制作wifi
防火墙: #ip vrouter trust-vr#router ospf 1#router-id 8.8.8.8#network 10.0.0.0/30 area 0.0.0.0#network 10.0.0.4/30 area 0.0.0.0#network 10.0.0.8/30 area 0.0.0.0 交换机: #vlan 10;50#ip add 192.168.10.1 255.255.255.0#int vlan 50#ip add 192.168.50.…...
Web前端开发技术之HTMLCSS知识点总结
学习路线 一、新闻网界面1. 代码示例2. 效果展示3. 知识点总结3.1 HTML标签和字符实体3.2 超链接、颜色描述与标题元素3.3 关于图片和视频标签:3.4 CSS引入方式3.5 CSS选择器优先级 二、flex布局1. 代码示例2. 效果展示3. 知识点总结3.1 span标签和flex容器的区别3.…...
客户案例:致远OA与携程商旅集成方案
一、前言 本项目原型客户公司创建于1992年,主要生产并销售包括糖果系列、巧克力系列、烘焙系列、卤制品系列4大类,200多款产品。公司具有行业领先的生产能力,拥有各类生产线100条,年产能超过10万吨。同时,经过30年的发展,公司积累了完善的销售网络,核心经销商已经超过1200个,超…...
【常见BUG】Spring Boot 和 Springfox(Swagger)版本兼容问题
???欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老…...
【Python】FastAPI入门
文章目录 第一节:FastAPI入门一、FastAPI框架介绍什么是ASGI服务(WSGI)1、补充Web开发1)Web前端开发2)Web后端开发 二、FastAPI安装1、安装Python虚拟环境2、安装FastAPI 三、第一个FastAPI案例1、访问接口和文档2、接…...
JavaScript系列(32)-- WebAssembly集成详解
JavaScript WebAssembly集成详解 🚀 今天,让我们深入了解JavaScript与WebAssembly的集成,这是一项能够显著提升Web应用性能的关键技术。 WebAssembly基础概念 🌟 💡 小知识:WebAssembly(简称W…...
wps数据分析000002
目录 一、快速定位技巧 二、快速选中技巧 全选 选中部分区域 选中部分区域(升级版) 三、快速移动技巧 四、快速录入技巧 五、总结 一、快速定位技巧 ctrl→(上下左右)快速定位光标对准单元格的上下部分双击名称单元格中…...
无降智o1 pro——一次特别的ChatGPT专业模式探索
这段时间和朋友们交流 ChatGPT 的使用心得,大家都提到一个很“神秘”的服务:它基于 O1 Pro 模型,能够在对话里一直保持相对高水平的理解和回复,不会突然变得“降智”。同时,整体使用还做了免折腾的网络设置——简单一点…...
前端:前端开发任务分解 / 开发清单
一、背景 前端开发过程中,好多任务同时开发,或者一个大的任务分解为若干个子任务进行开发,分解出去的很多内容容易记不清楚 / 不易过程管理,所以记录表格如下,方便开发同事,也辅助掌握整体开发情况。 二、…...
【Django自学】Django入门:如何使用django开发一个web项目(非常详细)
测试机器:windows11 x64 python版本:3.11 一、安装Django 安装步骤非常简单,使用pip安装就行 pip install django安装完成之后,python的 Scripts 文件夹下,会多一个 django-admin.exe (管理创建django项目的工具)。…...
面试经验分享-回忆版某小公司
说说你项目中数据仓库是怎么分层的,为什么要分层? 首先是ODS层,连接数据源和数据仓库,数据会进行简单的ETL操作,数据来源通常是业务数据库,用户日志文件或者来自消息队列的数据等 中间是核心的数据仓库层&a…...
WebSocket——推送方案选型
一、前言:为何需要服务端主动推送? 在现代应用中,很多功能都依赖于“消息推送”。比如: 小红点提醒:我们经常在手机应用里看到的一个小红点提示,表示有新的消息或任务需要我们关注。新消息提醒࿱…...
山石防火墙命令行配置示例
现网1台山石SG6000防火墙,配置都可以通过GUI实现。 但有一些配置在命令行下配置效率更高,比如在1个已有策略中添加1个host或端口。 下面的双引号可以不加 1 创建服务 1.1 单个端口 service "tcp-901"tcp dst-port 901 1.2 端口范围 servi…...
LLM - 大模型 ScallingLaws 的 C=6ND 公式推导 教程(1)
欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/145185794 Scaling Laws (缩放法则) 是大模型领域中,用于描述 模型性能(Loss) 与 模型规模N、数据量D、计算资源C 之间关系的经验规律…...
Leetcode 983. 最低票价 动态规划
原题链接:Leetcode 983. 最低票价 class Solution { public:int mincostTickets(vector<int>& days, vector<int>& costs) {int n days.size();int last days[n - 1];int dp[last 1];map<int, int> mp;for (auto x : days)mp[x] 1;dp…...
Kafka——两种集群搭建详解 k8s
1、简介 Kafka是一个能够支持高并发以及流式消息处理的消息中间件,并且Kafka天生就是支持集群的,今天就主要来介绍一下如何搭建Kafka集群。 Kafka目前支持使用Zookeeper模式搭建集群以及KRaft模式(即无Zookeeper)模式这两种模式搭…...
springboot使用websocket
文章目录 一、概述1、简介 二、 使用1、引包2、配置处理器3、前端测试 一、概述 1、简介 简介略,附上官方文档,spring5和spring6的官方文档内容大致是一样的: https://docs.spring.io/spring-framework/docs/5.2.25.RELEASE/spring-framewo…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...
wpf在image控件上快速显示内存图像
wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像(比如分辨率3000*3000的图像)的办法,尤其是想把内存中的裸数据(只有图像的数据,不包…...
GraphRAG优化新思路-开源的ROGRAG框架
目前的如微软开源的GraphRAG的工作流程都较为复杂,难以孤立地评估各个组件的贡献,传统的检索方法在处理复杂推理任务时可能不够有效,特别是在需要理解实体间关系或多跳知识的情况下。先说结论,看完后感觉这个框架性能上不会比Grap…...
