新闻详情

新闻详情

首页 / 资讯中心 / 详情

Dubbo接口测试实战指南:从原理到工具选型

发布时间:2026/9/28 14:28:16来源:尧图网络
Dubbo接口测试实战指南:从原理到工具选型
前阵子协助团队里的测试同学排查一个线上问题她拿着Postman兴冲冲地要去调一个新上线的服务结果连地址都不知道填什么问了一路“这个接口的URL是啥”。我告诉她这玩意儿叫Dubbo压根不走HTTPPostman那套在这基本废了。她一脸懵那接口测试怎么做这就是分布式架构里很典型的一个断层服务端接口测试的经验大多建立在HTTP协议之上一旦切到Dubbo这类RPC框架不少人直接卡在第一步——连“接口长什么样”都不知道。这篇我结合自己这些年实际测Dubbo服务的经验把整个思路、原理、工具选型、踩坑点完整梳理一遍目标是让读完的人真的能从零把一个Dubbo接口测通而不是只看到一堆概念。1. 为什么Postman测不了Dubbo两个协议体系的根本差异要搞清楚Dubbo接口怎么测先得明白它跟HTTP接口的差距到底在哪。很多人在这一层没用对劲后面全是错的。1.1 HTTP接口和Dubbo接口信息构成完全不同一个HTTP接口测试时我们关心的是四件套URL、MethodGET/POST、Header、请求体。这些信息是“自描述”的通过URL和Body就能把请求送到服务器。Postman、Apifox、JMeter这类工具能直接跑HTTP接口本质上就是因为它们只需要处理这么一套标准化的格式。Dubbo不是这样。Dubbo是一个RPC框架默认的dubbo协议走的是底层TCP长连接调用方和提供方之间通过Netty直接通信传递的是二进制数据不是什么URL加JSON。你面对的信息结构变成了接口全限定名interface、方法名method、方法参数类型列表parameter types、方法参数值。注意这里连“根路径”“请求头”这种概念都没有。这就意味着测试工具必须从“拼一个HTTP请求”的思路切换到“构造一次Java方法调用”的思路。工具能不能做Dubbo测试核心判断标准就是它能不能替你完成服务发现、协议编码和二进制传输这三件事而不是你填了什么URL。1.2 Dubbo协议的核心链路从注册中心到ProviderDubbo的经典调用链是Consumer从注册中心Nacos或Zookeeper拉取服务列表拿到Provider的IP和端口后通过长连接直接发起RPC调用。注册中心在这里扮演的角色类似于一个电话簿——它不参与业务数据的传输只告诉Consumer“你要找的服务在哪”。这套模型对接口测试的影响巨大。测试时你有两条路可以走走注册中心测试工具模拟一个Consumer连上注册中心查询到Provider地址后发起调用。这种方式最贴近生产真实的调用链路自动化测试平台多数走这条路。直连模式绕过注册中心手动指定某个Provider的IP和端口直接调。这种方式适合本地调试、单机排查、注册中心挂了临时验证等场景。先说结论两种方式都必须掌握。我在项目里见过不少测试工程师只会用直连模式调通一个服务一换环境就抓瞎也有只会跟着工具点注册中心的注册中心一抖动就完全不知道问题出在哪。上层的工具形态可能会变但这两条链路是Dubbo测试的底层通道所有工具、脚本、平台都是基于这两条链路在做文章。这个协议在设计上还有一些额外的坑比如典型的三个端口业务服务端口dubbo协议默认20880、心跳端口通常服务端口1、QoS端口默认22222。测试的时候你连的是业务服务端口但很多人配置防火墙只放行了20880结果服务能注册进去Consumer却连不上心跳断了之后Provider被踢下线。这种问题排查起来非常迷惑因为它不是配置逻辑问题而是网络边界问题。做环境准备时这三个端口要么都放行要么都别轻易隔离。1.3 接口测试思路的转变从“调URL”到“调方法”换一个更生活化的类比。HTTP接口就像一个服务窗口你递一张单据进去窗口办事员按单据办事最后给你一张回执。而Dubbo接口更像是你有一个单位内部的对接联系人你不需要知道联系的流程规则直接打对方电话说“帮我办个事”对方就直接办了。测试工具得先知道“这个联系人叫谁、电话是多少、他擅长办哪几类事”然后才能打得通。所以做Dubbo接口测试第一件事是转变心态别把它当接口去测把它当“远程调用一个Java方法”去测。你关心的是方法挂载在哪个接口上、方法签名长什么样、参数需要什么类型、返回值是什么结构。这个转变说起来容易实际影响每一环。比如你拿到一个Dubbo接口第一步不是想“我要POST什么参数”而是想“我要查这个接口的元数据”——接口名、方法名、各参数的类名。没这层信息后面全是空中楼阁。很多团队里开发和测试之间的沟通不畅根源就是两边心智模型不一致开发说“我这边接口是com.example.api.OrderService的getOrderById”测试理解成一个“路径是/order/getOrderById的GET接口”于是对不上岔子。2. 动手前必须弄懂的三个概念注册中心、分组版本、序列化2.1 注册中心Nacos和Zookeeper在测试中的角色现在的主流组合基本就是Dubbo加Nacos或者Dubbo加Zookeeper。这两种注册中心在Dubbo测试中有一个共同的典型使用场景测试工具通过配置注册中心地址拉取到服务提供方列表然后再发起调用。Nacos的一个关键概念是Namespace命名空间。它相当于一个环境隔离层同一个Nacos集群上可以划分出多个独立命名空间彼此之间服务列表不互通。常见的用法是dev、test、prod各一个namespace各环境的数据互不干扰。这个设计对测试者是双刃剑。好处是你只要把namespace指对就能精准找到某个环境里的服务坏处是配错了namespace测试工具会直接显示“没有可用Provider”而且这类的报错信息往往不直观。我见过很多测试的同学连注册中心地址、namespace、group这三层配置对不上时出现的各种诡异现象反复怀疑网络有问题其实问题就出在“公共命名空间之外的另一个namespace里压根没有这个服务的实例”。Zookeeper的原理不太一样它是树形节点结构路径通常是/dubbo/com.example.api.OrderService/providers/。通过zk的客户端可以看到每一层的Provider节点。它的ACL权限控制Access Control List在测试环境里很少被开启但一旦开启连接时没有对应的账号权限你就会发现zk能连上、节点却读不到表现形式跟服务发现失败一模一样。Nacos和Zookeeper的选择并非现代Dubbo唯一需要注意的。Dubbo 3.x开始引入了应用级服务发现机制不再像2.x那样完全依赖接口级别的注册。这意味着在较新的Dubbo架构里服务提供方注册的不再只是“接口名”还有应用名。测试工具、脚本的兼容性也要注意有些老版本的测试插件只能适配2.x的接口级注册到了3.x的应用级注册下面就失灵了。2.2 版本号与分组同接口多版本并存时怎么选Dubbo允许同一个接口存在多个版本和多个分组。这样做是为了支持微服务演进时的灰度发布、多环境隔离等场景。比如OrderService同时存在1.0.0和2.0.0版本两个版本的方法是同一个Interface但业务逻辑已经大改了。Consumer调用时必须明确指定version否则注册中心拿到的可能是多个Provider实例Dubbo的负载均衡策略会随机选一个结果是——同一条测试用例10次里面有几次走的是旧逻辑几次走的是新逻辑结果飘忽不定。组的概念类似。有些团队会把同一个服务按照业务维度拆成多个组比如“online”组和“backup”组。测试的时候如果不指定group默认会在DEFAULT_GROUP里找服务查不到就直接报No provider。所以正式开工之前的第一件事不是打开工具而是收集被测服务的完整坐标信息interface接口的全限定类名比如com.example.api.OrderServicemethod方法名比如getOrderByIdparameterTypes参数类型列表比如java.lang.Longversion服务版本号比如1.0.0group服务分组比如空、online、gray等registry注册中心地址和协议比如nacos://10.0.0.5:8848timeout超时时间建议测试场景设大一点比如3000ms起这组信息我习惯叫它“Dubbo接口五元组加超时”。缺了任何一个都有可能在调用时出现莫名其妙的现象。特别是version和group开发常常忘了在测试文档里写测试就得靠猜。碰到这种情况最直接的办法是去Nacos控制台的“服务列表”里查看服务详情或者去服务的元数据里查。务必不要在没有version和group信息的情况下“试运气”。2.3 序列化机制参数构造最容易翻车的地方Dubbo默认的序列化协议是Hessian2此外还有Kryo、JSON、Protobuf等可选实现。序列化这个东西是Dubbo测试中一个反复出现问题的区。因为你构造的测试参数看起来是对的比如传了个数字1传输过程中被序列化成二进制到了服务端反序列化时却可能对不上类型。举个例子接口方法的参数类型是java.math.BigDecimal你在工具里填了个数字1.00。有些测试工具按字面量处理转成了Double类型传给Consumer端。Consumer把它序列化后服务端反序列化成BigDecimal时就有概率报错因为Hessian2对类型匹配很敏感。你要么在工具里显式指定参数类型映射要么在代码里构造参数时用BigDecimal.valueOf(1.00)来创建。还有一个高频问题参数对象是自定义的POJO类比如OrderQueryParam里面有id、userId、status这些字段。Hessian2序列化时要求这个类实现Serializable且serialVersionUID在两端一致。测试时引入了不同的jar包版本或者反编译的工具类少了某个字段就可能在调用时直接抛SerializationException。这种问题从控制台看不出来根因只能从序列化器抛出的Message反推但排查思路其实很清楚比对Provider和Consumer两端引用的接口定义jar包版本是否一致。我的建议是在测试环境中维护一套跟生产Provider完全一致的接口jar包版本尽量别用“差不多能用”的版本。很多看起来玄乎的Dubbo调用失败最后都栽在这种“版本刚好对不上”的问题上。3. 从零跑通一次Dubbo接口测试两种实战路径3.1 路径AApifox可视化调试Dubbo接口Apifox从很早就开始支持Dubbo调试也是目前中文社区里最容易被搜到的工具。它同时支持Zookeeper和Nacos两种注册中心也支持直连模式。整体体验比较接近Postman但多了针对Dubbo的协议适配。实际操流程大致是这样第一步在Apifox项目里新建一个接口接口类型选择Dubbo。这里你会看到一个区别于HTTP接口的配置界面需要填写注册中心类型、地址、用户名/密码如果Nacos开启了鉴权。第二步选择服务。Apifox会去连接你配置的注册中心拉取服务列表。你可以根据Interface名称模糊搜索选择目标服务。拉到服务后工具会进一步展示方法列表、方法参数类型结构。第三步填写参数值。这一块跟HTTP接口流程差异最大。Apifox会把方法参数类型结构展开成表单或者让你以JSON格式整体填入。填的时候特别需要注意参数类型尤其是数值类型在JSON里的表示。返回结果会以JSON形式展示方便断言。Apifox用于日常开发联调、少量接口验证效率是真的高。因为不需要写代码改参数重新调用只要几秒钟。但它也有一个明显的短板对自定义复杂对象的序列化支持不够细当参数是嵌套很深的复杂结构、或者包含泛型集合时界面上操作起来很繁琐容易出现类型映射错误。这种时候我一般会切到代码路径。3.2 路径BJava工程内用泛化调用GenericService直连如果你在写自动化测试脚本或者碰到Apifox搞不定的复杂参数结构就得走Java代码这条路。Dubbo官方提供了泛化调用GenericService机制专门用于“不依赖接口类也能调用远程服务”的场景。这里的思路是Consumer端只依赖Dubbo框架本身用一个通用的GenericService接口发起调用。你传一个方法名加参数类型数组加参数值数组框架会帮你完成序列化和远程调用。对测试来说最大的价值是哪怕你的测试工程里根本没有引入业务接口的jar包也能发起调用。这在测试环境里很有用因为很多被测服务的API包属于内网制品库测试团队不一定有权限拉取依赖。一个最小可跑的泛化调用代码结构大致这样这里以Dubbo 2.7/3.x的org.apache.dubbo配置为参考import org.apache.dubbo.config.ApplicationConfig; import org.apache.dubbo.config.ReferenceConfig; import org.apache.dubbo.config.RegistryConfig; import org.apache.dubbo.rpc.service.GenericService; public class DubboGenericInvoker { public static void main(String[] args) { ApplicationConfig application new ApplicationConfig(); application.setName(test-consumer); RegistryConfig registry new RegistryConfig(); registry.setAddress(nacos://127.0.0.1:8848); // 如果Nacos开了鉴权加上这两行 registry.setUsername(nacos); registry.setPassword(nacos); ReferenceConfigGenericService reference new ReferenceConfig(); reference.setApplication(application); reference.setRegistry(registry); reference.setInterface(com.example.api.OrderService); reference.setVersion(1.0.0); reference.setGroup(online); reference.setGeneric(true); reference.setTimeout(5000); // 如果不想走注册中心直连Provider时启用下面这行 // reference.setUrl(dubbo://10.4.2.18:20880); GenericService genericService reference.get(); Object result genericService.$invoke( getOrderById, new String[]{java.lang.Long}, new Object[]{1001L} ); System.out.println(result); } }这段代码有几个关键点值得展开。一个是reference.setGeneric(true)。这一行决定了框架是否以泛化方式调用。没设置或设为false框架就会尝试强类型调用这时候必须引入接口类才能编译通过或运行成功。另一个是$invoke方法的三个参数。第二个参数是String数组每个元素是参数类型的全限定类名第三个是Object数组是具体的参数值。这里的类名必须跟Provider端接口方法签名完全一致哪怕名字写对了但大小写错了也会因为找不到匹配的方法而报错。还有一个返回值问题泛化调用返回的对象对于自定义POJO类型就是一个Map。框架把Provider传回的序列化数据反序列化成了Map结构因为Consumer端没有类型信息。断言的时候得按Map的key一层一层取。比如返回的是Order对象里面有orderId、amount、items列表你就得从最终返回的Map里先取items再遍历里面的每个Map。这就比强类型调用繁琐但胜在零依赖。如果你想要强类型返回、代码写起来更省事也可以在自己的测试工程里引入业务接口jar包用DubboReference或者ReferenceConfig 构造强类型引用然后像调本地方法一样调用。3.3 工具选型的几个判断标准我团队里实际是两种方式并存日常联调、冒烟测试用Apifox自动化回归和复杂场景用Java脚本。选型的判断标准总结下来有这么几条被测接口多少几个接口工具点击足够上百个接口必须脚本化、参数化。参数复杂程度只有基本类型和单层对象工具很轻松嵌套泛型、父类字段、枚举类型等代码更稳。断言要求简单判断返回值是否为空工具足够要做数据对比、数据库核对、关联断言必须走脚本。是否需要集成CI工具做的测试要集成到流水线里麻烦得多Java脚本则天然适合Jenkins。另外提一句JMeter。JMeter通过插件也能支持Dubbo测试但插件的维护良莠不齐在新版Dubbo 3.x下兼容性存在不确定因素我个人更推荐如果已经熟悉JMeter可以尝试插件方式如果是新团队直接从Apifox加Java脚本组合切入更平滑。4. 测试环境里最容易卡住的四个实际问题4.1 注册中心鉴权引发的401未登录问题如果你在测试工具或脚本里配置Nacos地址后控制台打印的报错长这样{code:401,message:未登录,请登录!}多数情况不是你的服务调用逻辑出错了而是Nacos服务端开启了鉴权你的客户端没带用户名密码。这个问题在新版Nacos2.x及以上里越来越常见因为不少团队出于安全考量在测试环境也打开了鉴权。解决办法是在注册中心配置里补上账号。Apifox的注册中心配置界面有独立的用户名和密码字段Java脚本里用registry.setUsername/setPassword。这里有一个容易忽略的细节Nacos的鉴权是用客户端SDK自动处理AccessToken的但如果你在本地调试时同时开着多个工具比如Apifox、Java脚本、Nacos客户端命令行每个工具都要单独配置凭据否则只有那个配了账号的工具能正常工作。还有一点401未登录这句话也可能来自业务系统本身。我曾在一个项目里遇到测试环境的所有Dubbo接口都返回类似“未登录”的错误那不是注册中心的问题而是服务端在每次调用时校验了RpcContext里的token信息。观察报错打印的堆栈能区分是发生在Consumer连接阶段还是Provider业务逻辑里。前者是注册中心问题后者是RpcContext传递问题——解决方案是先把登录接口的返回值塞到RpcContext的attachment里。4.2 Provider列表为空和服务发现延迟调用时报“No provider available”或“找不到服务提供者”是最常见的但原因往往不是一个。排查链路应该按顺序走第一确认注册中心里真有这个服务实例。去Nacos控制台的服务列表页搜索接口名或应用名看是否有多条实例。如果一条都没有先确认Provider是否在线再看Provider注册时用的namespace和group跟你配的是否一致。第二确认你的测试工具连的是同一个注册中心。很多时候开发本地的Provider注册的是localhost测试工具的注册中心地址却指向了测试环境的Nacos两头根本不在一个集群里。第三确认服务分组和版本。一个常见的坑是你的工具把version设置为空而Provider注册的版本是1.0.0服务列表里明明有实例但Consumer的version匹配不上同样会报No provider。服务发现的另一个坑是延迟。Consumer第一次连接注册中心从拉取服务列表到发起调用之间存在缓存刷新时间默认几秒到几十秒不等。你新建了一个ReferenceConfig之后立刻调用偶尔会碰巧赶上服务列表还没拉回来就报“找不到服务”。解决方案是本地测试时先用一个sleep或者循环重试拉取列表而在自动化脚本里我会在断言失败时自动重试一次间隔3秒基本能覆盖掉这种瞬时抖动。4.3 序列化失败与参数类型不匹配这类问题的典型报错是SerializationException、not support deserialize这种或者是服务端日志里出现ClassNotFoundException但客户端拿到的却是一个不带明确原因的超时或解码错误。最经典的一个场景Provider端方法参数是java.util.Listcom.example.api.OrderItemConsumer端在Apifox里填参数时用了JSON数组数组里每个元素被识别成了LinkedHashMap而不是OrderItem。Hessian2在序列化Map和序列化自定义对象时用的类型标签完全不一样服务端反序列化时Map无法转换成目标类型直接报错。解决办法有两条如果走Apifox参数结构区域一般能展开对象的字段最好切换到文档模式逐字段填让工具按目标类型自动构造对象而不是塞一个JSON进去。如果走Java脚本用Jackson或Gson先把JSON字符串反序列化成目标参数类型的Object再放进参数数组里然后传给$invoke。还有一个很隐蔽的问题是POJO构造函数。Hessian2序列化为了性能会绕过构造函数直接通过ASM设置字段值这本来问题不大但如果POJO类里有无参构造器校验或者初始化逻辑反序列化出来的对象可能处于“不完整”状态。上游测试脚本测出来的结果看起来数据是坏的排查到最后发现是序列化机制导致的构造器逻辑未执行。这种问题不要在测试脚本里硬扛建议直接反馈给服务方看看是否应该用DTO替代业务领域模型作为RPC出入参。4.4 超时重试造成的数据重复与副作用Dubbo的默认集群容错策略是Failover也就是失败自动切换重试。默认配置下retries等于2timeout等于1000毫秒。这意味着一次调用如果超过1秒返回Consumer会认为超时然后可能换一台Provider实例再次发起同样的请求。测试场景最痛的是你调用一个创建订单的接口第一次实际已经成功了只是响应超过了1秒客户端判定超时后自动重试了第二次结果数据库里产生了两条一模一样的订单。测试断言“创建成功”可能通过但下游统计却发现数据翻倍。这类坑不是测试工具的bug也不是接口有bug而是Dubbo的容错策略默认值在“非幂等写接口”上不适合自动重试。我在做接口测试时凡是遇到写操作、扣库存、发消息这类副作用明显的接口都会在ReferenceConfig里显式设置reference.setRetries(0); reference.setTimeout(5000);如果是在Apifox里也要确认超时参数有没有设置得足够大默认值往往不太适合慢接口。而在断言层面遇到超时异常时不要直接判定测试失败先查一次数据是否已经被写入再判断是“真失败”还是“假超时”。这个经验在测试治理不完善的团队里能帮你省下大量和开发互相扯皮的时间。5. 让Dubbo接口测试真正落地隔离、Mock与压测改造5.1 用Namespace真正隔离测试环境很多团队名义上有测试环境实际上测试环境用的Nacos跟开发环境共用一个命名空间服务之间互相能看到测试调用的时候根本没搞清楚打到的是哪个Provider实例。我的做法是每个独立测试环境都申请一个独立的Nacos namespace并为它开通独立的账号权限。Dubbo接口测试脚本里把namespace、group、version写进配置文件环境切换只需改一个环境变量。这样做的好处不只是隔离还包括测试结果的信任度更高——你测到的数据确实来自测试环境本身不会被开发同学临时起的一个本地Provider带偏。具体配置时RegistryConfig里有一个setNamespace方法可以用Apifox的注册中心配置里也有一栏命名空间ID填上Nacos控制台里那个长长的ID字符串不是名称。顺手补充一个坑Nacos的命名空间ID和名称是两回事工具里填错名称也不会报错但服务列表会变成空的。5.2 下游依赖Mock的思路Dubbo服务往往还依赖其他Dubbo服务、数据库、Redis、消息队列。真正做接口级测试时被测服务自身逻辑可能没问题但下游一抖动导致用例全挂。对测试而言最基本的Mock思路是把下游依赖用WireMock或者MQ的虚拟Topic替代但Dubbo服务之间的调用Mock起来稍微麻烦一点你可以把被测服务依赖的那个Provider临时替换成一个Mock Provider——用一个本地起一个Dubbo Provider注册同样的接口名被测试服务发现后就会调到你Mock的节点上。这个方案实施成本不低对于大多数测试团队来说性价比有限。实操中我更推荐另一个思路把下游依赖的真实测试环境摆好比如建立一套完整的测试数据池让下游的Redis和数据库保持稳定这样Dubbo链路本身就可以真连真跑。只有在外部依赖完全不可控、接口核心逻辑必须验证的情况下才用Mock Provider隔离。还有一个中间状态的服务Mock思路利用Dubbo的路由规则。Dubbo 3.x支持在注册中心配置路由规则例如临时把某个消费方到某个Provider的动态路由关掉或者按参数路由到Mock节点。测试团队如果能拿到注册中心控制台的权限这是一个非常灵活的治理手段但也需要谨慎操作避免干扰到其他项目。5.3 压测改造连接数、超时和吞吐量的调整接口测试做到后期难免要走到压测这一步。Dubbo默认在netty连接模型下一个Consumer到Provider只有一条长连接所有并发请求在这条连接上复用。这对一般功能测试不是问题但压测时如果QPS目标很高单连接会成为瓶颈表现为CPU没跑满但TPS上不去。压测状态下建议调整Consumer端连接数配置。如果是Java脚本在ReferenceConfig里可以设置连接数。例如连接到同一个Provider的并发连接从默认1调大到4或8吞吐往往明显改善。不过要注意连接数增加也会增加Provider端的线程压力调参时观察两端负载不要一味拉高。超时配置在压测场景下也需要单独处理。功能测试时可以把timeout设为5秒甚至更大保证业务逻辑充裕执行压测时为了防止线程堆积timeout反而要适当调小让快速失败的请求尽快释放线程资源。这两个方向是相反的实际操作中大家很容易用同一套配置跑两种场景结果要么功能测试误报超时要么压测时线程池被打满。连接数和超时之外还有一个容易被忽视的参数是payload的序列化大小。有些压测用例传的是几MB的大JSON对象序列化耗时占比会非常夸张导致整体TPS惨不忍睹。如果业务场景本身不是大对象传输压测前就要确认这个参数不能被过度放大否则你压的其实是序列化器不是业务逻辑。写在最后这套基于Dubbo的接口测试体系我在项目里落地后有个很深的感受测试工具和框架本身都不是瓶颈真正难的是让团队每个人都理解RPC调用链路的底层逻辑。被测服务的五元组信息能不能拿到、注册中心配得对不对、序列化类型匹不匹配、超时重试会不会污染数据——这些问题面试不会问你基础文档也很少写但每个都能让测试停摆半天。我个人的建议是测试同学至少动手写一次那种不带业务jar包的泛化调用脚本把从注册中心拉服务、配版本分组、传参数、拿返回值整个过程亲手跑一遍。走过这一步之后再看Apifox那些配置和报错会感觉很多东西突然通透了原来界面上那一栏栏选项背后都是在帮你填某个ReferenceConfig的字段而已。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Calibre GDS区域切图:calibredrv与SVRF实战及避坑指南 2026/9/29 4:37:53

Calibre GDS区域切图:calibredrv与SVRF实战及避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Unity Shader入门:渲染管线与纯色Shader实战 2026/9/29 4:37:53

Unity Shader入门:渲染管线与纯色Shader实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
VMware Workstation 安装 Ubuntu 24.04 虚拟机详解:从配置到 SSH 连接 2026/9/29 4:37:53

VMware Workstation 安装 Ubuntu 24.04 虚拟机详解:从配置到 SSH 连接

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Uniapp视频真机黑屏原因与跨端播放解决方案 2026/9/29 4:37:46

Uniapp视频真机黑屏原因与跨端播放解决方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
STM32开发必备:国内参考方案与资源渠道全攻略 2026/9/29 4:37:46

STM32开发必备:国内参考方案与资源渠道全攻略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
PS5核心硬件深度解析:从定制SSD到Tempest Engine的体验革命 2026/9/29 4:37:40

PS5核心硬件深度解析:从定制SSD到Tempest Engine的体验革命

昨晚 Mark Cerny 那场分享,我全程看完了。作为 PS5 的首席系统架构师,他这场面向开发者和玩家的技术说明,信息量比我预想的要密集得多。整个分享没有什么发布会常见的炫酷特效和主持人热场,就是一个人拿着 PPT 和原型机&#xff0…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉