- 浏览: 1704693 次
- 性别:
- 来自: 杭州699号
文章分类
最新评论
-
莫莫摸:
为什么不用dubbo
RCP数据传输模型回顾 -
大胡子爸爸:
String, Class 都实现了Serializable接 ...
RPC框架几行代码就够了 -
lss598018587:
谢谢大神分享,比起新手看复杂的dubbo框架还不如看大神的这一 ...
RPC框架几行代码就够了 -
15606915740:
你好,请问一下。<dubbo:consumer filt ...
Dubbo文档 -
joqk12345:
...
一些设计上的基本常识
转于自己在公司的Blog:
http://pt.alibaba-inc.com/wp/experience_1182/sofeware-configuration-design.html
Dubbo现在的设计是完全无侵入,也就是使用者只依赖于配置契约,
经过多个版本的发展,为了满足各种需求场景,配置越来越多,
为了保持兼容,配置只增不减,里面潜伏着各种风格,约定,规则,
新版本也将配置做了一次调整,去掉了dubbo.properties,改为全spring配置,
将想到的一些记在这,备忘。
1. 配置分类
首先,配置的用途是有多种的,大致可以分为:
(1) 环境配置,比如:连接数,超时等配置。
(2) 描述配置,比如:服务接口描述,服务版本等。
(3) 扩展配置,比如:协议扩展,策略扩展等。
2. 配置格式
(1) 通常环境配置,用properties配置会比较方便,
因为都是一些离散的简单值,用key-value配置可以减少配置的学习成本。
(2) 而描述配置,通常信息比较多,甚至有层次关系,
用xml配置会比较方便,因为树结构的配置表现力更强,
如果非常复杂,也可以考自定义DSL做为配置,
有时候这类配置也可以用Annotation代替,
因为这些配置和业务逻辑相关,放在代码里也是合理的。
(3) 另外扩展配置,可能不尽相同,
如果只是策略接口实现类替换,可以考虑properties等结构,
如果有复杂的生命周期管理,可能需要XML等配置,
有时候扩展会通过注册接口的方式提供。
3. 配置加载
(1) 对于环境配置,
在java世界里,比较常规的做法,
是在classpath下约定一个以项目为名称的properties配置,
比如:log4j.properties,velocity.properties等,
产品在初始化时,自动从classpath下加载该配置,
我们平台的很多项目也使用类似策略,
如:dubbo.properties,comsat.xml等,
这样有它的优势,就是基于约定,简化了用户对配置加载过程的干预,
但同样有它的缺点,当classpath存在同样的配置时,可能误加载,
以及在ClassLoader隔离时,可能找不到配置,
并且,当用户希望将配置放到统一的目录时,不太方便。
Dubbo新版本去掉了dubbo.properties,因为该约定经常造成配置冲突。
(2) 而对于描述配置,
因为要参与业务逻辑,通常会嵌到应用的生命周期管理中,
现在使用spring的项目越来越多,直接使用spring配置的比较普遍,
而且spring允许自定义schema,配置简化后很方便,
当然,也有它的缺点,就是强依赖spring,
可以提编程接口做了配套方案。
在Dubbo即存在描述配置,也有环境配置,
一部分用spring的schame配置加载,一部分从classpath扫描properties配置加载,
用户感觉非常不便,所以在新版本中进行了合并,
统一放到spring的schame配置加载,也增加了配置的灵活性。
(3) 扩展配置,通常对配置的聚合要求比较高,
因为产品需要发现第三方实现,将其加入产品内部,
在java世里,通常是约定在每个jar包下放一个指定文件加载,
比如:eclipse的plugin.xml,struts2的struts-plugin.xml等,
这类配置可以考虑java标准的服务发现机制,
即在jar包的META-INF/services下放置接口类全名文件,内容为每行一个实现类类名,
就像jdk中的加密算法扩展,脚本引擎扩展,新的JDBC驱动等,都是采用这种方式,
参见:ServiceProvider规范
Dubbo旧版本通过约定在每个jar包下,
放置名为dubbo-context.xml的spring配置进行扩展与集成,
新版本改成用jdk自带的META-INF/services方式,
去掉过多的spring依赖。
4. 可编程配置
配置的可编程性是非常必要的,不管你以何种方式加载配置文件,
都应该提供一个编程的配置方式,允许用户不使用配置文件,直接用代码完成配置过程,
因为一个产品,尤其是组件类产品,通常需要和其它产品协作使用,
当用户集成你的产品时,可能需要适配配置方式。
Dubbo新版本提供了与xml配置一对一的配置类,
如:ServiceConfig对应<dubbo:service />,并且属性也一对一,
这样有利于文件配置与编程配置的一致性理解,减少学习成本。
5. 配置缺省值
配置的缺省值,通常是设置一个常规环境的合理值,这样可以减少用户的配置量,
通常建议以线上环境为参考值,开发环境可以通过修改配置适应,
缺省值的设置,最好在最外层的配置加载就做处理,
程序底层如果发现配置不正确,就应该直接报错,容错在最外层做,
如果在程序底层使用时,发现配置值不合理,就填一个缺省值,
很容易掩盖表面问题,而引发更深层次的问题,
并且配置的中间传递层,很可能并不知道底层使用了一个缺省值,
一些中间的检测条件就可能失效,
Dubbo就出现过这样的问题,中间层用“地址”做为缓存Key,
而底层,给“地址”加了一个缺省端口号,
导致不加端口号的“地址”和加了缺省端口的“地址”并没有使用相同的缓存。
6. 配置一致性
配置总会隐含一些风格或潜规则,应尽可能保持其一致性,
比如:很多功能都有开关,然后有一个配置值:
(1) 是否使用注册中心,注册中心地址。
(2) 是否允许重试,重试次数。
你可以约定:
(1) 每个都是先配置一个boolean类型的开关,再配置一个值。
(2) 用一个无效值代表关闭,N/A地址,0重试次数等。
不管选哪种方式,所有配置项,都应保持同一风格,Dubbo选的是第二种,
相似的还有,超时时间,重试时间,定时器间隔时间,
如果一个单位是秒,另一个单位是毫秒(C3P0的配置项就是这样),配置人员会疯掉。
7. 配置覆盖
提供配置时,要同时考虑开发人员,测试人员,配管人员,系统管理员,
测试人员是不能修改代码的,而测试的环境很可能较为复杂,
需要为测试人员留一些“后门”,可以在外围修改配置项,
就像spring的PropertyPlaceholderConfigurer配置,支持SYSTEM_PROPERTIES_MODE_OVERRIDE,
可以通过JVM的-D参数,或者像hosts一样约定一个覆盖配置文件,
在程序外部,修改部分配置,便于测试。
Dubbo支持通过JVM参数-Dcom.xxx.XxxService=dubbo://10.1.1.1:1234
直接使远程服务调用绕过注册中心,进行点对点测试。
还有一种情况,开发人员增加配置时,都会按线上的部署情况做配置,如:
<dubbo:registry address="${dubbo.registry.address}" />
因为线上只有一个注册中心,这样的配置是没有问题的,
而测试环境可能有两个注册中心,测试人员不可能去修改配置,改为:
<dubbo:registry address="${dubbo.registry.address1}" />
<dubbo:registry address="${dubbo.registry.address2}" />
所以这个地方,Dubbo支持在${dubbo.registry.address}的值中,
通过竖号分隔多个注册中心地址,用于表示多注册中心地址。
8. 配置继承
配置也存在“重复代码”,也存在“泛化与精化”的问题,
比如:Dubbo的超时时间设置,每个服务,每个方法,都应该可以设置超时时间,
但很多服务不关心超时,如果要求每个方法都配置,是不现实的,
所以Dubbo采用了,方法超时继承服务超时,服务超时再继承缺省超时,没配置时,一层层向上查找。
另外,Dubbo旧版本所有的超时时间,重试次数,负载均衡策略等都只能在服务消费方配置,
但实际使用过程中发现,服务提供方比消费方更清楚,但这些配置项是在消费方执行时才用到的,
新版本,就加入了在服务提供方也能配这些参数,通过注册中心传递到消费方,
做为参考值,如果消费方没有配置,就以提供方的配置为准,相当于消费方继承了提供方的建议配置值,
而注册中心在传递配置时,也可以在中途修改配置,这样就达到了治理的目的,继承关系相当于:
服务消费者 --> 注册中心 --> 服务提供者
9. 配置向后兼容
向前兼容很好办,你只要保证配置只增不减,就基本上能保证向前兼容,
但向后兼容,也是要注意的,要为后续加入新的配置项做好准备,
如果配置出现一个特殊配置,就应该为这个“特殊”情况约定一个兼容规则,
因为这个特殊情况,很有可能在以后还会发生,
比如:有一个配置文件是保存“服务=地址”映射关系的,
其中有一行特殊,保存的是“注册中心=地址”,
现在程序加载时,约定“注册中心”这个Key是特殊的,
做特别处理,其它的都是“服务”,
然而,新版本发现,要加一项“监控中心=地址”,
这时,旧版本的程序会把“监控中心”做为“服务”处理,
因为旧代码是不能改的,兼容性就很会很麻烦,
如果先前约定“特殊标识+XXX”为特殊处理,后续就会方便很多。
向后兼容性,可以多向HTML5学习,参见:HTML5设计原理
------------------------
Dubbo设计分享系列:
防痴呆设计
负载均衡扩展接口重构
一些设计上的基本常识
谈谈泛化式扩展与组合式扩展
http://pt.alibaba-inc.com/wp/experience_1182/sofeware-configuration-design.html
Dubbo现在的设计是完全无侵入,也就是使用者只依赖于配置契约,
经过多个版本的发展,为了满足各种需求场景,配置越来越多,
为了保持兼容,配置只增不减,里面潜伏着各种风格,约定,规则,
新版本也将配置做了一次调整,去掉了dubbo.properties,改为全spring配置,
将想到的一些记在这,备忘。
1. 配置分类
首先,配置的用途是有多种的,大致可以分为:
(1) 环境配置,比如:连接数,超时等配置。
(2) 描述配置,比如:服务接口描述,服务版本等。
(3) 扩展配置,比如:协议扩展,策略扩展等。
2. 配置格式
(1) 通常环境配置,用properties配置会比较方便,
因为都是一些离散的简单值,用key-value配置可以减少配置的学习成本。
(2) 而描述配置,通常信息比较多,甚至有层次关系,
用xml配置会比较方便,因为树结构的配置表现力更强,
如果非常复杂,也可以考自定义DSL做为配置,
有时候这类配置也可以用Annotation代替,
因为这些配置和业务逻辑相关,放在代码里也是合理的。
(3) 另外扩展配置,可能不尽相同,
如果只是策略接口实现类替换,可以考虑properties等结构,
如果有复杂的生命周期管理,可能需要XML等配置,
有时候扩展会通过注册接口的方式提供。
3. 配置加载
(1) 对于环境配置,
在java世界里,比较常规的做法,
是在classpath下约定一个以项目为名称的properties配置,
比如:log4j.properties,velocity.properties等,
产品在初始化时,自动从classpath下加载该配置,
我们平台的很多项目也使用类似策略,
如:dubbo.properties,comsat.xml等,
这样有它的优势,就是基于约定,简化了用户对配置加载过程的干预,
但同样有它的缺点,当classpath存在同样的配置时,可能误加载,
以及在ClassLoader隔离时,可能找不到配置,
并且,当用户希望将配置放到统一的目录时,不太方便。
Dubbo新版本去掉了dubbo.properties,因为该约定经常造成配置冲突。
(2) 而对于描述配置,
因为要参与业务逻辑,通常会嵌到应用的生命周期管理中,
现在使用spring的项目越来越多,直接使用spring配置的比较普遍,
而且spring允许自定义schema,配置简化后很方便,
当然,也有它的缺点,就是强依赖spring,
可以提编程接口做了配套方案。
在Dubbo即存在描述配置,也有环境配置,
一部分用spring的schame配置加载,一部分从classpath扫描properties配置加载,
用户感觉非常不便,所以在新版本中进行了合并,
统一放到spring的schame配置加载,也增加了配置的灵活性。
(3) 扩展配置,通常对配置的聚合要求比较高,
因为产品需要发现第三方实现,将其加入产品内部,
在java世里,通常是约定在每个jar包下放一个指定文件加载,
比如:eclipse的plugin.xml,struts2的struts-plugin.xml等,
这类配置可以考虑java标准的服务发现机制,
即在jar包的META-INF/services下放置接口类全名文件,内容为每行一个实现类类名,
就像jdk中的加密算法扩展,脚本引擎扩展,新的JDBC驱动等,都是采用这种方式,
参见:ServiceProvider规范
Dubbo旧版本通过约定在每个jar包下,
放置名为dubbo-context.xml的spring配置进行扩展与集成,
新版本改成用jdk自带的META-INF/services方式,
去掉过多的spring依赖。
4. 可编程配置
配置的可编程性是非常必要的,不管你以何种方式加载配置文件,
都应该提供一个编程的配置方式,允许用户不使用配置文件,直接用代码完成配置过程,
因为一个产品,尤其是组件类产品,通常需要和其它产品协作使用,
当用户集成你的产品时,可能需要适配配置方式。
Dubbo新版本提供了与xml配置一对一的配置类,
如:ServiceConfig对应<dubbo:service />,并且属性也一对一,
这样有利于文件配置与编程配置的一致性理解,减少学习成本。
5. 配置缺省值
配置的缺省值,通常是设置一个常规环境的合理值,这样可以减少用户的配置量,
通常建议以线上环境为参考值,开发环境可以通过修改配置适应,
缺省值的设置,最好在最外层的配置加载就做处理,
程序底层如果发现配置不正确,就应该直接报错,容错在最外层做,
如果在程序底层使用时,发现配置值不合理,就填一个缺省值,
很容易掩盖表面问题,而引发更深层次的问题,
并且配置的中间传递层,很可能并不知道底层使用了一个缺省值,
一些中间的检测条件就可能失效,
Dubbo就出现过这样的问题,中间层用“地址”做为缓存Key,
而底层,给“地址”加了一个缺省端口号,
导致不加端口号的“地址”和加了缺省端口的“地址”并没有使用相同的缓存。
6. 配置一致性
配置总会隐含一些风格或潜规则,应尽可能保持其一致性,
比如:很多功能都有开关,然后有一个配置值:
(1) 是否使用注册中心,注册中心地址。
(2) 是否允许重试,重试次数。
你可以约定:
(1) 每个都是先配置一个boolean类型的开关,再配置一个值。
(2) 用一个无效值代表关闭,N/A地址,0重试次数等。
不管选哪种方式,所有配置项,都应保持同一风格,Dubbo选的是第二种,
相似的还有,超时时间,重试时间,定时器间隔时间,
如果一个单位是秒,另一个单位是毫秒(C3P0的配置项就是这样),配置人员会疯掉。
7. 配置覆盖
提供配置时,要同时考虑开发人员,测试人员,配管人员,系统管理员,
测试人员是不能修改代码的,而测试的环境很可能较为复杂,
需要为测试人员留一些“后门”,可以在外围修改配置项,
就像spring的PropertyPlaceholderConfigurer配置,支持SYSTEM_PROPERTIES_MODE_OVERRIDE,
可以通过JVM的-D参数,或者像hosts一样约定一个覆盖配置文件,
在程序外部,修改部分配置,便于测试。
Dubbo支持通过JVM参数-Dcom.xxx.XxxService=dubbo://10.1.1.1:1234
直接使远程服务调用绕过注册中心,进行点对点测试。
还有一种情况,开发人员增加配置时,都会按线上的部署情况做配置,如:
<dubbo:registry address="${dubbo.registry.address}" />
因为线上只有一个注册中心,这样的配置是没有问题的,
而测试环境可能有两个注册中心,测试人员不可能去修改配置,改为:
<dubbo:registry address="${dubbo.registry.address1}" />
<dubbo:registry address="${dubbo.registry.address2}" />
所以这个地方,Dubbo支持在${dubbo.registry.address}的值中,
通过竖号分隔多个注册中心地址,用于表示多注册中心地址。
8. 配置继承
配置也存在“重复代码”,也存在“泛化与精化”的问题,
比如:Dubbo的超时时间设置,每个服务,每个方法,都应该可以设置超时时间,
但很多服务不关心超时,如果要求每个方法都配置,是不现实的,
所以Dubbo采用了,方法超时继承服务超时,服务超时再继承缺省超时,没配置时,一层层向上查找。
另外,Dubbo旧版本所有的超时时间,重试次数,负载均衡策略等都只能在服务消费方配置,
但实际使用过程中发现,服务提供方比消费方更清楚,但这些配置项是在消费方执行时才用到的,
新版本,就加入了在服务提供方也能配这些参数,通过注册中心传递到消费方,
做为参考值,如果消费方没有配置,就以提供方的配置为准,相当于消费方继承了提供方的建议配置值,
而注册中心在传递配置时,也可以在中途修改配置,这样就达到了治理的目的,继承关系相当于:
服务消费者 --> 注册中心 --> 服务提供者
9. 配置向后兼容
向前兼容很好办,你只要保证配置只增不减,就基本上能保证向前兼容,
但向后兼容,也是要注意的,要为后续加入新的配置项做好准备,
如果配置出现一个特殊配置,就应该为这个“特殊”情况约定一个兼容规则,
因为这个特殊情况,很有可能在以后还会发生,
比如:有一个配置文件是保存“服务=地址”映射关系的,
其中有一行特殊,保存的是“注册中心=地址”,
现在程序加载时,约定“注册中心”这个Key是特殊的,
做特别处理,其它的都是“服务”,
然而,新版本发现,要加一项“监控中心=地址”,
这时,旧版本的程序会把“监控中心”做为“服务”处理,
因为旧代码是不能改的,兼容性就很会很麻烦,
如果先前约定“特殊标识+XXX”为特殊处理,后续就会方便很多。
向后兼容性,可以多向HTML5学习,参见:HTML5设计原理
------------------------
Dubbo设计分享系列:
防痴呆设计
负载均衡扩展接口重构
一些设计上的基本常识
谈谈泛化式扩展与组合式扩展
发表评论
-
能力成长模型
2012-05-09 00:28 23017最近看了温伯格1986年出版的《技术领导之路》, 很老的书,讲 ... -
以HTTL为例讲讲模块分包&领域模型&扩展框架
2011-10-09 20:08 16816注:该博客内容已加入 ... -
使用Map参数的Webx3扩展
2011-08-28 02:10 5935因Webx3是开源的,所以把这个简单的Webx3扩展发在博客上 ... -
Netty内存泄露
2011-08-02 20:09 24980转于自己在公司的Blog: ... -
Grizzly和Netty以及Mina简单性能对比
2011-07-17 02:48 29767转于自己在公司的Blog: http://pt.alibaba ... -
RPC框架几行代码就够了
2011-07-14 00:34 90291转于自己在公司的Blog: http://pt.alibaba ... -
魔鬼在细节中
2011-05-24 14:50 32255转于自己在公司的Blog: ... -
Dubbo扩展点重构
2011-05-12 22:09 38913转于自己在公司的Blog: http://pt.alibaba ... -
[转]HTML5设计原理
2011-03-09 22:57 7839Jeremy Keith在 Fronteers 2010 ... -
Hessian序列化不设SerializerFactory性能问题
2010-12-27 11:38 6490转于自己在公司的Blog: http://pt.alibaba ... -
动态代理方案性能对比
2010-11-17 21:38 46253转于自己在公司的Blog: http://pt.alibaba ... -
防痴呆设计
2010-11-05 18:58 17703转于自己在公司的Blog: ... -
负载均衡扩展接口重构
2010-11-05 18:53 8768转于自己在公司的Blog: ... -
分布式服务框架常被质疑的价值
2010-11-05 18:52 5743转于自己在公司的Blog: http://pt.alibaba ... -
Hessian3.2.1在序列化32.5k字符串时的问题
2010-11-05 18:49 7289转于自己在公司的Blog: http://pt.alibaba ... -
一些设计上的基本常识
2010-07-05 19:28 27806转于自己在公司的Blog: ... -
谈谈扩充式扩展与增量式扩展
2010-06-12 19:46 19427转于自己在公司的Blog: http://pt.alibaba ... -
Scaling Architecture
2010-02-25 10:31 4129Scaling Second Life: http://p ... -
EBay SOA
2010-02-23 18:23 4811EBay SOA PPT -
服务化基础设施
2009-11-15 23:11 6291服务化,也可以叫SOA, ...
相关推荐
建筑灭火器配置设计规范 中国国家标准 建筑灭火器配置设计规范 GBJ 140-90
国家标准,规定了建筑物灭火器配置设计的要求
json 配置设计,系统表单控制,json配置信息设计。json 配置设计,系统表单控制,json配置信息设计。json 配置设计,系统表单控制,json配置信息设计。json 配置设计,系统表单控制,json配置信息设计。json 配置...
### 简化FPGA配置设计过程的关键知识点 #### 一、引言 随着电子行业的快速发展,FPGA(Field-Programmable Gate Array,现场可编程门阵列)因其灵活性及高性能成为了众多电子设备中的核心部件之一。然而,在FPGA的...
总结而言,基于PCIe的FPGA动态配置设计与实现是现代互联技术发展的产物,它结合了PCIe技术的高速传输能力与FPGA的可编程灵活性,为高速互联系统的设计与应用提供了新的可能性。通过本文的研究,我们可以了解到...
《建筑灭火器配置设计规范》是中国建筑设计领域的重要标准之一,旨在确保建筑物内灭火设施的合理配置,以便在火灾发生时迅速有效地控制火势,保护人身和财产安全。本规范主要适用于新建、改建、扩建的工业与民用建筑...
该项目是基于Emacs Lisp的个性化Emacs配置设计源码,共包含8463个文件,其中包括2318个HTML页面文件、1246个Lisp源文件、941个EL文件、485个ELC文件、423个TXT文本文件、246个XPM图片文件、223个Python源文件、154个...
【配置设计】是电子工程领域中的一个重要环节,特别是在FPGA(Field-Programmable Gate Array,现场可编程门阵列)的设计中。本教程主要针对Xilinx和Altera两大FPGA厂商的配置设计进行讲解,重点是理解并掌握这两种...
为了应对这一问题,本研究提出了基于有向图形式构建的产品系列多级配置模板,利用图论数学理论和模板变异技术来实现机械产品的快速配置设计。 有向图作为图形表示方法,可以用来表示产品信息模型或其组成结构。在图...
"控制系统的极点配置设计法" 控制系统的极点配置设计法是指在控制系统设计中,对系统的极点进行配置和设计,以满足系统的性能要求。极点配置是指在 s 平面上选择合适的极点,使系统的传递函数满足性能指标要求。 ...
《建筑灭火器配置设计规范》(GB 50140-2005)为建筑灭火器的配置提供了详尽的指导,要求建筑必须根据规范配置合适的灭火器,这一措施在消防检查和验收时会被认真审核。灭火器的类型、规格、数量以及设置位置的规定...
### 园林景观工程中的植物配置设计要点 #### 基本内涵 在园林景观工程中,植物配置设计是一项至关重要的工作。它不仅涉及到植物的选择与搭配,还关乎到整个园林景观的功能性和美观度。植物配置设计的目标在于通过...
本项目为“基于Java的IntelliJ IDEA开发环境配置设计源码”,包含67个文件,其中包括66个XML配置文件、1个Java源文件。该项目利用Java语言开发,旨在为开发者提供一个IntelliJ IDEA开发环境的配置示例,涵盖了IDE...
《2017年建筑灭火器配置设计规范》(以下简称“规范”)应运而生,旨在为建筑灭火器配置提供科学、系统的指导,确保初期火灾可以被迅速有效地控制。 根据规范的要求,建筑设计中必须将灭火器配置纳入设计组成部分,...
本文提出的Leon3软核的FPGA SelectMap接口配置设计,是一种创新的方法,它不仅摆脱了传统使用CPLD(复杂可编程逻辑器件)和CPU(中央处理单元)组合的方式,而是将Leon3开源CPU软核嵌入到FPGA中,直接控制Virtex系列...
《建筑灭火器配置设计规范标准》是针对工业与民用建筑灭火器配置的重要指导文件,旨在合理配置灭火器,有效扑救初起火灾,减少火灾损失,保障人身和财产安全。该规范适用于新建、扩建的涉及可燃物的工业与民用建筑...
《建筑灭火器配置设计规范条文总则》是指导建筑灭火器配置的重要法规,旨在确保建筑内灭火器的合理配置,提升初期火灾的扑救能力。条文指出,灭火器作为初起火灾扑救的关键设备,其配置应当科学、统一,以避免因配置...
在本文中,作者探讨了基于Visual Basic和SQL Server的汽车钢板弹簧自组织配置设计系统的开发。该系统旨在满足汽车钢板弹簧的自组织配置设计需求,通过软件实现客户与设计人员之间的实时交流。 首先,汽车钢板弹簧是...
该项目为基于C语言与CUBEMX框架开发的TDK-HVC5221D芯片步进电机控制及ADC配置设计源码,包含125个文件,其中包括21个头文件、20个源文件、18个配置文件、17个寄存器定义文件、4个JSON文件、2个映射文件和2个文本文件...