中国电网Java面试被问:Dubbo的服务目录和路由链实现

一、服务目录(Directory)核心设计

1.服务目录的核心作用

图表

代码

复制

下载

全屏

graph TB A[服务消费者] --> B[服务目录Directory] B --> C[RegistryDirectory] B --> D[StaticDirectory] C --> E[服务发现] C --> F[配置变更监听] C --> G[Invoker列表维护]

2.RegistryDirectory核心实现

java

复制

下载

public class RegistryDirectory<T> extends AbstractDirectory<T> implements NotifyListener { // 核心数据结构 private final Map<String, Invoker<T>> urlInvokerMap = new ConcurrentHashMap<>(); private final Map<String, List<Invoker<T>>> methodInvokerMap = new ConcurrentHashMap<>(); // 服务发现与注册中心 private Registry registry; private URL consumerUrl; /** * 订阅服务变更通知 */ @Override public synchronized void notify(List<URL> urls) { // 1. 服务提供者URL分类 Map<String, List<URL>> categoryUrls = urls.stream() .filter(UrlUtils::isMatch) .collect(Collectors.groupingBy(url -> { if (UrlUtils.isConfigurator(url)) { return CONFIGURATORS_CATEGORY; } else if (UrlUtils.isRoute(url)) { return ROUTERS_CATEGORY; } else if (UrlUtils.isProvider(url)) { return PROVIDERS_CATEGORY; } return ""; })); // 2. 处理配置URL List<URL> configuratorUrls = categoryUrls.getOrDefault(CONFIGURATORS_CATEGORY, Collections.emptyList()); this.configurators = Configurator.toConfigurators(configuratorUrls); // 3. 处理路由URL List<URL> routerUrls = categoryUrls.getOrDefault(ROUTERS_CATEGORY, Collections.emptyList()); toRouters(routerUrls).ifPresent(this::addRouters); // 4. 处理服务提供者URL List<URL> providerUrls = categoryUrls.getOrDefault(PROVIDERS_CATEGORY, Collections.emptyList()); refreshOverrideAndInvoker(providerUrls); } /** * 刷新Invoker列表 */ private void refreshOverrideAndInvoker(List<URL> urls) { // 1. 覆盖配置处理 overrideDirectoryUrl(); // 2. 转换为Invoker Map<String, Invoker<T>> newUrlInvokerMap = toInvokers(urls); // 3. 状态转换 if (newUrlInvokerMap == null || newUrlInvokerMap.isEmpty()) { // 服务不可用 destroyAllInvokers(); } else { // 更新Invoker映射 this.urlInvokerMap = newUrlInvokerMap; // 4. 构建方法级Invoker映射 Map<String, List<Invoker<T>>> newMethodInvokerMap = toMethodInvokers(newUrlInvokerMap); // 5. 合并多组Invoker this.methodInvokerMap = multiGroup ? toMergeInvokerList(newMethodInvokerMap) : newMethodInvokerMap; // 6. 销毁无用Invoker destroyUnusedInvokers(newUrlInvokerMap); } } /** * URL转Invoker */ private Map<String, Invoker<T>> toInvokers(List<URL> urls) { Map<String, Invoker<T>> newUrlInvokerMap = new HashMap<>(); if (urls == null || urls.isEmpty()) { return newUrlInvokerMap; } Set<String> keys = new HashSet<>(); for (URL url : urls) { // 应用配置规则 URL configuredUrl = getConfiguredInvokerUrl(url); // 生成key: protocol://host:port/path?version String key = configuredUrl.toFullString(); if (keys.contains(key)) { continue; // 去重 } keys.add(key); // 缓存中获取或创建Invoker Invoker<T> invoker = invokersCache.get(key); if (invoker == null) { // 创建新的Invoker invoker = protocol.refer(serviceType, configuredUrl); invokersCache.put(key, invoker); } newUrlInvokerMap.put(key, invoker); } keys.clear(); return newUrlInvokerMap; } }

3.服务目录的核心功能

3.1 服务发现与注册

java

复制

下载

public class RegistryDirectory<T> extends AbstractDirectory<T> { // 订阅服务 public void subscribe(URL url) { this.consumerUrl = url; // 注册消费者 registry.register(consumerUrl); // 订阅服务提供者 registry.subscribe(url, this); } // 取消订阅 public void unsubscribe(URL url) { registry.unsubscribe(url, this); destroyAllInvokers(); } }
3.2 动态配置更新

java

复制

下载

public class RegistryDirectory<T> extends AbstractDirectory<T> { // 配置变更监听 private void refreshInvoker(List<URL> invokerUrls) { if (invokerUrls != null && invokerUrls.size() == 1 && invokerUrls.get(0) != null && Constants.EMPTY_PROTOCOL.equals(invokerUrls.get(0).getProtocol())) { // 服务提供者下线 this.forbidden = true; this.methodInvokerMap = null; destroyAllInvokers(); } else { this.forbidden = false; Map<String, Invoker<T>> localUrlInvokerMap = this.urlInvokerMap; // 对比新旧URL,增量更新 Map<String, Invoker<T>> newUrlInvokerMap = toInvokers(invokerUrls); // 找出需要销毁的Invoker List<Invoker<T>> destroyedInvokers = new ArrayList<>(); for (Map.Entry<String, Invoker<T>> entry : localUrlInvokerMap.entrySet()) { if (!newUrlInvokerMap.containsKey(entry.getKey())) { destroyedInvokers.add(entry.getValue()); } } // 销毁无用Invoker for (Invoker<T> invoker : destroyedInvokers) { invoker.destroy(); invokersCache.remove(invoker.getUrl().toFullString()); } } } }

篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafc

需要全套面试笔记及答案
【点击此处即可/免费获取】​​​

二、路由链(RouterChain)实现原理

1.路由链的构建过程

java

复制

下载

public class RouterChain<T> { private List<Router> routers = new ArrayList<>(); // 构建路由链 public static <T> RouterChain<T> buildChain(URL url) { RouterChain<T> chain = new RouterChain<>(); // 1. 内置路由 chain.addRouter(new TagRouter()); chain.addRouter(new AppRouter()); // 2. 配置的路由(从URL参数获取) String routerConfig = url.getParameter(Constants.ROUTER_KEY); if (StringUtils.isNotEmpty(routerConfig)) { String[] routerTypes = routerConfig.split(","); for (String routerType : routerTypes) { Router router = ExtensionLoader.getExtensionLoader(RouterFactory.class) .getExtension(routerType) .getRouter(url); chain.addRouter(router); } } // 3. 脚本路由 chain.addRouter(new ScriptRouter(url)); // 4. 条件路由 chain.addRouter(new ConditionRouter(url)); return chain; } // 路由调用 public List<Invoker<T>> route(URL url, Invocation invocation) { List<Invoker<T>> finalInvokers = invokers; // 依次通过各个路由筛选 for (Router router : routers) { finalInvokers = router.route(finalInvokers, url, invocation); // 如果已经没有可用Invoker,提前终止 if (finalInvokers == null || finalInvokers.isEmpty()) { return finalInvokers; } } return finalInvokers; } }

2.核心路由实现详解

2.1 条件路由(ConditionRouter)

java

复制

下载

public class ConditionRouter implements Router { // 路由规则解析 private final Map<String, MatchPair> whenCondition; private final Map<String, MatchPair> thenCondition; @Override public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation) { if (invokers == null || invokers.isEmpty()) { return invokers; } try { // 1. 判断是否匹配when条件 if (!matchWhen(url, invocation)) { return invokers; // 不匹配,返回所有 } List<Invoker<T>> result = new ArrayList<>(); // 2. 应用then条件筛选 for (Invoker<T> invoker : invokers) { if (matchThen(invoker.getUrl(), url)) { result.add(invoker); } } // 3. 如果有匹配的结果,返回;否则返回空 if (!result.isEmpty()) { return result; } else if (thenCondition.isEmpty()) { // then条件为空表示黑名单,返回空 return result; } } catch (Throwable t) { // 路由出错,返回所有 return invokers; } return invokers; } // 条件匹配 private boolean matchWhen(URL url, Invocation invocation) { return whenCondition == null || whenCondition.isEmpty() || matchCondition(whenCondition, url, null, invocation); } // 模式匹配引擎 private boolean matchCondition(Map<String, MatchPair> condition, URL url, URL param, Invocation invocation) { Map<String, String> sample = url.toMap(); for (Map.Entry<String, MatchPair> entry : condition.entrySet()) { String key = entry.getKey(); MatchPair pair = entry.getValue(); // 获取参数值 String sampleValue = getSampleValue(key, sample, url, param, invocation); if (sampleValue == null) { // 参数不存在但规则要求必须匹配,返回false if (!pair.matches.isEmpty()) { return false; } continue; } // 检查是否匹配 if (!pair.isMatch(sampleValue)) { return false; } } return true; } }
2.2 标签路由(TagRouter)

java

复制

下载

public class TagRouter implements Router { @Override public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation) { if (invokers == null || invokers.isEmpty()) { return invokers; } // 1. 获取请求标签 String tag = StringUtils.isNotEmpty(invocation.getAttachment(TAG_KEY)) ? invocation.getAttachment(TAG_KEY) : url.getParameter(TAG_KEY); // 2. 如果没有标签,过滤掉有标签的提供者 if (StringUtils.isEmpty(tag)) { return invokers.stream() .filter(invoker -> { String providerTag = invoker.getUrl().getParameter(TAG_KEY); return StringUtils.isEmpty(providerTag); }) .collect(Collectors.toList()); } // 3. 匹配标签 List<Invoker<T>> tagInvokers = invokers.stream() .filter(invoker -> tag.equals(invoker.getUrl().getParameter(TAG_KEY))) .collect(Collectors.toList()); // 4. 如果没有匹配的标签服务,降级到无标签服务 if (!tagInvokers.isEmpty()) { return tagInvokers; } else { return invokers.stream() .filter(invoker -> StringUtils.isEmpty(invoker.getUrl().getParameter(TAG_KEY))) .collect(Collectors.toList()); } } }

3.路由链的扩展机制

java

复制

下载

// 自定义路由实现 @SPI public interface Router extends Comparable<Router> { int DEFAULT_PRIORITY = 0; /** * 路由方法 */ <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation); /** * 获取路由URL */ URL getUrl(); /** * 路由优先级,数值越小优先级越高 */ default int getPriority() { return DEFAULT_PRIORITY; } } // 路由工厂 @SPI public interface RouterFactory { /** * 创建路由器 */ @Adaptive("protocol") Router getRouter(URL url); } // 扩展点配置 // META-INF/dubbo/internal/com.alibaba.dubbo.rpc.RouterFactory condition=com.alibaba.dubbo.rpc.cluster.router.condition.ConditionRouterFactory script=com.alibaba.dubbo.rpc.cluster.router.script.ScriptRouterFactory file=com.alibaba.dubbo.rpc.cluster.router.file.FileRouterFactory

三、服务目录与路由链的协同工作

1.完整的调用流程

java

复制

下载

public abstract class AbstractDirectory<T> implements Directory<T> { @Override public List<Invoker<T>> list(Invocation invocation) throws RpcException { // 1. 获取所有Invoker List<Invoker<T>> invokers = doList(invocation); // 2. 获取路由链 List<Router> routers = getRouters(); // 3. 应用路由链 if (routers != null && !routers.isEmpty()) { for (Router router : routers) { invokers = router.route(invokers, getConsumerUrl(), invocation); } } // 4. 返回过滤后的Invoker return invokers == null ? Collections.emptyList() : invokers; } // 具体实现 protected List<Invoker<T>> doList(Invocation invocation) { if (forbidden) { throw new RpcException("No provider available for service " + getInterface().getName()); } List<Invoker<T>> invokers = null; // 从缓存中获取 Map<String, List<Invoker<T>>> localMethodInvokerMap = this.methodInvokerMap; if (localMethodInvokerMap != null && localMethodInvokerMap.size() > 0) { String methodName = invocation.getMethodName(); invokers = localMethodInvokerMap.get(methodName); // 方法级路由 if (invokers == null) { invokers = localMethodInvokerMap.get(Constants.ANY_VALUE); } } return invokers; } }

2.动态配置更新机制

java

复制

下载

public class RegistryDirectory<T> extends AbstractDirectory<T> { // 监听配置变更 private void notify(List<URL> urls) { // 路由规则更新 List<URL> routerUrls = filterRouter(urls); if (!routerUrls.isEmpty()) { // 更新路由链 List<Router> routers = toRouters(routerUrls); if (routers != null) { setRouters(routers); } } // 配置规则更新 List<URL> configuratorUrls = filterConfigurator(urls); if (!configuratorUrls.isEmpty()) { // 刷新配置 refreshInvoker(invokerUrls); } } // 路由规则转换 private Optional<List<Router>> toRouters(List<URL> routerUrls) { List<Router> routers = new ArrayList<>(); for (URL routerUrl : routerUrls) { try { // 通过SPI加载路由工厂 RouterFactory factory = ExtensionLoader.getExtensionLoader(RouterFactory.class) .getAdaptiveExtension(); Router router = factory.getRouter(routerUrl); routers.add(router); } catch (Throwable t) { logger.error("Failed to create router from url: " + routerUrl, t); } } return Optional.of(routers); } }

四、高级特性与优化

1.路由缓存与性能优化

java

复制

下载

public class RouterChain<T> { // 路由结果缓存 private final Map<String, List<Invoker<T>>> routeCache = new LRUCache<>(1000); public List<Invoker<T>> route(URL url, Invocation invocation) { // 生成缓存key String cacheKey = generateCacheKey(url, invocation); // 尝试从缓存获取 List<Invoker<T>> cachedResult = routeCache.get(cacheKey); if (cachedResult != null) { return cachedResult; } // 计算路由结果 List<Invoker<T>> result = doRoute(url, invocation); // 放入缓存(设置合适的TTL) if (shouldCache(invocation)) { routeCache.put(cacheKey, result); } return result; } private String generateCacheKey(URL url, Invocation invocation) { StringBuilder sb = new StringBuilder(); sb.append(url.getServiceKey()) .append("#") .append(invocation.getMethodName()) .append("#") .append(getParameterHash(url, invocation)); return sb.toString(); } }

2.灰度发布与路由策略

java

复制

下载

// 基于权重的灰度路由 public class WeightRouter implements Router { @Override public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation) { // 计算总权重 int totalWeight = 0; List<WeightedInvoker<T>> weightedInvokers = new ArrayList<>(); for (Invoker<T> invoker : invokers) { int weight = invoker.getUrl().getParameter(WEIGHT_KEY, DEFAULT_WEIGHT); if (weight > 0) { totalWeight += weight; weightedInvokers.add(new WeightedInvoker<>(invoker, weight)); } } // 随机选择 if (totalWeight > 0) { int random = ThreadLocalRandom.current().nextInt(totalWeight); int current = 0; for (WeightedInvoker<T> weightedInvoker : weightedInvokers) { current += weightedInvoker.weight; if (random < current) { return Collections.singletonList(weightedInvoker.invoker); } } } // 降级到随机选择 return invokers; } private static class WeightedInvoker<T> { final Invoker<T> invoker; final int weight; WeightedInvoker(Invoker<T> invoker, int weight) { this.invoker = invoker; this.weight = weight; } } }

3.故障转移与熔断路由

java

复制

下载

public class FailoverRouter implements Router { private final CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.getInstance(); @Override public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation) { return invokers.stream() .filter(invoker -> { // 检查熔断器状态 String serviceKey = invoker.getUrl().getServiceKey(); CircuitBreaker circuitBreaker = circuitBreakerRegistry.getCircuitBreaker(serviceKey); if (circuitBreaker != null && circuitBreaker.isOpen()) { // 熔断器打开,跳过该服务 return false; } // 检查健康状态 return isHealthy(invoker); }) .collect(Collectors.toList()); } private <T> boolean isHealthy(Invoker<T> invoker) { // 检查最近错误率 // 检查响应时间 // 检查连接状态 return true; } }

篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafc

需要全套面试笔记及答案
【点击此处即可/免费获取】​​​

五、最佳实践与配置

1.配置示例

xml

复制

下载

运行

<!-- 服务消费者配置 --> <dubbo:reference id="userService" interface="com.example.UserService"> <!-- 路由规则 --> <dubbo:parameter key="router" value="tag,condition" /> <!-- 条件路由规则 --> <dubbo:parameter key="rule" value=" => host != 192.168.1.100 & method = find* => host = 192.168.1.* & version = 2.0 => cluster = cluster1 " /> <!-- 标签路由 --> <dubbo:parameter key="tag" value="gray" /> </dubbo:reference> <!-- 动态配置 --> <dubbo:config-center address="zookeeper://127.0.0.1:2181"> <dubbo:parameter key="router" value=" scope: service key: com.example.UserService enabled: true rules: - priority: 1 conditions: - method=find* => host=192.168.1.* - priority: 2 conditions: - => tag=gray " /> </dubbo:config-center>

2.监控与调试

java

复制

下载

// 路由链监控 public class RouterChainMonitor { public void monitorRouteChain(RouterChain<?> chain, Invocation invocation) { List<Invoker<?>> initialInvokers = chain.getInitialInvokers(); Map<String, List<Invoker<?>>> routeHistory = new LinkedHashMap<>(); // 记录每个路由器的输出 for (Router router : chain.getRouters()) { List<Invoker<?>> before = routeHistory.isEmpty() ? initialInvokers : routeHistory.values().iterator().next(); List<Invoker<?>> after = router.route(before, getUrl(), invocation); routeHistory.put(router.getClass().getSimpleName(), after); // 记录到监控系统 recordRouteMetrics(router, before.size(), after.size()); } // 输出路由链详情 logRouteChainDetail(routeHistory); } }

六、总结

Dubbo服务目录与路由链的核心要点:

  1. 服务目录

    • 负责维护可用的服务提供者列表

    • 监听注册中心变化,动态更新Invoker

    • 提供方法级的服务分组

  2. 路由链

    • 通过责任链模式实现多重路由规则

    • 支持条件路由、标签路由、脚本路由等

    • 路由优先级控制执行顺序

  3. 关键特性

    • 动态更新:配置热更新,无需重启

    • 扩展性强:SPI机制支持自定义路由

    • 性能优化:缓存、懒加载等优化手段

    • 容错机制:路由失败降级策略

  4. 最佳实践

    • 合理设计路由规则,避免过度复杂

    • 监控路由链性能,及时优化

    • 结合业务场景选择合适的路由策略

这种设计使得Dubbo能够实现复杂的流量治理需求,如灰度发布、蓝绿部署、区域路由等高级功能。

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

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

相关文章

通透理解Mamba:三步实现从理论推导到手撕代码,一行不落的实战保姆指南

文章目录 从0玩转Mamba神经网络:理论+实战的保姆级教程 一、Mamba:序列任务的“效率新贵” 二、核心原理:Mamba的“制胜逻辑” 1. 状态空间模型(SSM)的魔力 2. Mamba vs Transformer:核心差异 三、实战入门:搭建简易Mamba模型 1. 环境搭建 2. 代码实现:Mamba文本分类器…

手把手搞定毕设:基于YOLOv8从0到1构建检测系统,全流程详解(环境→训练→部署→答辩)

文章目录 基于YOLOv8的智能物体检测系统:毕设实战全流程,从搭建到上线,一路陪你跑通 第一步:环境搭建,别让基础坑了你后劲 第二步:数据集准备,喂对“食”才能长壮 第三步:模型训练,调参如炼丹,稳扎稳打出金 第四步:验证与推理,让模型“睁眼”看世界 第五步:优化导…

6D姿态估计落地难?拆解DenseFusion核心模块PoseRefineNet,附可复现的训练代码与损失函数详解

文章目录 《从DenseFusion突破6D姿态估计:手把手拆解PoseRefineNet与损失函数,让你的研究“姿态精准落地”》 一、技术内核:PoseRefineNet与多模态损失如何让6D姿态“精准估计”? (一)PoseRefineNet:让“位姿迭代”精细到微米 (二)多模态损失函数:让“信息融合”无死…

一站式掌握TensorRT量化:从PTQ到QAT实战,实现模型推理速度飞升

文章目录 TensorRT量化实战教程:从PTQ到QAT,让你的模型推理速度飞起来 引读 一、TensorRT量化技术全景:PTQ与QAT核心认知 1. TensorRT为何是量化首选? 2. PTQ(Post-Training Quantization):训练后量化的高效性 3. QAT(Quantization-Aware Training):带量化感知的训练…

毕设做物体检测无从下手?YOLOv8项目一条龙教程,从搭建到上线,让你少走弯路

文章目录 基于YOLOv8的智能物体检测系统:毕设实战全流程,从搭建到上线,一路陪你跑通 第一步:环境搭建,别让基础坑了你后劲 第二步:数据集准备,喂对“食”才能长壮 第三步:模型训练,调参如炼丹,稳扎稳打出金 第四步:验证与推理,让模型“睁眼”看世界 第五步:优化导…

艺术与科技结合:基于YOLOv5的艺术展品识别系统,一个完整可运行的毕业设计项目

文章目录 《深度学习实战:基于YOLOv5的公共艺术展艺术品识别毕设全指南》 一、为什么选择“公共艺术展艺术品识别”做毕设? 二、第一步:搞懂艺术品识别的“技术逻辑” 三、第二步:数据准备,给模型“喂”足艺术样本 1. 数据集从哪来? 2. 标注数据:给艺术品“画框框” 3. …

Nginx 配置实战:从摸鱼到部署,手把手教你搞定生产级配置

先灵魂拷问一下&#xff1a;写了一堆接口却不会部署&#xff1f;服务器被恶意请求打崩过&#xff1f;静态资源加载慢到用户想摔手机&#xff1f;别慌&#xff01;Nginx 作为后端工程师的「部署瑞士军刀」&#xff0c;能搞定反向代理、负载均衡、限流防刷等一堆骚操作。记住咯&a…

保姆级教程:手把手教你训练自己的YOLO-World,轻松实现定制目标检测

基于YOLO-world训练模型的完整教程:从数据准备到微调训练 前言 目标检测作为计算机视觉中的重要任务,在许多领域中具有广泛的应用,如自动驾驶、安防监控、人机交互等。YOLO(You Only Look Once)系列算法凭借其高效、快速的特点,已经成为了目标检测领域的主流方法之一。…

三步完成毕设:用YOLOv5实现艺术品识别(从数据采集到模型部署,轻松落地与展示)

文章目录 《深度学习实战:基于YOLOv5的公共艺术展艺术品识别毕设全指南》 一、为什么选择“公共艺术展艺术品识别”做毕设? 二、第一步:搞懂艺术品识别的“技术逻辑” 三、第二步:数据准备,给模型“喂”足艺术样本 1. 数据集从哪来? 2. 标注数据:给艺术品“画框框” 3. …

手把手毕设指南:基于YOLO的电动车识别(含数据集+代码),从环境搭建到模型部署上线

文章目录 《深度学习实战:基于YOLO系列的公共场所电动车识别毕设全流程指南》 一、为什么选择“公共场所电动车识别”做毕设? 二、第一步:搞懂YOLO系列,选对“武器”再开工 1. YOLOv5:经典且易上手 2. YOLOv8:性能全面升级 3. YOLOv10:最新旗舰模型 三、第二步:数据准备…

AbMole丨C12-200:高性能可电离脂质在mRNA疫苗递送领域的应用

C12-200是一种可电离脂质纳米颗粒&#xff08;LNP&#xff09;的关键组分&#xff0c;在核酸递送领域展现出显著优势。由C12-200参与形成的脂质体可以高效封装mRNA或DNA等核酸分子&#xff0c;并通过优化脂质组合方案&#xff0c;例如与DSPC联用等增强递送效率。研究表明&#…

手把手实现Lung-DETR:从理论到代码,逐模块解析DETR在稀疏肺结节检测中的创新实战

文章目录 Lung-DETR:变形检测Transformer在稀疏肺结节异常检测中的创新实践——从框架解析到端到端实现的深度指南 第一章:数据基石——从LUNA16 CT扫描到可训练管道的精炼 第二章:模型铸魂——从DETR基线到Lung-DETR的变形升级 第三章:验证落地——从mAP曲线到临床部署的桥…

在JSP中如何编写大附件上传的完整示例?

大三党毕业设计救星&#xff1a;10G大文件上传加密断点续传&#xff08;原生JSSpringBoot&#xff09; 兄弟&#xff0c;作为山西某高校计科专业的大三老狗&#xff0c;我太懂你现在的处境了——毕业设计要做文件管理系统&#xff0c;甲方&#xff08;老师&#xff09;要10G大…

ALS 算法详解:怎么解开“推荐系统”的死结?

写在前面的话 你有没有想过&#xff0c;为什么刚才在淘宝搜了“键盘”&#xff0c;下一秒打开抖音就给你推“机械键盘测评”&#xff1f;或者 Netflix 是怎么知道你可能会喜欢《黑镜》的&#xff1f; 这一切背后的功臣&#xff0c;往往是矩阵分解。而 ALS&#xff08;交替最小二…

手把手实现3D肺结节检测:基于Faster R-CNN的从CT处理、训练到部署的五步代码级实战与避坑指南

文章目录 毕设攻坚:3D Faster R-CNN实现肺部结节检测系统全流程,从CT影像到智能诊断 一、先懂“3D肺部结节检测”的毕设意义 二、技术拆解:3D Faster R-CNN的核心逻辑 1. 3D Faster R-CNN的架构解析 2. 肺部结节检测的核心挑战 三、实战:3D肺部结节检测系统的毕设级实现 1.…

Python_uniapp-微信小程序的员工宿舍报修系统

目录员工宿舍报修系统摘要关于博主开发技术路线相关技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;员工宿舍报修系统摘要 基于Python和UniApp开发的微信小程序员工宿舍报修系统&#xff0c;旨在为企业和学校…

JAVA web页面中大文件分块上传的示例步骤是什么?

大文件传输系统解决方案 项目背景与需求分析 作为北京某软件公司项目负责人&#xff0c;我们面临一个关键的大文件传输功能需求。经过深入分析&#xff0c;现有需求可归纳为以下几个核心要点&#xff1a; 大文件传输能力&#xff1a;需支持50G以上文件传输&#xff0c;包含文…

SGD 算法详解:蒙眼下山的寻宝者

写在前面的话 ALS&#xff08;交替最小二乘法&#xff09;&#xff0c;它是解决矩阵分解的“左右互搏术”。 但在机器学习的世界里&#xff0c;还有另一位更通用的“超级英雄” —— SGD&#xff08;随机梯度下降&#xff09;。 如果说 ALS 是精密的“数学解析解”&#xff08;…

【北京工业大学主办 | SPIE出版(ISSN、ISBN双号皆备) | 组委成员涵盖10+个国家,3位IEEE高级会员外专担任会议主讲】2026进化算法和智能控制国际研讨会(ISEAIC 2026)

【SPIE出版】2026进化算法和智能控制国际研讨会&#xff08;ISEAIC 2026&#xff09; 2026 International Symposium on Evolutionary Algorithm and Intelligent Control 2026年1月30日-2月1日 | 中国北京 高国际化&#xff1a;组委成员涵盖10个国家&#xff0c;3位IEEE高…

Python_uniapp-微信小程序的早教育教幼教知识学习系统

目录PythonUniapp微信小程序早教系统摘要关于博主开发技术路线相关技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;PythonUniapp微信小程序早教系统摘要 该系统基于Python后端与Uniapp跨平台框架开发&#x…