当前位置: 首页 > news >正文

国内定机票网站建设有需要网站建设网站推广请找我

国内定机票网站建设,有需要网站建设网站推广请找我,短视频app开发,人才网站建设经费用途说在前面 在40岁老架构师 尼恩的读者交流群(50)中#xff0c;最近有小伙伴拿到了一线互联网企业如阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格#xff0c;遇到很多很重要的面试题#xff1a; 谈谈你的高并发落地经验#xff1f; 谈谈你对DDD的理解#xf…说在前面 在40岁老架构师 尼恩的读者交流群(50)中最近有小伙伴拿到了一线互联网企业如阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格遇到很多很重要的面试题 谈谈你的高并发落地经验 谈谈你对DDD的理解 如何保证RPC代码不会腐烂升级能力强? 最近有小伙伴在字节又遇到了相关的面试题。小伙伴懵了 他从来没有用过DDD面挂了。关于DDD尼恩之前给大家梳理过一篇很全的文章 阿里一面谈一下你对DDD的理解2W字帮你实现DDD自由 但是尼恩的文章 太过理论化不适合刚入门的人员。所以尼恩也在不断的为大家找更好的学习资料。 前段时间尼恩在阿里的技术公众号上看到了一篇文章《殷浩详解DDD领域层设计规范》 作者是阿里 技术大佬殷浩非常适合于初学者入门同时也足够的有深度。 美中不足的是 殷浩那篇文章的行文风格对初学者不太友好 尼恩刚开始看的时候也比较晦涩。 于是尼恩在读的过程中把那些晦涩的内容给大家用尼恩的语言 浅化了一下 这样大家更容易懂。 本着技术学习、技术交流的目的这里把尼恩修改过的 《殷浩详解DDD领域层设计规范》通过尼恩的公众号《技术自由圈》发布出来。 特别声明由于没有殷浩同学的联系方式这里没有找殷浩的授权 如果殷浩同学或者阿里技术公众号不同意我的修改不同意我的发布 我即刻从《技术自由圈》公众号扯下来。 另外 文章也特别长 我也特别准备了PDF版本。如果需要尼恩修改过的PDF版本也可以通过《技术自由圈》公众号找到尼恩来获取。 本文是 《从0到1带大家精通DDD》系列的第3篇 第1、2篇的链接地址是 《阿里DDD大佬从0到1带大家精通DDD》 《阿里大佬DDD 落地两大步骤以及Repository核心模式》 大家可以先看第1篇、第2篇再来看第3篇效果更佳。 另外尼恩会结合一个工业级的DDD实操项目在第34章视频《DDD的顶奢面经》中给大家彻底介绍一下DDD的实操、COLA 框架、DDD的面试题。 文章目录 说在前面代码就变得腐败不堪咋整9 个微服务设计模式什么是防腐层Anti-corruption layer使用场景防腐层的设计与实现两个上下文相互依赖的简单例子一个简单的防腐层的设计与实现一个简单的防腐层的设计小结 COLA框架中的防腐层回顾COLA分层架构start层adapter层cilent层什么是CQRS Command 与 Query 分离 app层domain层infrastructure层COLA4.0分层总结 COLA框架中的防腐层对微服务中的远程调用进行防腐烂设计gateway登录网关防止rpc腐烂Feign的异常统一处理 未完待续尼恩说在最后推荐阅读 代码就变得腐败不堪咋整 一份业务代码尤其是互联网业务代码都有哪些特点 大概有这几点 互联网业务迭代快工期紧导致代码结构混乱几乎没有代码注释和文档。互联网人员变动频繁很容易接手别人的老项目新人根本没时间吃透代码结构紧迫的工期又只能让屎山越堆越大。多人一起开发每个人的编码习惯不同工具类代码各用个的业务命名也经常冲突影响效率。大部分团队几乎没有时间做代码重构任由代码腐烂。 每当我们新启动一个代码仓库都是信心满满结构整洁。但是时间越往后代码就变得腐败不堪技术债务越来越庞大。 这种情况有解决方案吗也是有的 小组内定期做代码重构解决技术债务。组内设计完善的应用架构让代码的腐烂来得慢一些。当然很难做到完全不腐烂设计尽量简单让不同层级的开发都能快速看懂并上手开发而不是在一堆复杂的没人看懂的代码上堆更多的屎山。 尼恩曾经见过一个极端的反面案例 10年多时间 衍生出 50多个不同的版本 每个版本80%的功能相同但是代码各种冲突没有合并10年多时间经历过至少 5次推倒重来 基本换一个领导恨不得推导重来一次 感觉老的版本都是不行只有自己设计的才好5次推倒重来每次都是 风风火火/加班到进ICU 投入了大量的人力/财力。其实大多是重复投入、重复建设可谓, 一将不才累死三军所以从项目角度来说一个优秀的架构对项目是多么重要从人才角度来说 一个优秀的架构师对一个团队来说是多么的重要 如何让你的代码腐烂的尽可能慢一些让团队的开发效率尽可能快一些。这里有一个核心的设计模式放腐层Anti-corruption layer模式。 9 个微服务设计模式 2017年微软 AzureCAT 模式和实践团队在 Azure 架构中心发布了 9 个新的微服务设计模式文中提到的9 个模式包括 外交官模式Ambassador放腐层Anti-corruption layer后端服务前端Backends for Frontends舱壁模式Bulkhead网关聚合Gateway Aggregation网关卸载Gateway Offloading网关路由Gateway Routing边车模式Sidecar绞杀者模式Strangler。 微软团队在 Azure 架构中心文章也给出了这些模式解决的问题、方案、使用场景、实现考量等。 微软团队称这 9 个模式有助于更好的设计和实现微服务同时看到业界对微服务的兴趣日渐增长所以也特意将这些模式记录并发布。 下图是微软团队建议如何在微服务架构中使用这些模式 微软微服务设计模式 注意请点击图像以查看清晰的视图 这些模式绝大多数也是目前业界比较常用的模式如 外交官模式Ambassador可以用与语言无关的方式处理常见的客户端连接任务如监视日志记录路由和安全性如 TLS。防腐层Anti-corruption layer介于新应用和遗留应用之间用于确保新应用的设计不受遗留应用的限制。后端服务前端Backends for Frontends为不同类型的客户端如桌面和移动设备创建单独的后端服务。这样单个后端服务就不需要处理各种客户端类型的冲突请求。这种模式可以通过分离客户端特定的关注来帮助保持每个微服务的简单性。舱壁模式Bulkhead隔离了每个工作负载或服务的关键资源如连接池、内存和 CPU。使用舱壁避免了单个工作负载或服务消耗掉所有资源从而导致其他服务出现故障的场景。这种模式主要是通过防止由一个服务引起的级联故障来增加系统的弹性。网关聚合Gateway Aggregation将对多个单独微服务的请求聚合成单个请求从而减少消费者和服务之间过多的请求。边车模式Sidecar将应用程序的辅助组件部署为单独的容器或进程以提供隔离和封装。 设计模式是对针对某一问题域的解决方案它的出现也代表了工程化的可能。 随着微服务在业界的广泛实践相信这个领域将会走向成熟和稳定。 这里主要介绍反腐层Anti-corruption layer模式 什么是防腐层 **反腐层Anti-corruption layer**模式最先由 **Eric Evans 在 Domain-Driven Design域驱动的设计**中描述。 在许多情况下我们的系统需要依赖其他系统但被依赖的系统可能具有不合理的数据结构、API、协议或技术实现。如果我们强烈依赖外部系统就会导致我们的系统受到**“腐蚀”**。 在这种情况下通过引入防腐层可以有效地隔离外部依赖和内部逻辑无论外部如何变化内部代码尽可能保持不变。 反腐层Anti-corruption layer简称 ACL介于新应用和旧应用之间用于确保新应用的设计不受老应用的限制。是一种在不同应用间转换的机制。 注意请点击图像以查看清晰的视图 创建一个反腐层以根据客户端自己的域模型为客户提供功能。 反腐层通过其现有接口与另一个系统进行通信几乎不需要对其进行任何修改。 反腐层是将一个域映射到另一个域这样使用第二个域的服务就不必被第一个域的概念“破坏”。因此反腐层隔离不仅是为了保护你的系统免受异常代码的侵害还在于分离不同的域并确保它们在将来保持分离。 该层可作为应用程序内的组件或作为独立服务实现。 防腐层不仅仅是一层简单的调用封装在实际开发中ACL可以提供更多强大的功能 适配器 很多时候外部依赖的数据、接口和协议并不符合内部规范通过适配器模式可以将数据转化逻辑封装到ACL内部降低对业务代码的侵入。 缓存 对于频繁调用且数据变更不频繁的外部依赖通过在ACL里嵌入缓存逻辑能够有效的降低对于外部依赖的请求压力。同时很多时候缓存逻辑是写在业务代码里的通过将缓存逻辑嵌入ACL能够降低业务代码的复杂度。 兜底 如果外部依赖的稳定性较差提高系统稳定性的策略之一是通过ACL充当兜底例如在外部依赖出问题时返回最近一次成功的缓存或业务兜底数据。这种兜底逻辑通常复杂如果散布在核心业务代码中会难以维护。通过集中在ACL中更容易进行测试和修改。 易于测试 ACL的接口类能够很容易的实现Mock或Stub以便于单元测试。 功能开关 有时候我们希望在某些场景下启用或禁用某个接口的功能或者让某个接口返回特定值。 我们可以在ACL中配置功能开关而不会影响真实的业务代码。 Anti-corruption layer使用场景 在以下情况下使用此模式 迁移计划为发生在多个阶段但是新旧系统之间的集成需要维护 很多人一看到旧系统就想要赶快替换掉他但是请不要急著想著去替换旧系统因为这条路充满困难与失败而且 旧系统通常反而是系统目前最赚钱的部分。更好的做法是在使用旧系统时包上一层 ACL让你的开发不受影响甚至可以一点一滴的替换旧系统的功能达到即使不影响目前功能下也能开发新功能达到重构的效果 两个或更多个子系统具有不同的语义需要对外部上下文的访问进行一次转义 例如对接第三方系統。缴费软件中的收银台系统需要对接不同的支付方式支付宝、各个银行、信用卡等这是就需要收银台系统充当一个Anti-corruption layer将用户的缴费支付信息转换成各个三方支付系统需要的数据格式。 如果内部多个组件对外部系统需要访问那么可以考虑将其放到通用上下文中。 例如我们有一个抽奖平台包含有现金券、折扣券、外卖券、出行券等组件但他们都需要对接用户信息服务这时就需要在抽奖平台中搭建一个Anti-corruption layer作为抽奖平台对接用户信息的通用适配层。 如果新旧系统之间没有重要的语义差异则此模式可能不适合。 防腐层的设计与实现 在应用服务中经常需要调用外部服务接口来实现某些业务功能这就在代码层面引入了对外部系统的依赖。这里就需要用到防腐层隔离 外部变化。 两个上下文相互依赖的简单例子 举个例子有 A 和 B 两个上下文 其中 B 通过开放主机服务提供对外访问A 上下文请求 B 上下文的 RPC 接口时B 将会返回一个模型BView如果 A 直接在领域模型中引用 B 返回的模型BView将会早上 A 上下文被污染。 B 上下文对外提供的 RPC 接口 /*** B上下文对外暴露的查询服务查询*/ public interface BRpcQueryService{ResponseBView query(Query query); }public class BView{private Integer property1;private String property2;//省略其他属性以及get/set方法 }当 A 调用ContextBQueryService 的query方法将会得到BView这个类。 如果 A 的领域模型直接引用了 BView将会导致 A 自己的上下文被污染容易引发很多问题 类级别的改变随着 B 上下文的迭代可能 BView 这个类路径、名称、属性名等都会改变。 举个例子B 上下文可能会进行系统重构重构时会重新发布一个新的 jar 包要求调用方切换到的新的 jar 包上这个情况在我实际工作中遇到的不少。如果直接将 BView 引入到本地上下文中A 将需要进行大量的改动并且需要大量回归测试才能确保切换无风险。 属性级别的BView 中的某个属性的类型与 A 上下文中对应的属性类型并不一致因而使用时必须进行强转BView 中某个字段的名称与本地上下文某个字段的名称相同调用时容易引起歧义例如我在工作中遇到过外部接口返回的模型中有个source字段本地领域模型中也有一个source字段但是两者的含义并不一致。 当有多个服务依赖此外部接口时全部的被依赖服务都需要迁移和改造这种的成本将会巨大。 同时外部依赖的兜底、限流和熔断策略也会受到影响。 在复杂系统中我们应该尽量避免自己的代码因为外部系统的变化而修改。 那么如何实现对外部系统的隔离呢答案就是引入防腐层Anti-Corruption Layer简称ACL。 一个简单的防腐层的设计与实现 防腐层的设计和实现并不难主要注意一下要点 要点1防腐层方法返回值必须是本地上下文的值对象或者基本数据类型不得返回外部上下文的模型 伪代码如下 public class BContextGateway{private BRpcQueryService bRpc;public SomeValue queryFromBContext(Prams params){//封装查询报文Query querythis.fromPrams(params);//执行查询ResponseBView bResponsebRpc.query(query);//忽略判空、查询失败等逻辑BView bViewbResponse.getData();//重点封装本地上下文的值对象进行返回return new SomeValue(bView.getProperty1());} }另外防腐层方法要捕获外部异常并抛出的本地上下文自定义的异常, 伪代码如下 public class BContextGateway{private BRpcQueryService bRpc;public SomeValue queryFromBContext(Prams params){//封转查询报文Query querythis.fromPrams(params);ResponseBView bResponse;try{//查询结果bResponsebRpc.query(query);}catch(Exception e){//重点捕获异常并抛出本地自定义的异常throw new QueryContextBException();}//省略其他逻辑} }要点2外部上下文返回的错误码应该转化成本地异常进行抛出不应该将错误码返回给上层, 要点2伪代码如下 public class BContextGateway{private BRpcQueryService bRpc;public SomeValue queryFromBContext(Prams params){//封转查询报文Query querythis.fromPrams(params);//执行查询ResponseBView bResponsebRpc.query(query);//重点根据错误码时抛出本地自定义的异常if(1.equals(bResponse.getCode())){throw new QueryContextBException();}//忽略其他逻辑} }要点3按需返回只返回需要的字段或者数据类型。 只返回需要的字段这个很好理解不用过多解释只返回需要的数据类型。 举个例子外部上下文可能返回字符串的 0 和 1 代表 false 和 true但是我们本地是使用布尔类型的因此要在防腐层转换好再返回。伪代码如下 public class BContextGateway{private BRpcQueryService bRpc;public Boolean checkFromBContext(Prams params){//封转查询报文Query querythis.fromPrams(params);//执行查询ResponseInteger bResponsebRpc.check(query);//重点查询失败根据错误码时抛出本地自定义的异常if(ERROR.equals(bResponse.getCode())){throw new QueryContextBException();}//转换成需要的布尔类型进行返回return 1.equals(bResponse.getData());} }这样经过ACL改造后ApplicationService的代码已不再直接依赖外部的类和方法而是依赖我们自己内部定义的值类和接口。 如果未来外部服务发生任何变化只需修改Facade类和数据转换逻辑而不需要修改ApplicationService的逻辑。 一个简单的防腐层的设计小结 在没有防腐层ACL的情况下系统需要直接依赖外部对象和外部调用接口调用逻辑如下 注意请点击图像以查看清晰的视图 而有了防腐层ACL后系统只需要依赖内部的值类和接口调用逻辑如下 注意请点击图像以查看清晰的视图 COLA框架中的防腐层 **COLA提供了一整套代码架构拿来即用。**COLA 架构是阿里发布的一套DDD脚手架是一个整洁的面向对象的分层的可扩展的应用架构可以帮助降低复杂应用场景的系统熵值提升系统开发和运维效率。 不管是传统的分层架构、六边形架构、还是洋葱架构都提倡以业务为核心解耦外部依赖分离业务复杂度和技术复杂度等COLA 架构在此基础上融合了 CQRS、DDD、SOLID 等设计思想形成一套可落地的应用架构。 COLA中包含了很多架构设计思想包括讨论度很高的领域驱动设计DDD等。 首先主要谈谈COLA架构COLA的官方博文中是这么介绍的 在平时我们的业务开发中大部分的系统都需要 接收request响应response做业务逻辑处理像校验参数状态流转业务计算等等和外部系统有联动像数据库微服务搜索引擎等 正是有这样的共性存在才会有很多普适的架构思想出现比如分层架构、六边形架构、洋葱圈架构、整洁架构Clean Architecture、DDD架构等等。 这些应用架构思想虽然很好但我们很多同学还是“不讲Co德明白了很多道理可还是过不好这一生”。问题就在于缺乏实践和指导。COLA的意义就在于他不仅是思想还提供了可落地的实践。应该是为数不多的应用架构层面的开源软件。 尼恩会结合一个工业级的DDD实操项目在第34章视频中给大家彻底介绍一个 COLA 框架。 回顾COLA分层架构 先来看两张官方介绍图 注意请点击图像以查看清晰的视图 注意请点击图像以查看清晰的视图 其次还有一个官方的表格介绍了COLA中每个层的命名和含义 层次包名功能必选Adapter层web处理页面请求的Controller否Adapter层wireless处理无线端的适配否Adapter层wap处理wap端的适配否App层executor处理request包括command和query是App层consumer处理外部message否App层scheduler处理定时任务否Domain层model领域模型否Domain层ability领域能力包括DomainService否Domain层gateway领域网关解耦利器是Infra层gatewayimpl领域网关实现是Infra层mapperibatis数据库映射否Infra层config配置信息否Client SDKapi服务对外透出的API是Client SDKdto服务对外的DTO是 这两张图和一个表格已经把整个COLA架构的绝大部分内容展现给了大家但是一下子这么多信息量可能很难消化。 COLA整个示例架构项目是一个Maven父子结构那我们就从父模块一个个好好过一遍。 首先父模块的pom.xml包含了如下子模块 modulesmoduledemo-web-client/modulemoduledemo-web-adapter/modulemoduledemo-web-app/modulemoduledemo-web-domain/modulemoduledemo-web-infrastructure/modulemodulestart/module /modulesstart层 COLA 的start模块作为整个应用的启动模块通常是一个SpringBoot应用只承担启动项目和全局相关配置项的存放职责。 COLA 的start模块代码目录如下 将启动独立出来好处是清晰简洁也能让新人一眼就看出如何运行项目以及项目的一些基础依赖。 adapter层 接下来就是 demo-web-adapter模块这里包括平时我们用的controller层对于Web应用来说换汤不换药。 只是在定位上比 web controller 的 层次更高包括 web 的接口还包括 mobile for APPwap for mobile html等等 为啥不叫 Controller Controller这个名字主要是来自于MVC因为是MVC所以自带了Web应用的烙印。 然而随着mobile的兴起现在很少有应用仅仅只支持Web端通常的标配是WebMobileWAP三端都要支持。 cilent层 有了我们说的“controller”层接下来有的小伙伴肯定就会想是不是service层啦。 是也不是。 传统的MVC应用中一个service层给controller层调用。 service层分为 service interface service implement controller 依赖的是 mvc service interface mvc service implement 的实例由 spring 容器完成注入。 所以在COLA中你的adapter层 /mvc controller层调用了client层client层中就是你服务接口的定义也就是mvc service interface。 从上图中可以看到client包里有 api文件夹存放服务接口定义dto文件夹存放传输实体 注意这里只是服务接口定义而不是服务层的具体实现所以在adapter层中调用的其实是client层的接口 RestController public class CustomerController {Autowiredprivate CustomerServiceI customerService;GetMapping(value /customer)public MultiResponseCustomerDTO listCustomerByName(RequestParam(required false) String name){CustomerListByNameQry customerListByNameQry new CustomerListByNameQry();customerListByNameQry.setName(name);return customerService.listByName(customerListByNameQry);}}而最终接口的具体实现逻辑( mvc service implement 的实例)放到了app层。 Service CatchAndLog public class CustomerServiceImpl implements CustomerServiceI {Resourceprivate CustomerListByNameQryExe customerListByNameQryExe;Overridepublic MultiResponseCustomerDTO listByName(CustomerListByNameQry customerListByNameQry) {return customerListByNameQryExe.execute(customerListByNameQry);} }总之 Client层包含的代码应该是常见的服务接口Facade和DTO数据传输对象如API、DTO、领域事件、Command和Query对象等等。 一个更加复杂的例子如下 什么是CQRS Command 与 Query 分离 CQRSCommand Query Responsibility Segregation是一种简单的设计模式。 CQRS衍生与CQS即命令和查询分离CQS是由Bertrand Meyer所设计。 按照这一设计概念系统中的方法应该分为两种改变状态的命令和返回值的查询。‘ Greg young将引入了这个设计概念并将其应用于对象或者组件当中这就是今天所要将的CQRS。 CQRS背后的主要思想是应用程序更改对象或组件状态Command应该与获取对象或者组件信息Query分开。 具体来说CQRS(Command Query Responsibility Segregation)Command 与 Query 分离的一种模式。 Command命令则是对会引起数据发生变化操作的总称即新增更新删除这些操作都是命令 Query查询则不会对数据产生变化的操作只是按照某些条件查找数据 CQRS 的核心思想是将这两类不同的操作进行分离可以是两个独立的应用两个不同的数据源也可以是同一个应用内的不同接口上。 注意请点击图像以查看清晰的视图 从上图可看出把数据的变更通过数据同步到另一个库用来查询数据其实就是数据异构。 但这不是我们现在需要做的我们是要利用CQRS的思想解决领域驱动中查询功能实现复杂的问题 CQRS 说白了就是“数据查询”和“业务操作”分离。 在COLA 4.0之前还有Command Bus和Query Bus 。Command Bus命令总线是一种接收命令并将命令传递给命令处理程序的队列。Query Bus查询总线是一种查询命令并将查询传递给查询处理程序的队列。 在COLA 4.0中已经移除了Command Bus和Query Bus的处理进一步简化了COLA架构。 app层 接着上面说的我们的app模块作为服务的实现存放了各个业务的实现类( mvc service implement )并且严格按照业务分包 这里划重点是先按照业务分包再按照功能分包的为何要这么做后面还会多说两句先看图 customer和order分别对应了消费着和订单两个业务子领域。 里面是COLA定义app层下面三种功能 App层executor处理request包括command和query是App层consumer处理外部message否App层scheduler处理定时任务否 可以看到消息队列的消费者和定时任务这类平时我们业务开发经常会遇到的场景也放在app层。 应用层Application Layer主要负责获取输入组装上下文参数校验调用领域层做业务处理如果需要的话发送消息通知等。 一个更加复杂的Application Layer代码结构大致如下 domain层 接下来便是domain也就是领域层先看一下领域层整体结构 可以看到首先是按照不同的领域customer和order分包里面则是三种主要的文件类型 领域实体实体模型是充血模型例如官方示例里的Customer.java如下 Data Entity public class Customer{private String customerId;private String memberId;private String globalId;private long registeredCapital;private String companyName;private SourceType sourceType;private CompanyType companyType;public Customer() {}public boolean isBigCompany() {return registeredCapital 10000000; //注册资金大于1000万的是大企业}public boolean isSME() {return registeredCapital 10000 registeredCapital 1000000; //注册资金大于10万小于100万的为中小企业}public void checkConfilict(){//Per different biz, the check policy could be different, if so, use ExtensionPointif(ConflictCompanyName.equals(this.companyName)){throw new BizException(this.companyName has already existed, you can not add it);}} }领域能力domainservice文件夹下是领域对外暴露的服务能力如上图中的CreditChecker领域网关gateway文件夹下的接口定义这里的接口你可以粗略的理解成一种SPI也就是交给infrastructure层去实现的接口。 例如CustomerGateway里定义了接口getByById要求infrastructure的实现类必须定义如何通过消费者Id获取消费者实体信息而infrastructure层可以实现任何数据源逻辑比如从MySQL获取从Redis获取还是从外部API获取等等。 public interface CustomerGateway {public Customer getByById(String customerId); }在示例代码的CustomerGatewayImpl位于infrastructure层中CustomerDO数据库实体经过MyBatis的查询转换为了Customer领域实体进行返回。完成了依赖倒置。 Component public class CustomerGatewayImpl implements CustomerGateway {Autowiredprivate CustomerMapper customerMapper;public Customer getByById(String customerId){CustomerDO customerDO customerMapper.getById(customerId);//Convert to Customerreturn null;} }注意请点击图像以查看清晰的视图 infrastructure层 最后是我们的infrastructure也就是基础设施层 infrastructure层有我们刚才提到的gatewayimpl网关实现当然infrastructure层有MyBatis的mapper等数据源的映射和config配置文件。 Infra层gatewayimpl网关实现是Infra层mapperibatis数据库映射否Infra层config配置信息否 COLA4.0分层总结 了解了这个6层COLA4.0很简单明了然后用一段官方介绍博客原文来总结COLA的层级 1适配层Adapter Layer 负责对前端展示webwirelesswap的路由和适配对于传统B/S系统而言adapter就相当于MVC中的controller 2应用层Application Layer 主要负责获取输入组装上下文参数校验调用领域层做业务处理如果需要的话发送消息通知等。层次是开放的应用层也可以绕过领域层直接访问基础实施层 3领域层Domain Layer 主要是封装了核心业务逻辑并通过领域服务Domain Service和领域对象Domain Entity的方法对App层提供业务实体和业务逻辑计算。领域是应用的核心不依赖任何其他层次 4基础实施层Infrastructure Layer 主要负责技术细节问题的处理比如数据库的CRUD、搜索引擎、文件系统、分布式服务的RPC等。 COLA框架中的防腐层 领域防腐的重任也落在Infrastructure Layer 基础实施层外部依赖需要通过gateway的代理和转义才能被上面的App层和Domain层使用。 对微服务中的远程调用进行防腐烂 在构建微服务时我们经常需要跨服务调用比如 登录的时候需要调用系统服务以获取用户详细信息。 以下是在微服务中使用OpenFeign实现跨服务调用的过程。 以登录为例authservice 需要调用 SystemService 获取用户信息 两个微服务之间的关系如下 在咱们的工程代码中调用的核心链路大致如下 以上链路是尼恩打断点通过调用链路画出来的。 设计gateway登录网关防止rpc腐烂 在mvc 架构中 登录服务 LoginDomainServiceImpl 如果需要通过rpc获取用户信息 直接注入 Feign的代理客户端stub 对象 完成RPC远程调用就可以了。 大致的流程如下所示 这样就会导致 LoginDomainServiceImpl 领域服务两个问题 1对 Feign RPC 框架进行强依赖使得 领域服务 LoginDomainServiceImpl 的代码不利于复用和扩展。 LoginDomainServiceImpl 的代码不是纯业务的 如果要拿到其他地方复用发现和现有的 cache、rpc等技术组件强耦合。 2也不利于底层技术组件的换代和升级 在尼恩的视频中介绍过使用Dubbo 替代Feign 进行性能调优的实操 进行性能10倍以上的调优。 但是这样就需要去修改 领域服务LoginDomainServiceImpl 的代码, 可能会修改引入 带来一些潜在问题 带来很多的不确定性。 两种现象我们这里统称为RPC腐烂。 解决的措施是 设计gateway登录网关封装 RPC组件 隔离特定的RPC 框架 防止rpc腐烂。 大致的流程如下所示 在代码维度 是 服务层依赖 领域 网关 在代码维度 领域 网关 依赖 Feign 组件 理论上为了彻底解耦 我们需要遵循上述ACL的实现逻辑gateway 内部 进行 数据的转换。 然而在实际开发中由于是内部系统差异性不太明显通常可以直接使用OpenFeign进行远程调用忽略Facade定义和内部类转换的过程。 Feign的异常统一处理 在使用OpenFeign进行远程调用时如果HTTP状态码为非200OpenFeign会触发异常解析并进入默认的异常解码器feign.codec.ErrorDecoder将业务异常包装成FeignException。 此时如果不做任何处理调用时可以返回的消息会变成FeignException的消息体如下所示 显然这个包装后的异常我们不需要应该直接将捕获到的生产者的业务异常抛给前端。 那么如何解决这个问题呢 可以通过重写OpenFeign的默认异常解码器来实现代码如下 Slf4j public class FeignClientErrorDecoder implements ErrorDecoder {Overridepublic Exception decode(String s, Response response) {log.error(捕获到fegin服务端内部异常);if(response.status() ! HttpStatus.OK.value()){if(response.status() HttpStatus.SERVICE_UNAVAILABLE.value()){String errContent;GlobalException exception new GlobalException(内部请求异常);try {errContent Util.toString(response.body().asReader());if(!StringUtils.isEmpty(errContent)){errContent errContent.replaceAll(\t,).replaceAll(\n,);JSONObject errResp JSONObject.parseObject(errContent);String errMessage errResp.getString(message);exception new GlobalException(errMessage);}}catch (Exception e){log.error(feign处理异常错误,e);}return exception;}}return new GlobalException(未知错误);} }此异常解码器直接将异常转化为自定义的GlobalException表示远程调用异常。 当然还需要在配置类中注入此异常解码器。 Slf4j Configuration public class FeignConfig {Beanpublic Request.Options options(){return new Request.Options(5000,10000);}Beanpublic Logger.Level feignLoggerLevel(){return Logger.Level.FULL;}Beanpublic ErrorDecoder errorDecoder() {return new FeignClientErrorDecoder();}Beanpublic FeignAuthInterceptor feignAuthRequestInterceptor(){return new FeignAuthInterceptor();} }当然可能有许多模块都需要远程调用我们可以将上述内容构建成一个通用的Starter模块以便其他业务模块共享。 org.springframework.boot.autoconfigure.EnableAutoConfiguration\com.xunheng.feign.config.FeignConfig,\com.xunheng.feign.config.FeignClientErrorDecoder,\com.xunheng.feign.interceptor.FeignAuthInterceptor未完待续尼恩说在最后 DDD 面试题是非常常见的面试题。 DDD的学习材料 汗牛塞屋又缺乏经典。 《殷浩详解DDD领域层设计规范》做到从0到1带大家精通DDD非常难得。 这里把尼恩修改过的 《殷浩详解DDD领域层设计规范》通过尼恩的公众号《技术自由圈》发布出来。 大家面试的时候 可以参考以上的内容去组织答案如果大家能做到对答如流如数家珍基本上 面试官会被你 震惊到、吸引到。 另外在面试之前建议大家系统化的刷一波 5000页《尼恩Java面试宝典PDF》并且在刷题过程中如果有啥问题大家可以来 找 40岁老架构师尼恩交流。 最终让面试官爱到 “不能自已、口水直流”。offer 也就来了。 当然关于DDD尼恩即将给大家发布一波视频 《第34章DDD的顶奢面经》。 推荐阅读 《百亿级访问量如何做缓存架构设计》 《多级缓存 架构设计》 《消息推送 架构设计》 《阿里2面你们部署多少节点1000W并发当如何部署》 《美团2面5个9高可用99.999%如何实现》 《网易一面单节点2000WtpsKafka怎么做的》 《字节一面事务补偿和事务重试关系是什么》 《网易一面25Wqps高吞吐写Mysql100W数据4秒写完如何实现》 《亿级短视频如何架构》 《炸裂靠“吹牛”过京东一面月薪40K》 《太猛了靠“吹牛”过顺丰一面月薪30K》 《炸裂了…京东一面索命40问过了就50W》 《问麻了…阿里一面索命27问过了就60W》 《百度狂问3小时大厂offer到手小伙真狠》 《饿了么太狠面个高级Java抖这多硬活、狠活》 《字节狂问一小时小伙offer到手太狠了》 《收个滴滴Offer从小伙三面经历看看需要学点啥》 《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》PDF请到下面公号【技术自由圈】取↓↓↓
http://www.hkea.cn/news/14329935/

相关文章:

  • 书店商城网站html模板下载互联网 网站建设价格
  • 陕西宏远建设集团网站企业网站开发摘要
  • 宝安建设网站软件app网址怎么找
  • jsp网站开发大作业社联网站建设的目的
  • 做公司做网站有用吗杭州商业空间设计公司
  • 河北省城乡住房和城乡建设厅网站郴州网络营销
  • 如何微信做演讲视频网站网络推广计划制定步骤
  • 用vue做网站一般用什么组件库东阳便宜自适应网站建设优惠
  • 有做任务赚赏金的网站吗凯里网站设计公司哪家好
  • 网站是不是网页茶叶网站建设公司
  • 试管婴儿网站建设自学建网站做网站优化
  • 仿站工具在线做关于什么内容的网站
  • seo优化方案书上海企业seo
  • 加强公司网站建设做网站的公司经营范围
  • 站群源码聊城做网站的公司渠道
  • 建设龙卡e付卡网站用付费网站做推广
  • 网站建设公司 云智互联长春网站建设q479185700惠
  • 房产网站源码wordpress扎染毕业设计代做网站
  • 吉安网站建设优化服务青海高端网站建设
  • 常州网站制作优化自己做的网站如何百度能搜索
  • 网站建设工作总结报告陕西做网站公司哪家好
  • 想做个网站广州建设银行投诉网站
  • 东港区建设局网站wordpress 淘宝模板
  • 佛山外贸网站建设信息照明网站建设
  • wordpress .po 在哪里优化网站seo策略
  • 江苏网站建设价格低wordpress 编辑器表情插件
  • 合肥seo网站推广费用品牌建设发展规划
  • 珠海市网络营销协会的官方网站会员卡管理系统价格
  • 建设专业网站哪家技术好网站开发亿玛酷适合5
  • 黄山市建设工程造价管理站网站用手机搭建wordpress