游戏电视苹果数码历史美丽
投稿投诉
美丽时装
彩妆资讯
历史明星
乐活安卓
数码常识
驾车健康
苹果问答
网络发型
电视车载
室内电影
游戏科学
音乐整形

基于Dubbo3。1。8分析Dubbo3源码

  前言
  从本章开始基于Dubbo3。1。8分析Dubbo3源码。
  由于Dubbo3中到处都会出现各种xxxModel,所以必须先搞清楚这些东西的作用。
  本章主要分析:
  1)DubboSPI的变更;
  2)多实例特性及其作用;
  3)Deployer新角色及其作用;一、SPI?Scope
  在3。x之前,ExtensionLoader针对于一个扩展点接口只有一个实例,针对一个扩展点实现Class也只有一个扩展点实现实例。
  2。xExtensionLoader全局缓存:
  在第一章的时候提到过,单例往往会针对一个scope来说,而在Dubbo3。0引入了Scope概念。
  ExtensionScope列举了目前支持的四种scope:FRAMEWORKdubbo框架级别、APPLICATION应用级别、MODULE模块级别、SELFprototype原型;publicenumExtensionScope{FRAMEWORK,APPLICATION,MODULE,SELF}复制代码
  不同scope有不同ScopeModel负责管理。
  ScopeModel实现ExtensionAccessor,提供获取SPI扩展点的能力。
  dubbo中所有用到扩展点的地方,都会通过ScopeModel来获取对应scope下的扩展点。
  而原来ExtensionLoadergetExtensionLoader(type)方法已经废弃,委派给全局单例ModuleModel获取扩展点。
  每个ScopeModel实例对应一个ExtensionDirector,所有获取扩展点逻辑都委派给这个ExtensionDirector。privatevolatileExtensionDirectorextensionDirector;protectedvoidinitialize(){synchronized(instLock){this。extensionDirectornewExtensionDirector(parent!null?parent。getExtensionDirector():null,scope,this);。。。}}复制代码
  ExtensionDirector存储一个scope范围中扩展接口class对应ExtensionLoader,从而实现了不同scope管理自己的ExtensionLoader实例。
  双亲委派?
  ExtensionDirectorgetExtensionLoader:获取或创建ExtensionLoader。
  1)如果scopeSELF,每次创建一个ExtensionLoader;
  2)优先走parent获取ExtensionLoader;
  3)parent找不到,自己判断scope是否和扩展点SPI注解scope一致,一致才创建ExtensionLoader;
  双亲关系:Framework最大,接着是Application,最后是Module。
  如果scopeFramework,通过ModuleModelApplicationModel也能获取到,且module、application、framework具备父子关系的三个ScopeModel都会拿到同一个扩展点实现。
  例如Codec2编解码器,一种Codec2编解码器在一个FrameworkModel中只有一个实例。
  如果scopeModule,只能通过ModuleModel获取,ApplicationModelFrameworkModel获取不到。
  例如Filter过滤器,一种Filter过滤器在一个ModuleModel中只有一个实例。
  依赖注入
  2。x仅支持setter注入。
  3。x增加了构造aware注入,主要是为了方便接入ScopeModel。
  ExtensionLoadercreateExtension:
  普通扩展点支持构造setteraware注入。
  构造注入
  InstantiationStrategyinstantiate:选择构造方法实例化扩展点。
  目前支持两种构造方法,一种无参构造,另一种是参数列表只有ScopeModel的构造方法。
  优先会取ScopeModel注入构造方法,默认采用无参构造。
  可以注入不同ScopeModel。
  setter注入
  和2。x相同,通过一个自适应扩展AdaptiveExtensionInjector,循环所有ExtensionInjector,获取setter方法的typename对应实现实例。
  SpiExtensionInjector
  和2。x相同,通过setter方法可以注入自适应扩展实现。
  区别在于需要通过关联ScopeModel获取对应scope下的扩展实例。
  ScopeBeanExtensionInjector
  3。x新支持从一个scope的BeanFactory中获取bean注入,这个BeanFactory后续再聊。
  SpringExtensionInjector
  3。x对于springioc容器注入更合理了,一个SpringExtensionInjector只能对应一个ioc容器。
  ApplicationContext是有父子关系的,2。x通过多个ApplicationContext循环获取bean,不太合理。
  Aware注入
  ExtensionLoaderpostProcessAfterInitialization:
  ExtensionAccessorAware接口实现,通过setExtensionAccessor注入scope对应ExtensionDirector。
  ScopeModelAwareExtensionProcessorpostProcessAfterInitialization:
  ScopeModelAware接口实现,注入当前scope持有的Model。
  ScopeModelAwareExtensionProcessorinitialize:
  不同scope能注入的Model不同。
  Wrapper增强
  2。7。8版本做了Wrapper增强(github。comapachedubb)。
  注:因为之前读的是2。7。6,说到Wrapper无序,这里澄清一下。
  1)支持直接获取未包装扩展点实现
  ExtensionLoadergetExtension支持传入wrap,决定是否获取被包装的扩展点实现。
  ExtensionLoader会缓存被包装和未被包装的扩展点实现。
  2)支持包装排序
  3)支持针对部分扩展点实现做包装
  注意:包装类仅支持SetterAware注入,不支持构造注入。BeanFactory?
  ScopeModelinitialize:每个ScopeModel都持有一个ScopeBeanFactory。
  这个BeanFactory是干嘛用的,和Extension扩展点有什么关系,有什么区别?
  ScopeBeanFactory用于统一管理ScopeModel范围内的非扩展点bean。注册bean
  ScopeModelInitializer扩展点负责在ScopeModel构造时,执行一些初始化任务。
  如FrameworkModel:
  如ApplicationModel:
  这些ScopeModelInitializer会向ScopeModel的beanFactory中注入一些自己需要用的bean。
  比如dubbocluster模块需要用到bean都会在ClusterScopeModelInitializer中注入,bean可以选择在某个scope下单例。
  无论是基于Class注册还是基于instance直接注册,最终都会执行初始化Aware注入,放入beanFactory缓存。
  获取bean
  获取bean,先走当前scopeBeanFactory获取,如果获取不到,走父scopeBeanFactory获取。
  注意:这里和SPI扩展点Scope双亲委派是相反的,但是和SpringIOC是一样的,子容器能感知到父容器,父容器对子容器无感知。
  底层优先name匹配,其次type匹配(匹配多个抛出异常),如果都匹配不到返回null。
  二、多实例
  基于ScopeModel非单例,3。0提供了多实例的新特性。
  FrameworkModel,支持同一个jvm内部dubbo框架级别隔离。
  ApplicationModel,支持应用级别隔离。
  ModuleModel,支持模块级别隔离。
  应用级别隔离案例
  通过DubboBootstrapnewInstance这个新api,可以构造多个DubboBootstrap实例。ApplicationConfigapplicationConfignewApplicationConfig(app1);applicationConfig。setRegisterMode(instance);应用实例级别注册ServiceConfigDemoServiceImplservicenewServiceConfig();service。setInterface(DemoService。class);service。setRef(newDemoServiceImpl());DubboBootstrap。newInstance()。application(applicationConfig)。registry(newRegistryConfig(zookeeper:127。0。0。1:2181))。protocol(newProtocolConfig(CommonConstants。DUBBO,20880))。service(service)。start();ApplicationConfigapplicationConfig2newApplicationConfig(app2);applicationConfig2。setRegisterMode(instance);应用实例级别注册ServiceConfigDemoServiceImplservice2newServiceConfig();service2。setInterface(DemoService。class);service2。setRef(newDemoServiceImpl());DubboBootstrap。newInstance()。application(applicationConfig2)。registry(newRegistryConfig(zookeeper:127。0。0。1:2181))。protocol(newProtocolConfig(CommonConstants。DUBBO,20880))。service(service2)。start();复制代码
  注意:两个应用使用了同样的dubbo端口20880,但是并不会触发端口冲突。
  原因是Protocol是framework级别的。
  Protocol成员变量serverMap在framework级别只有一份。
  DubboProtocolopenServer:发现已经存在20880端口上的ProtocolServer,跳过。
  多Bootstrap
  DubboBootstrap底层从2。7。5全局单例变为ApplicationModel纬度下单例。
  DubboBootstrapnewInstance:
  1)FrameworkModeldefaultModelnewApplication:利用全局默认FrameworkModel创建一个新的ApplicationModel
  2)DubboBootstrapgetInstance(ApplicationModel):创建DubboBootstrap放入全局缓存instanceMap
  对于2。7的DubboBootstrapgetInstanceapi,用全局默认ApplicationModel创建DubboBootstrap。
  应用级别对象
  2。xConfigManager管理所有AbstractConfig,到3。x这里只管理应用级别AbstractConfig。
  比如应用配置ApplicationConfig、配置中心配置ConfigCenterConfig、注册中心配置RegistryConfig等等。
  其中大部分配置对应实际实例都同样是应用级别对象。
  比如元数据中心。
  比如基于rpc服务级别的注册中心。
  比如基于应用级别的注册中心。
  比如配置中心。
  应用级别kv配置Environment。
  但是Protocol协议是框架级别。
  服务端处理rpc请求的线程池(DubboServerHandler线程)是独立的,默认200固定线程池。
  注意,线程池创建策略ThreadPool是框架级别的,但是线程池实例ExecutorService是应用级别的。
  有什么用
  DubboBootstrap多实例支持后,可以在一个jvm进程中部署多个dubbo应用。
  举个例子,下面这个issue因为多ioc容器的情况下,DubboBootstrap只能启动一次,导致部分服务没有暴露。
  github。comapachedubb模块级别隔离案例
  在配置ReferenceConfig时,可以指定所属模块,不同模块中的ReferenceConfig都是相互独立的。
  注:该案例即使不建立多个module,也没有问题,只是说明api的使用。System。setProperty(dubbo。application。servicediscovery。migration,FORCEAPPLICATION);ApplicationConfigconsumerAppnewApplicationConfig(multimoduleappconsumer);ReferenceConfigDemoServicedirectReferencenewReferenceConfig();directReference。setInterface(DemoService。class);directReference。setScope(remote);不走injvm调用ReferenceConfigDemoServicecacheReferencenewReferenceConfig();cacheReference。setInterface(DemoService。class);cacheReference。setScope(remote);不走injvm调用cacheReference。setCache(lfu);走dubbo自带本地缓存ApplicationModelapplicationModelFrameworkModel。defaultModel()。newApplication();DubboBootstrapbootstrapDubboBootstrap。getInstance(applicationModel)。application(consumerApp)。registry(newRegistryConfig(zookeeper:127。0。0。1:2181))。protocol(newProtocolConfig(CommonConstants。DUBBO,1))。reference(directReference,applicationModel。newModule())focus。reference(cacheReference,applicationModel。newModule())focus。start();复制代码多Module
  每个ReferenceConfig会关联一个ModuleModel。
  每个ModuleModel都有一个模块级别的ModuleConfigManager(类比ConfigManager),管理部分AbstractConfig,比如ReferenceConfig。
  模块级别对象
  ModuleConfigManger管理部分AbstractConfig,包括ServiceConfig、ReferenceConfig等等。
  这些配置都是从原来ConfigManager中拆分出来的,现在是模块级别配置。
  Module级别也有自己的ModuleEnvironment。
  Filter是模块级别的。
  即便如此,很多Filter内部依赖的还是应用级别甚至全局变量,比如CacheFilter管理本地缓存。
  CacheFactory走应用级别,所以本地缓存实际上是应用级别的。
  ClusterFilter是3。0引入的,用于代替ClusterInterceptor(废弃)的扩展点,也是模块级别的。
  Filter的javadoc,说明3。0在负载均衡前会经过ClusterFilter。
  有什么用
  2。x,dubbo在很多地方都用到了serviceKey,即rpc服务唯一标识interfacegroupversion。
  很多地方存储了serviceKey对应的全局配置(map结构),而dubbo并没有强制约束只能有一个serviceKey,导致部分配置相互覆盖。
  举个例子,下面这个issue在异步调用场景下,无法正确获取到Reference上配置的回调方法。
  github。comapachedubb。
  2。x因为一个serviceKey只能有一个ConsumerModel,所以无法获取到正确的AsyncMethodInfo。
  而在3。0,ModuleServiceRepository存储模块级别下的ConsumerModel,从根本上避免了类似问题。
  同一个serviceKey在不同module下可以存在多个ConsumerModel。
  三、Deployer
  引用自dubbo官网:cn。dubbo。apache。orgzhcnoverv
  当服务集群规模进一步扩大,带动IT治理结构进一步升级,需要实现动态部署,进行流动计算,现有分布式服务架构不会带来阻力。下图是未来可能的一种架构:
  dubbo3。0中提到一个新角色Deployer,自动部署服务的本地代理。
  目前Deployer只是一个接口,存在于应用jvm进程中,也并非是一个独立的角色。
  下面是一个案例,通过ModuleDeployer单独启动和停止一个DemoService服务。ApplicationConfigproviderAppnewApplicationConfig(app1);providerApp。setRegisterMode(instance);DubboBootstrapproviderDubboBootstrap。newInstance()。application(providerApp)。registry(newRegistryConfig(zookeeper:127。0。0。1:2181))。protocol(newProtocolConfig(CommonConstants。DUBBO,22880))启动GreetingService。service(tt。interfaceClass(GreetingService。class)。ref((GreetingService)()null))。start();使用ModuleDeployer单独启动DemoServiceModuleModelmodule1provider。getApplicationModel()。newModule();ServiceConfigDemoServiceImpldemoServicenewServiceConfig();demoService。setInterface(DemoService。class);demoService。setRef(newDemoServiceImpl());provider。service(demoService,module1);module1。getDeployer()。start();Assert。assertTrue(module1。getDeployer()。isStarted(),deployerstartfail);使用ModuleDeployer单独停止DemoServicemodule1。getDeployer()。stop();Assert。assertTrue(module1。getDeployer()。isStopped(),deployerstopfail);复制代码
  目前根据ScopeModel划分,支持两个纬度的Deployer,一个是应用,一个是模块。
  DefaultApplicationDeployer启动
  ConfigScopeModelInitializerinitializeApplicationModel
  在ApplicationModel构造期间,创建DefaultApplicationDeployer与当前ApplicationModel绑定。
  DubboBootstrapstart:委派给底层ApplicationDeployerstart(2。7的启动流程都下放到Deployer)。
  ApplicationDeployerstart:我们只考虑首次start的情况,分为两步
  1)DefaultApplicationDeployerinitialize:应用Deployer自己初始化
  2)DefaultApplicationDeployerstartModules:启动ApplicationModel下所有模块的ModuleDeployer
  DefaultApplicationDeployerinitialize:分为以下几步
  1)注册ShutdownHook
  2)连接配置中心,创建动态配置
  3)利用Environment中的kv配置,注入ConfigManager管理的AbstractConfig
  4)初始化模块Deployer
  5)连接元数据中心
  DefaultApplicationDeployerstartModules:所有模块级别的Deployer启动
  销毁
  DubboBootstrapdestroy:委派给对应ApplicationModeldestroy
  ApplicationModelonDestroy:销毁应用model所有依赖
  其中包含ApplicationDeployer和ModuleDeployer。
  DefaultApplicationDeployerpreDestroy:从注册中心注销应用实例。
  DefaultApplicationDeployerpostDestroy:当所有Module销毁后执行
  1)销毁注册中心,取消订阅
  2)销毁所有元数据中心
  3)执行ShutdownHook
  4)销毁线程池
  DefaultModuleDeployer启动
  DefaultModuleDeployerstart:可以由上层ApplicationDeployerstart触发,也可以主动启动
  1)模块级别AbstractConfig填充
  2)暴露服务
  3)引用服务
  销毁
  同样,模块Deployer可以由上层ApplicationModel销毁触发,也可以手动触发。
  DefaultModuleDeployerstop:走Deployer销毁,实际底层是销毁ModuleModel
  ModuleModelonDestroy:销毁ModuleModel
  需要注意的是ModuleModelonDestroy每次执行完成,都会执行ApplicationModeltryDestroy。
  ApplicationModeltryDestroy:判断如果没有ModuleModel存在,会销毁自身,所以ModuleModel销毁可能会触发ApplicationModel销毁。
  DefaultModuleDeployerpreDestroy:状态变更
  DefaultModuleDeployerpostDestroy:
  1)取消暴露
  2)取消引用
  3)销毁ModuleServiceRepository
  总结SPI?
  支持scope,每个ScopeModel管理自己scope下的扩展点。
  通过ScopeModel查找扩展点,走双亲委派模式,优先从父Scope找,父Scope找不到才从自身Scope找。
  每个ScopeModel持有一个BeanFactory,管理非扩展点bean。
  通过BeanFactory查找bean,走ioc父子容器模式,子Scope先从自身找,自身找不到从父Scope找。
  为了方便获取ScopeModel,ExtensionLoader支持构造注入、Aware注入ScopeModel。
  此外,Wrapper包装扩展点在2。7。8版本做了增强,支持排序,支持条件包装。多实例
  3。0支持DubboBootstrap存在多个,本质上是一个ApplicationModel对应一个DubboBoostrap。
  此外,同一个DubboBoostrap中还支持模块级别隔离,本质上是多个ModuleModel。Deployer
  Deployer是3。0提出的新角色。
  官网的解释是自动部署服务的本地代理。
  目前在代码中是以Deployer接口的形式出现。
  原来2。7中DubboBootstrap的启动和停止逻辑都下沉到Deployer中。
  ApplicationDeployer,借助ApplicationModel,实现应用粒度的自动部署服务,负责应用级别的启动和停止。
  比如连接配置中心、元数据中心。
  ModuleDeployer,借助ModuleModel,实现模块粒度的自动部署服务,负责模块级别的启动和停止。
  比如暴露服务、引用服务。

LSB碾压复仇T1,赛后选手再现弱爆大拇指!小吕布又被打爆了如今已经是来到了秋天,全球的LOL赛事也基本都靠近尾声了,不只是LPL,2022年LCK夏季常规赛结局也初步清晰,就在最近的LCK比赛中我们了解到的讯息是,T1以02的战绩狠狠……性能强劲功耗极低,夏天换机优选这6款,告别暖宝宝手机手机发热算是最烦人的问题,不少粉丝总问我有没有发热少的手机推荐。想要发热少,要么使用功耗小的处理器,比如一代神U骁龙870或者新晋控耗王天玑8100,功耗小性能强。或者是加入大……感悟一下人生有少年的年少轻狂、有青年的努力奋斗、有中年的成家立业、有晚年的天伦之乐一切都要经历,都要走过去,都将会成为回忆。人生就像一场途旅行。会有许许多多大大小小的站点,但不能让这……夏季赛韦神再登战神榜,老王重回赛场!NH强势夺得周冠对于大部分喜欢观看国内《绝地求生:大逃杀》游戏赛事的网友们而言,肯定都对当下正在火热开战的PCL夏季赛不会感到陌生。作为目前圈内公认知名度最高的一场职业赛事,依靠其独特的赛事风……仲夏节精美好物悉数上线,pick心动之选,美美开启度夏模式《一梦江湖》小伙伴期待已久的仲夏节好物终于上线啦!新时装、新坐骑、新玩具等一应俱全不知道大家有没有第一时间将自己心仪的精致外观收入囊中呢?这次的新时装月影传音拥有简单利落的剪裁……分享行李箱的一些小细节一个完整而愉快的旅程需要一个您喜欢的行李箱,今天就从箱体材质、拉杆、锁扣、箱轮四个方面为大家介绍如何选择自己喜欢和适合自己的旅行箱。一、手提箱的材质手提箱有两种类型……央视颜霸李红,被传嫁豪门,公公入狱,如今她过得怎么样?李红是中央电视台优秀的主持人之一,还有另一个称号央视颜霸,颜值高,气质好。李红主持过《想挑战吗》、《远方的家》、《唱给你听》等精彩节目,其中常驻节目,便是《海峡两岸》。……steam生存游戏节游戏推荐steam生存游戏节买什么游戏好steam生存游戏节,就是为了生存类游戏爱好者举办的。玩家在活动举办时间期间,可以免费试玩超多游戏的DEMO,还可以入手大量有折扣的生存游戏。下面是小编总结的几款steam生存……三一重工,徐工机械,京东方A白马分化能否布局?下周怎么走?大盘本周收出探底回升的K线,周小跌0。52,而三一重工,徐工机械,京东方A等白马本周迎来了分化。其中三一重工涨2。35,徐工机械大涨7。51,京东方A小跌0。52。这些白马龙头……蔡国庆儿子真争气,期末考试喜提三好学生和全科免考证蔡国庆:儿子真争气,期末考试喜提三好学生和全科免考证聚焦艺人最新动态,传递圈内主流声音。【晓今娱】全网特供今日头条独家首发,严禁转载【本文由晓今娱原创,欢迎关……幸福到万家六个不出名的角色,这次终于可以扬眉吐气了赵丽颖主演的《幸福到万家》一经上线就迅速火爆全网,主演原因还是赵丽颖自带流量,其次估计是剧中的配角们一个比一个出彩!估计很多配角通过《幸福到万家》这部剧已经火向了全国,终……人活到50岁,如果身上有这4个标志,恭喜你可能更容易长寿人的一生,就好像是一轮太阳:清晨也就是我们年轻的时候,朝气磅礴,富有青春和活力;傍晚的时候就是我们衰老的时候,虽然太阳还有余光,但终究也要落下山去;而中午的时……
银河系违章哥是谁?银河系违章哥说了什么?违章很多,但是一位来自银行系皇家的公子公然违章,与警察讲起了法律,你听过吗?这件事情确有其事,银河系违章哥的语录也爆红网络。银河系违章哥是谁?银河系违章哥说了什么?银河系……一季度彩电市场开门不大吉但有三大特点值得关注据奥维云网(AVC)预测数据显示,2022年第一季度中国彩电市场零售量规模为903万台,同比下降8。8;零售额规模为280亿元,同比下降10。1。可以看到,今年一季度量额都继续……梅花可以放卧室吗?梅花放在卧室风水好吗?梅花是冬天开的一种花,象征着一种气节。因此,一些比较追求雅致的人会养殖这种花。那么,梅花可以放卧室吗?梅花放在卧室风水好吗?梅花可以放卧室吗家里可以摆放梅花。……10月份可以种什么花?10月份种花好吗10月份正值秋季,很多人喜欢种花,那么10月份是否可以种花呢?10月份种什么花好呢?下面我们来为大家一起介绍下吧!10月份种花好吗可以啊,适合秋播秋种的花草很多呀,……胖哥俩在执法人员检查前丢弃食材吃死螃蟹有什么危害最近胖哥俩对于用死螃蟹的新闻是非常火爆的,很多人都多少有些了解,而这也引起了市监局的注意,但胖哥俩在执法人员到来之前将有问题的食材全部丢弃,我们接下来便一起了解一下。胖哥俩在执……碎碎念35哥又邀请我们去参观他们家的别墅,犹豫很久还是去了到达和顺古镇的第二天,一早醒来,草草吃过早饭,我们计划去国殇墓园,却被客栈老板告知,当天闭馆。于是,粉墙黛瓦的和顺古镇成为腾冲之行的第一印记。客栈老板陪我们两人,随意而悠闲漫无……柴胡注射剂说明书柴胡注射剂使用说明柴胡注射剂是一款很不错的退烧药品,但是这个是打针用的,很多人都想多了解一下这款药品,下面介绍柴胡注射剂说明书柴胡注射剂使用说明。柴胡注射剂说明书【药品名称】柴胡注射液……小柴胡颗粒产妇能吃吗?小柴胡颗粒产后能吃吗?产妇吃药也是需要好好注意的,很多药不能吃,下面5号网的小编为你们介绍小柴胡颗粒产妇能吃吗?小柴胡颗粒产后能吃吗?小柴胡颗粒产妇能吃吗产妇感冒是可以用药物的,一般的中成药都……北京密云大集一览表赶集这个词听起来不新鲜,但是随着城市的发展,农村大集越来越少。在北京的密云郊区的部分村镇,还保留着很多农村山货大集,每到开集的当天,村子里的一家老小结伴去赶集,人流涌动,……小柴胡颗粒可以和头孢一起吃吗可以解酒吗?服用头孢这种药品是有着很多限制的,不能与很多药一起吃,下面5号网的小编为你们介绍小柴胡颗粒可以和头孢一起吃吗可以解酒吗?小柴胡颗粒可以和头孢一起吃吗建议服用风寒感冒颗粒,……女网红徒步西藏直播时遇难徒步旅行需要准备什么现在越来越多的人都喜欢旅行,而同时现在很多的独自徒步也是非常火热的,引来了很多人的效仿,那么我们便来了解一下女网红徒步西藏直播时遇难?徒步旅行需要准备什么?女网红徒步西藏直播时……青藏高原,和南极北极齐名,你又了解多少?地球是这样划分的,南极、北极、第三极和其他地方。提起青藏高原,你想到的是什么?是皑皑雪山,是高耸入云,是冰天雪地,还是生命禁区?很久很久以前,青藏高原还是一片汹涌的海域,……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网