Exodus 的重构和向 Apollo 的迁移 1: Apollo 在哪些环节切入的? 2: 再谈 Webx 中容器的初始化 ( 重构过程的注意事项 ) 3: Exodus2 如何迁移?                    hongjiang...
Apollo 的切入点 1: pipeline 的 valve
替换 PerformActionValve 和           PerformScreenValve                                                             CheckCSRF...
1 ) DO 的 properties 由框架来自动装配2 ) AO 自动注入到 Action 中3 )新的 Action 不再走 CommandDispather
再来说说 webx 中 service 的初始化         ( 重构过程需要注意 )之前大部分的应用部署, web 和 biz 层的 service 容器都是分离的,中间 通过 CommandDispather 方式来交互;但实际上我们没...
现有系统上 (Exodus2 重构前 ) 使用 Apollo 注释:                                                              每个 car 的                  ...
如果维护一个上图布局的 Exodus ,非常头大 ,兼容性所带来的复杂性增加了犯错的可能 性。所以要迁移的话,必须将 Exodus 的布局 进行调整(当然,重构也不仅仅是为了向 apollo 迁移,本来 web/biz 分离的方式对我 们就已经...
合并后, Apollo 框架所期望       的                     全局 SpringxOtherService   ctx                          AO       BO      DAOMa...
注释:原先每个 car 里的 Spring 容器,不再配置任何对象, cd 和 ctx 移到全局 spring 中,它们之间是级联的,所以 car 中访问 cd 时会得到全局 spring 中的 cd 。旧的请求仍走以前的 cd 方式,新的则可...
解惑Web 层的 Service 分布在 main-instance( 全局 ) 和 sub-instance(car 级别 )把 Biz 层合并后,其中 biz 层的 service 要放到 main- instance 中同时考虑有些 su...
Web 层 Service 容器                           全局: name=null              Service 包装                   Service 包装           Ca...
在 DefaultServiceManager.initMapping 时,如果 全局配置了某些 Service ,局部没有配置(或者反 之)都会把做一个补全的工作,将全局有,局部没 有的 Service 也在局部创建一份该 Service 的...
创建好这个包装的时候,还没有对其中真正的 Service 进行初始化后续再对 Service 进行初始化的时候,调用 wrapper 中的 getInstance( 这个方法的命名 也不好,不如直观的叫 getRealService 意思 更清...
Main-instance?                                        Sub-instance                 全局                                     ...
►   如果这个 wrapper 是在全局( main-instance )中,►   getInstance 直接根据全局配置的 Class ,通过反射创建实例对象返回。►   如果这个 wrapper 是在局部( sub-instance ...
假设我们为全局配置了 A,B 两个 Service ;      为 car1 配置了 C Service ;为 car2 配置了 D Service 。         A 实现了 MultiInstance 接口 , 它大致是这个样子Ins...
现在解释清楚了 service 配置与创建问题,但每个 service 在配 置文件中的 property 是如何注入到 service 中的呢?这部分的实现是子 Service.init 方法中实现,对每个 service 要 根据当前 Se...
Configuration 类用 key-value 方式来存储对于全局的 Service ,它的 key 命名是这样的 :……services.RunDataService.class = …services.RunDataService.e...
还是具体的来看 DefaultBeanFactoryService 的 init() 过程中对 properties 的加载:见代码:String[] descriptors = getConfiguration().getStringArra...
Exodus2 的现状及重构  三层 service 容器的合并
Exodus2 的现状 , 有 3 个 service 容器Web 层 service 容器                          ViewCache                            Service    Ca...
ViewCache 主要是访问我们的类目信息,存放  在 vc.xml.china 文件中,加载到内存中大约  30 多 MWeb 和 biz 层都要访问到,所以把它独立提取  出来了。现在要把这 3 层 service 容器合并为一个容器 ,...
合并后                     全局 SpringOtherService   ctx                         AO       BO      DAOViewCache      cd   Car1  ...
更新:提交测试时发现 headquarters 二方库对 ViewCacheService 接口新增了方法,经交流 虽然上层可以补充实现此方法返回 null (我 们不会用到),但不排除后续 headquarters 仍有修改的可能,所以对 V...
Upcoming SlideShare
Loading in …5
×

Exodus重构和向apollo迁移

466 views

Published on

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
466
On SlideShare
0
From Embeds
0
Number of Embeds
6
Actions
Shares
0
Downloads
4
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Exodus重构和向apollo迁移

  1. 1. Exodus 的重构和向 Apollo 的迁移 1: Apollo 在哪些环节切入的? 2: 再谈 Webx 中容器的初始化 ( 重构过程的注意事项 ) 3: Exodus2 如何迁移? hongjiang 2009-11-14
  2. 2. Apollo 的切入点 1: pipeline 的 valve
  3. 3. 替换 PerformActionValve 和 PerformScreenValve CheckCSRF Hessian 可选Logging Auth AnalyzeURL Remote Screen GreenChanel Action Trace Template Screen Action ChooseRedirect TBStore CheckCode ExpiredUrl
  4. 4. 1 ) DO 的 properties 由框架来自动装配2 ) AO 自动注入到 Action 中3 )新的 Action 不再走 CommandDispather
  5. 5. 再来说说 webx 中 service 的初始化 ( 重构过程需要注意 )之前大部分的应用部署, web 和 biz 层的 service 容器都是分离的,中间 通过 CommandDispather 方式来交互;但实际上我们没有用到分布式 的方案(可能以后也不会需要), CommandDispather 没有发挥很大 的作用,反而麻烦并且弱化了类型系统,显得很“鸡肋”。Apollo 去除了它,在容器层面也比较“单纯”,都在同一个 Service 容器 中。但考虑对以前代码的兼容,又必须支持 commanddispather 模式,如果在 现有系统上,使用 Apollo 的话,它的布局会很乱,看上去如下:
  6. 6. 现有系统上 (Exodus2 重构前 ) 使用 Apollo 注释: 每个 car 的 pipeline 配置中 Web 层全局 Spring 容器 用新的 valve 替 ServiceA MailService Apollo 框架将从这里获取 AO/BO 代,判断请求类 型如果是旧的, 仍使用以前的 commanddispat her 方式找 biz 层 ,新的方式则不 cd cd cd 需要 commanddispat ctx ctx ctx her ,从 web 层 的全局 spring 中 去寻找。这意味 着 biz 层的所有 对象需要在 web 容器中再配置一 份。 缩写 cd 表示 Commanddispat AO BO DAO her 缩写 ctx 表示 WebApplicationC ontextUtilsBean( MailService TemplateSvc OtherService 见 web-tool.xml)
  7. 7. 如果维护一个上图布局的 Exodus ,非常头大 ,兼容性所带来的复杂性增加了犯错的可能 性。所以要迁移的话,必须将 Exodus 的布局 进行调整(当然,重构也不仅仅是为了向 apollo 迁移,本来 web/biz 分离的方式对我 们就已经没有意义。)我们期望一个简单直接的方式
  8. 8. 合并后, Apollo 框架所期望 的 全局 SpringxOtherService ctx AO BO DAOMailService cd Car1 Car2 Spring Spring ServiceA ServiceA ServiceB ServiceB注:红色和黄色表示兼容以前的,绿色表示新的请求方式
  9. 9. 注释:原先每个 car 里的 Spring 容器,不再配置任何对象, cd 和 ctx 移到全局 spring 中,它们之间是级联的,所以 car 中访问 cd 时会得到全局 spring 中的 cd 。旧的请求仍走以前的 cd 方式,新的则可以直接访问全局 spring 中的 AO ;(同样是因为 spring 容器级联的原因)对于 cd 和 ctx 我们改变它的访问为全局的 spring 容器(也就 是自身所在的容器)即可,甚至不必修改代码,只要不再配 置 biz 层 service 容器,它就会访问它所在的 spring 容器。注: cd 和 ctx 到 AO 之间的虚线不是表示它们有引用关系,表 示旧的请求方式仍通过 cd 或 ctx 才能得到 AO 的
  10. 10. 解惑Web 层的 Service 分布在 main-instance( 全局 ) 和 sub-instance(car 级别 )把 Biz 层合并后,其中 biz 层的 service 要放到 main- instance 中同时考虑有些 sub-instance 的 service 是否也可以放 到 main-instance 中,要做这个调整,必须弄清楚 service 的创建过程以前在《 Exodus2 大局观》中分享过,但说的不特别 细,这次再详细的了解一下这里,先看一下 web 层 Service 容器的布局 :
  11. 11. Web 层 Service 容器 全局: name=null Service 包装 Service 包装 Car1 Car2 Car3 name=home name=offer name=member Service 包装 Service 包装 Service 包装 Service 包装 Service 包装 Service 包装 注释:每个 car(sub-instance) 是一个 ServiceInstanceContext ,它的 name 就是 car 的 name 全局 (main-instance) 也是一个 ServiceInstanceContext ,它的 name=null
  12. 12. 在 DefaultServiceManager.initMapping 时,如果 全局配置了某些 Service ,局部没有配置(或者反 之)都会把做一个补全的工作,将全局有,局部没 有的 Service 也在局部创建一份该 Service 的包装 (注意,不是直接创建一个 Service )这个包装类的名字是 ServiceInstance ,个人感觉命 名很不好,容易理解成其他意思,改为 ServiceWrapper 更好(后续我会用 Wrapper 来指 代)。
  13. 13. 创建好这个包装的时候,还没有对其中真正的 Service 进行初始化后续再对 Service 进行初始化的时候,调用 wrapper 中的 getInstance( 这个方法的命名 也不好,不如直观的叫 getRealService 意思 更清晰些 )来获取真正的 Service 对象,得到它的 Class , 返回 class.newInstance ,才真正进行了初始 化。
  14. 14. Main-instance? Sub-instance 全局 sub 指定了 class? 全局指定了 class? yes yes 该 class 在全局 该 class 在全局 也指定了 ? 也指定了 ? 返回 Class. returnnewInstance null 全局有 全局无 全局有 全局无 该类实现了 MultiInstance 接口 创建一份 Service 实例 该类实现了 return MultiInstance 接口 null 使用全局 创建一份 Service Service 实例 使用全局 创建一份 Service Service 实例
  15. 15. ► 如果这个 wrapper 是在全局( main-instance )中,► getInstance 直接根据全局配置的 Class ,通过反射创建实例对象返回。► 如果这个 wrapper 是在局部( sub-instance )中,则:► 1) 局部配置了 Class :► 判断这个类是否在全局也配置过?► 1.1) 全局有,并且该类实现了 MultiInstance 接口,则将全局的那个 Service 对象再做一层包装返回给局部。► (可以理解成全局和局部共享 service )► 1.1) 全局无,或者全局有但该 Service 类没有实现 MultiInstance 接口: 局部创建一份 Service 类实例(通过 Class.newInstance )► 2 )局部没有配置 Class :► 判断这个类是否在全局也配置过?► 2.1 )全局无,返回 null► 2.2) 全局有,并且该类实现了 MultiInstance 接口,则将全局的那个 Service 对象再做一层包装返回给局部。 ( 同 1.1)► 2.3) 全局有,但该类没有实现 MultiInstance 接口: 局部创建一份 Service 类实例(同 1.2 )上面是大致的逻辑,全部的逻辑见 DefautlServiceManager 的内部类 ServiceInstance.getInstance 方法。
  16. 16. 假设我们为全局配置了 A,B 两个 Service ; 为 car1 配置了 C Service ;为 car2 配置了 D Service 。 A 实现了 MultiInstance 接口 , 它大致是这个样子InstanceA InstanceB InstanceC InstanceD A B null null Car1 Car2 A A B B C null null D
  17. 17. 现在解释清楚了 service 配置与创建问题,但每个 service 在配 置文件中的 property 是如何注入到 service 中的呢?这部分的实现是子 Service.init 方法中实现,对每个 service 要 根据当前 ServiceInstanceContext 中的 Configuration 来获取 它所需要的 properties.框架初始化时,把所有的配置文件 : webx- default.xml(webroot 下面 ), webx-turbine- default.xml(TurbineScheme 的 ), webx- default.xml(DefaultScheme 的 ) ,以及每个 car 下面的 webx.xml 都合并起来。(当然里面做了去重工作)
  18. 18. Configuration 类用 key-value 方式来存储对于全局的 Service ,它的 key 命名是这样的 :……services.RunDataService.class = …services.RunDataService.earlyInit = …services.RunDataService.rundata.class = ..services.RunDataService.request.buffered.class = ………services.PullService.class = ..……而对于某个 car ,比如 offer 的,它会用自己的 name 作为 key 的前缀,命名是这样的:……offer.services.ResourceLoaderService.class =…offer.services.ResourceLoaderService.earlyInit = …offer.services.ResourceLoaderService.resource.descriptors = …offer.services.PullService.class = ………
  19. 19. 还是具体的来看 DefaultBeanFactoryService 的 init() 过程中对 properties 的加载:见代码:String[] descriptors = getConfiguration().getStringArray(BEAN_DESCRIPTORS);1) 如果是在全局从 Configuration 中获取 services.BeanFactoryService.bean.descriptors 这个 key 的值。因为全局对 BeanFactoryService 配置了 bean.descriptors ,则能够得到这些 properties ,放入 descriptors 数组。( 对于 BeanFactoryService 它的 properties 通常是另一个或多个 xml ,在此 xml 里面描述了要 加载的 bean)2) 如果是在某个 car 下,比如 offer 下从 Configuration 中获取 offer.services.BeanFactoryService.bean.descriptors 这个 key 的值 。如果我们没有在局部设定 BeanFactoryService ,当然找不到上面的 key 了,得到的 descriptors 是一个空数组。它后续也不会设置任何 property 。所以如果我们考虑将某个 sub-instance 的 service 移到 main 中,如果此 service 不是 MultiInstance 接口实现者,要考虑其中的 properties 问题
  20. 20. Exodus2 的现状及重构 三层 service 容器的合并
  21. 21. Exodus2 的现状 , 有 3 个 service 容器Web 层 service 容器 ViewCache Service Car1 Car2 Car3 Viewcache 层 Service 容器 ResourceLoaderSvc ViewCacheSupport ServiceBiz 层 service 容器 AO/BO/DAO ... ViewCache Mail Template Others Service
  22. 22. ViewCache 主要是访问我们的类目信息,存放 在 vc.xml.china 文件中,加载到内存中大约 30 多 MWeb 和 biz 层都要访问到,所以把它独立提取 出来了。现在要把这 3 层 service 容器合并为一个容器 ,使得后续更容易迁移到 apollo 框架
  23. 23. 合并后 全局 SpringOtherService ctx AO BO DAOViewCache cd Car1 Car2 Spring Spring ServiceA ServiceA ServiceB ServiceB
  24. 24. 更新:提交测试时发现 headquarters 二方库对 ViewCacheService 接口新增了方法,经交流 虽然上层可以补充实现此方法返回 null (我 们不会用到),但不排除后续 headquarters 仍有修改的可能,所以对 ViewCache 最终放 弃了合并,仍独立使用一个 service 容器

×