面向切面编程(AOP)
2016-06-22 14:19:28摘要:参考 在.net core 中使用AOP .NET Core中实现AOP编程--.NET西安社区 为AOP而生 — ASP.Net MVC默认的过滤器 AspNetCore 基于AOP实现Polly的使用 面向方面的编程 - 使用 RealProxy 类进行面向方面的编程 主要应用 日志记录 安全控制 性能统计 事务处理 异常处理 阅读全文
摘要:参考 在.net core 中使用AOP .NET Core中实现AOP编程--.NET西安社区 为AOP而生 — ASP.Net MVC默认的过滤器 AspNetCore 基于AOP实现Polly的使用 面向方面的编程 - 使用 RealProxy 类进行面向方面的编程 主要应用 日志记录 安全控制 性能统计 事务处理 异常处理 阅读全文
摘要:参考 C#执行异步操作的几种方式比较和总结 异步与多线程的区别(异步是目的,多线程是实现它的一种方式,异步的优先级有时候比主线程还高) - 子福当自强 - 博客园 c#异步编程 JavaScript异步机制与异步原理 异步编程的本质:绑定 - zzfx - 博客园 异步编程的本质:怎么处理异步请求(事件)与响应的关系 进阶篇:以IL为剑,直指async/await 官方文档 使用 Async 和 Await 的异步编程 .NET 异步详解 --能说清楚异步与多线程的区别,涉及到操作系统原理 await,async 我要把它翻个底朝天,这回你总该明白了吧 异步开发是什么 异步开发,就是利用线程技术,当执行一个占用时间长的任务时,不会阻止用户其它工作,而且其完成时会通知用户。 虽然是通过多线程来实现异步,但是因为一般异步时耗时的操作都不是针对CPU的,所以对CPU压力影响不大。 异步本质是通过线程池提高线程的利用率。 异步采用IO的DMA模式,不会消耗CPU资源。计算密集的工作,采用多线程。IO密集的工作,采用异步 举例:网络爬虫爬数据,如果数据很庞大,这个时候就需要使用异步了。 DMA:Direct Memory Access是IO的操作模式,可以直接访问内存,不经过CPU,不消耗CPU资源。 异步和多线程区别就是,充分利用DMA释放CPU压力。 异步实现方式:.net中实现异步的方式有定时器和多线程,一般都是使用多线程。 **使用场景:**要执行耗时且不需要立刻返回结果的操作,如:I/O操作、网络操作 争议: 有种说法是:异步是不阻塞当前主线程执行,通过子线程去执行,还有总说法刚好相反,具体参考:异步与线程阻塞 同步、异步、并行区别 同步:代码执行顺序默认是一行一行执行的,要等当前行的代码执行完后,才会执行下一行的代码。 异步:不用等当前行代码执行完毕就会执行下一行的代码。异步编程是一项关键技术,可以直接处理多个核心上的阻塞 I/O 和并发操作 并行:许多个人计算机和工作站都有多个 CPU 内核,以便多个线程能够同时执行。 为了利用硬件,你可以对代码进行并行化,以将工作分摊在多个处理器上。 并行和多线程、异步和多线程有啥关系? 异步和多线程:多线程是创建多个线程,消耗的是CPU,异步呢? 异步方法返回类型:void、Task、Task 异步编程模式: 基于…… 阅读全文
摘要:CPU是什么 我们都知道的定义是这样的:CPU又称中央处理器,它的英文全称为:Central Processing Unit,但同时如果你听到:Central Processor或者Main Processor往往同样也指的是CPU。 普通程序员开发的程序,其实绝大多数指的就是对中央处理器也就是CPU的编程。这句话也可能会被面试人员反着描述为,计算机的可编程性主要是指对中央处理器的编程。 在最初的时候,大约是1970年代以前,中央处理器由多个独立单元构成,后来才发展成集成电路,这些高度收缩的组件就是所谓的:微处理器。 另外,中央处理器广义上来说,是可以指代一系列可以执行复杂的计算机程序的逻辑机器。还记得三体中秦始皇嬴政派出无数士兵进行逻辑与或非运算吗?那样的场景,其实就是实现了广义上的中央处理器。 注意:ENIAC(Electronic Numerical Integrator And Computer)是世界上第一台”电子存储式可编程计算机”,但是由于他们也存在计算功能,而CPU的标准定义为:执行软件(计算机程序)的设备所以,ENIAC理论上不存在标准的CPU,但是最早于存储程序型计算机一通登场的设备是可以被称作CPU的,也就是说:CPU并不一定是微型的,早起的同步CPU是非常大的。直到1950~60年代的晶体管CPU时,CPU才慢慢变小。不再以体积庞大,不可靠与易碎的开关组件(继电器/真空管)组成或建造。 参考来自于维基百科,与哈佛计算机原理书籍,国内的一些小众参考资料与翻译是错误的,一定要注意。CPU并不小。尤其是百度百科,它所提供的参考资料只提及了”微”,但是万物相对论,没有相对何来形容词?从本段落开始,咱们只讨论:冯·诺依曼机,不讨论哈佛架构。 CPU的主要运作原理 CPU的主要运作原理很简单。不论其外观,都是执行存储与被称为”程序”里的一系列指令。所以说计算机是最愚蠢的傻子,没有码农他们就是一坨铁。 在冯诺依曼架构中,程序以一系列数字存储在计算机存储器中。 而只要是冯诺依曼机,CPU的运作原理就可以看成四个阶段:提取,解码,执行,回写。 提取:从程序内存中检索指令(程序内存,指的可不是你程序里面定义了一个int的这个内存,而是存储程序的内存),由程序计数器指定程序存储器的位置,计数器保存供识别当前程序位置的数值(原始资料原文)。 拿人话说:程序计数…… 阅读全文
摘要:前面介绍了 DDD 分层架构,同时也提到了微服务架构模型其实还有好多种,不知道你注意到了没?这些架构模型在我们的实际应用中都具有很高的借鉴价值。 那么今天我们就把 DDD 分层架构、整洁架构、六边形架构这三种架构模型放到一起,对比分析,看看如何利用好它们,帮助我们设计出高内聚低耦合的中台以及微服务架构。 整洁架构 整洁架构又名“洋葱架构”。为什么叫它洋葱架构?看看下面这张图你就明白了。整洁架构的层就像洋葱片一样,它体现了分层的设计思想。 在整洁架构里,同心圆代表应用软件的不同部分,从里到外依次是领域模型、领域服务、应用服务和最外围的容易变化的内容,比如用户界面和基础设施。 整洁架构最主要的原则是依赖原则,它定义了各层的依赖关系,越往里依赖越低,代码级别越高,越是核心能力。外圆代码依赖只能指向内圆,内圆不需要知道外圆的任何情况。 在洋葱架构中,各层的职能是这样划分的: 领域模型实现领域内核心业务逻辑,它封装了企业级的业务规则。领域模型的主体是实体,一个实体可以是一个带方法的对象,也可以是一个数据结构和方法集合。 领域服务实现涉及多个实体的复杂业务逻辑。 应用服务实现与用户操作相关的服务组合与编排,它包含了应用特有的业务流程规则,封装和实现了系统所有用例。 最外层主要提供适配的能力,适配能力分为主动适配和被动适配。主动适配主要实现外部用户、网页、批处理和自动化测试等对内层业务逻辑访问适配。被动适配主要是实现核心业务逻辑对基础资源访问的适配,比如数据库、缓存、文件系统和消息中间件等。 红圈内的领域模型、领域服务和应用服务一起组成软件核心业务能力。 六边形架构 六边形架构又名“端口适配器架构”。追溯微服务架构的渊源,一般都会涉及到六边形架构。 六边形架构的核心理念是:应用是通过端口与外部进行交互的。我想这也是微服务架构下API 网关盛行的主要原因吧。 也就是说,在下图的六边形架构中,红圈内的核心业务逻辑(应用程序和领域模型)与外部资源(包括 APP、Web应用以及数据库资源等)完全隔离,仅通过适配器进行交互。它解决了业务逻辑与用户界面的代码交错问题,很好地实现了前后端分离。六边形架构各层的依赖关系与整洁架构一样,都是由外向内依赖。 六边形架构将系统分为内六边形和外六边形两层,这两层的职能划分如下: 红圈内的六边形实现应用的核心业务逻辑; 外六边形完成外部应用、…… 阅读全文
摘要:前面我们讲了 DDD 的一些重要概念以及领域模型的设计理念。 今天我们来聊聊“DDD 分层架构”。微服务架构模型有好多种,例如整洁架构、CQRS 和六边形架构等等。每种架构模式虽然提出的时代和背景不同,但其核心理念都是为了设计出“高内聚低耦合”的架构,轻松实现架构演进。而 DDD 分层架构的出现,使架构边界变得越来越清晰,它在微服务架构模型中,占有非常重要的位置。 那 DDD 分层架构到底长什么样?DDD 分层架构如何推动架构演进?我们该怎么转向 DDD 分层架构?这就是我们这一讲重点要解决的问题。 什么是 DDD 分层架构? DDD 的分层架构在不断发展。最早是传统的四层架构;后来四层架构有了进一步的优化,实现了各层对基础层的解耦;再后来领域层和应用层之间增加了上下文环境(Context)层,五层架构(DCI)就此形成了。 我们看一下上面这张图,在最早的传统四层架构中,基础层是被其它层依赖的,它位于最核心的位置,那按照分层架构的思想,它应该就是核心,但实际上领域层才是软件的核心,所以这种依赖是有问题的。后来我们采用了依赖倒置(Dependencyinversion principle,DIP)的设计,优化了传统的四层架构,实现了各层对基础层的解耦。 我们今天讲的 DDD分层架构就是优化后的四层架构。在下面这张图中,从上到下依次是:用户接口层、应用层、领域层和基础层。那 DDD各层的主要职责是什么呢?下面我来逐一介绍一下。 1.用户接口层 用户接口层负责向用户显示信息和解释用户指令。这里的用户可能是:用户、程序、自动化测试和批处理脚本等等。 2.应用层 应用层是很薄的一层,理论上不应该有业务规则或逻辑,主要面向用例和流程相关的操作。但应用层又位于领域层之上,因为领域层包含多个聚合,所以它可以协调多个聚合的服务和领域对象完成服务编排和组合,协作完成业务操作。 此外,应用层也是微服务之间交互的通道,它可以调用其它微服务的应用服务,完成微服务之间的服务组合和编排。 这里我要提醒你一下:在设计和开发时,不要将本该放在领域层的业务逻辑放到应用层中实现。因为庞大的应用层会使领域模型失焦,时间一长你的微服务就会演化为传统的三层架构,业务逻辑会变得混乱。 另外,应用服务是在应用层的,它负责服务的组合、编排和转发,负责处理业务用例的执行顺序以及结果的拼装,以粗粒度的服务通过A…… 阅读全文
摘要:在事件风暴(EventStorming)时,我们发现除了命令和操作等业务行为以外,还有一种非常重要的事件,这种事件发生后通常会导致进一步的业务操作,在 DDD中这种事件被称为领域事件。这只是最简单的定义,并不能让我们真正理解它。那到底什么是领域事件?领域事件的技术实现机制是怎样的?今天,我们就重点解决这两个大的问题。 领域事件 领域事件是领域模型中非常重要的一部分,用来表示领域中发生的事件。一个领域事件将导致进一步的业务操作,在实现业务解耦的同时,还有助于形成完整的业务闭环。 举例来说的话,领域事件可以是业务流程的一个步骤,比如投保业务缴费完成后,触发投保单转保单的动作;也可能是定时批处理过程中发生的事件,比如批处理生成季缴保费通知单,触发发送缴费邮件通知操作;或者一个事件发生后触发的后续动作,比如密码连续输错三次,触发锁定账户的动作。 那如何识别领域事件呢? 很简单,和刚才讲的定义是强关联的。在做用户旅程或者场景分析时,我们要捕捉业务、需求人员或领域专家口中的关键词:“如果发生……,则……”“当做完……的时候,请通知……”“发生……时,则……”等。在这些场景中,如果发生某种事件后,会触发进一步的操作,那么这个事件很可能就是领域事件。 那领域事件为什么要用最终一致性,而不是传统SOA 的直接调用的方式呢? 我们一起回顾一下之前讲到的聚合的一个设计原则:在边界之外使用最终一致性。一次事务最多只能更改一个聚合的状态。如果一次业务操作涉及多个聚合状态的更改,应采用领域事件的最终一致性。 领域事件驱动设计可以切断领域模型之间的强依赖关系,事件发布完成后,发布方不必关心后续订阅方事件处理是否成功,这样可以实现领域模型的解耦,维护领域模型的独立性和数据的一致性。在领域模型映射到微服务系统架构时,领域事件可以解耦微服务,微服务之间的数据不必要求强一致性,而是基于事件的最终一致性。 回到具体的业务场景,我们发现有的领域事件发生在微服务内的聚合之间,有的则发生在微服务之间,还有两者皆有的场景,一般来说跨微服务的领域事件处理居多。在微服务设计时不同领域事件的处理方式会不一样。 1.微服务内的领域事件 当领域事件发生在微服务内的聚合之间,领域事件发生后完成事件实体构建和事件数据持久化,发布方聚合将事件发布到事件总线,订阅方接收事件数据完成后续业务操作。 微服务内大部分事件的集成,都发…… 阅读全文
摘要:我们先回顾下上一讲,在事件风暴中,我们会根据一些业务操作和行为找出实体(Entity)或值对象(ValueObject),进而将业务关联紧密的实体和值对象进行组合,构成聚合,再根据业务语义将多个聚合划定到同一个限界上下文(BoundedContext)中,并在限界上下文内完成领域建模。 那你知道为什么要在限界上下文和实体之间增加聚合和聚合根这两个概念吗?它们的作用是什么?怎么设计聚合?这就是我们这一讲重点要关注的问题。 聚合 在 DDD 中,实体和值对象是很基础的领域对象。实体一般对应业务对象,它具有业务属性和业务行为;而值对象主要是属性集合,对实体的状态和特征进行描述。但实体和值对象都只是个体化的对象,它们的行为表现出来的是个体的能力。 那聚合在其中起什么作用呢? 举个例子。社会是由一个个的个体组成的,象征着我们每一个人。随着社会的发展,慢慢出现了社团、机构、部门等组织,我们开始从个人变成了组织的一员,大家可以协同一致的工作,朝着一个最大的目标前进,发挥出更大的力量。 领域模型内的实体和值对象就好比个体,而能让实体和值对象协同工作的组织就是聚合,它用来确保这些领域对象在实现共同的业务逻辑时,能保证数据的一致性。 你可以这么理解,聚合就是由业务和逻辑紧密关联的实体和值对象组合而成的,聚合是数据修改和持久化的基本单元,每一个聚合对应一个仓储,实现数据的持久化。 聚合有一个聚合根和上下文边界,这个边界根据业务单一职责和高内聚原则,定义了聚合内部应该包含哪些实体和值对象,而聚合之间的边界是松耦合的。按照这种方式设计出来的微服务很自然就是“高内聚、低耦合”的。 聚合在DDD分层架构里属于领域层,领域层包含了多个聚合,共同实现核心业务逻辑。聚合内实体以充血模型实现个体业务能力,以及业务逻辑的高内聚。跨多个实体的业务逻辑通过领域服务来实现,跨多个聚合的业务逻辑通过应用服务来实现。比如有的业务场景需要同一个聚合的A 和 B 两个实体来共同完成,我们就可以将这段业务逻辑用领域服务来实现;而有的业务逻辑需要聚合 C 和聚合 D中的两个服务共同完成,这时你就可以用应用服务来组合这两个服务。 聚合根 聚合根的主要目的是为了避免由于复杂数据模型缺少统一的业务规则控制,而导致聚合、实体之间数据不一致性的问题。 传统数据模型中的每一个实体都是对等的,如果任由实体进行无控制地调用和数据修改,…… 阅读全文
摘要:这两个概念都是领域模型中的领域对象。它们在领域模型中起什么作用,战术设计时如何将它们映射到代码和数据模型中去?就是我们这一讲重点要关注的问题。 另外,在战略设计向战术设计过渡的这个过程中,理解和区分实体和值对象在不同阶段的形态是很重要的,毕竟阶段不同,它们的形态也会发生变化,这与我们的设计和代码实现密切相关。 接下来,我们就分别看看实体和值对象的这些问题,从中找找答案。 实体 我们先来看一下实体是什么东西? 在 DDD中有这样一类对象,它们拥有唯一标识符,且标识符在历经各种状态变更后仍能保持一致。对这些对象而言,重要的不是其属性,而是其延续性和标识,对象的延续性和标识会跨越甚至超出软件的生命周期。我们把这样的对象称为实体。没理解?没关系!请继续阅读。 实体的业务形态 在DDD不同的设计过程中,实体的形态是不同的。在战略设计时,实体是领域模型的一个重要对象。领域模型中的实体是多个属性、操作或行为的载体。在事件风暴中,我们可以根据命令、操作或者事件,找出产生这些行为的业务实体对象,进而按照一定的业务规则将依存度高和业务关联紧密的多个实体对象和值对象进行聚类,形成聚合。你可以这么理解,实体和值对象是组成领域模型的基础单元。 实体的代码形态 在代码模型中,实体的表现形式是实体类,这个类包含了实体的属性和方法,通过这些方法实现实体自身的业务逻辑。在 DDD里,这些实体类通常采用充血模型,与这个实体相关的所有业务逻辑都在实体类的方法中实现,跨多个实体的领域逻辑则在领域服务中实现。 实体的运行形态 实体以 DO(领域对象)的形式存在,每个实体对象都有唯一的ID。我们可以对一个实体对象进行多次修改,修改后的数据和原来的数据可能会大不相同。但是,由于它们拥有相同的ID,它们依然是同一个实体。比如商品是商品上下文的一个实体,通过唯一的商品 ID 来标识,不管这个商品的数据如何变化,商品的 ID一直保持不变,它始终是同一个商品。 实体的数据库形态 与传统数据模型设计优先不同,DDD是先构建领域模型,针对实际业务场景构建实体对象和行为,再将实体对象映射到数据持久化对象。 在领域模型映射到数据模型时,一个实体可能对应 0 个、1个或者多个数据库持久化对象。 大多数情况下实体与持久化对象是一对一。在某些场景中,有些实体只是暂驻静态内存的一个运行态实体,它不需要持久化。比如,基于多个价格配置…… 阅读全文
摘要:在 DDD领域建模和系统建设过程中,有很多的参与者,包括领域专家、产品经理、项目经理、架构师、开发经理和测试经理等。对同样的领域知识,不同的参与角色可能会有不同的理解,那大家交流起来就会有障碍,怎么办呢?因此,在DDD中就出现了“通用语言”和“限界上下文”这两个重要的概念。 这两者相辅相成,通用语言定义上下文含义,限界上下文则定义领域边界,以确保每个上下文含义在它特定的边界内都具有唯一的含义,领域模型则存在于这个边界之内。你是不是感觉这么描述很抽象?没关系,接下来我会给你一一详细讲解。 在这之前,请你先看这样两个问题,这也是今天内容的核心。 为什么要提出限界上下文的概念(也就是说除了解决交流障碍这个广义的原因,还有更具体的吗)? 限界上下文在微服务设计中的作用和意义是什么? 什么是通用语言? 为了更好地理解限界上下文,回答这两个问题,我们先从通用语言讲起。 怎么理解通用语言这个概念呢?在事件风暴过程中,通过团队交流达成共识的,能够简单、清晰、准确描述业务涵义和规则的语言就是通用语言。也就是说,通用语言是团队统一的语言,不管你在团队中承担什么角色,在同一个领域的软件生命周期里都使用统一的语言进行交流。 那么,通用语言的价值也就很明了了,它可以解决交流障碍这个问题,使领域专家和开发人员能够协同合作,从而确保业务需求的正确表达。 但是,对这个概念的理解,到这里还不够。 通用语言包含术语和用例场景,并且能够直接反映在代码中。通用语言中的名词可以给领域对象命名,如商品、订单等,对应实体对象;而动词则表示一个动作或事件,如商品已下单、订单已付款等,对应领域事件或者命令。 通用语言贯穿DDD的整个设计过程。作为项目团队沟通和协商形成的统一语言,基于它,你就能够开发出可读性更好的代码,将业务需求准确转化为代码设计。 下面我带你看一张图,这张图描述了从事件风暴建立通用语言到领域对象设计和代码落地的完整过程。 在事件风暴的过程中,领域专家会和设计、开发人员一起建立领域模型,在领域建模的过程中会形成通用的业务术语和用户故事。事件风暴也是一个项目团队统一语言的过程。 通过用户故事分析会形成一个个的领域对象,这些领域对象对应领域模型的业务对象,每一个业务对象和领域对象都有通用的名词术语,并且一一映射。 微服务代码模型来源于领域模型,每个代码模型的代码对象跟领域对象一一对应。 这…… 阅读全文
摘要:DDD的知识体系提出了很多的名词,像:领域、子域、核心域、通用域、支撑域、限界上下文、聚合、聚合根、实体、值对象等等,非常多。这些名词,都是关键概念,但它们实在有些晦涩难懂,可能导致你还没开始实践 DDD就打起了退堂鼓。因此,在基础篇中,我希望能带着你一起做好实践前的准备工作。 除此之外,这些名词在你的微服务设计和开发过程中不一定都用得上,但它可以帮你理解DDD 的核心设计思想和理念。而这些思想和理念,在 IT 战略设计、业务建模和微服务设计中都是可以借鉴的。 今天就围绕以上这些DDD 关键概念来彻底理清它们与微服务的关系,了解它们在微服务设计中的作用。今天重点了解 DDD的领域、子域、核心域、通用域和支撑域等重要概念。 如何理解领域和子域? 我们先看一下汉语词典中对领域的解释:“领域是从事一种专门活动或事业的范围、部类或部门。”百度百科对领域的解释:“领域具体指一种特定的范围或区域。” 两个解释有一个共同点——范围。对了!领域就是用来确定范围的,范围即边界,这也是DDD 在设计中不断强调边界的原因。 在研究和解决业务问题时,DDD 会按照一定的规则将业务领域进行细分,当领域细分到一定的程度后,DDD 会将问题范围限定在特定的边界内,在这个边界内建立领域模型,进而用代码实现该领域模型,解决相应的业务问题。简言之,DDD的领域就是这个边界内要解决的业务问题域。 既然领域是用来限定业务边界和范围的,那么就会有大小之分,领域越大,业务范围就越大,反之则相反。 领域可以进一步划分为子领域。我们把划分出来的多个子领域称为子域,每个子域对应一个更小的问题域或更小的业务范围。 我们知道,DDD是一种处理高度复杂领域的设计思想,它试图分离技术实现的复杂度。那么面对错综复杂的业务领域,DDD是如何使业务从复杂变得简单,更容易让人理解,技术实现更容易呢? 其实很好理解,DDD的研究方法与自然科学的研究方法类似。当人们在自然科学研究中遇到复杂问题时,通常的做法就是将问题一步一步地细分,再针对细分出来的问题域,逐个深入研究,探索和建立所有子域的知识体系。当所有问题子域完成研究时,我们就建立了全部领域的完整知识体系了。 我们来看一下上面这张图。这个例子是在讲如何给桃树建立一个完整的生物学知识体系。初中生物课其实早就告诉我们研究方法了。它的研究过程是这样的。 第一步:确定研究对象,即研究…… 阅读全文