架构运维

一、前言我们在用缓存的时候,不管是Redis或者Memcached,基本上会通用遇到以下三个问题: 缓存穿透 缓存并发 缓存失效 缓存穿透 注: 上面三个图会有什么问题呢? 我们在项目中使用缓存通常都是先检查缓存中是否存在,如果存在直接返回缓存内容,如果不存在就直接查询数据库然后再缓存查询结果返回。这个时候如果我们查询的某一个数据在缓存中一直不存在,就会造成每一次请求都查询DB,这样缓存就失去了意义,在流量大时,可能DB就挂掉了。那这种问题有什么好办法解决呢? 要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞。 有一个比较巧妙的作法是,可以将这个不存在的key预先设定一个值。 比如,”key” , “&&”。 在返回这个&&值的时候,我们的应用就可以认为这是不存在的key,那我们的应用就可以决定是否继续等待继续访问,还是放弃掉这次操作。...

Jenkins Pipeline 插件对于 Jenkins 用户来说可以让用户能够改变游戏规则。基于 Groovy 中的领域特定语言(DSL),Pipeline 插件使 Pipelines 可以有脚本来定义,并且提供了非常强大的方法来开发复杂的、多步 DevOps Pipeline 。本文记录了编写 Jenkins Pipeline 的一些的最佳实践和不推荐的代码示例和说明。 1. 要使用真正的 Jenkins Pipeline不要使用像 Build Pipeline 插件或者 Buildflow 插件这样的旧插件。而是使用真正的 Jenkins Pipiline 插件套装。 这是因为 Pipeline 插件是底层工作自身的一个改变和提升的 Step。与 Freestyle 任务不同,Pipeline 对 Jenkins 主机重新启动具有适应能力,并且有可以替代以前用于构建多步、...

虽然之前在《Spring Cloud构建微服务架构》系列文章中介绍了Hystrix服务降级与Hystrix断路器的概念。但是,还是一直收到这样的提问:降级与熔断区别是什么?并且在很多交流过程中,发现有不少童鞋对降级和熔断的概念有混淆的情况。所以,这篇博文准备换一种方式来说说这两个概念,以帮助读者更好的理解之前两篇文章中介绍的这两个重要知识。 下面通过一个日常的故事来说明一下什么是服务降级,什么是熔断。 故事的背景是这样的:由于小强在工作中碰到一些问题,于是想请教一下业界大牛小壮。于是发生了下面的两个场景: 小强在拿起常用手机拨号时发现该手机没有能够拨通,所以就拿出了备用手机拨通了某A的电话,这个过程就叫做降级(主逻辑失败采用备用逻辑的过程)。 由于每次小壮的解释都属于长篇大论,不太容易理解,所以小强每次找小壮沟通的时候都希望通过常用手机来完成,因为该手机有录音功能,这样自己可以慢慢消...

前文导读:《都在说微服务,那么微服务的反模式和陷阱是什么(一)》《都在说微服务,那么微服务的反模式和陷阱是什么(二)》 九、通信协议使用的陷阱在微服务架构体系中要求每个服务都是独立布署,这就意味着服务之间会有通信,也就是说会有很多的远程访问。 当你不知道这些远程访问需要多长时间的时候,就会掉入到这个陷阱,当然我们可以假定远程访问一次50毫秒,但我们是否真正的进行过测试呢?那么服务的平均响应时间是多少呢?即使有看上去很好的平均响应时间,那么糟糕的“长尾延迟”也会将整体系统摧毁。 9.1 延迟测量在生产环境中进行压力测试,是检测我们系统性能的重要手段之一,举个例子:我们有一个特定业务需要四个服务来协调处理,假如远程访问一次的时间是100毫秒,那么这个特定业务就需要消耗500毫秒(初始请求+四个服务的调用时间),这个只是远程访问的时间,还不算实际业务代码的执行时间,这是大多数应用系统都...

上一篇:《都在说微服务,那么微服务的反模式和陷阱是什么(一)》 六、无因的开发者陷阱名字来自詹姆斯·迪恩演的电影《无因的反叛》(Rebel Without a Cause),一个问题青年因为错误的原因做了错误的决定。 很多架构师和开发者在微服务的开发中权衡利弊, 比如服务粒度和运维工具,但是基于错误的原因,做了错误的决定。 6.1 做出错误的决定图6-1说明了一种情况是通过测试发现服务划分的太细了,因此非常影响性能,主要是由于服务划分的太细导致增加了通信工作量也在一定程度上对稳定性造成一定影响。在这种情况下,开发人员或架构师决定将这些服务整合到一个更粗粒度的服务中,以解决性能和可靠性问题。 这个方案看起来似乎合情合理,但是之后的布署、更改控制和测试都会受到影响。 再看图6-2,这种场景是左边的服务太粗了,影响了服务的测试和布署,于是进行了拆分,减少了每个服务的范围。 通过以上...

一、数据驱动的迁移反模式微服务会创建大量小的、分布式的、单一用途的服务,每个服务拥有自己的数据。这种服务和数据耦合支持一个有界的上下文和一个无共享数据的架构,其中,每个服务及其对应的数据是独立一块,完全独立于所有其他服务。服务只暴露了一个明确的接口(服务契约)。有界的上下文可以允许开发者以最小的依赖快速轻松地开发,测试和部署。 采用数据驱动迁移反模式主要发生在当你从一个单体应用向微服务架构做迁移的时候。我们之所以称之为反模式主要原因是,刚开始我们觉得创建微服务是一个不错的主意,服务和相应的数据都独立成微服务,但这可能会将你带向一个错误的道路上,导致高风险、过剩成本和额外的迁移工作。 单体应用迁移到微服务架构有两个主要目标: 第一个目标是单体应用程序的功能分割成小的,单一用途的服务。 第二个目标是单体应用的数据迁移到每个服务自己独占的小数据库(或独立的服务)。 下图展示了一个典型的...

概述微服务架构是一种非常流行的新概念,即便可供以借鉴的经验比较少,当然不能阻挡它成为热门话题与研究对象。 令人惊讶地是,其实微服务的概念早在五十多年前就已经被提出,多年来,很久研究表明了这些观点的准确性。这就是本文所介绍的——康威定律。现在已经有很多企业正在尝试使用它创建高效的微服务架构。 在这篇文章中最有名的一句话莫过于: 设计系统的企业受限于生产设计,这些设计是企业沟通结构的副本——Melvin Conway(1967)。 这意味着设计系统的企业,它们生产的设计等同于企业内的沟通结构。下图说明了此概念: 该图展现了企业现有沟通结构,简单地说:企业结构等于系统设计。 作者这里提到的系统并不局限于应用系统,据说这篇文章最初投稿于哈佛商业评论,但被拒绝,因此康威将其提交到了一个编程杂志,所以被误解为只针对应用开发,起初,作者并没有把这种理论作为定律,只是描述了发现和结论,不过著名的...

DDD社区官网上一篇关于聚合设计的几个原则的简单讨论:文章地址:http://dddcommunity.org/library/vernon_2011/,该地址中包含了一篇关于介绍如何有效的设计聚合的一些原则,共3个pdf文件。该文章中指出了以下几个聚合设计的原则: 聚合是用来封装真正的不变性,而不是简单的将对象组合在一起; 聚合应尽量设计的小; 聚合之间的关联通过ID,而不是对象引用; 聚合内强一致性,聚合之间最终一致性; 上面这几条原则,作者通过一个例子来逐步阐述。下面我按照我的理解对每个原则做一个简单的描述。 聚合是用来封装真正的不变性,而不是简单的将对象组合在一起这个原则,就是强调聚合的真正用途除了封装我们本身所关心的信息外,最主要的目的是为了封装业务规则,保证数据的一致性。在我看来,这一点是设计聚合时最重要和最需要考虑的点;当我们在设计聚合时,要多想想当前聚合封装了哪些...

领域驱动设计之领域模型2004年Eric Evans 发表Domain-Driven Design –Tackling Complexity in the Heart of Software (领域驱动设计),简称Evans DDD。领域驱动设计分为两个阶段: 以一种领域专家、设计人员、开发人员都能理解的通用语言作为相互交流的工具,在交流的过程中发现领域概念,然后将这些概念设计成一个领域模型;由领域模型驱动软件设计,用代码来实现该领域模型; 由此可见,领域驱动设计的核心是建立正确的领域模型。 为什么建立一个领域模型是重要的领域驱动设计告诉我们,在通过软件实现一个业务系统时,建立一个领域模型是非常重要和必要的,因为领域模型具有以下特点: 领域模型是对具有某个边界的领域的一个抽象,反映了领域内用户业务需求的本质;领域模型是有边界的,只反应了我们在领域内所关注的部分; 领域模型只反映业务...

消息场景:用户 A 发送一个消息给用户 B,用户 B 回复一个消息给用户 A。。。 现有设计:消息设计为实体并为聚合根,发件人、收件人设计为值对象。 三个问题: 实体最重要的特性是什么? Message 实体是怎么得来的? 发件人、收件人为什么不是实体? 1. 实体最重要的特性是什么?《领域驱动设计》5.2 实体: 摘录一段:许多对象不是由它们的属性来定义,而是通过一系列的连续性(continuity)和标识(identity)来从根本上定义的。 归纳: 标识(identity) 连续性(continuity) 标识在实体中的另一种体现就是唯一和不可变,其概念在很多资料中有说明,这也是实体最重要的特性。 我有一个双胞胎哥哥,我们俩出生的时候,长得一模一样,以至于我们的爸妈都分不清,不得已他们在我们脖子上系个项链来标记:谁是老大?谁是老二?其实这个“标记”就可以看作是实体的...

REST围绕着资源这个概念而构建的,然后用URI来表示。然后一个HTTP动词和资源URI组合起来对指定资源进行HTTP调用来执行操作。大多数REST框架提供了指定资源名称的生成器,框架围绕着它来生成脚手架。不幸的是,许多这些生成器使用CRUD模型(Create,Read, Update, Delete)作为默认的起始点。资源被定义为一系列的属性,使用类似JSON Schema或某个具体语言的数据对象来定义,然后生成方法存根,然后来创建,读取,更新和删除该资源。 尽管这可以让开发人员觉得理解和开始工作变得简单了许多,是一个很好的起点,但是使用CRUD作为API的起点,我有一个很大的疑问。就是CRUD中的U是我最不喜欢的。让我们来谈谈U.通用更新方法允许客户端更新资源的任何字段,然后使用新版本覆盖现有版本。但是,如果允许客户端执行这样的操作,您的服务API在其使用的任何底层数据存储之上,...

我以前写过一篇关于领域事件的文章——实现领域事件,随着在项目中深入的使用DDD架构,我对领域事件有了新的认识。尤其是采用领域事件来解耦代码这种方式对项目的发展具有深远的影响。 我在实现领域事件中主要谈到了如何在技术层面去实现发布事件与订阅事件,比较了几种不同的方式以及它们背后的原理。但随着我在自己负责的项目中严格地实施DDD架构时,我发现如何去发布订阅领域事件的意义远没有决定去做这件事情本身重要。换句话说,与其纠结与是使用基于Spring的事件架构还是Guava提供的EventBus,是使用同步发布还是异步发布,还不如想想去做这件事情对你的项目会产生怎样的影响。 为什么要使用事件?我认为这是所有人应该考虑的首要问题。对我来说,使用事件的意义有两个方面,一是在于流程上的解耦,二是在于代码层面的解耦。在代码层面的解耦是显而易见的,我就不再赘述了。那么流程上的解耦是什么意思了?我们先看一下...

当你的系统或者业务变得日益复杂时,DDD的模式是一种非常值得尝试的架构模式。DDD让你更加关注于你的业务领域,思考你的业务模型,帮组你理清繁杂的业务关系。我推荐所有还没有了解过或者接触过DDD的后端工程师都去学习一下该架构模式。本文主要关注DDD中的领域事件,以及一种可能的实践方式。 我们知道领域模型的变化会产生领域事件。例如,用户在完成注册后,系统会发出一封带有确认信息的邮件到用户的邮箱;用户关注的好友发送动态后他会收到相应的通知等等。在业务比较简单或者不用考虑性能的情况下,我们可以直接把对领域事件的处理嵌入到领域服务中。考虑这样一个场景:用户回复了某条评论,那么被回复的那个用户(也就是那条评论的所有者)需要收到一个PUSH消息。这个场景比较简单,我们可能直接写出类似下面的代码: void reply(long fromUserId,long toUserId,String ...

关于领域驱动设计这篇文章参考了Eric Evans《领域驱动设计》一书以及Jimmy Nilsson《以C# .NET为例运用领域驱动设计和模式》,二者详细描述了领域驱动设计的核心概念、技术和模式。在某些情况下,直接使用这些书的措辞是有意义的,并且我认为Eric Evans和Jimmy Nilsson也允许我们这么做。 尽管将方法本身呈现出来是很有用的,但是仅仅对方法进行描述,DDD的许多微妙之处就会消失。这些方法应该是你的工具,而不是你束缚你的规则。它们是为设计而生的语言,在团队内沟通创意和模型十分有益。更为重要的是,记住实践DDD的目的是为了做出更加务实的决定。不要试图将一个方法强加于一个模型。另外,如果你“打破”了一个方法,确保你已经理解了这么做的理由,并将其与其他人沟通。 通常认为,DDD在面向对象范式下表现良好,但远不止这些。DDD解决了如何去理解问题空间这一挑战,甚至是更...

本系列内容是来自Mashape.com的Marco在nginx.conf上的一次演讲。 上一集我们介绍了为什么我们需要API网关:微服务与API 网关(上): 为什么需要API网关? 本系列第一部分(上集)主要介绍了单体和微服务之间的差别,以及为什么我们需要一个API网关等等。 本系列的第二部分(也就是本集)主要关注Mashape.com的API网关,Kong,这个框架。我们来看看怎么使用这个框架。 ok,开始吧。 目录 23:52 API网关和Kong能为你做些什么(API Gateways and Kong Can Help) API 网关可以通过实现一些中间件来解决一些问题,这些中间件的功能你就不用再到每个service中实现了。你也是知道的,不同的团队使用不同的方式来实现了不同的微服务。 如果你不去做一些中心化和抽象化的事情,你将会死于不同的认证方式以及不同的速率限制实...