关于架构设计:架构师日记到底该如何搭建一个新系统-京东云技术团队

一 前言架构设计依照施行过程可分为工程架构,业务架构,部署架构等多个维度,一个好的零碎架构规范应该具备可扩大、可保护、可靠性、安全性和高性能等特点。只管这些特点大家都熟知,但在理论落地时,咱们更为迫切的想晓得实现这些要求的要害门路,以便在架构设计中融入这些特点。只有这样,能力确保零碎可能适应将来的业务增长和交付效率。本文将重点围绕如何进行工程架构设计开展探讨。 二 价值为先在计划呈现歧义时,站在产品(商业)价值的视角扫视计划并作出决策,这一点十分重要; 技术容易陷入的两个误区: 1.来者不拒:产品经理提的需要,都是有情理的,我负责实现; 2.技术驱动:这种技术实现特地奇妙,让产品个性适配于技术实现; 以上两类误区,很容易让研发对产品价值的了解造成偏差,容易对后续的技术迭代产生颠覆性的影响。站在产品(商业)价值维度,可能让合作各方站在平等的视角看问题,不仅可能容易达成共识,也能更好的为业务演进和技术迭代做好布局。 软件也是产品,在零碎设计的时候,也会围绕着市场,组织,资源几个生产因素开展。 1.市场就是咱们产品的指标,这是咱们的搭建零碎的基本; 2.组织就是围绕着产品交付过程中的资源协调和保障机制; 3.资源就是围绕着产品投入的机器,人员,工夫,经营等生产资料; 软件开发是围绕着投入产出比(ROI)开展的生产经营流动。可扩大,可保护,可靠性,安全性,高性能都是咱们产品的个性,每一项个性都须要投入相当的老本来实现。 1.跑车速度快,是最突出的个性,它就义了路况适应性,乘坐舒适性和驾驶安全性; 2.越野车突出的是路况适应性,它就义了速度和舒适性; 3.轿车在路况适应性,乘坐舒适性,驾驶安全性和行驶速度之间做到了绝对平衡,成为了常见的代步工具; 正所谓:“将军赶路,不追小兔”,总是有所取舍。咱们不谋求打造一个完满的简单零碎,但能够在限定的前提下谋求卓越! 三 架构设计架构模式形容了软件系统中各个组件之间的关系、职责和交互方式,从而为软件设计提供了一种标准和束缚,进而进步软件生产效率。次要体现在一下两个方面: 1.帮忙开发人员更好地组织和设计软件系统; 2.促成团队之间的合作和沟通,使得团队成员更容易了解和分工; 3.1 工程框架新零碎往往从搭建我的项目的工程根底框架开始,包含目录构造、配置文件、代码模板等工程束缚,次要用来标准我的项目构造、职责边界和代码格调,从而进步代码品质和可维护性。具体包含以下几个方面: 1.约定了各个模块的依赖关系和交互方式; 2.标准接口交互协定; 3.对立异样编码、捕捉和解决; 4.标准日志打印格局; 5.其它公共标准束缚; 上面就最罕用的分层架构和DDD架构给出一些实际思路。 3.1.1 分层架构分层架构有多种形式,例如MVC、六边形架构等,它们是随着业务和技术的倒退逐渐演变而来的。 在互联网初期,因为计算机硬件性能差、网络速度慢、存储老本低等因素的限度,互联网产品的状态绝对繁多,只能实现简略的门户网站、BBS论坛等绝对简略的产品。过后的技术架构没有分层的概念,次要应用ASP、JSP、PHP等脚本语言,在这些脚本文件中混合着编写HTML、JavaScript、CSS和SQL是很常见的。随着互联网技术的倒退以及更多简单业务的线上化诉求,动静脚本语言的劣势也逐步浮现,以JSP脚本语言为例: 1.复杂性:JSP脚本语言的开发和保护比较复杂,因为须要解决Java代码和HTML代码的混合; 2.安全性:JSP脚本语言容易受到SQL注入攻打等安全漏洞的影响,从而导致系统不稳固或被攻打; 3.扩展性:脚本语言的可扩展性比拟无限,因为须要在HTML页面中间接编写Java代码,从而导致系统结构不够清晰; 为了解决上述问题,呈现了各种框架,如Spring、Struts等。这些框架逐步代替了JSP脚本语言,同时也提出了分层架构的概念。其中最典型的就是MVC(模型、视图和控制器)架构模式,其次要目标是解耦应用程序的不同局部,使其更易于保护和扩大。具体实现形式如下: 1.拆散关注点:将应用程序分为三个次要局部,使得每个局部都能够独立开发和测试,从而更好地拆散关注点; 2.进步可维护性:因为做了三个层面的关注点拆散,更容易保护和批改应用程序的不同局部; 3.进步可扩展性:展现逻辑和业务逻辑管制拆散,更容易扩大应用程序的不同局部; 在多层架构中,视图层通常会应用基于模板的框架(如Thymeleaf、Freemarker、Velocity)或前后端拆散的技术栈(如Vue.js、React)。这些技术的演进可能解决更加简单的问题,如金融保险和电子商务等场景,但同时也会带来一些新的痛点: 1.学习曲线较平缓:因为MVC架构模式须要开发人员理解和把握多个概念和技术,学习曲线较平缓; 2.进步了复杂性:因为MVC架构模式须要将应用程序分为多个局部,减少了应用程序的复杂性; 3.减少了开发工夫:须要进行更多的测试和集成工作,减少了开发工夫; 为了进步产品交付效率并升高技术门槛,古代研发工作通常会拆分为多个岗位,包含前端开发、后端开发、品质测试、运维保障等。这些岗位须要协同工作,共同完成产品的研发工作。为了保障多业务线和多岗位之间的有序合作,无效个管控过程危险,通常还会设有项目管理岗位。 MVC架构是对整个业务实现进行了关注点拆散,但在更为简单的大型项目中,特地是多人合作,多业务并行的场景下,MVC架构往往显得力不从心。此时须要对其进行更细粒度的拆分,以达到多业务线并行,而不会存在大的工作资源抵触问题。当然,不同的业务场景会有不同的拆分模式,最常见的拆分模式是多层架构模式,如下图: 通过横向的分层架构咱们实现了研发分工协作,所有的教训束缚在这里得以体现。 上图中,将管制层进行了二次细分。也能够依照理论利用场景进行从新调整。比方web模块是否依赖RPC模块就能够在POM文件中进行限定,如此以来,大家依照既有的工程约定,施行开发工作就能够了。 简略形容一下各个模块分层的作用: 1.数据拜访层:将业务逻辑层和数据存储层进行解耦,属于模型层的领域。它与底层数据源(MySQL、Hbase,EleasicSearch)进行数据交互,常见框架有:MyIbatis,Hibernate等; 2.近程调用层:即RPC层,与DAO层平行的数据拜访层,区别是它是通过第三方接口或平台服务提供拜访能力。和DAO层的区别在于数据归属权和畛域事务控制权; 3.事务管理层:也叫通用业务解决层,它有如下特色: ◦对下层业务,进行业务和技术共用能力下沉,比方:多个业态的对立订单生产能力,通用的分布式事务一致性的解决方案等; ◦对上层依赖,组合DAO层和RPC层的能力,实现繁多业务的事务管理; ◦对于简略的业务零碎,Manager层的职责能够由Service层代替; 4.业务逻辑层:绝对具体的业务逻辑服务层,次要负责业务流程的组装和编排,真正的灵活性和扩展性次要体现在这里; 5.申请解决层:次要是对访问控制进行转发,入参整形,出参定制等,其职责是间接面向的是各个终端或第三方服务方; 6.凋谢服务层:定义对外提供的RPC服务,性能职责和Web层相似,同样须要思考网关安全控制、流量管制等因素; 7.终端显示层: 各个端的模板渲染并执行显示,velocity ,React,IOS挪动端等; 传统的软件设计往往会导致各个组件之间严密耦合,从而导致代码难以保护和扩大。六边形架构模式是分层模式的一种变体,通过将业务逻辑与框架、库等技术细节拆散,从而实现了松耦合的设计,使得代码更易于保护和扩大。 同时,六边形架构模式还能够帮忙开发人员更好地实现单元测试和集成测试,从而进步软件品质。这在各种技术中台性质的业务场景下,十分有用,如下图: 3.1.2 DDD架构畛域驱动设计(DDD)是一种软件开发办法,它以业务畛域为核心,通过深刻了解业务畛域的常识,将业务逻辑封装在畛域模型中,以此来实现更好的代码可维护性、可扩展性和可重用性。 DDD属于涣散的分层架构,每层职责和作用如下: 1.用户接口层:web申请,rpc申请,mq音讯等内部输出申请; ...

July 12, 2023 · 1 min · jiezi

关于架构设计:图灵Java架构班第六期华容碧影生晚寒

download:图灵Java架构班第六期华容碧影生晚寒应用UML剖析人员治理模块在古代企业中,对人员的治理是十分重要的一项工作。 为了更好地管理人员,许多企业抉择应用信息系统来帮忙他们实现这个指标。本文将介绍如何应用UML(Unified Modeling Language,对立建模语言)剖析人员治理模块。什么是UML? UML是一种图形化建模语言,用于形容软件系统的架构和设计。它提供了各种类型的图表来形容零碎的不同方面,包含用例图、流动图、类图等等。应用UML能够使开发者更加清晰地了解零碎,并且可能更好地进行团队合作。 剖析人员治理模块以下是应用UML剖析人员治理模块的步骤:定义用例首先须要定义人员治理模块的用例。 一个典型的人员管理系统可能包含以下用例: 增加人员批改人员信息删除人员查问人员信息统计人员信息设计用例图在定义完用例之后,你能够开始设计用例图了。 用例图能够形容零碎中的各种用例和参与者之间的关系。下图是一个简略的人员管理系统的用例图示例: 设计类图在实现了用例图的设计之后,你能够开始设计类图了。类图是形容零碎中各种对象、类和它们之间关系的图表。下图是一个简略的人员管理系统的类图示例: 设计时序图时序图形容了零碎中各个对象之间的交互过程。下图是一个增加人员时序图的示例:实现代码最初,依据剖析失去的模型,编写代码实现人员管理系统。在实现代码时,须要参考UML模型,确保程序可能正确地实现预期性能。 论断应用UML剖析人员治理模块能够帮忙团队更好地了解和合作开发该模块。通过定义用例、设计用例图、类图和时序图等步骤,能够更加清晰地示意出零碎中的各种对象、类和它们之间的关系,并为开发者提供一个清晰的模型,以便更好地实现人员治理模块。

June 14, 2023 · 1 min · jiezi

关于架构设计:Java-亿级项目架构设计与落地应用芭蕉叶大栀子肥

download:Java 亿级我的项目架构设计与落地利用Node.js+Koa2框架生态实战 - 从零模仿新浪微博前言Node.js是一种基于Chrome V8引擎的JavaScript运行时,能够使JavaScript在服务器端运行。而Koa2则是一个轻量级的Web框架,它应用了ES6的async/await语法,让异步代码变得更加简洁明了。本文将介绍如何应用Node.js+Koa2框架来模仿新浪微博的性能。 环境筹备首先,咱们须要装置Node.js和npm,能够从官网下载并装置。而后,应用npm装置Koa2和相干的依赖: npm install koa koa-bodyparser koa-router koa-static koa-session sequelize mysql2数据库设计咱们应用MySQL数据库来存储数据,并应用Sequelize ORM库来操作数据库。上面是咱们所须要的表构造: 用户表字段 类型 形容id INT 用户IDusername VARCHAR 用户名password VARCHAR 明码微博表字段 类型 形容id INT 微博IDcontent TEXT 微博内容userId INT 发布者ID关注关系表字段 类型 形容id INT 关系IDuserId INT 用户IDfollowerId INT 粉丝ID性能实现用户注册和登录咱们首先须要实现用户注册和登录性能。通过Koa2提供的路由和中间件机制,能够很不便地实现这两个性能。 // 注册router.post('/register', async (ctx, next) => { const { username, password } = ctx.request.body; // 查看数据库中是否已存在该用户名 const user = await User.findOne({ where: { username } }); if (user) { ...

May 24, 2023 · 2 min · jiezi

关于架构设计:Java-亿级项目架构设计与落地应用江潭落月复西斜

download:Java 亿级我的项目架构设计与落地利用把握架构相干外围概念 在软件工程中,架构是十分重要的一个环节。良好的架构能够进步软件系统的可维护性、可扩展性和可靠性。本文将介绍几个与架构相干的外围概念。 层次结构层次结构是一种罕用的软件架构模式。它将整个零碎分解成多个档次,每个档次都有明确的职责和性能。档次之间通过接口进行通信,从而实现零碎外部的解耦。层次结构通常包含以下几个档次: 用户界面层:负责与用户交互,接管用户输出,向用户输入后果。利用程序逻辑层:负责解决用户申请,协调各个子系统之间的数据流动。业务逻辑层:负责实现具体的业务逻辑,对数据进行解决和计算。数据拜访层:负责与数据库进行交互,实现数据的增删改查操作。分布式系统分布式系统是由多个独立计算机组成的零碎,这些计算机通过网络连接进行通信和合作。分布式系统通常具备以下特点: 可扩展性:能够依据业务需要减少或删除计算机节点,实现零碎的横向扩大。可靠性:因为零碎中存在多个节点,当某个节点呈现故障时,其余节点能够接替其工作,保障整个零碎的可用性。去中心化:分布式系统中不存在繁多的管制节点,每个节点都具备雷同的位置。微服务架构微服务架构是一种近年来十分风行的架构模式。它将应用程序拆解成多个小型的服务,每个服务都有本人独立的代码库和数据库。不同服务之间通过 API 进行通信,从而实现零碎的松耦合和高内聚。微服务架构具备以下长处: 可扩展性:因为每个服务都是独立部署的,因而能够依据须要进行程度扩大。灵活性:每个服务都能够应用不同的技术栈和编程语言,能够依据具体业务需要抉择最适宜的计划。可靠性:当某个服务呈现故障时,其余服务能够持续运行,从而保障整个零碎的可用性。总结 理解以上几个外围概念对于把握软件架构设计十分重要。在理论利用中,须要依据具体的业务需要和技术栈来抉择最适宜的架构模式。

May 22, 2023 · 1 min · jiezi

关于架构设计:手把手教你用代码画架构图-京东云技术团队

作者:京东物流 覃玉杰 1. 前言本文将给大家介绍一种简洁明了软件架构可视化模型——C4模型,并手把手教大家如何应用代码绘制出精美的C4架构图。 浏览本文之后,读者画的架构图将会是这样的: 注:该图例仅作绘图示例应用,不确保其完整性、可行性。2. C4模型2.1 C4模型整体介绍C4是软件架构可视化的一种计划。架构可视化,指的是用图例的形式,把软件架构设计精确、清晰、好看地示意进去。架构可视化不是领导开发者如何进行架构设计,而是领导开发者将架构设计表达出来,产出简洁直观的架构图。 架构可视化的办法有很多,支流的有“4+1”视图模型、C4模型。视图模型形容的是架构自身,架构确定之后,不论用什么模型去表白,实质上都应该是一样的,并没有优劣之分。 C4 模型是一种易于学习、对开发人员敌对的软件架构图示办法,C4模型没有规定应用特定的图形、特定的建模语言来画图,因此使用者能够非常灵活地产出架构图。 C4模型将零碎从上往下分为System Context, Containers, Components, Code四层视图,每一层都是对上一层的欠缺和开展,层层递进地对系统进行形容,如下图。 2.2 System Context diagramSystem Context(零碎上下文)视图位于顶层,是软件系统架构图的终点,表白的是零碎的全貌。System Context视图重点展现的是零碎边界、零碎相干的用户、其余撑持零碎以及与本零碎的交互。本层不波及到具体细节(例如技术选型、协定、部署计划和其余低级细节),因而System Context能够很好地向非技术人员介绍零碎。 作用:清晰地展现待构建的零碎、用户以及现有的IT基础设施。 范畴:待形容的外围零碎以及其相干用户、撑持零碎,不应该呈现与外围零碎无关的其余零碎。例如咱们要形容一个打车零碎,不应该把无关联的药店零碎绘制进去,并且要确保一个System Context只有一个待形容的软件系统。 次要元素:Context内待形容的软件系统。 反对元素:在范畴内间接与次要元素中的软件系统有关联的人员(例如用户、参与者、角色或角色)和内部依赖零碎。通常,这些内部依赖零碎位于咱们本人的软件系统边界之外。 指标受众:软件开发团队内外的所有人,包含技术人员和非技术人员。 举荐给大多数团队:是的。 示例: 这是该网上银行零碎的零碎上下文图。它显示了应用它的人,以及与该零碎有关系的其余软件系统。网上银行零碎是将要建设的零碎,银行的集体客户应用网上银行零碎查看其银行账户的信息并进行领取。网上银行零碎自身应用银行现有的大型机银行零碎来执行此操作,并应用银行现有的电子邮件系统向客户发送电子邮件。 图例: 2.3 Container diagramContainer(容器)视图是对System Context的放大,是对System Context细节的补充。 留神这里的容器,指的不是Docker等容器中间件。Container的形容范畴是一个可独自运行/可部署的单元。Container个别指的是利用以及依赖的中间件,例如服务器端 Web 应用程序、单页应用程序、桌面应用程序、挪动应用程序、数据库架构、文件系统、Redis、ElasticSeach、MQ等。 Container显示了软件架构的高级形态以及零碎内各容器之间的职责分工。 在Container这一层,还显示了零碎的次要的技术选型以及容器间的通信和交互。 作用:展现零碎整体的开发边界,体现高层次的技术选型,裸露零碎内容器之间的分工交互。 范畴:单个软件系统,关注的零碎外部的利用形成。 次要元素:软件系统范畴内的容器,例如Spring Boot打包后的利用,MySQL数据库、Redis、MQ等。 反对元素:间接应用容器的人员和内部依赖零碎。 指标受众:软件开发团队内外的技术人员,包含软件架构师、开发人员和经营/反对人员。 举荐给大多数团队:是的。 留神:Container视图没有阐明部署计划、集群、复制、故障转移等。部署相干的视图,会通过Deployment视图进行展现。 示例: 网上银行零碎(此时System Contenxt中的零碎曾经被开展,所以用虚线框示意)由五个容器组成:服务器端 Web 应用程序、单页应用程序、挪动应用程序、服务器端 API 应用程序和数据库。 Web 应用程序是一个 Java/Spring MVC Web 应用程序,它只提供形成单页应用程序的动态内容(HTML、CSS 和 JS)。单页应用程序是在客户的网络浏览器中运行的 Angular 应用程序,是网上银行性能的前端。客户也能够应用跨平台 Xamarin 挪动应用程序来拜访网上银行。单页应用程序和挪动应用程序都应用 JSON+HTTPS API,该 API 由运行在服务器上的另一个 Java/Spring MVC 应用程序提供。API 应用程序从关系数据库中获取用户信息。API 应用程序还应用专有的 XML/HTTPS 接口与现有的大型机银行零碎进行通信,以获取无关银行账户的信息或进行交易。如果 API 应用程序须要向客户发送电子邮件,它也会应用现有的电子邮件系统。 ...

May 15, 2023 · 3 min · jiezi

关于架构设计:架构与设计常见微服务分层架构的区别和落地实践

作者:京东科技 康志兴 前言从强调内外隔离的六边形架构,逐步倒退衍生出的层层递进、重视畛域模型的洋葱架构,再到和DDD完满符合的整洁架构。架构格调的一直演进,其实就是为了适应软件需要越来越简单的特点。 能够看到,越古代的架构格调越偏向于清晰的职责定位,且让畛域模型成为架构的外围。 基于这些架构格调,在软件架构设计过程中又有十分多的架构分层模型。 传统三层架构传统服务通常应用三层架构: • 门面层:作为服务裸露的入口,解决所有的内部申请。局部状况下,门面层甚至不须要独自定义对象而是间接应用服务层的实体定义。 • 服务层:作为外围业务层,蕴含所有业务逻辑。并对根底层能力进行简略组合提供肯定的能力复用。通常服务层会进行实体定义来避免上层对象体间接裸露给内部服务,导致底层任何变动都有可能间接传递到内部,十分不稳固。 • 根底层:用来寄存dao和内部rpc服务的封装,二者能够拆分为不同的module,也可合二为一,以不同package进行隔离。 三层架构特点就是简略,实用于一些无简单业务场景的小型利用,或者“数据不可变”作为根底准则的DOP(面向数据编程)服务。 然而当业务场景略微简单一些、调用层级较多时,可复用性、可维护性就都十分差了,很多代码都耦合在一起,牵一动员全身。 DDD架构DDD架构能够看做是整洁架构的一种实现,分层职责如下: • 适配层:用来做内部不同端申请的适配器,隔离不同端的协定差别,包装不同端不同款式的响应体。 • 应用层:用例、工作入口、音讯队列监听均在这一层,能够了解为业务流程的入口,通过聚合根的结构执行相应的命令操作。 • 畛域服务层:蕴含外围的畛域服务定义,并定义了gateway来做一层依赖倒置,使基础设施层仅做实现。 • 基础设施层蕴含所有根底能力:数据库、ES、近程调用封装等等。 长处• 外围稳固:畛域模型在依赖链上是顶层角色,不依赖任何其余模块,所以极其稳固。其余任何业务域、存储、边缘能力的变动都不会对畛域模型造成影响。 • 麻利:适宜不同团队一起开发和保护而不会产生抵触。 • 可拆分:当有届上下文随着演进逐步收缩时,很容易拆分成微服务。 • 可扩大:增加新的性能非常简单,从而使得开发人员可能更快的部署和调整。 • 可演进:良好的可测试性带来非常低的重构老本,不会随着一直迭代导致我的项目成为难以批改的“大泥球”。 如此多的长处天然带来明确的毛病• 专业性要求较高:须要对业务、架构准则了解粗浅的人员进行设计和保护,不失当的畛域模型将使后续迭代极为苦楚。 • 开发成本高:简单的架构设计,更多的架构分层,天然带来代码行数的指数级增长。尤其是项目前期的开发工作变得异样沉重。 • 不再适宜简略的业务场景:实现一个简略的CRUD显得过于简单。 • 扭转决策艰难:尝试应用整洁架构须要和团队的管理层和其余成员达成统一,这往往须要十分弱小的说服力。如果在架构演进过程中想切换回其余架构模式也十分困难,简直是整个我的项目级别的重构工作。 简略的微服务分层架构基于六边形架构标准的接口适配准则和防腐理念,同时借鉴了CQRS模式的长处,咱们定义了一个简略的微服务分层架构。 分层定义如下: • 门面层:作为程序的入口,通过包隔离来寄存JSF服务、Rest服务、定时工作和MQ生产,其中对外提供服务的接口定义寄存在独自的api包中。该层的申请定义命名以Request结尾,响应体命名以Response结尾。 • 畛域服务层:每一个畛域服务寄存在独自的module中,并通过独自的api包对外裸露能力。该层的命令申请定义命名以Command结尾,查问申请定义命名以Query结尾,响应体命名以Dto结尾。 • 基础设施层:寄存数据库、ES、近程调用服务的封装。该层的长久化数据定义命名以Po结尾。近程命令服务入参命名以RpcCommand结尾,近程查问服务入参命名以RpcQuery结尾,响应体命名以RpcDto结尾。 最佳实际命令服务必须拜访畛域服务层,容许简略查问间接调用基础设施层。参数校验、申请出入参日志、审计日志记录、TraceID预埋、异样解决等非核心业务能力均由公共组件实现,缩小我的项目外部的边缘能力代码。因为在门面层进行对立的异样解决,非必要时无需在我的项目中进行大面积的try-catch,让代码更清新。理论开发过程中,门面层、畛域服务层和基础设施层均有各自的实体定义,跨层调用的对象体转换应用MapStruct组件来缩小手写映射代码的工作量。数据层应用Fluent-Mybatis,最大益处是缩小前期迭代中,数据对象增减字段时批改Mapper的老本。长处1. 开发效率 简略的业务开发过程中,相比拟书写外围业务逻辑,更多的工作量简直都是来自解决跨层调用时对象转换和Mapper定义,通过MapStruct和Fluent-Mybatis等组件的应用(兴许再加上GitHub Copilot),编写一个实体的增删改查接口根本在5分钟内搞定,省下来的工夫能够多走读两遍代码或者多写几个分支的测试用例,也算是降本增效了。 2. 服务隔离 通过module隔离不同的畛域服务,升高不同畛域服务之间的耦合水平。 3. 内部服务防腐 近程调用对立封装在基础设施层中,升高内部变动对系统外部的影响。 毛病基础设施层的实体作为顶层依赖因为对基础设施层的依赖没有通过api包进行隔离,所以基础设施层的对象会间接裸露在畛域服务层和门面层。对此能够通过应用ArchUnit组件进行架构防腐。 如果须要定义欠缺的畛域实体充血模型,倡议参考DDD架构定义gateway层来进行基础设施层的依赖倒置。 最初软件工程的方方面面都遵循一个最根本的情理:没有银弹,架构分层模型更是如此,每一种都有各自优缺点,所以请依据不同的业务场景,并遵循简略、可演进这两个重要的架构准则抉择适合的架构分层模型即可。 架构不只是工作,更是一门艺术。

April 18, 2023 · 1 min · jiezi

关于架构设计:vivo全球商城电商交易平台设计

作者:vivo 官网商城开发团队 - Cheng Kun、Liu Wei本文介绍了交易平台的设计理念和关键技术计划,以及实际过程中的思考与挑战。 点击查阅:《vivo 寰球商城》系列文章 一、背景vivo官网商城通过了七年的迭代,从单体架构逐渐演进到微服务架构,咱们的开发团队积淀了许多贵重的技术与教训,对电商畛域业务也有相当粗浅的了解。 去年初,团队承接了O2O商城的建设工作,还有行将成立的礼品中台,以及官网商城的线上购买线下门店送货需要,都须要搭建底层的商品、交易和库存能力。 为节约研发与运维老本,防止反复造轮子,咱们决定采纳平台化的思维来搭建底层零碎,以通用能力灵便撑持下层业务的个性化需要。 包含交易平台、商品平台、库存平台、营销平台在内的一整套电商平台化零碎应运而生。 本文将介绍交易平台的架构设计理念与实际,以及上线后继续迭代过程中的挑战与思考。 二、整体架构2.1 架构指标除了高并发、高性能、高可用这三高外,还心愿做到: 1.低成本 重视模型与服务的可重用性,灵便撑持各业务的个性化需要,进步开发效率,升高人力老本。 2.高扩大 零碎架构简略清晰,利用零碎间耦合低,容易程度扩大,业务性能增改方便快捷。 2.2 零碎架构(1)电商平台整体架构中的交易平台 (2)交易平台零碎架构 2.3 数据模型 三、要害方案设计3.1 多租户设计(1)背景和指标 交易平台面向多个租户(业务方),须要可能存储大量订单数据,并提供高可用高性能的服务。不同租户的数据量和并发量可能有很大区别,要能依据理论状况灵便调配存储资源。(2)设计方案 思考到交易系统OLTP个性和开发人员熟练程度,采纳MySQL作为底层存储、ShardingSphere作为分库分表中间件,将用户标识(userId)作为分片键,保障同一个用户的订单落在同一个库中。接入新租户时约定一个租户编码(tenantCode),所有接口都要带上这个参数;租户对数据量和并发量进行评估,调配至多满足将来五年需要的库表数量。租户与库表的映射关系:租户编码 -\> {库数量,表数量,起始库编号,起始表编号}。通过下面的映射关系,能够为每个租户灵便调配存储资源,数据量很小的租户还能复用已有的库表。 示例一: 新租户接入前已有4库*16表,新租户的订单量少且并发低,间接复用已有的0号库0号表,映射关系是:租户编码-> 1,1,0,0示例二: 新租户接入前已有4库*16表,新租户的订单量多但并发低,用原有的0号库中新建8张表来存储,映射关系是:租户编码-> 1,8,0,16示例三: 新租户接入前已有4库_16表,新租户的订单量多且并发高,用新的4库_8表来存储,映射关系是:租户编码-> 4,8,4,0 用户订单所属库表计算公式 库序号 = Hash(userId) / 表数量 % 库数量 + 起始库编号 表序号 = Hash(userId) % 表数量 + 起始表编号 可能有小伙伴会问:为什么计算库序号时要先除以表数量?上面的公式会有什么问题? 库序号 = Hash(userId) % 库数量 + 起始库编号 表序号 = Hash(userId) % 表数量 + 起始表编号 ...

April 14, 2023 · 1 min · jiezi

关于架构设计:腾讯专家10年沉淀后海量时代的架构设计

腾小云导读 挪动互联网后半场,海量技术曾经成为了标配。在架构设计时,开发者能做什么、要思考什么,从而实现一个设计精良的架构?欢送往下浏览,和腾讯后盾技术专家吕远方一起聊架构设计! 看目录点珍藏 1 背景 2 架构的边界 3 架构的组织属性 4 架构的反馈 5 总结 01、背景腾讯面向外部开发者的海量服务之道系列课程颇具名气,它为司内外海量用户提供互联网服务的教训传承。有数开发者尤其是后盾技术栈的开发者都获益于这些课程,从而成长起来。本篇咱们将提炼这个外围课程精华,供宽泛开发者参考。 海量服务的外围是可用性,最终的目标是用高可用性来撑持海量用户的海量申请。无论是意识、方法论、价值观还是伎俩,都体现了对于某个方面的形式办法的高可用性谋求。下述是海量服务之道的课程,同时这里也列出业界的三个最重要分布式实践: 最近几年,大量互联网产品的体量也逐步壮大。日活大几千万甚至上亿的产品不在少数,不一一列举。业界也涌现了十分多技术,如各种 rpc 框架、docker、云计算、微服务、Service Mesh、分布式存储、DevOps、NoSQL、大数据、各种计算框架等等。 正是因为这些技术的蓬勃发展,才撑持了越来越大量级的各种互联网服务公司。反过来说,从挪动互联网倒退起来之后,智能终端用户量的暴发,冲破了 PC 时代的互联网服务的应用场景,互联网/挪动互联网服务的用户规模也越来越大,减速了这些撑持大规模互联网服务公司的技术倒退。总的来说,技术倒退和理论利用素来都是相辅相成的。 到了挪动互联网倒退的后半场,海量技术曾经成为了标配。在架构设计上,到底还能做什么或者要思考什么,能力体现出一个架构的设计精良?这个问题值得思考。 集体了解的后海量时代的架构设计,更应该要思考的是系统性和外部、内部之间的逻辑关系和复杂度。总结了以下几个方面(海量服务之道只是列举局部并非全副能力): 海量服务的架构都非常复杂,波及 Android、iOS、H5 等各种端的展示和拜访接入。后端也有接入层、业务逻辑层、根底层之分。有内存 Cache、分布式 Cache,NoSQL 和 RDBMS 关系型数据库,可能还有离线解决局部,有时为理解耦还会引入 MessageQueue、音讯总线等。 不仅分层分级,还会有各种同构或者异构的子系统。这些子系统之间有相互依赖和简单的调用关系。还会有很多第三方的依赖,有不同类型的接口定义和协定交互方式等等。 怎么去界定每个模块的性能定义?每一个模块和子系统怎么做到高内聚低耦合以及互相隔离?因而在海量根底的架构设计中,第一个要思考的问题就是架构的边界。 02、架构的边界架构边界要思考的点如下: 边界思维、边界意识,摸索边界、扩张边界职责拆散、防火隔离契约精力高内聚、低耦合、层次分明举个例子:在开发一个 App,须要和后盾通过 HTTP 来交互。那么首先要明确的有以下几个问题: 协定通信的 layout 怎么定义?个别分包头和包体。终端和后盾有几次交互,每次交互的申请和返回字段是什么?采纳什么样的协定交互,JSON、JCE、ProtocolBuffers ?错误码怎么定义?是否有二级错误码?头部一个错误码,代表整体的谬误和异常情况,比方登录过期等。而包体有错误码定义,标识以后申请的返回状况。在我的项目中,终端和后盾是通过 HTTP Post 来交互的,定义了 layout,JCE 来做为交互协定的具体格局,定义了如下 Jce 构造(为了简化,这里只示例申请包体)。注:JCE 是 TAF(腾讯外部应用多年的基于微服务的对立利用框架TAF,Total Application Framework,从2017年开源 ) 框架中客户端和服务端的通信协议,相似thrift和pb协定。 struct ReqHead { Int cmdId; ...}struct Request { ReqHead head; vector<char> body;}struct PkgReq { PkgReqHead head; Request request;}HTTP Body 分为 3 局部: ...

April 13, 2023 · 2 min · jiezi

关于架构设计:架构师日记为什么数据一致性那么难

作者:京东批发 刘慧卿 一 前言在古代大型分布式软件系统中,有一个绕不过来的课题,那就是如何保证系统的数据一致性。驰名的Paxos算法(Megastore、Spanner),Raft协定(ETCD、TiKV、Consul ),ZAB协定(ZooKeeper)等分布式一致性解决方案,都是在此背景下而诞生的。 数据一致性保障为什么难呢?先来看一下咱们熟知的本地数据库事务是如何实现数据一致性的。家喻户晓,数据库事务有ACID四大个性,即原子性 (Atomicity)、 一致性(Consistency)、隔离性(Isolation) 和持久性(Durability)。任何反对数据库事务的存储引擎都须要满足这四大个性。以Mysql数据库的Innodb存储引擎的设计实现举例,数据一致性过程如下: 持久性:通过binlog、redolog来实现;(用于数据重放,从库备份)原子性:通过undolog来实现;(用于数据回滚)隔离性:通过读写锁+MVCC(undolog)来实现;(用于隔离级别的实现)一致性:通过原子性,持久性,隔离性最终实现数据一致性;由此能够见,一致性的实现是在持久性,原子性,隔离性等各种个性根底之上的。从技术实现伎俩来看,为什么是实现数据一致性的过程须要借助这么多种日志文件呢? 这还得从硬件效率上讲起,咱们先来看一组数据(仅做示意,不同硬盘型号指标存在很大差别): 通过测试数据咱们能够得出以下几点论断: 机械硬盘读写效率方面,程序读写速率是随机读写性能的100倍左右;SSD硬盘读写效率方面,程序读写速率是随机读性能的10倍左右;硬盘的程序读写速率比内存随机读写还要快;通过磁盘的读写效率咱们能够发现,数据的程序读写性能要远远高于随机读写,而是数据库的读写场景往往是随机的,为了进步性能效率,就须要尽量将随机读写转换成程序读写的实现形式。而这些拆分进去的各种日志文件就是其实现形式之一,当然还会有内存缓冲池(Buffer Pool)等其它伎俩一起配合来实现读写效率的晋升。 相似的场景,在数据库利用层面也是存在的,比方:举荐应用数据库自增ID作为主键。为什么有这条倡议呢? 这是因为B+ 树结构为了保护索引的有序性,在插入新值的时候须要做必要构造保护。如果插入的值比最大值ID大,则只须要在最初记录前面插入一个新记录。如果新插入的ID值在原先的有序记录两头,就须要移动前面的数据,空出对应的地位,而后填充新值。如果所在的数据页曾经满了,依据 B+ 树算法,这时候须要申请一个新的数据页,而后移动局部数据过来(页决裂),前面两种状况,性能会受到较大的影响。为了缩小地位移动和页决裂过程中数据的挪动,应用层保障新增的索引数据始终是程序追加模式(新增数据是索引数据的最大值),就十分有必要了。 以上示例,仅仅是本地数据一致性的简略窥探,如果叠加上集群、网络两个维度,实现分布式数据一致性,就变的更加具备挑战了。 二 分布式系统为什么分布式系统中数据一致性会更加简单呢?次要体现在上面几点: 共享内存:分布式系统没有共享内存,不能像本地零碎一样,从共享内存中间接获取整个零碎的数据快照。而是须要别离取得各个过程(信道)的本地状态,再组合成全局状态;全局时钟:分布式系统没有全局时钟,各个过程无奈正确取得事件音讯的时序关系,状态的一致性难以保障;网络超时:分布式环境下网络超时状态的存在,须要咱们找到具备高度容错个性的解决办法;2.1 CAP定理CAP定理也称为不可能三角束缚,是由加州大学伯克利分校Eric Brewer传授提出来的,他指出网络服务无奈同时满足以下三个个性: 一致性(Consistency):在某个写操作实现之后的任何读操作都必须返回该写操作写入的值,或者之后的写操作写入的值。即:各个数据备份的数据内容要保持一致且都为最新数据。可用性(Availability) :任何一个在线的节点收到的申请必须都做出响应。即:不管成功失败,都有回应。分区容错性(Partition tolerance) :容许网络失落从一个服务节点到另外一个服务节点的任意信息(包含音讯的提早、失落、反复、乱序,还有网络分区)。即:不同的节点可能会数据不统一,这种状况下咱们要保证系统还能失常运行。依据CAP原理将数据库分成了满足CA准则、满足CP准则和满足AP准则三大类: CA - 单点集群,满足一致性,可用性的个性,分区容忍性受到限制。CP- 满足一致性,分区容忍性的个性,性能收到限度。AP - 满足可用性,分区容忍性的个性,数据一致性上受到限制。 CAP定理通知咱们,在网络可能呈现分区故障的状况下,一致性和可用性(提早)之间必须进行衡量。以Paxos协定来看,它在C和A之间抉择了前者,即严格的一致性,而A则降级为大多数一致性(majority available),这和咱们接下来要介绍的BASE定理的抉择恰恰相反。 2.2 BASE定理BASE定理是对CAP中一致性和可用性衡量的后果(网络带来的分区容错性无奈漠视),是对大型互联网分布式实际的总结,是基于CAP定理逐渐演变而来。 根本可用(Basically Available):指在分布式系统呈现不可预知的故障时(网络或存储故障等),容许损失零碎的局部个性来换取零碎的可用性。比方零碎通过断路爱护而引发疾速失败,在疾速失败模式下,反对加载默认显示的内容(动态化的或者被缓存的数据),从而保障服务仍然可用。软状态(Soft state):指运行零碎中的数据存在中间状态,并认为该中间状态不会影响零碎的整体可用性和最终一致性,即容许零碎在不同节点的数据正本进行数据同步时存在延时。也就是说,如果一个节点承受了数据变更,然而还没有同步到其余备份节点,这个状态是被零碎所承受的,也会被标识为数据变更胜利。最终一致性(Eventuallyconsistent):指零碎中所有的数据正本在通过一段时间的同步后,最终状态能达到统一。在分布式环境下,思考依赖服务和网络的不确定性,传统ACID事务会让零碎的可用性升高、响应工夫变长,这可能达不到零碎的要求,因而理论生产中应用柔性事务是一个好的抉择。BASE实践的核心思想就是:依照理论利用场景,优先满足分区容错性和可用性,采纳适当的形式来使零碎达到最终一致性(不谋求强一致性),这一实践思维对于咱们在设计业务零碎时,有很大的指导意义。 2.3 事件时序在分布式系统中,不同的服务散布在不同的机器上,如何确定不同机器上的两个事件产生的先后顺序呢?首先解释下为什么分布式系统须要晓得两个事件的先后顺序。举个例子:分布式数据库中不同事务并发执行的时候,须要做事务隔离。隔离的一种做法是应用 MVCC(Multiple Version Concurrent Control)多版本并发管制,依据数据的版本号来管制该版本数据的可见性。这时候就须要晓得数据批改事件产生的先后顺序,能力正确的实现隔离性。 如何辨认事件产生的先后顺序?有以下两种思路, 逻辑工夫:只须要一个原子递增的序号标识每一个音讯即可。物理工夫:间接采纳工夫戳来标识音讯程序。Linux 将时钟分为零碎时钟 (System Clock) 和硬件 (Real Time Clock,简称 RTC) 时钟两种。零碎工夫是指以后 Linux Kernel 中的时钟,而硬件时钟则是主板上由电池供电的那个主板硬件时钟,这个时钟能够在 BIOS 的 “Standard BIOS Feture” 项中进行设置。 当 Linux 启动时,零碎时钟会去读取硬件时钟的设置,而后零碎时钟就会独立于硬件运作。 ...

April 4, 2023 · 1 min · jiezi

关于架构设计:Golang整洁架构实践

腾小云导读 为了升高零碎组件之间的耦合、晋升零碎的可维护性,一个好的代码框架显得尤为重要。本文将为大家介绍家喻户晓的三种代码框架,并从三种框架引申出COLA 架构以及作者基于 COLA 架构设计的 Go 语言我的项目脚手架实际计划。心愿能给宽广开发爱好者带来帮忙和启发! 看目录,点珍藏 1.为什么要有代码架构 2.好的代码架构是如何构建的 2.1 整洁架构 2.2 洋葱架构 2.3 六边形架构 2.4 COLA架构 3.举荐一种 Go 代码架构实际 4.总结 *本文提及的架构次要指我的项目组织的“代码架构”,留神与微服务架构等名词中的服务架构进行辨别。 01、为什么要有代码架构历史悠久的我的项目大都会有很多开发人员参加“奉献”,在没有好的领导规定束缚的状况下,大抵会变成一团乱麻。剪一直,理还乱,也没有开发壮士违心去剪去理。被迫接手的开发壮士如果想要减少一个小需要,可能须要花10倍的工夫去理顺业务逻辑,再花 10 倍的工夫去补充测试代码,切实是低效又苦楚。 这是一个广泛的痛点问题,有有数开发者尝试过来解决它。这么多年倒退下来,业界天然也诞生了很多软件架构。大家耳熟能详的就有六边形架构(Hexagonal Architecture),洋葱架构(Onion Architecture),整洁架构(Clean Architecture)等。 这些架构在细节上有所差别,然而外围指标是统一的:致力于实现软件系统的关注点拆散(separation of concerns)。 关注点拆散之后的软件系统都具备如下特色: 不依赖特定 UI。 UI 能够任意替换,不会影响零碎中其余组件。从 Web UI 变成桌面 UI,甚至变成控制台 UI 都无所谓,业务逻辑不会被影响。不依赖特定框架。 以 JavaScript 生态举例,不论是应用 web 框架 koa、express,还是应用桌面利用框架 electron,还是控制台框架 commander,业务逻辑都不会被影响,被影响的只会是框架接入的那一层。不依赖特定内部组件。 零碎能够任意应用 MySQL、MongoDB或 Neo4j 作为数据库,任意应用 Redis、Memcached或 etcd 作为键值存储等。业务逻辑不会因为这些内部组件的替换而变动。容易测试。 外围业务逻辑能够在不须要 UI、不须要数据库、不须要 Web 服务器等所有外界组件的状况下被测试。这种纯正的代码逻辑意味着清晰容易的测试。软件系统有了这些特色后,易于测试,更易于保护、更新,大大加重了软件开发人员的心理累赘。所以,好的代码架构值得推崇。 02、好的代码架构是如何构建的前文所述的三个架构在理念上是近似的,从下文图 1 到图 3 三幅架构图中也能看出类似的圈层构造。图中能够看到,越往外层越具体,越往内层越形象。这也意味着,越往外越有可能发生变化,包含但不限于框架降级、中间件变更、适配新终端等等。 ...

March 30, 2023 · 5 min · jiezi

关于架构设计:微电平台高并发实战经验奇葩问题解决之旅

作者:京东科技 孙亮 微电平台微电平台是集电销、企业微信等于一体的综合智能SCRM SAAS化零碎,涵盖多渠道治理、全客户生命周期治理、私域营销经营等次要性能,目前曾经有60+京东各业务线入驻,专一于为业务提供职场外包式的一站式客户治理及一体化私域经营服务。 导读本文介绍电销零碎在遇到【客户名单离线打标】问题时,从排查、重复验证到最终解决问题并额定晋升50%吞吐的过程,适宜所有服务端研发同学,提供生产环遇到一些简单问题时排查思路及解决方案,正确应用京东外部例如sgm、jmq、jsf等工具抓到问题根因并彻底解决,用技术为业务倒退保驾护航~ 上面开始介绍电销零碎理论生产环境遇到的离线回绝营销打标流程吞吐问题。 案例背景1、概述每日凌晨1~8点会应用80台机器为电销零碎上亿客户名单进行回绝营销打标,均匀95万名单/分钟,回绝营销jsf服务总tps约2万,tp99在100~110ms,若夜间没有实现标记加工操作,会导致白天职场无奈失常作业,并且存在客户骚扰隐患、升高职场经营效率的问题,因内部接口依赖数量较多打标程序只能凌晨启动和完结。 2、复杂度面向业务提供千人千面的配置性能,底层基于规定引擎设计实现,调用链路中蕴含泛滥内部接口,例如金融刷单标记、风控标记、人群画像标记、商城风控标记、商城实名标记等,蕴含的维度多、复杂度较高。 3、问题2023年2月24日早上通过监控发现回绝营销打标没有执行实现,体现为jmq生产端tp99过高、进而升高了打标程序吞吐,通过长期扩容、下掉“问题机器”(上帝视角:其实是程序导致的问题机器)进步吞吐,减速实现回绝营销打标。 但,为什么会频繁有机器问题?为什么机器有问题会升高40%吞吐?后续如何防止此类情况? 带着上述问题,上面开启问题根因定位及解决之旅~ 抓出幕后黑手1、为什么几台机器出问题就会导致吞吐急剧下降? 如上图所示,每有一条音讯生产报错(在本案例中是打到“问题机器”上),会本地尝试sleep并从新生产拉下来的所有音讯(本案例中jmq的batchSize=10),即每次报错产生的总耗时至多会减少一千毫秒,一共80台机器,jsf应用默认负载平衡算法,服务申请打到4台问题机器的概率是5%,jmq一次拉下来10条音讯,只有有一条音讯命中“问题机器”就会极大升高吞吐。 综上所述,大量机器有问题吞吐就会急剧升高的起因是jsf随机负载平衡算法下每个实例的命中率雷同以及报错后jmq consumer重试时默认休眠1秒的机制导致。 解决:当然consumer不报错是齐全能够躲避问题,那如果保障不了不报错,能够通过: 1)批改jmq的重试次数、重试延迟时间来尽可能的缩小影响 <jmq:consumer id="cusAttributionMarkConsumer" transport="jmqTransport"> <jmq:listener topic="${jmq.topic}" listener="jmqListener" retryDelay="10" maxRetryDelay="20" maxRetrys="1"/> </jmq:consumer>2)批改jsf负载平衡算法 配置样例: <jsf:consumer loadbalance="shortestresponse"/>原理图: 上图中的consumer图是从jsf wiki里摘取,下面的红字是看jsf代码提取的要害信息,总而言之就是:默认的random是齐全随机算法,最快响应工夫是基于服务申请体现进行负载平衡,所以应用最快响应算法能够很大水平上躲避此类问题,相似于熔断的作用(本次解决过程中也应用了jsf的实例熔断、预热能力,具体看jsf wiki,在此不过多介绍)。 2、如何断定是实例问题、找出有问题的实例ip?通过监控察看,耗时高的景象只存在于4台机器上,第一反馈的确是认为机器问题,但联合之前(1月份有过相似景象)的状况,感觉此事必有蹊跷。 下图是第一反馈认为是机器问题的日志(对应sgm监控这台机器耗时也是间断高),下掉此类机器的确能够长期解决问题: 综上所述,当时间段内耗时高或失败的都是某个ip,此时能够断定该ip对应的实例有问题(例如网络、硬件等),如果是大量ip存在相似景象,断定不是机器自身的问题,本案例波及到的问题不是机器自身问题而是程序导致的景象,持续往下看揭晓答案。 3、是什么导致机器频繁假死、成为故障机器?通过上述剖析能够得悉,问题机器报错为jsf线程池打满,机器出问题期间tps简直为0,期间有申请过去就会报jsf线程池(非业务线程池)打满,此时有两种可能,一是jsf线程池有问题,二是jsf线程池的线程始终被占用着,抱着信赖中间件的思路,抉择可能性二持续排查。 通过行云进行如下操作: 1)dump内存对象 无显著问题,内存占用也不大,合乎监控上的大量gc景象,持续排查堆栈 2)jstack堆栈 从此来看与问题机器表象统一了,根本得出结论:所有jsf线程都在waiting,所以有流量进来就会报jsf线程池满谬误,并且与机器cpu、内存都很低景象相符,持续看具体栈信息,抽取两个比拟有代表的jsf线程。 线程编号JSF-BZ-22000-92-T-200: stackTrace:java.lang.Thread.State: WAITING (parking)at sun.misc.Unsafe.park(Native Method)- parking to wait for <0x00000007280021f8> (a java.util.concurrent.FutureTask)at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:429)at java.util.concurrent.FutureTask.get(FutureTask.java:191)at com.jd.jr.scg.service.common.crowd.UserCrowdHitResult.isHit(UserCrowdHitResult.java:36)at com.jd.jr.scg.service.impl.BlacklistTempNewServiceImpl.callTimes(BlacklistTempNewServiceImpl.java:409)at com.jd.jr.scg.service.impl.BlacklistTempNewServiceImpl.hit(BlacklistTempNewServiceImpl.java:168)线程编号JSF-BZ-22000-92-T-199: stackTrace:java.lang.Thread.State: WAITING (parking)at sun.misc.Unsafe.park(Native Method)- parking to wait for <0x00000007286c9a68> (a java.util.concurrent.FutureTask)at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:429)at java.util.concurrent.FutureTask.get(FutureTask.java:191)at com.jd.jr.scg.service.biz.BlacklistBiz.isBlacklist(BlacklistBiz.java:337)````**推断**:线程编号JSF-BZ-22000-92-T-200在UserCrowdHitResult的36行**期待**,线程编号JSF-BZ-22000-92-T-199在BlacklistBiz的337行**期待**,查到这,根本能推断出问题起因是线程期待,**造成问题的相似代码场景**是1)main线程让线程池A去执行一个工作X;2)工作X中又让同一个线程池去执行另一个工作,当第二步获取不到线程时就会始终等,而后第一步又会始终等第二步执行实现,就是造成线程相互期待的假死景象。**小结**:查到这根本能够确认问题,但因代码保护人到职以及程序盘根错节,此时为验证论断先批改业务线程池A线程数:50->200(此处是为了验证没有线程期待景象时的吞吐体现),再进行验证,论断是**tps会有小范畴抖动**,但不会呈现tps到0或是大幅升高的景象。单机tps300~500,流量失常了,即**未产生线程期待问题时能够失常提供服务**,如图:![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/261c1e2d0bf74403ab25a953182804f5~tplv-k3u1fbpfcp-zoom-1.image)**印证推断**:通过堆栈定位到具体代码,代码逻辑如下:BlacklistBiz->【线程池A】blacklistTempNewService.hitblacklistTempNewService.hit->callTimescallTimes->userCrowdServiceClient.isHit->【线程池A】crowdIdServiceRpc.groupFacadeHit ...

March 17, 2023 · 1 min · jiezi

关于架构设计:工作十年在腾讯沉淀的高可用系统架构设计经验

腾小云导读 在零碎的开发过程中,很多开发者都为了实现零碎的高可用性而发愁。本文从研发标准层面、应用服务层面、存储层面、产品层面、运维部署层面、异样应急层面这六大层面去分析一个高可用零碎的架构设计须要有哪些要害的设计和思考。心愿腾讯的教训办法,可能给宽广开发者提供参考。内容较长,您能够珍藏后继续浏览。 看目录点珍藏,随时涨技术 1 高可用零碎的架构设计思维 1.1 可用性和高可用概念 1.2 高可用零碎设计思维 2 研发标准层面 2.1 方案设计和编码标准 2.2 容量布局和评估 2.3 QPS 预估(漏斗型) 3 应用服务层面 3.1 无状态和负载平衡设计 3.2 弹性扩缩容设计 3.3 异步解耦和削峰设计(音讯队列) 3.4 故障和容错设计 3.5 过载爱护设计(限流、熔断、降级) 4 存储层面 4.1 集群存储(集中式存储) 4.2 分布式存储 5 产品层面 6 运维部署层面 6.1 开发阶段-灰度公布、接口测试设计 6.2 开发阶段-监控告警设计 6.3 开发阶段-安全性、防攻打设计 6.4 部署阶段-多机房部署(容灾设计) 6.5 线上运行阶段-故障演练(混沌试验) 6.6 线上运行阶段-接口拨测系列设计 7 异样应急层面 01、高可用零碎的架构设计思维1.1 可用性和高可用概念可用性是一个能够量化的指标,是指在某个考查工夫,零碎可能失常运行的概率或工夫占有率期望值。行业内个别用几个 9 示意可用性指标,对利用的可用性水平个别衡量标准有三个 9 到五个 9。个别咱们的零碎至多要到 4 个 9(99.99%)的可用性能力谈得上高可用。 高可用 High Availability 的定义(From 维基百科): 高可用是 IT 术语,指零碎无中断地执行其性能的能力,代表零碎的可用性水平,是进行零碎设计时的准则之一。服务不可能 100% 可用,因而要进步咱们的高可用,就要尽最大可能的去减少咱们服务的可用性,进步可用性指标。一句话来表述就是:高可用就是让咱们的服务在任何状况下,都尽最大可能地可能对外提供服务。 ...

March 14, 2023 · 2 min · jiezi

关于架构设计:基于Istio的灰度发布架构方案实践之路

作者:京东物流 赵勇萍 1. 背景介绍灰度公布,又名金丝雀公布,是指可能平滑过渡的一种公布形式。基于零碎稳定性和疾速业务迭代的综合思考,业务利用开发团队采取了新版本服务灰度上线的形式,即新版本服务并非全量公布到线上环境,而是公布少数几个实例进行灰度验证,没有问题后再全量公布。在局部外围服务进行接口降级和逻辑迁徙时,还会通过在业务逻辑代码中减少黑白名单或者流量百分比管制的形式,逐渐将旧版本接口实现迁徙至新版本接口实现。尤其是对于toB业务和SAAS类平台,很多状况须要依据租户或用户维度进行灰度管制,实现业务上的A/Best性能。 对于之前咱们业务中实现的传统的灰度公布, 较好地衡量了服务稳定性和业务迭代效率,但仍存在以下问题: a. 零碎侵入性强,业务开发人员在服务接口中编码大量与业务逻辑无关的黑白名单或流量百分比控制代码。 b. 当新版本接口呈现稳定或异样,通常须要业务团队通过紧急批改代码和紧急公布,来更新黑白名单和流量百分比控制策略,工夫较长,业务影响较大。 c. 调整黑白名单或流量管制百分比,须要业务团队公布代码或者接入动静配置核心,过程简单、可复用性差、操作灵活性差. d. 对于单体利用来说,灰度公布计划实现还算简略,但对于微服务利用,每次公布版本可能不是全副服务须要灰度公布,实现微服务灰度公布的原子维度管制,也是导致微服务框架下灰度计划不能很好落地的起因。 笔者理论业务我的项目(采灵通零碎)采纳的是微服务的架构设计,总计服务个数60+,技术底座采纳K8s+Istio的服务治理计划。如果采纳传统的灰度公布计划,每个服务上下游依赖过多,绝对于传统的灰度公布计划,并不能很好满足业务诉求。因而,摸索了一条基于Istio的服务流量治理计划下的灵便可配置的灰度公布计划。 2. 计划详情先上一个计划简介图: 本发明的技术计划以k8s服务部署为根底,以istio服务流量治理为外围,以Mysql为数据存储,同时联合jenkins的自动化部署计划,能够实现低成本动静的高效微服务公布计划,并且带业务服务无代码侵入。 本发明的技术计划以activiti开源工作流引擎为根底, 以Mysql作为数据存储, 通过自定义的一套规定引擎框架, 能够实现流程规定的的疾速搭建和动静批改性能. a. 如图所示,k8s management实现对服务的pod治理,在k8s治理中,正式环境和灰度环境别离附属两个命名空间,通过deployment实现服务的创立,创立中,灰度和正式的pod实例会打上prod或gray的标签。Deployment创立过程通过jenkins治理,能够实现部署的自动化流程。具体deployment配置计划详情请跳转至3.2.2 b. 如图所示,istio管制立体能够创立虚构服务,通过对虚构服务的路由策略的配置不同,能够实现不同的灰度策略,配置下发通过jenkins治理,能够实现配置的自动化下发。具体策略详情请跳转至2.1 c. 如图所示,具体业务申请实现流程如上: 用户首先须要登录申请,申请动员到咱们自建的认证核心服务中。如图中1标所示。认证核心接管到申请会到cookie生成器中获取用户认证的cookie,如图中2标所示Cookie生成器会到数据库中读取灰度白名单信息,来确定是否在cookie中打灰度标签。如图中3标所示。认证核心拿到cookie后返回给前端用户 ,如图中4,5标所示。用户带着cookie申请业务申请到虚构服务A.虚构服务A中存在istio控制面板下发的的灰度配置信息,通过配置信息,决定以后的申请流量是流入正式环境实例A还是灰度环境实例A。如图中6,7标所示。服务A中存在调用服务B的业务逻辑,所以服务A会申请到虚构服务B中,虚构服务B中存在istio控制面板下发的的灰度配置信息,通过配置信息,决定以后的申请流量是流入正式环境实例B还是灰度环境实例B。如图中8标所示。通过以上8个步骤,咱们实现了灰度计划下的流量管控,该计划对于业务服务A和业务服务B无任何代码侵入,同时,灰度的配置计划能够实时疾速的通过jenkins治理页面进行自动化下发,实现灰度公布的动静灵便切换. 至于灰度环境的低成本,当代码实现灰度拉平线上后,通过更改灰度下发策略,能够实现灰度环境和正式环境的负载平衡,独特承当正式环境的业务流量,保障了灰度环境的主机资源不会被节约。 2.1 k8s Management治理在k8s治理方面,要创立两个命名空间,一个是prod环境,一个是gray环境,通过命名空间隔离正式环境和灰度环境资源,次要起因是能够更好的治理。当然此处并不强制。同时,须要配置一下deployment的标签项,在标签项减少一个profile键,依据场景,profile能够配置为prod和gray,具体配置demo如下图所示。 2.2 基于istio灰度整体配置计划 灰度整体计划流程图如上图所属,该流程图中次要分为三大整体计划,包含:基于用户白名单的灰度计划,依照流量百分比灰度计划,灰度拉平线上的负载平衡计划。以上灰度环境能够满足之前提到的多场景,低成本,动静,无侵入的灰度计划要求。 以下2.3,2.4,2.5将别离具体介绍三种灰度计划的具体配置策略。 2.3 基于用户白名单的灰度计划策略 cookie中打标签。通过认证核心,能够实现业务维度的灰度管制,cookie中会依据用户白名单,进行灰度打标签。Cookie格局如下: cookie:tenantGray=0;rememberMe=;channel=* 当tenantGray=0时,示意以后用户不是灰度用户,当tenantGray=1时,示意以后用户是灰度用户。 当抉择依据cookie动静配置灰度服务时,依据选中的服务,virtualService配置如下: 如图所示,当申请的cookie信息匹配到tenantGray=1时,依据istio的虚构服务规定,走test-A.gray.svc.cluster.local路由,而后申请会打到灰度环境的服务实例上。当tennatGray=0时,依据istio的虚构服务规定,走test-A.prod.svc.cluster.local的路由,而后申请会打到正式环境的服务实例上。 如果用户抉择依据灰度标签进行灰度计划抉择,配置计划如下: 在k8s集群中咱们之前创立灰度服务的deployment时,过后减少过一个标签,标签为profile: pray,用来标记该服务为灰度服务。 如图所示配置,match条件为,当申请起源是来自带有灰度标签的deployment服务时,走test-A.gray.svc.cluster.local路由,而后申请会打到灰度环境的服务实例上。反之,走test-A.prod.svc.cluster.local的路由,而后申请会打到正式环境的服务实例上。 而后把所有须要灰度公布的服务对应的vistualService的配置信息通过jenkins的自动化流程下发到k8s集群中。2.4 依照流量百分比的灰度计划 当咱们的业务场景不须要针对具体的用户进行灰度时,尤其是咱们只是在肯定范畴内做A/Btest,这样的话,咱们能够更改配置信息,实现业务的依照流量比例进行灰度管制,具体的配置virtualService计划如下: 2.5 灰度拉平线上的负载平衡计划 该灰度计划比拟明确,就是当该服务不再须要灰度时,为了不节约服务器资源,将灰度服务跟线上服务代码拉平,而后通过流量治理,正式环境的流量实现负载平衡的目标。假如灰度服务跟正式服务的服务实例数比率为1:1,具体virtualService配置如下: 2.6 微服务灰度公布治理计划家喻户晓,对于单体利用来说,灰度公布只须要对繁多服务进行灰度管制就会要了。然而到了微服务框架下,会存在泛滥服务,服务之间存在简单的网络拓扑关系,所以当咱们进行服务的灰度公布时,须要管制服务之间的灰度调用关系,实现灰度公布的服务治理性能,解决了微服务框架下动静治理多服务之间的灰度计划串联问题。 以下举例三种不同的灰度治理场景。 下图实例场景是,服务A采纳基于灰度白名单的灰度策略,服务B采纳灰度拉平线上的灰度策略,而后服务A拜访服务B,能够实现服务A的灰度公布,服务B为正式环境。 b. 下图实例场景是,服务A采纳基于灰度白名单的灰度策略,服务B采纳基于服务灰度标签的拜访策略,而后服务A拜访服务B,能够实现灰度服务A的流量拜访灰度服务B,正式服务A的流量拜访正式服务B。 c. 图实例场景是,服务A采纳基于流量比率的灰度策略正式环境和灰度环境的比率为8:2,服务B采纳基于灰度白名单的灰度策略,而后服务A拜访服务B时,在灰度白名单中的用户,在灰度服务B,不在灰度白名单中的用户,走正式服务B。 ...

March 10, 2023 · 1 min · jiezi

关于架构设计:阿里云架构设计

云架构设计及工具应用什么是云架构云架构是指在云计算环境下的架构设计。与传统架构不同,云架构须要思考云服务的可用性、可伸缩性、安全性和老本效益。首先,云架构须要思考可用性。这意味着零碎必须可能在网络、硬件或其余故障产生时持续运行,保障用户对系统的拜访。其次,云架构须要思考可伸缩性。这意味着零碎必须可能随着用户数量的减少而扩大,而不会影响零碎的性能。第三,云架构须要思考安全性。云环境中的数据和应用程序须要失去爱护,避免未经受权的拜访。最初,云架构须要思考老本效益。在云环境中运行零碎可能会带来费用上的扭转,因而须要抉择适合的云服务并进行优化以降低成本。为了实现这些指标,云架构通常采纳微服务架构、容器化和自动化运维技术。微服务架构将零碎划分为独立的服务,能够更好地实现可伸缩性和可用性。容器化能够进步零碎的可移植性和可部署性。而自动化运维技术能够进步零碎的可靠性和安全性。在云架构设计中,咱们还须要抉择适合的云服务。云服务提供商提供了各种不同的云服务,如计算、存储、数据库、网络等。咱们须要依据我的项目的需要来抉择适合的云服务。此外,在云架构中,咱们还须要思考到老本治理。因为云计算是基于资源应用付费的模式,因而咱们须要确保咱们只在应用时付费。这能够通过监控资源应用状况并在不应用时进行付费的实例来实现。总的来说,云架构设计是一个简单的过程,须要思考多个因素,包含可用性、可伸缩性、安全性、老本效益以及抉择适合的云服务。它须要一直的评估和调整来确保零碎满足业务需要并放弃高效运行。在设计云架构时,还须要思考数据的治理和安全性。 云存储与传统存储不同,须要思考数据的散布性和冗余性以确保数据的可用性。 同时还须要思考加密和访问控制等安全措施来爱护数据不被未经受权的拜访。通过应用云负载均衡器,能够将流量散发到多个实例上,从而进步可用性和可伸缩性。 通过应用云监控工具,能够监控零碎的性能和资源应用状况,从而在发现问题时及时采取行动。另外, 利用云平台的自动化性能,可能简化运维的工作,并且可能进步零碎的可用性和安全性。在总结,云架构设计是一项十分重要且具备挑战性的工作,须要思考多种因素,从而确保零碎具备高可用性、可伸缩性、安全性和老本效益。 通过应用微服务架构、容器化、自动化运维技术和云服务,能够在云环境中构建牢靠和高效的零碎。另外,在云架构设计中,咱们还能够思考应用云原生技术。云原生是一种基于云计算构建和运行应用程序的办法。它应用容器、服务网格和微服务等技术,能够更好地利用云环境中的伸缩性和可用性。云原生还能够进步零碎的可维护性和可靠性。它能够自动检测和复原零碎中的故障,并主动进行负载平衡。这样能够缩小人工干预,进步零碎的效率和可靠性。总之,云架构设计是一个一直倒退和演变的过程,云原生技术是以后设计中的一个重要方向。它能够帮忙咱们更好地利用云环境的劣势,进步零碎的可用性、可伸缩性、可靠性和可维护性。此外,在云架构设计中咱们须要思考到网络架构。云环境中的网络架构须要可能反对高带宽、低提早和高可用性,以确保零碎的高性能和可用性。对于网络的可用性,能够通过应用冗余和负载平衡来确保网络的高可用性。对于网络的安全性,能够应用防火墙和入侵检测零碎来爱护网络免受攻打。在云架构设计中还须要思考到多地区部署和数据复制。多地区部署能够确保零碎在地理位置上的冗余性,并且可能进步零碎的可用性。而数据复制能够保证数据的安全性和可用性。总之,网络架构是云架构设计中重要的一部分。咱们须要思考网络的可用性、安全性、带宽、提早等因素,并采取措施来确保网络的高可用性和安全性,从而进步零碎的性能和可用性。如何应用云架构工具进行设计阿里云提供了一个名为”Aliyun Resource Manager (ARM)”的工具,能够帮忙用户在线制作阿里云的原生云架构图。 ARM是一个基于Web的可视化编排工具,能够轻松地绘制和治理阿里云上的资源,包含云服务器、数据库、存储和网络等。应用步骤:登录阿里云控制台。抉择“ARM”服务。创立新模板。应用左侧面板中的元素,在画布上增加和连贯各种资源。应用“保留”和“公布”按钮,将模板保留到您的阿里云账户中。能够应用这种办法制作阿里云上各种类型的原生云架构图,如云服务器集群、数据库集群、云存储系统、网络拓扑等。您还能够应用第三方的在线制图工具来制作阿里云的原生云架构图,例如Visio或Lucidchart。这些工具提供了丰盛的图形元素和连接线来形容云架构,并且还反对团队合作和版本控制等性能。抉择一个在线制图工具,例如 Visio 或 Freedgo Design,上面应用Freedgo Design 进行阿里云架构设计.拜访 https://www.freedgo.com 登录并进入 https://www.freedgo.com/draw-... 创立一个新图表.点击 更多图形...,在弹出的对话框中抉择aliyun,也能够抉择局部阿里云的组件,比方数据库,阿里云 / 专有云,阿里云/域名和网站,阿里云/弹性计算,阿里云/Extras,阿里云/ Iot,阿里云/媒体服务,阿里云/中间件等等.应用工具中的元素和连接线在画布上绘制阿里云的云架构将图表保留到云端或本地如果须要,能够共享图表或导出为各种格局。最初实现对应的制图.阿里云图图例商用车联网解决方案媒体公布经营解决方案广告需求方平台DSP解决方案阿里云图图例阿里云图图例阿里云图图例

February 8, 2023 · 1 min · jiezi

关于架构设计:7天DAU超亿级羊了个羊技术架构升级实战

导语 | 在短短的7天内,羊了个羊小游戏的DAU冲破了1亿。然而,其最后技术架构仅撑持5000QPS并发,无论技术、人力、资源以及服务都难以应答。用户涌入、数据飙升,给原有的技术架构、运维体系、以及平安防备等技术体系都带来了微小的挑战。如何通过架构优化,让一款小程序游戏能够在短时间内实现对上亿DAU的反对?本文将从技术角度解读这背地的技术实际历程,心愿为正在从事小游戏开发的技术同行带来一些参考。 背景谁也没有想到,去年9月,一款卡通背景打消闯关游戏《羊了个羊》全网迅速刷屏。凡是一个拿着手机左顾右盼的人,九成概率都在忙着通关,还有少量的人,因为不能通关而通宵达旦,夜不能寐。 后盾数据显示,在短短的7天内,这款小游戏的DAU就冲破了1亿。要晓得,除了王者光荣、原神等比比皆是的景象级手游之外,1亿DAU是这个行业的喜马拉雅山,可是,它却被一个看上去设计毛糙的小程序游戏轻松实现了。 用户涌入、数据飙升,实际上给原有的技术架构、运维体系、以及平安防备等技术体系都带来了微小的挑战,这个守业团队一共只有几个人,最后的技术架构仅撑持5000QPS并发,因而,无论技术、人力、资源以及服务都越来越难以应答。 如何通过架构优化,让一款小程序游戏能够在短时间内实现对上亿DAU的反对?本文将从技术角度解读这背地的技术实际历程,心愿为正在从事小游戏开发的技术同行一些参考。 架构全面降级一款小游戏能不能胜利,不仅和自身的通关设计有着微小的关系,而且还和上量之后,零碎是否继续稳固也密切相关。《羊了个羊》这款小游戏在爆火之后的前几天,已经在技术架构面临严峻考验,这对一款正在用户量疾速爬坡的小游戏来说,能够说是致命的挑战,如果不能疾速解决,将会大幅升高玩家的游戏体验,从而疾速被用户摈弃。 《羊了个羊》在最开始也遇到了这样的问题,就是一瞬间,涌入海量用户,速度之快,人数之多,超过了所有人的预期。就像一条双向两车道,车流量不大的状况下,还能失常行驶,可一旦来了成千上万辆车,交通的效率必定大打折扣,甚至堵死。 当初回过头看,最开始的技术架构因为技术以及工夫等因素,在设计上有些简略,如下图1所示,玩家流量通过一个LB进入,传输给几个POD进行游戏逻辑解决, 再将数据进行存储,其中,热数据存储在Redis中, 长久化数据存在MongoDB。 因为设计时,对如此大流量不足充分考虑,实际上也没有料想到会有这么大的流量,而且单点服务的性能瓶颈,再加上代码未进行充沛优化,造成过后的零碎最高只能接受5000的QPS,但理论流量增长很快, 并且继续升高并达到性能瓶颈,游戏服务开始瘫痪,全副玩家无奈再进行游戏。 《羊了个羊》最开始技术架构 面对服务中断, 《羊了个羊》和腾讯云服务团队在详细分析原来架构的有余之后,决定从三个方面,针对原有架构做重点优化:在计算扩容层,依附腾讯云云原生产品为原有技术架构降级,实现服务高可用;为疾速补齐运维能力,通过业务日志诊断程序性能,配合业务调优以缩小服务器压力;最初在平安防备畛域,通过平安计划抵制异样流量攻打。 《羊了个羊》最新技术架构 具体措施上,首先通过引入腾讯云TKE Serverless 的弹性机制, 实现游戏服主动纵向和横向扩大,实现服务解藕,减少容错和熔断机制; 其次,通过腾讯云开箱即用的日志服务 CLS,对游戏接口稳定性/异样调用趋势进行监控,帮忙用户疾速观测产品质量 ,并第一工夫获取到异样panic统计分析和告警 。 同时,还要针对许多歹意BOT流量大量涌入到游戏中,导致游戏服务器 QPS、带宽疾速升高,影响服务可用性等状况,引入WAF+高防包, 抵挡内部异样流量攻打。 在此之外,单方产研团队还通过启用CDN做游戏动动态资源拆散,让玩家应用的游戏资源实现就近下载,加重网络端压力;设计多LB入口实现入口高可用和限流,防止零碎被超额流量过载;把MongoDB转换为读写拆散模式,配合代码逻辑优化实现性能晋升,引入分库实现业务分层与隔离,Redis缓存热数据,分担数据库查问压力等。 通过上述一系列技术升级, 新架构禁受住了一波又一波的流量峰值考验,甚至在高峰期DAU过亿后,游戏技术零碎仍旧体现稳固,这对于一个公布才几个月的小游戏来说,在国内也很难再找到这样的例子。 技术实战:扩容、运维、平安上面咱们将从扩容、运维、以及平安三大外围环节动手,具体介绍在具体实操过程中,单方是如何应答流量的暴发挑战的。 3.1 一崩再崩,主动扩容为何不灵?**在开展之前,先说下这次起到至关重要的一款产品----TKE Serverless ,它是基于腾讯云 TKE 容器服务孵化进去的一种全新的无需治理服务器状态的 Kubernetes 容器服务平台,最外围的利器是领有一个全新的集群节点管理模式,称之为超级节点。 上云的开发者都晓得虚拟机,超级节点就相似于一台超大规格的 CVM 虚拟机,它是基于 Serverless 容器技术,模仿 Serverful 有节点治理体验的新形态容器集群节点。如果用户须要进行固定资源的扩缩容,仅须要对这台“超大规格的 CVM”进行升降配,简略点击几个鼠标,就能够配置实现,资源管理变得极为简略。 实际上,《羊了个羊》在6月上线初期就采纳了 TKE Serverless 的云原生形式部署游戏零碎,心愿借助产品的免运维及疾速扩缩容能力,撑持将来玩家的规模增长,但在9月上旬,《羊了个羊》忽然一夜爆火,玩家规模急剧回升,游戏零碎开始呈现不稳固的状况。 通过梳理发现,因为初始配置的容器规格比拟低,正本数也绝对较少,当初始玩家规模一直上涨时,《羊了个羊》团队依据 TKE 控制台的监控/告警能力,发现容器的 CPU/内存等各项指标都达到了最大值,运维同学过后随即做出调整,游戏服务的各项指标稳固了下来。 但随着玩家规模持续上涨达到千万级别时,游戏又开始呈现了偶发的不稳固问题,体现为内存指标疾速减少直到打满整个容器,且流量还在一直增长中。腾讯云团队紧急联结《羊了个羊》产研团队剖析利用的瓶颈,疾速解决了如服务内存泄露、服务分级缓存策略、云产品配额限度等多个问题,这才让游戏服务逐步稳固了下来。 因为《羊了个羊》技术团队配置了基于 CPU 指标的容器 HPA 动静扩缩容策略,在游戏日活继续陡增的状况下,零碎可能在秒级主动扩容了近万核容器资源。在此期间,也无需投入人力运维 Kubernetes 集群以及放心资源有余等问题,从而能够把精力都投入到游戏玩法优化上来。在随后的两周工夫,只管玩家规模增长到几百倍以上,最终达到了上亿的日活,这套服务仍旧保持稳定。 ...

January 18, 2023 · 1 min · jiezi

关于架构设计:轻量级的架构决策记录机制

作者:倪新明 ADR是一种性价比十分高的架构决策文档化实际,团队引入和实际老本很低,却能为团队带来极大收益! 1 团队研发面临的问题不论是在传统的IT行业,还是互联网行业,研发团队在架构决策层面或多或少的都会面临以下问题或挑战: •新成员退出团队,对系统现有的架构决策可能会自觉恪守,只知其然,不知其所以然;或者挑战或违反束缚,继续挑战以后决策,“质疑”决策的合理性和正确性,负责人须要不间断的解释、同步、推动达成共识 •架构决策的潜在问题随着时间推移裸露,但,如果决策时进行充沛剖析这些问题可能会提前发现和躲避 •现有零碎架构决策是如何演进?以后决策背地的动机是什么?有可能团队内曾经没有人能精确的答复 •类似架构决策场景在零碎中反复呈现,因为忘记决策起因,或团队成员变动等因素,仍要花工夫去剖析、设计和推动干系人达成共识 •团队内只有少部分人负责架构设计,其余团队成员无机会参加,但实际上团队成员有相应诉求,至多可能理解某项要害架构设计的决策过程 •即便团队外部接手的我的项目,你能疾速获取零碎要害架构决策及其起因吗?你可能会从代码库中寻找架构决策的蛛丝马迹,但很难获取架构决策背地的动机以及决策的演进过程 基于以上这些问题,咱们想: •通过最小但仍然高效的形式记录零碎的架构决策 •可能识别系统要害决策的演进过程 •架构决策以及设计最佳实际可能在团队间高效同步 •团队成员都有机会参加到架构设计决策过程中 通过文档模式记录架构决策首当其冲的问题是:文档过期!! 的确,过期问题是文档化必然面临的问题。无论通过什么机制,比方强流程、自动化更新等都存在过期危险。那为什么还要抉择记录架构决策呢?基于以下两个起因: •性价比:架构决策文档化的收益远大于保护过期带来的老本 •轻量级:放弃ADR的简短、轻量,规模越小的文档越容易放弃与理论的同步。 2 ADR分析Architecture Decision Record,缩写ADR,即架构决策记录,该实际最先由Michael Nygard发动,是记录架构决策最无效的形式之一。简略来说,ADR是一种对架构决策的文档化记录,其目标是通过文档化的模式记录零碎的架构决策、起因以及决策过程。 通过对系统架构决策进行无效记录,团队能够从以下几个层面取得收益: •新人疏导,便于疾速相熟零碎新的团队成员能够疾速获取零碎的历史架构决策,了解决策背地的背景、决策过程以及相干影响 •我的项目交接,对已有决策进行文档化积攒麻利环境强调团队对常识的疾速学习,基于ADRs团队能够疾速相熟已有零碎的架构演进过程 •对齐认知通过推动落地ADRs,团队成员更容易对设计最佳实际达成统一意识和了解,进一步防止后续建设过程中的“反复造轮子”,晋升设计常识在团队间复用 倡议的ADR的根本构造包含题目、状态、背景、决策、影响共五个局部,个别状况下,举荐减少一致性和备注两个极具价值的额定章节作为补充。 须要阐明的是,团队能够按需减少其余章节以加强ADR的体现能力,比方减少可选计划章节对可选计划进行详细描述。 题目【必选】 ADR的 “题目” 局部次要包含两局部,其一是程序编号,其二是对架构决策的简短形容。题目的形容须要确保对架构决策进行精确形容、清晰无歧义,同时,也要放弃简短明了。 例如:ADR 01. 订单服务和履约服务之间采纳异步音讯机制 状态【必选】 ADR的 "状态" 限定为 待审核 , 审核通过,被取代 三种状态之一。 •待审核:决策必须被高级别决策者或ARB审核 •审核通过:架构决策曾经被审核,并已准备就绪进行实现 •被取代:架构决策已产生变更,并被另一个ADR取代。该状态表明,之前的ADR肯定是被审核通过的,处于提议状态未审核通过的ADR是不容许流向该状态。处于提议状态的ADR只能继续批改直到审核通过。被取代状态提供了一种无效的架构决策追溯机制,可能帮忙团队辨认架构决策的演进过程。 背景【必选】 推动架构师对此项架构决策的具体背景或问题进行形容,以及简洁简要地表述可能的可选计划。决策背景在肯定水平上也是对系统架构的一种形容。 阐明:不倡议在此章节进行具体的代替计划剖析和阐明,如果的确须要进行具体论述,则倡议减少额定的章节进行阐明。 可选计划【可选】 对可选的代替计划进行详细描述,比照不同计划的优劣势 决策【必选】 该局部蕴含了具体的架构决策以及相应的决策依据,原则上要应用必定式、命令式的形容形式表述具体的架构决策,不要存在主观的、消极的、不置可否的、可能存在歧义的措辞。阐明:关注Why 而非 How,了解架构决策的起因比了解怎么实现更加重要 影响【必选】 该局部形容此项架构决策的整体影响。每项决策都会或多或少的对现有零碎产生影响,包含好的影响和坏的影响,通过该章节推动架构师思考这些影响是否超过架构决策的收益。 一致性【可选】 该局部并不是规范ADR元素,但同样颇具价值,其作用在于推动架构师从架构一致性的视角思考所作架构决策如何进行度量和治理。架构师必须确定该项架构决策的一致性保障是通过人工形式还是通过自动化形式实现。如果能够通过自动化形式进行,则在该章节明确阐明自动化的执行计划。 备注【必选】 备注局部并不是规范ADR的构造,然而强烈推荐减少该章节。备注局部次要蕴含的ADR的各种元数据,例如: 原作者、审核日期、审核人、代替日期、最初批改日期、批改人、最初批改内容 阐明:有些团队认为备注局部的元数据信息没有太大价值,特地是,当团队将ADRs与代码一起存储在配置库时(并不举荐该种存储形式)。但实际上,将元信息作为ADR的一部分比依赖配置库更具价值和劣势。 3 ADR的组织和存储ADR文档具体寄存在什么地位,比方FTP服务器、WIKI或者同我的项目代码配置库,不同的团队能够依据状况进行灵便抉择。准则:ADR可能被干系人便捷地获取。 ...

December 15, 2022 · 1 min · jiezi

关于架构设计:京东云开发者|软件架构可视化及C4模型架构设计不仅仅是UML

软件系统架构设计的指标不在于设计自身,而在于架构设计用意的传播。图形化有助于在团队间进行高效的信息同步,但不同的图形化形式须要语义一致性和效率间实现均衡。C4模型通过不同的形象层级来表白零碎的动态构造,并提供了最小集的形象建模元素,为设计人员提供了一种低认知负载、易于学习和应用的高效建模形式。 1 为什么要进行架构可视化?软件系统架构设计的指标不在于设计自身,而在于架构设计用意的传播。如果不能清晰、统一的在干系世间进行设计用意的同步,即便再好的设计也只是海市蜃楼。软件架构设计实质上也是一种形象和建模的过程(对模型和形象的实质参考文章《 畛域驱动设计开篇 》),软件架构设计模型的表白有多种形式:图形化、语言和文字。绝大部分场景下,图形化在架构设计的表现力层面成果更佳。因而,对于软件系统架构进行可视化表白是有价值,且是必要的。 软件架构可视化的形式有多种,不同的团队有不同的实际形式,最为常见的由如下几种: • 线框图:通过线框图和连线表白架构元素及之间的关系 • UML:对立建模语言,表白零碎的动态构造和动静行为 • 草图:非正式的图形 不同的可视化形式各有优劣,以下局部将对不同的表现形式进行阐明 1.1 可视化形式-线框图线框图是最为通用的可视化表达方式之一,架构师或设计人员大量的架构图,比方技术架构、性能架构、数据架构、逻辑架构等等都通过线框图的模式表白。该种可视化形式的劣势是: • 建模工具多样化:你能够基于Viso、Drawio、PPT等任何一款反对线框图的软件进行建模工作 • 学习成本低:设计人员简直不须要进行专门的建模语言以及建模工具的学习,门槛较低 但,基于线框图表白软件系统架构存在的问题也非常明显:语义的一致性问题 你可能本人画过很多软件系统架构图,也可能参加评审过其余团队的架构图,我置信,对你而言并不是的所有的图都是“清晰且易于了解的”。举个简略的场景,如果咱们在百度搜寻 “架构图” ,你可能失去以下后果: 各式各样的 “架构图”:不同形态和色彩的图形元素、不同形态和色彩的连线、不同的用意。 咱们能够看出:线框图尽管简略,但其其图形化的语义一致性是大问题。尽管都是通过线框表白软件系统架构,但不同的人可能应用不同的元素、不同的色彩、不同的连线和分层等等,线框自在表白的灵活性和图形化语义的一致性存在潜在抵触,最终都会妨碍架构设计用意传播。 1.2 可视化形式-UMLUML是对立建模语言,相比于线框图而言,其劣势是在软件建模层面提供了一致性的建模元语言。简略来说,UML提供了大家达成统一的(UML反对扩大的场景除外)建模元素。如果团队成员比拟相熟UML,那么通过UML表白的零碎架构图人造具备认知一致性。 丰盛灵便的建模元语言在晋升语义一致性的同时,也必然会导致复杂性的回升。把握UML具备肯定的学习老本,而纯熟的利用对研发人员也提出了更高的要求。基于 Simon Brown给出的数据,理论状况只有多数团队真正应用UML。不论是UML的复杂度和学习老本起因,还是麻利化下对UML的排挤,很多团队都放弃了UML。 咱们不能否定UML的价值,基于对立建模语言可能更无效的进行架构设计的信息传递和沟通,也能基于UML提供的具体的模型图元素进行充沛的设计表白。团队中是否要基于UML进行沟通须要衡量,尽管UML不能表白你所要传播的全副的架构信息,但其在某些维度的表白绝对比拟适宜。 • 表白流程和工作流能够采纳UML流动图 • 表白运行时的交互能够采纳UML时序图 • 表白畛域模型或者设计模式能够采纳UML类图 • 表白状态转换能够采纳UML状态机 • 表白零碎的部署构造能够应用UML部署图 1.3 可视化形式-草图架构可视化另一个十分常见的形式是:草图。草图是一种非正式的、易于疾速沟通的图形化形式。团队基于特定的场景,能够通过草图的模式进行疾速的沟通,以便高效的在干系世间拉齐要害信息。 但,草图的劣势与线框图一样:语义一致性低 咱们能够在白板上 “得心应手” 的画各式各样的草图,草图上的元素、连线,又或者布局都可能是涌现式的、临时性的,这些草图的价值在于 “会话周期内的高效沟通”。如果干系人没有齐全参加到草图的探讨,又或是后置查看,大略也很难精准捕捉这些草图所要表白的设计用意。 2 C4 模型2.1 C4模型的对立形象团队须要对立语言进行高效沟通 !!! C4模型在不同的级别提供了对立的形象以表白软件系统的动态构造。如下图所示: • 软件系统:最顶层的形象,其对用户提供价值。蕴含待构建的零碎以及内部依赖的零碎 • 容器:示意一个利用或者数据存储,容器须要运行以支持系统的失常运行。每个容器都是独立部署或运行的单元,容器间的通信个别式跨过程交互 • 组件:提供肯定能力封装的单元。在C4模型上下文中,组件不是独立部署的单元,个别状况下运行于容器之中。 • 代码:零碎的实现细节相干 • 人:零碎的应用用户 2.2 上下文图:System Context Diagram咱们要构建的零碎不会孤立存在,都会依赖现有的IT设施。要明确咱们构建的零碎是什么,宏观上须要答复:咱们的零碎如何融入到现有的IT设施。 ...

November 7, 2022 · 1 min · jiezi

关于架构设计:浅谈接口幂等性

前言幂等性,是开发人员在日常开发中必须要思考的,尤其是转账、领取等波及金额交易的场景,如果呈现幂等性的问题,造成的结果是十分重大的。 本文将分享一下什么是幂等性以及如何保障幂等性。 什么是幂等性幂等(idempotent、idempotence)是一个数学与计算机学概念,常见于抽象代数中。 在编程中一个幂等操作的特点是其任意屡次执行所产生的影响均与一次执行的影响雷同。幂等函数,或幂等办法,是指能够应用雷同参数反复执行,并能取得雷同后果的函数。这些函数不会影响零碎状态,也不必放心反复执行会对系统造成扭转。 幂等性产生起因前端未做限度,导致用户反复提交应用浏览器后退,或者按F5刷新,或者应用历史记录,反复提交表单网络稳定,引起反复申请超时重试,引起接口反复调用定时工作设置不合理,导致数据反复解决应用音讯队列时,音讯反复生产如何保障幂等性1.前端解决提交按钮点击置灰,或者减少loading页面重定向(PRG),PRG模式即POST-REDIRECT-GET,当用户进行表单提交时,会重定向到另外一个提交胜利页面,而不是停留在原先的表单页面。这样就防止了用户刷新导致反复提交。同时避免了通过浏览器按钮后退/后退导致表单反复提交。2.先select后insert + 惟一索引抵触在保留数据前,咱们须要先select一下数据是否存在。如果数据已存在,则返回失败(具体操作视业务状况而定),如果数据不存在,则执行insert操作。 但在高并发的场景下,可能会呈现两个申请select的时候,都没有查到数据,而后都执行了insert操作,所以此时会有反复数据产生,因而在数据库中,咱们须要增加惟一索引来保障幂等。 流程图如下:此计划实用于新增操作的接口,如用户注册。 3.建去重表某些业务场景,是容许反复数据存在的,仅在流程的某个环节才不容许呈现反复数据,这种状况间接在表中增加惟一索引是不适合的,所以就须要创立一张去重表。 CREATE TABLE `table_name` ( `id` bigint(15) NOT NULL AUTO_INCREMENT COMMENT '自增主键', `order_id` varchar(100) NOT NULL COMMENT '订单号', `create_time` datetime DEFAULT NULL COMMENT '创立工夫', PRIMARY KEY (`id`), UNIQUE KEY `index_order_id` (`order_id`),) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='去重表';流程图如下:特地留神,防重表与业务表必须在同一数据库,并且操作要在同一事务中。 此计划实用于在业务中有惟一标识的插入场景中,比方在领取业务中,若一个订单只会领取一次,则订单ID能够作为惟一标识。 4.应用乐观锁乐观锁,正如其名,具备强烈的独占和排他个性。它指的是对数据被外界(包含本零碎以后的其余事务,以及来自内部零碎的事务处理)批改持激进态度,因而,在整个数据处理过程中,将数据处于锁定状态。乐观锁的实现,往往依附数据库提供的锁机制(也只有数据库层提供的锁机制能力真正保证数据拜访的排他性,否则,即便在本零碎中实现了加锁机制,也无奈保障内部零碎不会批改数据)。在交易场景中,用户账户余额有100元,转出50元,失常状况下用户的余额残余50元。 update account set amount-50 where id = 123;如果此时有多个雷同的申请,可能会导致用户的金额变为正数。所以此时能够应用乐观锁,将用户的行数据锁住,在同一时刻只容许一个申请取得锁,其余申请期待。 select * from account where id = 123 for update;流程图如下: 须要特地留神的是:如果应用的是mysql数据库,存储引擎必须用innodb,因为它才反对事务。此外,这里id字段肯定要是主键或者惟一索引,不然会锁住整张表。因为乐观锁是须要在同一事务中锁住一行数据,所以如果事务比拟长,会造成大量申请期待,影响接口性能。 5.应用乐观锁乐观锁( Optimistic Locking ) 绝对乐观锁而言,乐观锁机制采取了更加宽松的加锁机制。乐观锁大多数状况下依附数据库的锁机制实现,以保障操作最大水平的独占性。但随之而来的就是数据库性能的大量开销,特地是对长事务而言,这样的开销往往无奈接受。而乐观锁机制在肯定水平上解决了这个问题。乐观锁,大多是基于数据版本( Version )记录机制实现。何谓数据版本?即为数据减少一个版本标识,在基于数据库表的版本解决方案中,个别是通过为数据库表减少一个 “version” 字段来实现。读取出数据时,将此版本号一起读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的以后版本信息进行比对,如果提交的数据版本号等于数据库表以后版本号,则予以更新,否则认为是过期数据。乐观锁次要基于版本标识(version)进行操作,即每次操作查问数据时都要先查问出版本标识(version),而后依据版本标识(version)进行update操作。 ...

September 29, 2022 · 1 min · jiezi

关于架构设计:5分钟get一个技术点揭秘一种加密框架的技术实现

导语 | 本文推选自腾讯云开发者社区-【技思广益 · 腾讯技术人原创集】专栏。该专栏是腾讯云开发者社区为腾讯技术人与宽泛开发者打造的分享交换窗口。栏目邀约腾讯技术人分享原创的技术积淀,与宽泛开发者互启迪共成长。本文作者是腾讯高级开发工程师杨波。 背景 对互联网公司来说,数据安全始终是极为器重和敏感的话题。波及客户平安数据或者一些商业性敏感数据,如身份证号、手机号、卡号、客户号等个人信息如果被泄露进来,就会引发重大的数据安全危险。 在实在业务场景中,相干业务开发团队往往须要针对公司安全部门需要,自行履行并保护一套加解密零碎,自行保护的加解密零碎往往又面临着重构或批改危险。因而心愿实现一个通用的敏感数据处理框架,如何在不批改业务逻辑、业务SQL的状况下,透明化、平安低危险地实现无缝进行数据加解密革新。 加密框架实现计划比拟先通过上面列表来探讨几种加密实现计划的优缺点: 通过下面几种计划比拟,得出实现一种加密框架至多有如下几个需要: 代码侵入性少。接入成本低。笼罩更多框架。高性能,高可用。反对存量数据加密。能够发现对数据库驱动层革新,绝对其余几种计划毛病更少。那么是不是有一种计划,能够在不革新数据库驱动状况下,又能达到通明加解密数据的需要? 数据库拜访架构计算机领域的任何问题都能够通过减少一个间接的中间层来解决,这自身就体现了分层的重要性。比方,Unix零碎也是基于分层开发的,它能够大抵上分为三层,别离是内核、零碎调用、应用层。每一层都对下层封装实现细节,裸露形象的接口来调用。 对于数据库拜访也能够基于这样的软件思维来实现。因为各个厂商的数据库服务器差别比拟大,因而须要通过定义一种用于执行SQL语句的API,为多种数据库提供对立拜访。比方Java的JDBC,go的database,它们提供了一种基准和标准,据此能够构建更高级的工具和接口。数据库开发人员听从这种基准和标准,编写的应用程序称之为数据库驱动。 (一)面向切面编程面向切面编程(AOP),是软件开发中的一个热点。通过预编译形式和运行期间动静代理实现程序性能的对立保护的一种技术。利用AOP能够将与业务非关联的性能剥离开来,比方权限认证,日志记录,性能监控,错误处理等。通过对指定办法执行前后进行拦挡形式,实现雷同性能的复用,防止对业务代码的侵入。因而AOP能够升高代码逻辑之间的耦合度,进步程序的可重用性,同时进步了开发的效率。 (二)通过AOP对业务SQL拦挡重写假如实现一种数据库驱动XDriver,它是对XDBC的规范API具体实现,上面通过伪代码来实现通过AOP对XDriver拦挡,从而对业务SQL重写。 public interface Database {    /**     * 执行SQL     */    ResultSet executeQuery(String sql);} public class XDriver implements Database {    @Override    public ResultSet executeQuery(String sql) {       ResultSet resultSet = null;       //TODO        return resultSet;    }} public class XDriverIntercepter implements Database {    private Database database;        public void setDatabase(Database database) {        this.Database = database;    }     @Override    public ResultSet executeQuery(String sql) {        String newSql = rewriteSql(sql);        return database.executeQuery(newSql);    }        /**     * 重写SQL     */    private String rewriteSql(String sql) {        String newSql = "";        //TODO        return newSql;    }}如上代码所示假如有一张表叫account,须要对表字段mobile,address加密,能够做如下解决: ...

September 14, 2022 · 1 min · jiezi

关于架构设计:靠谱开源IM项目OpenIM压测程序介绍自己动手压测性能和稳定性

压测前筹备(一)服务端配置调整 config/config.yaml 以8核16G为例(1)openImMessagePort: [ 10130, 10131, 10132, 10133, 10134,10135 ](2)openImPushPort: [ 10170, 10171, 10172, 10173 ](3)remainLogLevel: 3(4)chatpersistencemysql: false (5) dbMaxOpenConns: 100 dbMaxIdleConns: 10 dbMaxLifeTime: 5(二)调整path_info.cfg中msg_transfer_service_num=4(三)kafka分区调整(1)设置ws2ms_chat为8个分区 msg_transfer_service_num的2倍(2)设置msg_to_mongo为8个分区 msg_transfer_service_num的2倍(3)设置ms2ps_chat为8个分区 openImMessagePort的2倍(四)mysql服务端设置最大连接数为2000注意事项(1)因为须要本地解决sqlite读写,检测程序倡议设置2个客户端,发送音讯休眠100毫秒;(2)留神压测客户端和服务端的网络带宽;(3)如果客户端和服务端同一台机器,留神压测程序cpu占用;单聊压测程序仓库地址 https://github.com/OpenIMSDK/...代码阐明 press_open_im.go 压测音讯发送,但发送者不校验是否实现接管到 msg_delay_open_im.go 检测音讯发送和接管,在大压力状况下,音讯的可靠性和时延测试应用阐明 (1)批改../test/config.go TESTIP和SECRET(2)go build press_open_im.go./press_open_im -sn 10000 -mn 1000 -t 100参数sn 10000示意:启动10000个压测客户端;参数mn 1000示意:每个客户端发送音讯数量为1000条;参数t 100示意:每次发送一条音讯后,休眠100毫秒;如果是1万客户端,算起来大略是每秒钟发送10万条音讯;(3)go build msg_delay_open_im.go./msg_delay_open_im -sn 2 -mn 1000 -t 100参数sn 2 示意:启动2个客户端音讯收发检测;参数mn 1000示意:每个客户端发送1000条音讯;参数t 100示意:每次发送一条音讯,休眠100毫秒;压测程序应用示例./press_open_im -sn 100 -mn 100000 -t 100呈现[send msg begin ] 示意初始化实现,开始发送音讯此时再启动可靠性及音讯时延测试:./msg_delay_open_im -sn 2 -mn 1000 -t 100服务端统计日志查看tail -f OpenIM.log.all.2022-08-30 |grep "msg_gateway sendMsgCount"system stat msg_gateway 60 second recv to msg_gateway sendMsgCount 45267 示意一分钟收到45267条音讯时延检测查看minCostTime: 729 ms, maxCostTime: 6332 ms, average cost time: 3295 ms 发送2000条数据 从发送到对方收到,均匀时延是3.2秒CheckReliabilityResult ok, exit 示意收回去的所有音讯,对方都能准确收到群聊压测程序仓库地址 https://github.com/OpenIMSDK/...代码阐明 create_work_group_open_im.go 创立测试群press_open_im.go 压测音讯发送,但发送者不校验是否实现接管到 msg_delay_open_im.go 检测音讯发送和接管,在大压力状况下,音讯的可靠性和时延测试应用阐明 (1)批改../test/config.go TESTIP和SECRET(2)go build create_work_group_open_im.go./create_work_group_open_im -gmn 10参数gmn示意:创立群成员为10的测试群,理论会创立13个成员。(3)go build press_open_im.go./press_open_im -gid 1510503557 -sn 10 -mn 1000 -t 100 参数gid 1510503557 示意:压测群聊groupID参数sn 10示意:压测客户端数量,要小于等于群成员数参数mn 1000示意:每个客户端发送音讯数量为1000条;参数t 100示意:每次发送一条音讯,休眠100毫秒;(4)go build msg_delay_open_im.go./msg_delay_open_im -gid 1510503557 -mn 100 -t 100参数gid 1510503557 示意:压测群聊groupID参数mn 100示意:每个客户端发送音讯数量为100条;参数t 100示意每次发送一条音讯,休眠100毫秒;压测程序应用示例./create_work_group_open_im -gmn 10呈现[[CREATE GROUP {"errCode":0,"errMsg":"","data":{"creatorUserID":"openIM123456","groupID":"3144245614","groupName":"Group Chat","groupType":2,"memberCount":13,"ownerUserID":"openIM123456"}} ] 示意创立群聊胜利,记录groupID 3144245614启动压测程序:./press_open_im -gid 3144245614 -sn 10 -mn 1000 -t 100 此时再启动可靠性及音讯时延测试:./msg_delay_open_im -gid 3144245614 -mn 100 -t 100服务端统计日志查看tail -f OpenIM.log.all.2022-08-30 |grep "msg_gateway sendMsgCount"system stat msg_gateway 60 second recv to msg_gateway sendMsgCount 45267 示意一分钟收到45267条音讯时延检测查看minCostTime: 594 ms, maxCostTime: 5181 ms, average cost time: 2930 ms 发送2000条数据 从发送群聊到对方收到,均匀时延是3.2秒CheckReliabilityResult ok, exit 示意收回去的所有群聊音讯,对方都能准确收到。对于OpenIMOpenIM是由IM技术专家打造开源即时通讯组件,也是目前最受欢迎的开源IM我的项目之一,开发者通过集成OpenIM组件,并私有化部署服务端,能够将即时通讯、实时通信能力疾速集成到本身利用中,并确保业务数据的安全性和私密性。github社区沉闷,star近万,排名遥遥领先,开发者万人,OpenM力争开源IM我的项目No1,打造开源IM第一社区。反对Android、iOS原生开发,反对Flutter、uni-app跨端开发,反对小程序、React等所有支流web前端技术框架, PC反对Electron。重点利用在政务办公,社交,web3场景,所有皆可控,让OpenIM深刻到各行业。从开源的外在含意来看,须要这五个维度:透明度;合作;继续公布;精英制度;社区经营,OpenIM在这五方面还须要继续致力,巩固生态建设,坚固OpenIM影响力。作为开源IM领跑者,OpenIM开源有几个目标:(1)IM外围数据应该掌控在运营者手中(2)IM需要宽泛,有很多人收费应用,并能发现问题(3)让更多开发者参加我的项目我的项目,特地是IM需要繁多。 在开源社区外面,每个我的项目都能够开启pr,pr性能将容许每一位开发者对代码进行批改,然而须要我的项目拥有者的合并代码。个体的力量是最大的,充分体现开源的价值。github地址:https://github.com/OpenIMSDK/...开发者核心:https://doc.rentsoft.cn/# ...

September 1, 2022 · 1 min · jiezi

关于架构设计:OpenIM重大优化消息按需加载-一致性缓存-uniapp发布

新性能介绍(1)服务端退出一致性缓存(dtm:https://www.dtm.pub/),优化db读写性能;(2)对于群读扩散群,登录时先同步最新的100条音讯,历史音讯按需加载;(3)申请进群时,群主或者管理员能看到进群形式以及由谁邀请进群;(4)遣散群,不能再发送音讯;(5)好友备注可删除,删除后复原原来名称 ;(6)群主和管理员能看到群成员的进群形式:扫码进群,谁邀请进群,搜寻进群;(7)群主和管理员设置群成员权限:是否容许查看其余群成员材料;是否容许增加群成员好友;做技术的敌人对于读扩散写扩散应该不生疏,无论是信息流、论坛、信箱,还是私聊、群聊、告诉,都能用到读写扩散。本文不解说技术细节,OpenIM基于推拉联合的读扩散次要解决群聊模式下音讯冗余存储,音讯实时性,新用户入群无奈查看新音讯,超级大群等。安卓端体验:https://www.pgyer.com/OpenIM群聊读扩散-按需加载(1)创立时指定工作群,这种群采纳读扩散模型,每个群有独立seq,群成员共享此seq,能大幅缩小群音讯冗余,且晋升音讯实时性。(2)音讯按需加载机制做好铺垫,对于长时间不登录或者卸载后重装场景,默认加载最新的100条音讯,对于历史音讯,如果本地db不存在,则从服务端拉取。(3)新用户入群能够查看历史音讯,后续减少选择项,给开发者更多抉择。uniapp版demo公布uniapp,期待已久,demo已公布,可能还有一些瑕疵,请多多包涵。请返回github下载应用:https://github.com/OpenIMSDK/...我的项目成绩从服务端到客户端SDK开源即时通讯(IM)整体解决方案,能够轻松代替第三方IM云服务,并能依据业务需要高度自定义和二次开发,打造具备聊天、社交、办公性能的app。OpenIM持续领跑开源IM畛域,在宽广开发者的大力支持下,目前github star继续冲破。越来越多的开发者把OpenIM利用在社交,协同办公畛域。在经营过程中也裸露并修复了代码的一些bug,因为应用场景宽泛,OpenIM越来越强壮,开源价值也凸显进去了。尤其对于政务零碎来说,开源产品更有准入条件的劣势。“开源”的价值在于可能突破资源垄断,让开发者 能够自我掌控。“开源”的价值在于可能晋升软件品质,优化零碎架构。“开源”的价值在于可能丰盛文化外延,共建工程师文化。开源不仅仅是凋谢源代码。作为开源IM领跑者,OpenIM开源有几个目标:(1)IM外围数据应该掌控在运营者手中(2)IM需要宽泛,有很多人收费应用,并能发现问题(3)让更多开发者参加我的项目我的项目,特地是IM需要繁多。在开源社区外面,每个我的项目都能够开启pr,pr性能将容许每一位开发者对代码进行批改,然而须要我的项目拥有者的合并代码。个体的力量是最大的,充分体现开源的价值。OpenIM社区经营有所欠缺,将来打算直播解说技术架构,让社区开发者能深度参加开发。github地址:https://github.com/OpenIMSDK/...开发者核心:https://doc.rentsoft.cn/#/咱们的团队OpenIM是由IM技术专家打造开源即时通讯组件,目前github社区沉闷,star近万,排名遥遥领先,开发者7000人,OpenM力争开源IM我的项目No1,打造开源IM第一社区。反对Android、iOS原生开发,反对Flutter、uni-app跨端开发,反对小程序、React等所有支流web前端技术框架, PC反对Electron。重点利用在政务办公,社交,web3场景,所有皆可控,让OpenIM深刻到各行业。从开源的外在含意来看,须要这五个维度:透明度;合作;继续公布;精英制度;社区经营,OpenIM在这五方面还须要继续致力,巩固生态建设,坚固OpenIM影响力。开源的价值是凋谢应用,不限度设想及开发的空间,高效利用。每个开发者对于产品及技术的设想及登程不同,这就造就一个最根本的状态变成百花盛放,争奇斗艳的成果。

July 23, 2022 · 1 min · jiezi

关于架构设计:浅析专网通信领域的前端架构设计

前言随着时代的倒退,网络通信曾经成为人们日常生活中不可或缺的一部分。在5G时代背景下,传统的网络通信曾经不能满足工业侧及企业强利用通信的需要,出于安全性、稳定性的要求,专有网络通信逐渐成为通信市场的一支重要力量。作为通信运营商,咱们更是应该在专网通信畛域展现出本身的通信劣势。 除了通信技术的倒退之外,对应于CT通信技术的倒退需要,作为IT侧的Web前端开发也须要顺应时代倒退构建出合乎业务及产业模式的架构模型,为ICT交融提供技术计划反对。本文旨在通过专网通信畛域的业务实际,从系统性、结构性、健壮性等几个不同的维度来论述前端架构设计过程中的考量与剖析。 系统性零碎设计作为整个软件工程我的项目的顶层设计,是依据系统分析的后果,使用零碎迷信的思维和办法,设计出能最大限度满足所要求的指标的新零碎的过程。在整个软件架构中,系统性作为整体我的项目的先导及前驱,须要可能贯通整个我的项目时段,本章将通过设计理念、设计办法、设计模型、设计准则四个方面来论述在系统性方面的思考。 设计理念设计理念作为整个零碎架构的指导方针,是整个零碎架构的核心理念及设计哲学。在专网通信畛域中,联合业务须要及软件工程中的设计办法,整体的设计理念是: 简洁、无效、解构、可控、扩大简洁:以最简略的形式实现,最大限度的保障以后粒度的复杂度最低。不便开发与验证,提供简略的设计模式,有利于零碎内的所有人员达成统一,为无效且高效的组织提供可能。 无效:以适合的划分粒度分拆问题,不进行适度设计,以防止引入不必要的复杂度到零碎中;也不进行过少设计,防止冗余。在精益中晋升软件品质,以最高性价比的形式解决问题,防止任何模式的繁杂。 解构:以清晰的边界确定粒度与粒度之间的权责,本颗粒度下外部共融;本颗粒度外,须要裸露的对外共享,不须要不裸露的隔离关闭。 可控:以牢靠的观测办法输出,以同一后果输入,可观测;问题呈现,定位清晰,可追寻;长期更改,及时应变,可容错。 扩大:提供渐进的解决方案,提供残缺生态,兼容并包,依据需要定制,可扩大、可插拔。 设计办法设计办法作为一组依照架构畛域的开发程序而排列的一套办法实践,是对简单业务需要的梳理后做的全面办法总结。在前端开发过程中,联合对应常见不同的架构分类,对不同档次各个子集做对应的方法论总结。 业务架构业务架构定义了合乎业务产出的对应的能力或者性能矩阵,明确业务流程。对应于前端工程而言,则是要落地到业务时序、角色调配、权限认证等。 数据架构数据架构形容了组织的物理及逻辑数据资产,以及数据资源的构造。在前端工程中,则是对应最后的数据结构的设计,从方法论上能够参考不同的数据汇合进行数据库模式的设计与接入。 利用架构利用架构提供了一个蓝图,波及各个应用程序部署,它们之间的相互作用,以及它们的分割,该组织的外围业务流程等。对于前端畛域而言,则是对于不同利用之间的聚合对立以及隔离出现,包含但不限于跨端出现以及上下游逻辑串联。 技术架构技术架构形容了须要反对的业务,数据和应用服务部署的逻辑软件和硬件的能力;这包含IT基础设施、中间件、网络等。对于前端而言,则是蕴含各种框架体系以及对应的生态延展,筛选更加合乎业务的场景落地技术计划。 设计模型软件设计采纳不同的视角来设计形象软件的零碎,对需要进行剖析而产生概念模型。常见的设计模型蕴含:面向对象模型(OOP)、面向畛域模型(DDD)、六边形模型(Hexagonal Architecture)、洋葱模型(Onion Architecture)等。软件设计最重要的过程就是形象,对业务及畛域进行建模,通过抽象化的伎俩将共性及元信息抽离,通过不同的组合模式构建属于本人业务及零碎的模型。抽离设计模型是一个高度凝练和萃取的过程,须要思考多方因素。形象设计模型既要做顶层设计,又要做底层设计,视线要从上而下,拆解要从下而上。 设计准则软件设计过程中要合乎软件开发的特色,通常来说须要合乎以下几大准则: 繁多职责准则繁多职责准则是指每一个颗粒度都只专一于一件事件,从而能够升高单颗粒度的复杂度,简化逻辑,职责简略,进步可读性及零碎可维护性。在批改及变动过程中,能够减低对其余颗粒度的性能影响。 凋谢关闭准则凋谢关闭准则是指面向扩大凋谢,面向批改敞开,这意味着在需要变动时,对代码变动所做的批改应该以扩大为主,而不是批改之前的代码,这就要求在设计颗粒度过程中保留扩大项,以应答变动。软件需要总是变动的,因此在不对原有零碎做批改的状况下,能够基于不同的设计模型构建不同的零碎扩大。 里氏替换准则里氏替换准则是指具象粒度能够替换形象粒度,也就是形象粒度的元信息是齐全抽离的具象内容,其也是开闭准则的重要验证形式之一,满足里氏替换准则表明其开闭性是能够保障的,在不同的设计模型中,能够使用不同的办法来实现形象粒度与具象粒度之间的链接关系。 接口隔离准则接口隔离准则是指颗粒度对外应该提供尽可能具体的接口,而不是提供宏观的接口,对外裸露的行为应该越少越具体也好,这样能力保障内部对外部的影响及侵害做到最小,尽量细化接口。通过扩散定义多个接口,能够预防外来变更的扩散,进步零碎的灵活性和可维护性,在隔离与外界的界线过程中,也能做到边界的清晰与确立。 依赖倒置准则依赖倒置准则是指实现应该尽量依赖形象,不依赖具体实现。具体依赖形象,下层依赖上层,能够缩小颗粒度之间的耦合性,进步零碎的稳定性,缩小并行开发引发的危险,进步代码的可读性和可维护性 迪米特准则迪米特准则又叫起码常识准则,一个软件架构实体该当尽可能少的与其余实体产生相互作用。颗粒度与颗粒度之间的关系越亲密,耦合度也就越来越大,只有尽量升高颗粒度与颗粒度之间的耦合才合乎软件设计的模式。一个颗粒度对另一个颗粒度中援用或者应用越少越好,这样能够防止发生变化时,相互之间产生关联反馈,如果必须进行相干的关联操作,能够通过第三者进行互相的分割,后续变动只需对第三者进行相干的操作即可,不便保护。 组合/聚合复用准则组合/聚合复用准则是指应尽可能多的进行复用,而不是复制,通过繁多职责的颗粒度构建,在其余业务中能够尽可能多的复用相干的颗粒度组合,从而在发生变化时,只须要在外部批改对应的颗粒度内容,对外做到接口隔离而不影响外界的应用。 结构性 软件系统作为一个有机的整体,其外部是由若干个不同的局部形成的,结构性则次要是从软件组织构造的角度来掂量,它蕴含或关联了一些不同档次的信息。从最早的单体架构,到面向服务的SOA架构,再到起初的微服务架构,不同的软件架构演变,都体现了结构性的重要性。对于前端工程而言,常见的分层设计是软件系统结构化的一种无效实现形式,本章将从网关层、应用层、根底层三个划分档次来论述专网我的项目中的架构设计的结构性特色。 网关层在传统软件开发过程中,不同的业务类型所对外界裸露的办法不尽相同。在网络通信中,咱们经常应用网关来作为内网与外网的通信传输连贯。在软件开发过程中,咱们也能够借鉴这样的思路来对咱们的软件系统做对应的设计和解决。 对于专网畛域的前端而言,对于各种利用的收敛和汇集就成为一个对外裸露的重要层级。网关层的呈现,突破了框架及业务栈的解放:对外部利用,能够提供服务注册机制用于各种利用的汇集和收集;对外部用户,能够提供对立的服务地址,从而隔离开用户与外部利用变动带来的割裂感。 应用层应用层作为各种业务的不同出现状态,是实在落地到各种业务状态的子状态。对外部而言。各个利用之间的关联及解决能够通过网关层做对应的服务散发和拉起;对外部而言,则能够抉择对应的框架状态来更好的解决所须要的业务,从而实现了高内聚、低耦合的软件系统关联与隔离。 对专网业务状态而言,须要提供业余的业务解决服务,也即通用化的中台产品服务;同时也须要提供对应的可视化产品服务,更好的展示业务数据信息,从而将CT侧的业务内容进行IT化的展示。应用层能够基于不同的业务需要,扩大不同的状态,跨端、互动等新的业务状态也能够插件化的模式注入,从而对扩大凋谢,共建生态圈。 根底层根底层为所有业务提供公共的根底技术服务,防止单个业务利用各自为战,造成各自的独立技术烟囱;同时,也为业务的技术积淀积攒提供面向更多业务状态的技术支持,做到了技术能力的形象通解。 对于专网业务状态而言,其根底层次要提供了面向整个产研链路的根底服务反对,不便产品、设计、前端、后端、测试、运维同学的全链路通路连贯,一站式解决整体的前端上下游沟通屏障,打造高效、简略的产研一体化解决方案。在产品侧,提供了wiki文档化的反对;在设计侧,提供了图床、设计物料、设计组件库的撑持;在前端侧,提供了脚手架、监控等开发模板工具;在后端侧,提供了动态转发、BFF转化、接口联调配置等技术设置;在测试侧,提供了通用的测试套件,不便测试用例的设计及验证;在运维侧,提供了高效的CICD流水线解决,提供故事版等功能性解决计划。 健壮性健壮性是指软件系统在肯定参数的摄动下,维持失常的个性。依据不同的零碎级别的要求,通常要求软件架构零碎在设计的过程中思考不同的健壮性要求。本章将通过高可用、高性能、高平安、高扩大来论述零碎的健壮性。 高可用高可用次要目标是为了保障业务的连续性,即在用户眼里,业务永远是失常对外提供服务的。要保障架构的高可用,就要保障架构中的所有颗粒度及其对外裸露的服务都能尽可能做到高可用。对于前端而言,通常须要在服务拉起的过程中保障高可用,那么能够采纳冗余及主动故障转移等办法来解决。 对于专网业务而言,在根底层提供了云化相干的根底操作,利用云化的一些高可用多正本做到服务可达,同时在运维公布过程中基于不同的业务需要做到公布的策略分化,从而更好的为业务及用户数据收集等产品需要做到技术实践撑持,闭环整个链路。 高性能高性能是指对于资源的最高利用,能够最大限度的施展软硬件的劣势。要保障架构的高性能,通常须要在不同业务状态中利用不同的性能瓶颈做对应的优化与革新。对于前端而言,因为更加贴近用户侧,其通常高性能蕴含网络、渲染、用户体验等几个方面。 在专网业务中,因为网络层的非凡传输特点,其对于网络的优化通常都是基于云原生相干的网络侧优化,而对于渲染侧的压力,则能够基于不同的业务状态抉择诸如客户端渲染(CSR)、服务端渲染(SSR)、原生渲染(NSR)、边缘渲染(ESR)等不同的渲染模式或者混合渲染模式。 高平安高平安是指对于零碎的攻打保障无效的防护及对于潜在危险的及时革除。要保障架构的高平安,除了要应答常见的攻打伎俩之外,还须要对系统自身做到监控可控。对于前端而言,因为面向用户更近,对于用户的操作最可能攻打到自身零碎的平安,因此做好诸如XSS、CSRF等前端平安防护是非常重要的,同时也要对危险做到评估和监控。 在专网业务中,在根底层对于不同应用层的利用做到了前端的监控,对于性能、谬误等做到数据的收集与解决,对于密钥及明码的设定做到高级别防护,网络通信采纳加密传输等伎俩防护,同时对于两头拜访做到不同层级的拦挡和鉴权验证。 高扩大高扩大是指在不扭转零碎整体外围架构下,为了反对一直增长的需要而保证系统的疾速响应。要保障架构的高扩大,通常须要对内核状态做到充沛考量,明确可更改及不可更改的边界。对于前端而言,通常须要思考不同的产品需要变动对可抽离的局部尽可能抽离,对于不同的编程范式,采纳合乎业务办法的编程计划,比方:在应用面向对象编程过程中,尽可能应用设计模式等来解决业务需要和正确编码等。 对于专网业务而言,高扩大通过应用前端网关的服务发现及注册机制来拉起对应的微利用,做到前端的微服务化,对于单个利用中能够再进一步拆分,能够应用诸如类单页模式、类iframe模式、类web组件模式、类容器化模式等的微前端计划来解决,从而实现整体的高扩大和兼容解决。 总结相较于后端倒退的历程,前端的倒退过程则经验了以下几个时代变动:在上古时代,浏览器诞生,随同着第一点浏览器大战,前端重视在动态页面的搭建;到了石器时代,ajax技术的呈现,前端工作波及到了一部分的数据交互工作,同时也进行着第二代浏览器大战;而在农业时代,面对不同浏览器所提供的的各自api的兼容性需要,前端第一次呈现了基于库的开发的模式,突现出了一批诸如jQuery、YUI、ExtJS等类库;紧接着,随着工业时代的到来,前端也承接了更多的数据交互工作,从之前的服务端渲染页面,转换到了浏览器客户端来渲染页面的时代,也在这个时代呈现了前端框架的理念;到了更近一些的信息时代,随着不同终端的呈现,前端呈现了各种跨端体验一致性的需要,从而带来了不同渲染模式的计划;在以后的云边端时代,目前基于不同的业务状态和业务方向,前端呈现出更加多样化和复杂化的状态,借助其他软件畛域的倒退,前端状态更加多元和泛化。 对于层出不穷的业务状态与需要,前端从单纯的页面切图也慢慢演变到了整体软件架构的治理。在软件工程畛域,所有的业务状态都能够通过不同的形象组合架构拼接实现,但正当优雅的架构形式不仅要思考全局的调度与共生,也须要兼顾部分的优化与衡量。道以明向,法以立本,术以立策,势以立人,器以成事。 参考全面意识高并发:高性能、高可用、高扩大《软件架构》高扩大架构Freewheel 首席工程师:我对软件分层设计的思考软件设计七大准则

July 18, 2022 · 1 min · jiezi

关于架构设计:Java分布式架构设计与开发实战2022全新版超清网盘

download:Java分布式架构设计与开发实战2022全新版再次意识 WebAssembly简略地说,Wasm 是一个编译指标,能够应用大概 30 种语言编写的代码,应用特定于 WebAssembly 的工具来编译它,将其编译为 .wasm 文件,目前最风行的针对 Wasm 的语言是 C、C++ 和 Rust(即因为它们本人治理内存并且不须要垃圾收集器)。对 Go、Python 和 JavaScript 生态系统的反对也在快速增长。编译生成的.wasm 文件能够在浏览器或服务器上。Wasm 文件蕴含虚拟机能够读取的二进制指令,并且因为 Wasm 以虚拟机为指标,因而它实用于许多芯片架构,它以风行硬件的最小公分母为指标,堆栈机,这是它区别于其余产生二进制代码的指标的中央。Wasm 最后是为浏览器构建的,然而随着技术的成熟,在服务器端看到了越来越多的用例。本文再次介绍 WebAssembly 的劣势及利用场景,并通过示例意识其我的项目开发的过程,点击查看代码。 领有什么劣势Wasm 容许应用相熟的语言编写代码并在任何中央运行它。 更快的启动工夫在服务器上,Wasm 能够实现比 Docker 容器快 10-100 倍的冷启动工夫,因为它不须要为每个容器创立一个 OS 过程。在浏览器中,解码 Wasm 比解析、解释和优化 JavaScript 更快,因而 Wasm 代码在浏览器中的执行速度比 JavaScript 更快。 近乎原生的性能对于 Wasm 的性能细节存在一些争议,但它的劣势在于容许用户将其应用程序的计算密集型局部封装到较低级别的语言。 Wasm 的许多性能劣势来自于它(它是 Wasm 代码)被构建为尽可能靠近本机机器代码这一事实。 轻量级Wasm 二进制文件体积小,因而只应用大量带宽,通常比浏览器中的穿插编译 JavaScript 破费更少的工夫通过网络传输。便捷通用任何 Wasm 运行时都能够运行任何 Wasm 代码(只管并非所有运行时都反对所有 Wasm 扩大,即不同的 WASI 接口类型)。大多数浏览器都反对 WebAssembly,并且在服务器端(WasmEdge、Wasmtime 等)有许多运行 Wasm 代码的运行时。鉴于浏览器和服务器(以及硬件)对 Wasm 的广泛支持,它是具备可移植的,并且也十分通用,大概 30 种语言能够编译或在其中执行(C、C++、Rust、Python、Go、AssemblyScript、JavaScript等等)。 ...

June 24, 2022 · 2 min · jiezi

关于架构设计:架构设计-12架构实战之技术演进

导读:《架构设计》系列为极客工夫李运华老师《从0开始学架构》课程笔记。本文为第十二局部。次要介绍了技术演进的能源和演进模式,如不同期间所面临的问题以及该如何解决。 扫描文末二维码 关注公众号 回复 “架构设计” 获取架构设计笔记残缺思维导图技术演进能源对于产品类业务:技术创新推动业务倒退!对于“服务”类的业务:业务倒退推动技术的倒退!互联网技术演进模式互联网业务千差万别,但因为它们具备“规模决定所有”的相同点,其倒退门路也基本上是统一的。互联网业务倒退个别分为几个期间: 初创期发展期竞争期成熟期不同期间的差异次要体现业务复杂性初创期初创期的业务对技术就一个要求:“快”,但这个时候却又是守业团队最强大的期间,可能就几个技术人员,所以这个时候十八般武艺都须要用上:能买就买,有开源的就用开源的。 发展期堆性能期业务进入疾速发展期的初期,此时团队规模也不大,业务需要又很紧,最快实现业务需要的形式是持续在原有的零碎外面一直地减少新的性能,重构、优化、架构等方面的工作即便想做,也会受制于人力和业务倒退的压力而放在一边。 优化期优化派 核心思想是将现有的系统优化架构派 核心思想是调整零碎架构,次要是将原来的大零碎拆分为多个互相配合的小零碎。架构期通过优化期后,如果业务可能持续倒退,缓缓就会发现优化也顶不住了,毕竟再怎么优化,零碎的能力总是有极限的。架构期能够用的伎俩很多,但归根结底能够总结为一个字“拆”,什么中央都能够拆。竞争期反复造轮子零碎交互一团乱麻解决方案平台化:目标在于解决“反复造轮子”的问题。 存储平台化:淘宝的 TFS、京东 JFS。数据库平台化:百度的 DBProxy、淘宝 TDDL。缓存平台化:Twitter 的 Twemproxy,豆瓣的 BeansDB、腾讯 TTC。服务化:目标在于解决“零碎交互”的问题,常见的做法是通过音讯队列来实现零碎间的异步告诉,通过服务框架来实现零碎间的同步调用。 音讯队列:淘宝的 Notify、MetaQ,开源的 Kafka、ActiveMQ 等。服务框架:Facebook 的 thrift、当当网的 Dubbox、淘宝的 HSF 等。成熟期此时技术上其实也根本进入了成熟期,该拆的也拆了,该平台化的也平台化了,技术上能做的大动作其实也不多了,更多的是进行优化。这个时候的技术优化没有固定的套路,只能依照竞争的要求,找出本人的弱项,而后逐项优化。在逐项优化时,能够采取之前各个期间采纳的伎俩。 用户规模用户量增大对技术的影响次要体现 性能要求越来越高可用性要求越来越高质变到量变互联网业务驱动技术倒退的两大次要因素是复杂性和用户规模,而这两个因素的实质其实都是“质变带来量变”。应答业务量变带来的技术压力,不同期间有不同的解决形式,但不论什么样的形式,其外围指标都是为了满足业务“快”的要求,当发现你的业务快不起来的时候,其实就是技术的程度曾经跟不上业务倒退的须要了,技术改革和倒退的时候就到了。reference《从 0 开始学架构》 https://time.geekbang.org/col...

June 13, 2022 · 1 min · jiezi

关于架构设计:架构设计-11可扩展架构之微内核架构

导读:《架构设计》系列为极客工夫李运华老师《从0开始学架构》课程笔记。本文为第十一部分。次要介绍了如何面向性能拆分架构,首先介绍了微内核架构的根本架构设计,以及几种常见架构的实现与特点。最初分享了微内核架构典型开源规定引擎 JBoss Drools。 扫描文末二维码 关注公众号 回复 “架构设计” 获取架构设计笔记残缺思维导图根本架构两类组件外围零碎(core system)负责和具体业务性能无关的通用性能: 模块加载模块间通信插件模块(plug-in modules):负责实现具体的业务逻辑 外围零碎设计插件治理外围零碎须要晓得以后有哪些插件可用,如何加载这些插件,什么时候加载插件。常见的实现办法是插件注册表机制。外围零碎提供插件注册表(能够是配置文件,也能够是代码,还能够是数据库),插件注册表含有每个插件模块的信息,包含它的名字、地位、加载机会(启动就加载,还是按需加载)等。插件连贯插件连贯指插件如何连贯到外围零碎。通常来说,外围零碎必须制订插件和外围零碎的连贯标准,而后插件依照标准实现,外围零碎依照标准加载即可。常见的连贯机制有 OSGi(Eclipse 应用)、音讯模式、依赖注入(Spring 应用),甚至应用分布式的协定都是能够的,比方 RPC 或者 HTTP Web 的形式。插件通信插件通信指插件间的通信。尽管设计的时候插件间是齐全解耦的,但理论业务运行过程中,必然会呈现某个业务流程须要多个插件合作,这就要求两个插件间进行通信。微内核的外围零碎也必须提供相似的通信机制,各个插件之间能力进行失常的通信。常见架构OSGi 架构OSGi 的全称是 Open Services Gateway initiative,自身其实是指 OSGi Alliance。OSGi 联盟的初始指标是构建一个在广域网和局域网或设施上开展业务的根底平台,所以 OSGi 的最早设计也是针对嵌入式应用的。当初咱们议论 OSGi,曾经和嵌入式应用关联不大了,更多是将 OSGi 当作一个微内核的架构模式。 逻辑架构模块层(Module 层)模块层实现插件治理性能。OSGi 中,插件被称为 Bundle,每个 Bundle 是一个 Java 的 JAR 文件,每个 Bundle 外面都蕴含一个元数据文件 MANIFEST.MF,这个文件蕴含了 Bundle 的根本信息生命周期层(Lifecycle 层)生命周期层实现插件连接功能,提供了执行时模块治理、模块对底层 OSGi 框架的拜访。生命周期层准确地定义了 Bundle 生命周期的操作(装置、更新、启动、进行、卸载),Bundle 必须依照标准实现各个操作。服务层(Service 层)服务层实现插件通信的性能。OSGi 提供了一个服务注册的性能,用于各个插件将本人能提供的服务注册到 OSGi 外围的服务注册核心,如果某个服务想用其余服务,则间接在服务注册核心搜寻可用服务中心就能够了。规定引擎架构规定引擎从构造上来看也属于微内核架构的一种具体实现,其中执行引擎能够看作是微内核,执行引擎解析配置好的业务流,执行其中的条件和规定,通过这种形式来反对业务的灵便多变。特点: 可扩大:通过引入规定引擎,业务逻辑实现与业务零碎拆散,能够在不改变业务零碎的状况下扩大新的业务性能。易了解:规定通过自然语言形容,业务人员易于了解和操作,而不像代码那样只有程序员能力了解和开发。高效率:规定引擎零碎个别提供可视化的规定定制、审批、查问及治理,不便业务人员疾速配置新的业务。根本架构开发人员将业务性能合成提炼为多个规定,将规定保留在规定库中。业务人员依据业务须要,通过将规定排列组合,配置成业务流程,保留在业务库中。规定引擎执行业务流程实现业务性能。实现插件治理规定引擎中的规定就是微内核架构的插件,引擎就是微内核架构的内核。规定能够被引擎加载和执行。规定引擎架构中,规定个别保留在规定库中,通常应用数据库来存储。插件连贯相似于程序员开发的时候须要采纳 Java、C++ 等语言,规定引擎也规定了规定开发的语言,业务人员须要基于规定语言来编写规定文件,而后由规定引擎加载执行规定文件来实现业务性能,因而,规定引擎的插件连贯实现机制其实就是规定语言。 插件通信规定引擎的规定之间进行通信的形式就是数据流和事件流,因为单个规定并不需要依赖其余规定,因而规定之间没有被动的通信,规定只须要输入数据或者事件,由引擎将数据或者事件传递到下一个规定。 开源规定引擎 JBoss Drools采纳 Java 语言编写,基于 Rete 算法。 ...

May 26, 2022 · 1 min · jiezi

关于架构设计:架构设计-9可扩展架构之分层架构

导读:《架构设计》系列为极客工夫李运华老师《从0开始学架构》课程笔记。本文为第九局部。首先整体介绍可扩大架构的根本思维——“拆”,以及如何拆;随后介绍了面向流程的拆分,即分层架构。 扫描文末二维码 关注公众号 回复 “架构设计” 获取架构设计笔记残缺思维导图根本思维所有的可扩展性架构设计,背地的根本思维都能够总结为一个字:拆! 拆,就是将本来大一统的零碎拆分成多个规模小的局部,扩大时只批改其中一部分即可,毋庸整个零碎到处都改,通过这种形式来缩小改变范畴,升高改变危险。 不同的拆分形式,实质上决定了零碎的扩大形式。 拆分思路面向流程拆分计划:将整个业务流程拆分为几个阶段,每个阶段作为一部分劣势:扩大时大部分状况只须要批改某一层,少部分状况可能批改关联的两层,不会呈现所有层都同时要批改典型架构:分层架构面向服务拆分计划:将零碎提供的服务拆分,每个服务作为一部分劣势:对某个服务扩大,或者要减少新的服务时,只须要扩大相干服务即可,毋庸批改所有的服务。典型架构:SOA & 微服务面向性能拆分计划:将零碎提供的性能拆分,每个性能作为一部分劣势:对某个性能扩大,或者要减少新的性能时,只须要扩大相干性能即可,毋庸批改所有的服务典型架构:微内核架构分层架构概念:分层架构是很常见的架构模式,它也叫 N 层架构,通常状况下,N 至多是 2 层。 依据不同的划分维度和对象可分为:C/S 架构&B/S 架构、MVC 架构&MVP 架构、逻辑分层架构。 C/S 架构、B/S 架构划分的对象是整个业务零碎划分的维度是用户交互,行将和用户交互的局部独立为一层,撑持用户交互的后盾作为另外一层MVC 架构、MVP 架构划分的对象是单个业务子系统划分的维度是职责,将不同的职责划分到独立层,但各层的依赖关系比拟灵便逻辑分层架构划分的对象能够是单个业务子系统,也能够是整个业务零碎划分的维度也是职责,逻辑分层架构中的层是自顶向下依赖的外围要点须要保障各层之间的差别足够清晰,边界足够显著,让人看到架构图后就能看懂整个架构分层架构之所以可能较好地撑持零碎扩大,实质在于隔离关注点(separation of concerns),即每个层中的组件只会解决本层的逻辑并不是简略地分层就肯定可能实现隔离关注点从而撑持疾速扩大,分层时要保障层与层之间的依赖是稳固的,能力真正撑持疾速扩大。分层构造的另外一个特点就是层层传递,也就是说一旦分层确定,整个业务流程是依照层进行顺次传递的,不能在层之间进行跳跃。优缺点长处强制将分层依赖限定为两两依赖,升高了整体零碎复杂度。 毛病分层架构另外一个典型的毛病就是性能,因为每一次业务申请都须要穿梭所有的架构分层,有一些事件是多余的,多少都会有一些性能的节约分层构造的代价就是冗余,也就是说,不论这个业务有如许简略,每层都必须要参加解决,甚至可能每层都写了一个简略的包装函数。

May 16, 2022 · 1 min · jiezi

关于架构设计:架构设计-8高可用架构设计之故障处理

导读:《架构设计》系列为极客工夫李运华老师《从0开始学架构》课程笔记。本文为第八局部,次要介绍故障解决,包口典型体现、起因、常见状况、解决思维以及解决办法。如果异地多活看作事先解决的话,那么故障解决能够看作预先预案。 扫描文末二维码 关注公众号 回复 “架构设计” 获取架构设计笔记残缺思维导图典型体现零碎并没有宕机、网络也没有中断,但业务却呈现问题了如业务响应迟缓、大量拜访超时和大量拜访出现异常次要起因在于零碎压力太大、负载太高,导致无奈疾速解决业务申请,由此引发更多的后续问题。起因分类: 外部起因:包含程序 bug 导致死循环,某个接口导致数据库慢查问,程序逻辑不欠缺导致耗尽内存等。内部起因:包含黑客攻击,促销或者抢购引入了超出平时几倍甚至几十倍的用户,第三方零碎大量申请,第三方零碎响应迟缓等。常见状况最常见的状况就是,数据库慢查问将数据库的服务器资源耗尽,导致读写超时,业务读写数据库时要么无奈连贯数据库、要么超时,最终用户看到的景象就是拜访很慢,一会儿拜访抛出异样,一会儿拜访又是失常后果。 解决接口级故障的核心思想优先保障外围业务优先保障绝大部分用户应答办法降级降级指零碎将某些业务或者接口的性能升高,能够是只提供局部性能,也能够是齐全停掉所有性能。核心思想:丢车保帅,优先保障外围业务。 常见的实现降级的形式零碎后门降级:就是零碎预留了后门用于降级操作 长处:零碎后门降级的形式实现成本低毛病:如果服务器数量多,须要一台一台去操作,效率比拟低,这在故障解决争分夺秒的场景下是比拟浪费时间的。独立降级零碎:将降级操作独立到一个独自的零碎中,实现简单的权限治理、批量操作等性能。熔断熔断是指依照规定停掉内部接口的拜访,避免某些内部接口故障导致本人的零碎解决能力急剧下降或者出故障。与降级区别: 降级的目标是应答零碎本身的故障熔断的目标是应答依赖的内部系统故障的状况实现熔断机制键点 一是须要有一个对立的 API 调用层,由 API 调用层来进行采样或者统计。如果接口调用散落在代码各处,就没法进行对立解决了。二是阈值的设计,例如 1 分钟内 30% 的申请响应工夫超过 1 秒就熔断,这个策略中的“1 分钟”“30%”“1 秒”都对最终的熔断成果有影响。实际中,个别都是先依据剖析确定阈值,而后上线察看成果,再进行调优。限流限流指只容许零碎可能接受的访问量进来,超出零碎拜访能力的申请将被抛弃。与降级区别: 降级是从零碎性能优先级的角度思考如何应答故障限流则是从用户拜访压力的角度来思考如何应答故障基于申请限流分类 限度总量,也就是限度某个指标的累积下限,常见的是限度以后零碎服务的用户总量限度工夫量,也就是限度一段时间内某个指标的下限,例如 1 分钟内只容许 10000 个用户拜访;每秒申请峰值最高为 10 万。长处:无论是限度总量还是限度工夫量,独特的特点都是实现简略。 毛病: 比拟难以找到适合的阈值即便找到了适合的阈值,基于申请限流还面临硬件相干的问题。例如一台 32 核的机器和 64 核的机器解决能力差异很大解决方案 为了找到正当的阈值,通常状况下能够采纳性能压测来确定阈值,但性能压测也存在笼罩场景无限的问题,可能呈现某个性能压测没有笼罩的性能导致系统压力很大逐渐优化:先设定一个阈值而后上线察看运行状况,发现不合理就调整阈值。实用场景:依据阈值来限度访问量的形式更多的适应于业务性能比较简单的零碎,例如负载平衡零碎、网关零碎、抢购零碎等。 基于资源限流基于申请限流是从零碎内部思考的,而基于资源限流是从零碎外部思考的,也就是找到零碎外部影响性能的要害资源,对其应用下限进行限度。常见的外部资源包含连接数、文件句柄、线程数和申请队列等。基于资源限流相比基于申请限流可能更加无效地反映以后零碎的压力。难点: 如何确定要害资源如何确定要害资源的阈值解决方案:逐渐调优的过程:设计的时候先依据推断抉择某个要害资源和阈值,而后测试验证,再上线察看,如果发现不合理,再进行优化。算法工夫窗:限度肯定工夫窗口内的申请量或者资源消耗量 固定工夫窗:统计固定工夫周期内的申请量或者资源消耗量,超过限额就会启动限流。优缺点: 长处:实现简略毛病:存在临界点问题滑动工夫窗:两个统计周期局部重叠,从而防止短时间内的两个统计点分属不同的工夫窗的状况。优缺点: 长处:解决了临界点问题毛病:实现简单些桶算法:用一个虚构的“桶”来长期存储一些货色,来起到管制速率的成果。 漏桶:将申请放入“桶”(音讯队列等),业务处理单元(线程、过程和利用等)从桶里拿申请解决,桶满则抛弃新的申请。 设计关键点: 流入速率不固定:可能霎时流入十分多的申请,例如 0 点签到、整点秒杀。匀速 (极速) 流出:这是了解漏桶算法的要害,也就是说即便大量申请进入了漏桶,然而从漏桶流出的速度是匀速的,速度的最大值就是零碎的极限处理速度。须要留神的是:如果漏桶没有沉积,那么流出速度就等于流入速度,这个时候流出速度就不是匀速的。这样就保障了零碎在收到海量申请的时候不被压垮,这是第一层的保护措施。桶满则抛弃申请:这是第二层保护措施,也就是说漏桶不是有限容量,而是无限容量,例如漏桶最多存储 100 万个申请,桶满了则间接抛弃前面的申请。长处 实现简略提供双层保护措施毛病 突发大量流量时抛弃的申请较少,因为漏桶自身有缓存申请的作用。桶大小动静调整比拟艰难(例如 Java BlockingQueue),须要一直的尝试能力找到合乎业务需要的最佳桶大小。无奈准确管制流出速度,也就是业务的处理速度。实用场景:次要实用于刹时高并发流量的场景(例如方才提到的 0 点签到、整点秒杀等)。令牌桶:令牌桶算法和漏桶算法的不同之处在于,桶中放入的不是申请,而是“令牌”,这个令牌就是业务解决前须要拿到的“许可证”。也就是说,当零碎收到一个申请时,先要到令牌桶外面拿“令牌”,拿到令牌能力进一步解决,拿不到就要抛弃申请。 设计关键点 有一个处理单元往桶外面放令牌,放的速率是能够管制的。桶外面能够累积肯定数量的令牌,当突发流量过去的时候,因为桶外面有累积的令牌,此时的业务处理速度会超过令牌放入的速度。如果令牌有余,即便零碎有能力解决,也会抛弃申请。长处:能够动静调整解决速率,实现更加灵便。毛病 突发大量流量的时候可能抛弃很多申请,因为令牌桶不能累积太多令牌。实现绝对简单。实用场景 一种是须要管制拜访第三方服务的速度,避免把上游压垮,例如支付宝须要管制拜访银行接口的速率;一种是须要管制本人的处理速度,避免过载,例如压测结果显示零碎最大解决 TPS 是 100,那么就能够用令牌桶来限度最大的处理速度。排队排队实际上是限流的一个变种,限流是间接回绝用户,排队是让用户期待一段时间。优缺点: 长处:排队尽管没有间接回绝用户。毛病: ...

May 14, 2022 · 1 min · jiezi

关于架构设计:架构设计-7高可用架构设计之异地多活

导读:《架构设计》系列为极客工夫李运华老师《从0开始学架构》课程笔记。本文为第七局部,次要介绍异地多活,异地多活缩短了时延,进步可用性,然而带来复杂度和老本无疑是微小的,不是个别公司能够接受的,只有在对可用性要求特地高的业务场景才倡议应用。 扫描文末二维码 关注公众号 回复 “架构设计” 获取架构设计笔记残缺思维导图利用场景两个规范失常状况下,用户无论拜访哪一个地点的业务零碎,都可能失去正确的业务服务。某个中央业务异样的时候,用户拜访其余中央失常的业务零碎,可能失去正确的业务服务。 代价很高零碎复杂度会产生质的变动,须要设计简单的异地多活架构。老本会回升,毕竟要多在一个或者多个机房搭建独立的一套业务零碎。架构模式同城异区联合复杂度、老本、故障产生概率来综合思考,同城异区是应答机房级别故障的最优架构。关键在于搭建高速网络将两个机房连接起来,达到近似一个本地机房的成果。架构设计上能够将两个机房当作本地机房来设计,毋庸额定思考。跨城异地跨城异地间隔较远带来的网络传输提早问题,给异地多活架构设计带来了复杂性,如果要做到真正意义上的多活,业务零碎须要思考部署在不同地点的两个机房,在数据短时间不统一的状况下,还可能失常提供业务。关键在于数据不统一的状况下,业务不受影响或者影响很小,这从逻辑的角度上来说其实是矛盾的,架构设计的次要目标就是为了解决这个矛盾。这就引入了一个看似矛盾的中央:数据不统一业务必定不会失常,但跨城异地必定会导致数据不统一。如果是强一致性要求的数据,例如银行存款余额、支付宝余额等,这类数据实际上是无奈做到跨城异地多活的。跨国异地为不同地区用户提供服务只读类业务做多活技巧保障外围业务的异地多活保障外围数据最终一致性 尽量减少异地多活机房的间隔,搭建高速网络尽量减少数据同步,只同步外围业务相干的数据保障最终一致性,不保障实时一致性采纳多种手段同步数据 音讯队列形式:对于账号数据,因为账号只会创立,不会批改和删除(假如咱们不提供删除性能),咱们能够将账号数据通过音讯队列同步到其余业务核心。二次读取形式:第一次读取本地,本地失败后第二次读取对端存储系统同步形式:对于明码数据,因为用户改明码频率较低,而且用户不可能在 1 秒内间断改屡次明码,所以通过数据库的同步机制将数据复制到其余业务核心即可,用户信息数据和明码相似。回源读取形式:当用户在 A 核心登录后,而后又在 B 核心登录,B 核心拿到用户上传的 session id 后,依据路由判断 session 属于 A 核心,间接去 A 核心申请 session 数据即可;反之亦然,A 核心也能够到 B 核心去获取 session 数据。从新生成数据形式:对于“回源读取”场景,如果异常情况下,A 核心宕机了,B 核心申请 session 数据失败,此时就只能登录失败,让用户从新在 B 核心登录,生成新的 session 数据。只保障绝大部分用户的异地多活核心思想:采纳多种手段,保障绝大部分用户的外围业务异地多活!四步走业务分级依照肯定的规范将业务进行分级,挑选出外围的业务,只为外围业务设计异地多活,升高计划整体复杂度和实现老本。常见的分级规范: 访问量大的业务外围业务产生大量支出的业务数据分类挑选出外围业务后,须要对外围业务相干的数据进一步剖析,目标在于辨认所有的数据及数据特色,这些数据特色会影响前面的方案设计。常见的数据特征分析维度: 数据量:这里的数据量包含总的数据量和新增、批改、删除的量。对异地多活架构来说,新增、批改、删除的数据就是可能要同步的数据,数据量越大,同步提早的几率越高,同步计划须要思考相应的解决方案。唯一性:唯一性指数据是否要求多个异地机房产生的同类数据必须保障惟一。 数据的唯一性影响业务的多活设计,如果数据不须要惟一,那就阐明两个中央都产生同类数据是可能的;如果数据要求必须惟一,要么只能一个中心点产生数据,要么须要设计一个数据惟一生成的算法。实时性:实时性要求越高,对同步的要求越高,计划越简单。可失落性:可失落性指数据是否能够失落。可恢复性:可恢复性指数据失落后,是否能够通过某种伎俩进行复原,如果数据能够复原,至多阐明对业务的影响不会那么大,这样能够相应地升高异地多活架构设计的复杂度。数据同步常见的数据同步计划: 存储系统同步: 长处:应用简略,因为简直支流的存储系统都会有本人的同步计划毛病:这类同步计划都是通用的,无奈针对业务数据特点做定制化的管制。音讯队列同步:音讯队列同步适宜无事务性或者无时序性要求的数据。对于新注册的用户账号,咱们能够采纳音讯队列同步了;而对于用户明码,就不能采纳音讯队列同步了。反复生成:数据不同步到异地机房,每个机房都能够生成数据,这个计划适宜于能够反复生成的数据。异样解决无论数据同步计划如何设计,一旦呈现极其异样的状况,总是会有局部数据出现异常的: 同步提早数据失落数据不统一异样解决次要目标问题产生时,防止大量数据异样导致整体业务不可用。问题复原后,将异样的数据进行修改。对用户进行安抚,补救用户损失。常见的异样解决措施多通道同步采取多种形式来进行数据同步,其中某条通道故障的状况下,零碎能够通过其余形式来进行同步,这种形式能够应答同步通道处故障的状况。计划关键点: 个别状况下,采取两通道即可,采取更多通道实践上可能升高危险,但付出的老本也会减少很多。数据库同步通道和音讯队列同步通道不能采纳雷同的网络连接,否则一旦网络故障,两个通道都同时故障;能够一个走公网连贯,一个走内网连贯。须要数据是能够反复笼罩的,即无论哪个通道先到哪个通道后到,最终后果是一样的。例如,新建账号数据就合乎这个规范,而明码数据则不合乎这个规范。同步和拜访联合拜访指异地机房通过零碎的接口来进行数据拜访。设计关键点: 接口拜访通道和数据库同步通道不能采纳雷同的网络连接,不能让数据库同步和接口拜访都走同一条网络通道,能够采纳接口拜访走公网连贯,数据库同步走内网连贯这种形式。数据有路由规定,能够依据数据来推断应该拜访哪个机房的接口来读取数据。因为有同步通道,优先读取本地数据,本地数据无奈读取到再通过接口去拜访,这样能够大大降低跨机房的异地接口拜访数量,适宜于实时性要求十分高的数据。日志记录次要用于用户故障复原后对数据进行复原,其次要形式是每个要害操作前后都记录相干一条日志,而后将日志保留在一个独立的中央,当故障复原后,拿出日志跟数据进行比照,对数据进行修复。常见日志保留形式: 服务器上保留日志,数据库中保留数据,这种形式能够应答单台数据库服务器故障或者宕机的状况。本地独立零碎保留日志,这种形式能够应答某业务服务器和数据库同时宕机的状况。日志异地保留,这种形式能够应答机房宕机的状况。用户弥补无论如许完满的计划,故障的场景下总是可能有一小部分用户业务上出问题,零碎无法弥补这部分用户的损失。能够采纳人工的形式对用户进行弥补,补救用户损失,造就用户的忠诚度。简略来说,零碎的计划是为了保障 99.99% 的用户在故障的场景下业务不受影响,人工的弥补是为了补救 0.01% 的用户的损失。集体思考异地多活在前司个人感觉是个默认选项。比方 Redis 存储三地区双正本,一份数据要存6份:即本机房一主一从,而后同步到余下两个机房,而且是N+1冗余,也就是一个机房挂了,余下 N 个机房可能承接全副流量。这样做的益处就是: 用户都是就近拜访的,速度快可用性高,一个机房挂,间接主动切机房了,光缆挖断了、机房断电了也分分钟止损。毛病就是:太节约了,也比较复杂。比方我过后负责的几个 Redis 集群,有的是基础架构提供的多机房同步,有的是业务本人异步写近程机房,当然过后只是衡量之后这么搞的,如果要搞成 CP 就简单了,也不适宜业务本人搞。 现司就比拟粗犷了,大部分业务只是单地区,而后通过同城多机房来做容灾。这种形式其实比较简单,比方在上海和苏州个有一个机房,然而对于业务来说这两个机房无差别,申请会平均调配到两个机房的机器上,当上海的机房挂了,申请天然到了苏州了。简略粗犷,成果好。问题就是,如果服务都部署在深圳的机房了,北京的用户申请也要跑到深圳再回来,耗时多了几十毫秒。 简略的说,异地多活,是富家子的操作,谋求最初的 0.00001 的收益。大厂能够搞搞,小厂如果不是对可用性有特地特地高的需要还是算了吧。 reference从 0 开始学架构 ...

May 13, 2022 · 1 min · jiezi

关于架构设计:架构设计-6高可用架构之高可用计算架构

导读:《架构设计》系列为极客工夫李运华老师《从0开始学架构》课程笔记。本文为第六局部,次要介绍高可用计算架构,介绍了高可用架构设计的要点以及不同架构形式的优缺点。 扫描文末二维码 关注公众号 回复 “架构设计” 获取架构设计笔记残缺思维导图高可用计算架构设计思维:通过减少更多服务器来达到计算高可用设计复杂度:次要体现在工作治理方面,即当工作在某台服务器上执行失败后,如何将工作重新分配到新的服务器进行执行 哪些服务器能够执行工作每个服务器都能够执行工作只有特定服务器(通常叫“主机”)能够执行工作。当执行工作的服务器故障后,零碎须要筛选新的服务器来执行工作工作如何从新执行对于曾经调配的工作即便执行失败也不做任何解决,零碎只须要保障新的工作可能调配到其余非故障服务器上执行即可设计一个工作管理器来治理须要执行的计算工作,服务器执行完工作后,须要向工作管理器反馈工作执行后果,工作管理器依据工作执行后果来决定是否须要将工作重新分配到另外的服务器上执行架构设计主备主备架构是计算高可用最简略的架构,和存储高可用的主备复制架构相似,然而要更简略一些,因为计算高可用的主备架构毋庸数据复制 具体设计主机执行所有计算工作当主机故障(例如,主机宕机)时,工作分配器不会主动将计算工作发送给备机,此时零碎处于不可用状态如果主机可能复原(不论是人工复原还是主动复原),工作分配器持续将工作发送给主机。如果主机不可能复原(例如,机器硬盘损坏,短时间内无奈复原),则须要人工操作,将备机升为主机,而后让工作分配器将工作发送给新的主机(即原来的备机);同时,为了持续放弃主备架构,须要人工减少新的机器作为备机。备机冷备:备机上的程序包和配置文件都筹备好,但备机上的业务零碎没有启动温备:备机上的业务零碎曾经启动,只是不对外提供服务优缺点长处就是简略,主备机之间不须要进行交互,状态判断和切换操作由人工执行,零碎实现很简略毛病正好也体现在“人工操作”这点上主从计算高可用的主从架构中的从机也是要执行工作的。工作分配器须要将工作进行分类,确定哪些工作能够发送给主机执行,哪些工作能够发送给备机执行 具体设计失常状况下,主机执行局部计算工作,,备机执行局部计算工作当主机故障(例如,主机宕机)时,工作分配器不会主动将本来发送给主机的工作发送给从机,而是持续发送给主机,不论这些工作执行是否胜利如果主机可能复原(不论是人工复原还是主动复原),工作分配器持续依照原有的设计策略分配任务如果主机不可能复原,则须要人工操作,将原来的从机降级为主机(个别只是批改配置即可),减少新的机器作为从机,新的从机准备就绪后,工作分配器持续依照原有的设计策略分配任务优缺点长处:主从架构的从机也执行工作,施展了从机的硬件性能。毛病:主从架构须要将工作分类,工作分配器会简单一些。集群计算高可用集群蕴含 2 台服务器的集群,这点和存储高可用集群不太一样。存储高可用集群把双机架构和集群架构进行了辨别;而在计算高可用集群架构中,2 台服务器的集群和多台服务器的集群,在设计上没有本质区别,因而不须要进行辨别 对称集群艰深的叫法是负载平衡集群。集群中每个服务器的角色都是一样的,都能够执行所有工作 具体设计失常状况下,工作分配器采取某种策略(随机、轮询等)将计算任务分配给集群中的不同服务器当集群中的某台服务器故障后,工作分配器不再将任务分配给它,而是将任务分配给其余服务器执行。设计关键点工作分配器须要选取调配策略 任务分配策略比较简单,轮询和随机根本就够了工作分配器须要检测服务器状态 状态检测略微简单一些,既要检测服务器的状态,例如服务器是否宕机、网络是否失常等;同时还要检测工作的执行状态,例如工作是否卡死、是否执行工夫过长等。罕用的做法是工作分配器和服务器之间通过心跳来传递信息,包含服务器信息和工作信息,而后依据理论状况来确定状态判断条件。非对称集群非对称集群中不同服务器的角色是不同的,不同角色的服务器承当不同的职责 具体设计集群会通过某种形式来辨别不同服务器的角色。工作分配器将不同工作发送给不同服务器。当指定类型的服务器故障时,须要重新分配角色。设计复杂度任务分配策略更加简单:须要将工作划分为不同类型并调配给不同角色的集群节点。角色调配策略实现比较复杂:例如,可能须要应用 ZAB、Raft 这类简单的算法来实现 Leader 的选举。集体思考绝对高可用存储架构,计算架构绝对简略,不波及数据同步和一致性。关键点在于如何将申请路由到适合的实例上。 reference从 0 开始学架构

May 12, 2022 · 1 min · jiezi

关于架构设计:架构设计-5高可用架构之高可用存储架构

导读:《架构设计》系列为极客工夫李运华老师《从0开始学架构》课程笔记。本文为第五局部,次要介绍高可用存储架构,别离介绍了双机架构和集群架构以及各种具体计划的优缺点和利用场景。 扫描文末二维码 关注公众号 回复 “架构设计” 获取架构设计笔记残缺思维导图双机架构主备复制其整体架构比较简单,主备架构中的“备机”次要还是起到一个备份作用,并不承当理论的业务读写操作,如果要把备机改为主机,须要人工操作。 长处对于客户端来说,不须要感知备机的存在,即便劫难复原后,原来的备机被人工批改为主机后,对于客户端来说,只是认为主机的地址换了而已,毋庸晓得是原来的备机降级为主机。对于主机和备机来说,单方只须要进行数据复制即可,毋庸进行状态判断和主备切换这类简单的操作。毛病备机仅仅只为备份,并没有提供读写操作,硬件老本上有节约。故障后须要人工干预,无奈主动复原。场景主备复制是最常见也是最简略的一种存储高可用计划,简直所有的存储系统都提供了主备复制的性能,例如 MySQL、Redis、MongoDB 等 主从复制主机负责读写操作,从机只负责读操作,不负责写操作。 长处主从复制在主机故障时,读操作相干的业务能够持续运行。主从复制架构的从机提供读操作,施展了硬件的性能。毛病主从复制架构中,客户端须要感知主从关系,并将不同的操作发给不同的机器进行解决,复杂度比主备复制要高。主从复制架构中,从机提供读业务,如果主从复制提早比拟大,业务会因为数据不统一呈现问题。故障时须要人工干预。场景综合主从复制的优缺点,个别状况下,写少读多的业务应用主从复制的存储架构比拟多。例如,论坛、BBS、新闻网站这类业务,此类业务的读操作数量是写操作数量的 10 倍甚至 100 倍以上。 主主复制主主复制指的是两台机器都是主机,相互将数据复制给对方,客户端能够任意筛选其中一台机器进行读写操作。 长处两台都是主机,不存在切换的概念客户端毋庸辨别不同角色的主机,轻易将读写操作发送给哪台主机都能够。毛病如果采取主主复制架构,必须保证数据可能双向复制,而很多数据是不能双向复制的,如: 用户注册后生成的用户 ID,如果依照数字增长,那就不能双向复制库存不能双向复制场景主主复制架构对数据的设计有严格的要求,个别适宜于那些临时性、可失落、可笼罩的数据场景。例如,用户登录产生的 session 数据(能够从新登录生成)、用户行为的日志数据(能够失落)、论坛的草稿数据(能够失落)等。 双机切换设计要害主备复制和主从复制计划共性的问题主机故障后,无奈进行写操作。如果主机无奈复原,须要人工指定新的主机角色。欠缺的切换计划,要害设计点主备间状态判断 状态传递的渠道:是相互间相互连贯,还是第三方仲裁?状态检测的内容:例如机器是否掉电、过程是否存在、响应是否迟缓等。切换决策 切换机会:什么状况下备机应该降级为主机?是机器掉电后备机才降级,还是主机上的过程不存在就降级,还是主机响应工夫超过 2 秒就降级,还是 3 分钟内主机间断重启 3 次就降级等。切换策略:原来的主机故障复原后,要再次切换,确保原来的主机持续做主机,还是原来的主机故障复原后主动成为新的备机?主动水平:切换是齐全主动的,还是半自动的?例如,零碎判断以后须要切换,但须要人工做最终的确认操作数据抵触解决 当原有故障的主机复原后,新旧主机之间可能存在数据抵触常见架构互连式互连式就是指主备机间接建设状态传递的渠道,在主备复制的架构根底上,主机和备机多了一个“状态传递”的通道,这个通道就是用来传递状态信息的。 能够是网络连接(例如,各开一个端口),也能够是非网络连接(用串口线连贯)能够是主机发送状态给备机,也能够是备机到主机来获取状态信息。能够和数据复制通道共用,也能够独立一条通道。状态传递通道能够是一条,也能够是多条,还能够是不同类型的通道混合客户端影响 为了切换后不影响客户端的拜访,主机和备机之间共享一个对客户端来说惟一的地址。例如虚构 IP,主机须要绑定这个虚构的 IP客户端同时记录主备机的地址,哪个能拜访就拜访哪个;备机尽管能收到客户端的操作申请,然而会间接回绝,回绝的起因就是“备机不对外提供服务”毛病 如果状态传递的通道自身有故障(例如,网线被人不小心踢掉了),那么备机也会认为主机故障了从而将本人降级为主机,而此时主机并没有故障,最终就可能呈现两个主机。尽管能够通过减少多个通道来加强状态传递的可靠性,但这样做只是升高了通道故障概率而已,不能从根本上解决这个毛病,而且通道越多,后续的状态决策会更加简单,因为对备机来说,可能从不同的通道收到了不同甚至矛盾的状态信息。中介式中介式指的是在主备两者之外引入第三方中介,主备机之间不间接连贯,而都去连贯中介,并且通过中介来传递状态信息 长处 连贯治理更简略:主备机无须再建设和治理多种类型的状态传递连贯通道,只有连贯到中介即可,实际上是升高了主备机的连贯治理复杂度。状态决策更简略:主备机的状态决策简略了,毋庸思考多种类型的连贯通道获取的状态信息如何决策的问题,只须要依照上面简略的算法即可实现状态决策。 无论是主机还是备机,初始状态都是备机,并且只有与中介断开连接,就将本人降级为备机,因而可能呈现双备机的状况。主机与中介断连后,中介可能立即告知备机,备机将本人降级为主机。如果是网络中断导致主机与中介断连,主机本人会降级为备机,网络复原后,旧的主机以新的备机身份向中介上报本人的状态。主备机与中介连贯都失常的状况下,依照理论的状态决定是否进行切换。例如,主机响应工夫超过 3 秒就进行切换,主机降级为备机,备机降级为主机即可。毛病 尽管中介式架构在状态传递和状态决策上更加简略,但并不意味着这种长处是没有代价的,其要害代价就在于如何实现中介自身的高可用。如果中介本人宕机了,整个零碎就进入了双备的状态,写操作相干的业务就不可用了场景 MongoDB 的 Replica Set 采取的就是这种形式开源计划曾经有比拟成熟的中介式解决方案,例如 ZooKeeper 和 Keepalived。ZooKeeper 自身曾经实现了高可用集群架构,因而曾经帮咱们解决了中介自身的可靠性问题,在工程实际中举荐基于 ZooKeeper 搭建中介式切换架构。模拟式模拟式指主备机之间并不传递任何状态数据,而是备机模仿成一个客户端,向主机发动模仿的读写操作,依据读写操作的响应状况来判断主机的状态。 长处 比照一下互连式切换架构,咱们能够看到,主备机之间只有数据复制通道,而没有状态传递通道,备机通过模仿的读写操作来探测主机的状态,而后依据读写操作的响应状况来进行状态决策。模拟式切换与互连式切换相比,长处是实现更加简略,因为省去了状态传递通道的建设和管理工作。毛病 模拟式读写操作获取的状态信息只有响应信息(例如,HTTP 404,超时、响应工夫超过 3 秒等),没有互连式那样多样(除了响应信息,还能够蕴含 CPU 负载、I/O 负载、吞吐量、响应工夫等),基于无限的状态来做状态决策,可能呈现偏差。集群&分区集中集群数据集中集群与主备、主从这类架构类似,咱们也能够称数据集中集群为 1 主多备或者 1 主多从无论是 1 主 1 从、1 主 1 备,还是 1 主多备、1 主多从,数据都只能往主机中写,而读操作能够参考主备、主从架构进行灵便多变复杂度主机如何将数据复制给备机主 ...

May 11, 2022 · 1 min · jiezi

关于架构设计:架构设计-4高可用架构之FMEA方法

导读:《架构设计》系列为极客工夫李运华老师《从0开始学架构》课程笔记。本文为第三局部,次要介绍 FMEA 办法,以及如何将 FMEA 办法利用于架构设计之中以进步服务可用性。 扫描文末二维码 关注公众号 回复 “架构设计” 获取架构设计笔记残缺思维导图什么是FMEAFMEA(Failure mode and effects analysis,故障模式与影响剖析)又称为生效模式与结果剖析、生效模式与效应剖析、故障模式与结果剖析等 在架构设计畛域,FMEA 的具体分析办法 给出初始的架构设计图假如架构中某个部件产生故障剖析此故障对系统性能造成的影响依据剖析后果,判断架构是否须要进行优化FMEA 剖析表性能点以后的 FMEA 剖析波及的性能点,留神这里的“性能点”指的是从用户角度来看的,而不是从零碎各个模块性能点划分来看的。 故障模式故障模式指的是零碎会呈现什么样的故障,包含故障点和故障模式。须要特地留神的是,这里的故障模式并不需要给出真正的故障起因,咱们只须要假如呈现某种故障景象即可。 故障模式的形容要尽量准确,多应用量化形容,防止应用泛化的形容 故障影响当产生故障模式中形容的故障时,性能点具体会受到什么影响。常见的影响有: 性能点偶然不可用性能点齐全不可用局部用户性能点不可用性能点响应迟缓性能点出错等故障影响也须要尽量精确形容。 重大水平重大水平指站在业务的角度故障的影响水平 个别分为“致命 / 高 / 中 / 低 / 无”五个品位 重大水平依照这个公式进行评估:重大水平 = 性能点重要水平 × 故障影响范畴 × 性能点受损水平 故障起因不同的故障起因产生概率不雷同 不同的故障起因检测伎俩不一样 不同的故障起因的解决措施不一样 故障概率这里的概率就是指某个具体故障起因产生的概率。具体评估的时候须要重点关注: 硬件:硬件随着应用时间推移,故障概率会越来越高开源零碎:成熟的开源零碎 bug 率低,刚公布的开源零碎 bug 率相比会高一些;本人曾经有应用教训的开源零碎 bug 率会低,刚开始尝试应用的开源零碎 bug 率会高自研零碎:和开源零碎相似,成熟的自研系统故障概率会低,而新开发的系统故障概率会高危险水平危险水平就是综合重大水平和故障概率来一起判断某个故障的最终等级 危险水平 = 重大水平 × 故障概率。因而可能呈现某个故障影响十分重大,但其概率很低,最终来看危险水平就低 已有措施针对具体的故障起因,零碎当初是否提供了某些措施来应答。次要措施: 检测告警:最简略的措施就是检测故障,而后告警,零碎本人不针对故障进行解决,须要人工干预。容错:检测到故障后,零碎可能通过备份伎俩应答。例如,MySQL 主备机,当业务服务器检测到主机无奈连贯后,主动连贯备机读取数据。自复原:检测到故障后,零碎可能本人复原。例如,Hadoop 检测到某台机器故障后,可能将存储在这台机器的正本重新分配到其余机器。躲避措施躲避措施指为了升高故障产生概率而做的一些事件。次要伎俩: 技术手段:为了防止新引入的 MongoDB 失落数据,在 MySQL 中冗余一份。管理手段:为了升高磁盘坏道的概率,强制对立更换服务工夫超过 2 年的磁盘。解决措施解决措施指为了可能解决问题而做的一些事件,个别都是技术手段。例子: ...

May 10, 2022 · 1 min · jiezi

关于架构设计:架构设计-3高可用架构之CAP理论

导读:《架构设计》系列为极客工夫李运华老师《从0开始学架构》课程笔记。本文为第三局部,次要介绍分布式系统中的 CAP 实践以及相干的 ACID 实践和 BASE实践。对分布式系统架构有一个实践上的感知。 CAP 实践在一个分布式系统(指相互连贯并共享数据的节点的汇合)中,当波及读写操作时,只能保障一致性(Consistence)、可用性(Availability)、分区容错性(Partition Tolerance)三者中的两个,另外一个必须被就义。 P 分区容忍性(Partition Tolerance):当呈现网络分区后,零碎可能持续“履行职责”A 可用性(Availability):非故障的节点在正当的工夫内返回正当的响应(不是谬误和超时的响应)C 一致性(Consistency):对某个指定的客户端来说,读操作保障可能返回最新的写操作后果CAP 特点:分布式系统并不一定会互联和共享数据CAP 关注的是对数据的读写操作,而不是分布式系统的所有性能CAP 利用CP - Consistency/Partition ToleranceAP - Availability/Partition Tolerance一些细节CAP 关注的粒度是数据,而不是整个零碎在理论设计过程中,每个零碎不可能只解决一种数据,而是蕴含多种类型的数据,有的数据必须抉择 CP,有的数据必须抉择 AP。。但在理论设计过程中,每个零碎不可能只解决一种数据,而是蕴含多种类型的数据,有的数据必须抉择 CP,有的数据必须抉择 AP。CAP 是疏忽网络提早的CAP 实践中的 C 在实践中是不可能完满实现的,在数据复制的过程中,节点 A 和节点 B 的数据并不统一。 失常运行状况下,不存在 CP 和 AP 的抉择,能够同时满足 CACAP 实践通知咱们分布式系统只能抉择 CP 或者 AP,但其实这里的前提是零碎产生了“分区”景象。架构设计的时候既要思考分区产生时抉择 CP 还是 AP,也要思考分区没有产生时如何保障 CA放弃并不等于什么都不做,须要为分区复原后做筹备最典型的就是在分区期间记录一些日志,当分区故障解决后,零碎依据日志进行数据恢复,使得从新达到 CA 状态。分区期间放弃 C 或者 A,并不意味着永远放弃 C 和 A,咱们能够在分区期间进行一些操作,从而让分区故障解决后,零碎可能从新达到 CA 的状态。ACIDACID 是数据库管理系统为了保障事务的正确性而提出来的一个实践: Atomicity(原子性):一个事务中的所有操作,要么全副实现,要么全副不实现,不会在两头某个环节完结Consistency(一致性):在事务开始之前和事务完结当前,数据库的完整性没有被毁坏Isolation(隔离性):数据库容许多个并发事务同时对数据进行读写和批改的能力。隔离性能够避免多个事务并发执行时因为穿插执行而导致数据的不统一。事务隔离分为不同级别,包含读未提交(Read uncommitted)、读提交(read committed)、可反复读(repeatable read)和串行化(Serializable)。Durability(持久性):事务处理完结后,对数据的批改就是永恒的,即使系统故障也不会失落。与 CAP 区别ACID 中的 C 是指数据库的数据完整性,而 CAP 中的 C 是指分布式节点中的数据一致性ACID 的利用场景是数据库事务,CAP 关注的是分布式系统数据读写ACID 中的 A(Atomicity)和 CAP 中的 A(Availability)意义齐全不同这里须要补充一点,上述了解能够认为是将 ACID 限度在单机事务。如果放在分布式场景,ACID 个性了解为 CAP 中一致性的边界,最强的一致性。但这须要一些分布式协定来反对,如:二阶段提交协定,TCC协定等。 ...

May 7, 2022 · 1 min · jiezi

关于架构设计:架构设计之一基础架构

导读:《架构设计》系列为极客工夫李运华老师《从0开始学架构》课程笔记。本文为第一局部,次要介绍架构设计的历史背景、相干概念、目标、复杂度、准则以及流程。从整体上对架构设计有所理解。 架构设计的历史背景机器语言(1940 年之前)机器语言的次要问题是三难:太难写、太难读、太难改! 汇编语言(20 世纪 40 年代)实质上还是面向机器的,因为写汇编语言须要咱们准确理解计算机底层的常识。 高级语言(20 世纪 50 年代)第一次软件危机与结构化程序设计(20 世纪 60 年代~20 世纪 70 年代)典型体现有软件品质低下、我的项目无奈如期完成、我的项目重大超支等,因为软件而导致的重大事故时有发生。软件工程同样无奈铲除软件危机,只能在肯定水平上缓解软件危机。结构化程序设计的次要特点是摈弃 goto 语句,采取“自顶向下、逐渐细化、模块化”的指导思想。结构化程序设计实质上还是一种面向过程的设计思维,但通过“自顶向下、逐渐细化、模块化”的办法,将软件的复杂度管制在肯定范畴内,从而从整体上升高了软件开发的复杂度。第二次软件危机与面向对象(20 世纪 80 年代)第二次软件危机的根本原因还是在于软件生产力远远跟不上硬件和业务的倒退。第一次软件危机的本源在于软件的“逻辑”变得非常复杂,而第二次软件危机次要体现在软件的“扩大”变得非常复杂。结构化程序设计尽管可能解决(兴许用“缓解”更适合)软件逻辑的复杂性,然而对于业务变动带来的软件扩大却无能为力,软件畛域迫切希望找到新的银弹来解决软件危机,在这种背景下,面向对象的思维开始流行起来。软件架构的历史背景随着软件系统规模的减少,计算相干的算法和数据结构不再形成次要的设计问题;当零碎由许多局部组成时,整个零碎的组织,也就是所说的“软件架构”,导致了一系列新的设计问题。 零碎规模宏大,外部耦合重大,开发效率低;零碎耦合重大,牵一动员全身,后续批改和扩大艰难;零碎逻辑简单,容易出问题,出问题后很难排查和修复三组容易混同的概念零碎与子系统零碎零碎泛指由一群有关联的个体组成,依据某种规定运作,能实现个别元件不能独自实现的工作的群体。它的意思是“总体”“整体”或“联盟”关系:零碎是由一群有关联的个体组成的,没有关联的个体堆在一起不能成为一个零碎。规定:零碎内的个体须要依照指定的规定运作,而不是单个个体各自为政。规定规定了零碎内个体分工和合作的形式。能力:零碎能力与个体能力有实质的差异,零碎能力不是个体能力之和,而是产生了新的能力。子系统子系统也是由一群有关联的个体所组成的零碎,多半会是更大零碎中的一部分。 总结一个零碎的架构,只包含顶层这一个层级的架构,而不包含上司子系统层级的架构。所以微信架构,就是指微信零碎这个层级的架构。当然,微信的子系统,比方领取零碎,也有它本人的架构,同样只包含顶层。 模块与组件模块软件模块(Module)是一套统一而相互有严密关联的软件组织。它别离蕴含了程序和数据结构两局部。古代软件开发往往利用模块作为合成的单位。模块的接口表白了由该模块提供的性能和调用它时所需的元素。模块是可能离开被编写的单位。这使它们可再用和容许人员同时合作、编写及钻研不同的模块。 组件软件组件定义为自蕴含的、可编程的、可重用的、与语言无关的软件单元,软件组件能够很容易被用于组装应用程序中。 总结模块和组件都是零碎的组成部分,只是从不同的角度拆分零碎而已。从业务逻辑的角度来拆分零碎后,失去的单元就是“模块”;从物理部署的角度来拆分零碎后,失去的单元就是“组件”。划分模块的次要目标是职责拆散;划分组件的次要目标是单元复用。假如咱们要做一个学生信息管理系统,这个零碎从逻辑的角度来拆分,能够分为“登录注册模块”“个人信息模块”和“集体问题模块”;从物理的角度来拆分,能够拆分为 Nginx、Web 服务器和 MySQL。业务零碎的架构师,首先须要思考怎么从业务逻辑的角度把零碎拆分成一个个模块角色,其次须要思考怎么从物理部署的角度把零碎拆分成组件角色,例如抉择 MySQL 作为存储系统。然而对于 MySQL 外部的体系架构(是能够不必关注的,也不须要在你的业务零碎架构中展示这些内容。框架与架构框架软件框架(Software framework)通常指的是为了实现某个业界规范或实现特定根本工作的软件组件标准,也指为了实现某个软件组件标准时,提供标准所要求之根底性能的软件产品。 架构软件架构指软件系统的“根底构造”,发明这些根底构造的准则,以及对这些构造的形容。 总结框架关注的是“标准”,架构关注的是“构造”。框架是一整套开发标准,架构是某一套开发标准下的具体落地计划,包含各个模块之间的组合关系以及它们协同起来实现性能的运作规定。从新定义架构:4R 架构软件架构指软件系统的顶层(Rank)构造,它定义了零碎由哪些角色(Role)组成,角色之间的关系(Relation)和运作规定(Rule)Rank:它是指软件架构是分层的,对应“零碎”和“子系统”的分层关系。通常状况下,咱们只须要关注某一层的架构,最多展现相邻两层的架构,而不须要把每一层的架构全副糅杂在一起。无论是架构设计还是画架构图,都应该采取“自顶向下,逐渐细化”的形式。Role:它是指软件系统蕴含哪些角色,每个角色都会负责零碎的一部分性能。架构设计最重要的工作之一就是将零碎拆分为多个角色。最常见的微服务拆分其实就是将整体简单的业务零碎依照业务畛域的形式,拆分为多个微服务,每个微服务就是零碎的一个角色。Relation:它是指软件系统的角色之间的关系,对应到架构图中其实就是连接线,角色之间的关系不能乱连,任何关系最初都须要代码来实现,包含连贯形式(HTTP、TCP、UDP 和串口等)、数据协定(JSON、XML 和二进制等)以及具体的接口等。Rule:它是指软件系统角色之间如何合作来实现零碎性能。架构设计的目标架构也是为了应答软件系统复杂度而提出的一个解决方案,即架构设计的次要目标是为了解决软件系统复杂度带来的问题。 遵循这条准则可能让“老手”架构师成竹在胸,而不是一头雾水。遵循这条准则可能让“老鸟”架构师对症下药,而不是贪大求全。复杂性起源高性能软件系统中高性能带来的复杂度次要体现在两方面,一方面是单台计算机外部为了高性能带来的复杂度;另一方面是多台计算机集群为了高性能带来的复杂度。 单机复杂度操作系统和性能最相干的就是过程和线程如果咱们要实现一个高性能的软件系统,须要思考如多过程、多线程、过程间通信、多线程并发等技术点,而且这些技术并不是最新的就是最好的,也不是非此即彼的抉择。集群复杂度任务分配,负载平衡工作合成,微服务 简略的零碎更加容易做到高性能能够针对单个工作进行扩大指标掂量软件性能包含了响应工夫、TPS、服务器资源利用率等主观指标 高可用零碎无中断地执行其性能的能力,代表零碎的可用性水平,是进行零碎设计时的准则之一。零碎的高可用计划形形色色,但万变不离其宗,实质上都是通过“冗余”来实现高可用。 高性能减少机器目标在于“扩大”解决性能;高可用减少机器目标在于“冗余”处理单元。计算高可用“计算”指的是业务的逻辑解决。计算有一个特点就是无论在哪台机器上进行计算,同样的算法和输出数据,产出的后果都是一样的 存储高可用整个零碎的高可用设计关键点和难点就在于“存储高可用”。存储与计算相比,有一个实质上的区别:将数据从一台机器搬到到另一台机器,须要通过线路进行传输。存储高可用的难点不在于如何备份数据,而在于如何缩小或者躲避数据不统一对业务造成的影响。高可用状态决策无论是计算高可用还是存储高可用,其根底都是“状态决策”,即零碎须要可能判断以后的状态是失常还是异样,如果呈现了异样就要采取行动来保障高可用 独裁式协商式专制式可扩展性可扩展性是指,零碎为了应答未来需要变动而提供的一种扩大能力,当有新的需要呈现时,零碎不须要或者仅须要大量批改就能够反对,无需整个零碎重构或者重建。设计具备良好可扩展性的零碎,有两个根本条件: 正确预测变动 准则:只预测 2 年内的可能变动,不要试图预测 5 年甚至 10 年后的变动。完满应答变动 计划一:提炼出“变动层”和“稳固层”,核心思想是通过变动层来隔离变动计划二:提炼出“形象层”和“实现层”,核心思想就是通过实现层来封装变动。准则:1 写 2 抄 3 重构准则其余起源老本往往只有“翻新”能力达到低成本指标 引进新技术自研新技术低成本实质上是与高性能和高可用抵触的,所以低成本很多时候不会是架构设计的首要指标,而是架构设计的附加束缚。 平安性能平安:其实就是“防小偷”架构平安:就是“防匪徒”规模规模带来复杂度的次要起因就是“质变引起量变”数据越来越多,零碎复杂度产生量变架构设计准则适合准则,“适合优于业界当先”不适宜的状况 没那么多人,却想干那么多活没有那么多积攒,却想平步青云没有那么卓越的业务场景,却空想灵光一闪成为蠢才简洁准则,“简洁优于简单”简单的体现构造的复杂性 景象 组成简单零碎的组件数量更多同时这些组件之间的关系也更加简单问题 组件越多,就越有可能其中某个组件呈现故障某个组件改变,会影响关联的所有组件定位一个简单零碎中的问题总是比简略零碎更加艰难逻辑的复杂性 单个组件承当了太多的性能采纳了简单的算法演进准则,“演变优于一步到位”对于软件来说,变动才是主题软件架构设计其实更加相似于大自然“设计”一个生物,通过演变让生物适应环境,逐渐变得更加弱小 避坑时刻揭示本人不要贪大求全防止自觉照搬大公司的做法最佳实际应该认真剖析以后业务的特点,明确业务面临的次要问题,设计正当的架构,疾速落地以满足业务须要在运行过程中不断完善架构,一直随着业务演变架构架构设计流程辨认复杂度将次要的复杂度问题列出来,而后依据业务、技术、团队等综合状况进行排序,优先解决以后面临的最次要的复杂度问题。设计的指标应该以峰值来计算。峰值个别取平均值的 3 倍,设计指标设定为峰值的 4 倍是依据业务倒退速度来预估的,不是固定为 4 倍,不同的业务能够是 2 倍,也能够是 8 倍,但个别不要设定在 10 倍以上,更不要一上来就依照 100 倍预估。设计备选计划新技术都是在现有技术的根底上倒退起来的。`` ...

May 1, 2022 · 1 min · jiezi

关于架构设计:vivo推送平台架构演进

本文依据Li Qingxin老师在“2021 vivo开发者大会"现场演讲内容整顿而成。公众号回复【2021VDC】获取互联网技术分会场议题相干材料。一、vivo推送平台介绍1.1 从产品和技术角度理解推送平台推送平台是做什么的? 有的小伙伴可能理解过,有的可能是第一次接触到。无论您是哪一种状况都心愿通过明天的分享,可能让您对咱们有新的理解。接下来我将从产品和技术两个不同视角,给大家介绍vivo推送平台。 首先,从产品角度来看,vivo推送平台通过和零碎的深度联合,建设稳固牢靠、平安可控、反对每秒100w推送速度、亿级用户同时在线的音讯推送服务,帮忙不同行业的开发者开掘更多的经营价值。推送平台的外围能力是利用长连贯技术 ,以智能设施、手机为载体为用户提供具备实时、双向的内容和服务传输的能力。  所以如果你是经营人员,能够思考应用咱们推送平台来经营你们在vivo 手机零碎上的APP来晋升你们APP的沉闷和留存。对于推送平台的实质是什么? 从技术角上来看,咱们是一个通过TCP长连贯,将音讯发送给用户的平台。所以推送平台的实质其实就是借助网络通道,将音讯发送到用户设施上。 大家日常都收到过快递告诉吧!当快递员将快递放到快递柜中,快递后盾就会主动推送一条音讯,告诉你有快递。我置信,如果你是一位经营人员,你也会喜爱这种主动下发音讯高效的形式。大家感兴趣的,能够在分享完结之后,通过vivo开放平台入口,抉择音讯推送来更进一步理解咱们。 1.2 内容、服务、设施互联在这个万物互联的时代,咱们平台也具备连贯多的能力,咱们通过长连贯将内容、服务、用户连在一起,将内容分发给用户,为终端设备提供实时、双向通信能力。 这里有个概念长连贯,那么什么是长连贯?所谓的长连贯就是,客户端与服务端维持的一条,在绝对较长的工夫里,都可能进行网络通信的网络连接(比方:基于TCP的长连贯)。 为什么咱们要采纳长连贯而不是短连贯作为平台底层的网络通信。 咱们先来看看短连贯下音讯下发的场景:应用短连贯的形式就是轮询,即客户端定时的去询问后盾有没有设施A的音讯,当有设施A的音讯时后盾返回对应的音讯,可能很多状况下都是无功而返,节约流量;当后盾有音讯须要发送给设施A时,因为设施A没有过去取导致音讯无奈下发。而应用长连贯,当有设施A的音讯时后盾间接发送给设施A而不必等设施A本人过拉取,所以长连贯让数据交互更加天然、高效;除此之外,咱们平台技术上还具备以下劣势: 超过亿级设施同时在线;反对百万每秒的推送速度;反对每天超百亿级的音讯吞吐量;实时推送成果剖析;全量推送音讯实时审计。咱们推送平台具备的这些能力可能为音讯的时效性提供保障,咱们平台具备的这些能力是通过一直的演进而来的,接下来跟大家分享vivo推送平台的架构这几年的变动。 二、vivo推送平台架构演进2.1 拥抱业务IT畛域的架构它是动静的,不同阶段都可能会发生变化,而推动架构进行演进的推力,次要来自于业务需要,接下来咱们一起来回顾,咱们平台的业务倒退历程。 自2015年立项以来,随着业务量增长,咱们一直为零碎添砖加瓦,丰盛整个零碎的能力使其满足不同的业务场景需要。比方反对内容齐全审核、反对IM、反对IoT、反对WebSocket 通信等。 从图上能够看到,咱们业务量简直每年都有几十亿的增长,一直攀高,给零碎带来了挑战,原有的零碎架构存在的问题,也逐步浮出水面,比方提早、性能瓶颈。架构服务于业务,2018年之前咱们平台所有服务都放在云上,然而咱们依赖的其余外部业务部署在自建机房。 2.2 敢于扭转随着业务量增长与自建机房的数据传输,曾经呈现了提早的问题,并且在逐步好转,不利于咱们平台性能的拓展。所以在2018年下半年,咱们对部署架构进行调整:将所有外围逻辑模块都迁徙到自建机房,架构优化之后,数据提早问题失去彻底解决。同时也为架构进一步演进奠定了根底。从下面的图中能够看到咱们接入网关也进行优化三地部署。 为什么要进行三地部署而不是更多区域部署呢?次要基于以下三点思考: 第一是基于用户散布及老本的思考;第二是能为用户提供就近接入;第三是可能让接入网关具备肯定容灾能力。大家能够构想下,如果没有三地部署,接入网关机房故障时,那么咱们平台就瘫痪了。 随着咱们平台业务规模的进一步扩充,日吞吐量达到10亿的量级,用户对于时效性、并发要求越来越高,而咱们2018年的逻辑服务的零碎架构曾经无奈业务高并发的需要或者须要更高的服务器老本能力满足高并发需要。所以从平台性能、老本优化登程,咱们在2019年对系统进行了重构,为用户提供更加丰盛的产品性能及更稳固、更高性能的平台。 2.3 利用长连贯能力给业务赋能 作为公司较大规模的长连贯服务平台,咱们积攒了十分丰盛的长连贯教训。咱们也始终在思考,如何让长连贯能力为更多业务赋能。咱们平台服务端各个模块之间通过RPC调用,这是一种十分高效的开发模式,不必每个开发人员都去关怀底层网络层数据包的。 咱们构想下,如果客户端也能通过RPC调用后盾,这肯定是十分棒的开发体验。将来咱们将会提供VRPC通信框架,用于解决客户端与后盾通信及开发效率问题,为客户端与后盾提供统一的开发体验,让更多的开发人员不再关怀网络通信问题,分心开发业务逻辑。 三、零碎稳定性、高性能、平安作为一个吞吐量超过百亿的推送平台其稳定性、高性能、平安都十分重要,那么接下来和大家分享,咱们在零碎稳定性、高性能、平安方面的实践经验。 从上图的畛域模型能够看出,咱们推送平台以通信服务作为外围能力,在外围能力的根底上咱们又提供了,大数据服务以及经营零碎,通过不同接口对外提供不同的性能、服务。以通信服务为外围的推送平台,其稳定性和性能都会影响音讯的时效性。音讯的时效性是指,音讯从业务方发动用设施收到的耗时,那么如何掂量音讯的时效性呢? 3.1 监控与品质度量 传统的音讯时效性测量方法如左图所示,发送端和接收端在两个设施上,在发送的时候取工夫t1、在接管到音讯的时候取工夫t2,这两个工夫相减失去音讯的耗时。然而这种办法并不谨严,为什么呢?因为这两个设施的工夫基准,很有可能是不统一的。咱们采纳的解决方案如右图所示,将发送端和接收端放在同一个设施上,这样就能够解决工夫基准的问题。咱们基于该计划,搭建了一套拨测系统,来被动监控音讯送达耗时散布。 3.2 高性能、稳固的长连贯网关过来10年探讨单机长连贯性能时面对的是单机一万连贯的问题,作为一个上亿级设施同时在线的平台,咱们要面对的是单机100万连贯的问题。 作为长连贯网关,主要职责是保护与设施端的TCP连贯及数据包转发。对于长连贯网关,咱们应该尽可能使其轻量化,所以咱们从架构设计、编码、操作系统配置、以及硬件个性,自上而下穿透整个档次来进行重构优化。 调整零碎最大文件句柄数、单个过程最大的文件句柄数;调整零碎网卡软中断负载平衡或者开启网卡多队列、RPS/RFS;调整TCP相干参数比方keepalive(须要依据宿主机的session工夫进行调整)、敞开timewait recycles;硬件上应用AES-NI指令减速数据的加解密。通过咱们优化之后,线上8C32GB 的服务器能够稳固反对170万的长连贯。 另外一大难点在于,连贯保活,一条端到端的 TCP连贯,两头通过层层路由器、网关,而每个硬件的资源都是无限的,不可能将所有TCP连贯状态都长期保留。所以为了防止TCP资源,被两头路由器回收导致连贯断开,咱们须要定时发送心跳申请,来放弃连贯的沉闷状态。 心跳的发送频率多高才适合?发送太快了会引起功耗、流量问题,太慢了又起不到成果,所以为了缩小不必要的心跳及晋升连贯稳定性,咱们采纳智能心跳,为不同网络环境采纳差异性的频率。 3.3 亿级设施负载平衡咱们平台超过亿级设施同时在线,各个设施连贯长连贯网关时是通过流量调度零碎进行负载平衡的。当客户端申请获取IP时,流量调度零碎会下发多个就近接入网关IP。 那么调度零碎是如何确保下发的ip是可用的呢?大家能够简略思考下,而咱们采纳四种策略:就近接入 、公网探测 、 机器负载以及接口成功率。采纳这几种策略呢?大家能够想下,这两个问题: 内网失常,公网就肯定能联通吗?连接数少服务器,就肯定是可用的吗?答案是否定的,因为长连贯网关与流量调度零碎是通过内网进行心跳保活的,所以在流量调度零碎上看到的长连贯网关是失常的,然而很有可能长连贯网关公网连贯是异样的比方没有开明公网权限等,所以咱们须要联合多种策略,来评估节点的可用性,保障系统的负载平衡、为零碎稳定性提供保障。 3.4 如何满足高并发需要有这么一个场景:以每秒一千的推送速度,将一条新闻发送给几亿用户,那么有的用户可能是几天后才收到这条音讯,这就十分影响用户体验,所以高并发对音讯的时效性来说是十分重要的。 大家从图上的推送流程来看,会不会感觉TiDB会成为推送的性能瓶颈?其实不会,初步看可能会感觉它们作为核心存储,因为咱们采纳分布式缓存,将核心存储的数据,依据肯定的策略缓存到各个业务节点,充分利用服务器资源,晋升零碎性能、吞吐量。咱们线上的分布式缓存命中率99.9% 为核心存储挡住了绝大部分申请,即便TiDB短时间故障,对咱们影响也比拟小。 3.5 如何保障系统稳定性作为推送平台,咱们平台的流量次要分为内部调用及外部上下游之间的调用。它们大幅稳定都会影响零碎的稳定性,所以咱们要进行限流、控速,保障系统稳固运行。 3.5.1 推送网关限流推送网关作为流量入口其稳定性十分重要,要让推送网关稳固运行,咱们首先要解决流量平衡的问题即防止流量歪斜的问题。因为流量歪斜之后,很有可能会引起雪崩的状况。 咱们是采纳轮询的机制,进行流量的负载平衡,来防止流量歪斜问题。然而这里有个前提条件,那就是所有推送网关节点,服务器配置要保持一致,否则很有可能会因为某个解决能力有余导致过载问题。其次是咱们要管制流入咱们零碎的并发量,防止流量洪峰穿透推送网关导致后端服务过载。咱们采纳的是令牌桶算法,管制每个推送网关投放速度,进而可能对上游节点起到爱护作用。 那么令牌数量设置多少才适合呢?设置低了,上游节点资源不能充分利用;设置太高了,上游节点有可能扛不住,咱们能够采纳被动+被动的动静调整的策略: 1)当流量超过上游集群解决能力时,告诉上游进行限速; 2)当调用上游接口超时,达到肯定比例是进行限流。 ...

January 17, 2022 · 1 min · jiezi

关于架构设计:阿里云-FaaS-架构

摘要:心愿通过本系列课程,让大家更深刻理解阿里云FaaS架构设计,以及神龙高密部署的FaaS介绍。 本篇内容将从2个局部为读者介绍对于阿里云 FaaS 架构设计和神龙高密部署的 FaaS,心愿能够让大家对阿里云FaaS 有更深刻的理解,并能够将 FaaS 利用到我的项目中,达到降本提效的目标。 一、基于 ECS 的 FaaS 在阿里云传统架构,用户通过互联网进入到负载平衡零碎中,再通过负载平衡把零碎的申请调度到不同的机器下来。这种传统的架构带来的问题比拟多,一方面是多利用配比比例容易失衡,造成资源节约;另一方面是镜像降级比拟繁琐,整个过程的开机速度在分钟级,扩容速度也绝对较慢。 (1) 架构设计基于 ECS 的 FaaS 架构设计同样也是通过互联网进入,落到 SLB 负载平衡上。SLB 负载平衡这个零碎是部署在阿里云外部的,次要用于抵御 DDoS 攻打及申请平衡到多台 api_server 上。api_server 再发动函数的 CRUD 操作,并向 Scheduler 申请容器。Scheduler 治理容器在 worker 的搁置,申请落在容器上的调度散发。用户所在 worker 就是咱们称之为的计算节点,如果须要拜访用户的 VPC 环境则在计算节点上通过 ENI 网卡买通到用户 VPC 环境。 (2) 多租户多利用部署的反对 namespace 是 linux 前几年推出的一个资源隔离计划,能够在内核层面做一些设置指定一部分过程固定。并且能够在 cgroup 的这一套设置计划里设置,管制资源的拜访。在 namespace、cgroup 整套计划下,衍生出了 container,社区中罕用的的 Docker 计划把镜像操作系统中的很多细节包装成一个计划,用户看到了一个绝对比拟残缺的操作系统,把用户当成一个单个用户搁置在虚拟机当中。这就是一个 vm,相当于说一台 ECS,这里就是操作系统层面,把整个 cpu、memory、包含设施全副给屏蔽掉,在下面用 cgroup 封一层,对应的就是 Docker 容器。 利用搁置策略包含用户独占虚拟机、同 VPC 独占虚拟机、资源拜访权限统一的 APP 混部在同机器。把两个不同的用户混在一个 vm 下,也就是 ECS 下面,对于用户之间来说是存在危险的。为了屏蔽掉共用 kernel 带来的危险,ECS 上的实现,咱们单个 ECS 只有一个租户,这样解决也存在一些问题,最突出的就是对于低频调用函数资源使用率低。 ...

December 28, 2021 · 1 min · jiezi

关于架构设计:2021-VDC-vivo-互联网服务亿级用户的技术架构演进之路

关注公众号【vivo互联网技术】——回复【2021VDC】获取大会PPT。2021年12月16日,vivo 开发者大会圆满闭幕。在互联网技术专场中,来自vivo 互联网技术的6位研发专家,从基础架构、效力晋升两方面分享了 vivo互联网技术服务亿级用户的技术架构演进之路。 01. 音讯推送服务反对每秒100w推送速度、亿级用户同时在线随着互联网的遍及以及各类互联网产品的层出不穷,咱们走入信息爆炸时代,互联网产品信息量一直上涨给推送零碎带来不同的挑战。 vivo 推送平台零碎架构师李青鑫在《vivo推送平台架构演进》中和大家分享vivo推送是如何解决在业务倒退过程中遇到的问题及挑战。 (vivo 推送平台零碎架构师李青鑫) vivo推送平台通过和零碎的深度联合,建设稳固牢靠、平安可控、反对每秒100w推送速度、亿级用户同时在线的音讯推送服务,帮忙不同行业的开发者开掘更多的经营价值。推送平台的外围能力是利用长连贯技术 ,以智能设施、手机为载体为用户提供具备实时、双向的内容和服务传输的能力。 推送平台技术上已具备: 实时百万/秒推送速度日最高122亿推送量实时推送成果剖析全量推送音讯实时审计02. vivo自主研发一站式智能存储平台,撑持vivo在网总用户数达2.7亿近几年vivo互联网业务处于高速倒退的状态,为晋升用户服务质量和外部降本增效,2018年启动了自研数据库与存储平台的打算。 此次,vivo存储技术团队研发总监肖博分享了《vivo 数据库与存储平台建设和摸索》,讲述vivo在数据库产品、存储服务、数据库服务支撑体系几个方向的建设思路和思考。 (vivo存储技术团队研发总监肖博) vivo数据库与存储平台是vivo自主研发的交互便捷、体验良好、自助化、智能化的笼罩通用存储产品运维和研发需要的一站式智能存储平台。目前平台具备5万+数据库实例,4000+数据库&存储服务器,撑持vivo 在网总用户数达2.7亿(不含内销),数十款月活过亿的利用。 03. 全链路的3D展现平台,从3D编辑器到前台页面一条龙实现随着3D技术的一直倒退,电商平台能够将商品的3D模型间接放在详情页展现给用户,使用户能够更加直观的360无死角体验最新的产品。 然而H5的360展现多基于开源计划,存在调试繁琐,手机发热,内存占用多,成果没有达到预期等问题。针对这些问题咱们搭建了全链路的360度展现平台。 vivo用户经营前端专家苏宁带来了《前端可视化提效法宝-全链路360度展现平台》的主题分享。 (vivo用户经营前端专家苏宁) vivo 全链路的360度展现平台是一个从模型导入调试到上线全程无需研发参加的360演示编辑平台,反对主动格局转换和材质复用,相较于传统的开源展现计划领有更好的光影和材质的体现。 平台具备以下特点: 从模型输入到上线,研发全程无需染指在线360场景编辑,主动格局转换,已编辑的素材可复用更好的光影和材质的展现成果04. 沉迷式代码笼罩体验平台,为业务提供一站式代码覆盖率治理服务集成代码覆盖率平台作为品质把控环节下面一个重要的工具,在前端很少有成熟的计划或产品可供选择,究其原因是前端代码运行在各个终端,数据收集合并难度很大,为了解决这一问题,vivo 研发团队从零搭建了一个前端集成代码覆盖率平台 —— 马可平台。 vivo商城前端专家宋加超为大家分享了《前端品质晋升利器-马可代码覆盖率平台》从零到一搭建的技术历程。 (vivo商城前端专家宋加超) 马可平台是vivo首个前端集成代码覆盖率平台,反对实时报告,增量报告,并和Git 、音讯集成买通,实时渲染报告大屏。 05. vivo流量录制回放平台,为业务疾速、高质量迭代保驾护航随着业务零碎规模和复杂度一直进步,各种问题和挑战随之而来,其中之一就是业务迭代降级甚至重构的时候,人工回归测试将会受到极大挑战,流量回放就是解决这种简单场景下回归难、效率低问题。流量回放怎么实现?有哪些问题和挑战?能给咱们带来多少收益? vivo 平台产品零碎架构师刘延江通过《vivo流量录制回放平台实际》给大家提供一些借鉴和参考。 (vivo 平台产品零碎架构师 刘延江) vivo 业务品种多、流量大、零碎复杂度高、可靠性要求高。尤其是业务迭代降级甚至重构时,人工回归测试将会受到极大挑战。vivo 流量录制回放平台旨在解决上述简单场景下回归难、效率低问题。 具备以下技术劣势: 零应用老本无需编写测试用例、无需保护测试环境;接入简略,无需代码开发。 无侵入可插拔对利用零碎无侵入,随时启动、随时进行。 通用可扩大执行框架易于扩大,容器、非容器利用都能方便使用。 06. 定制化直播SDK和一站式直播解决方案vivo手机终端每日亿级日活,内容流量散发业务场景泛滥,在5G高速倒退和疫情的双重背景下,直播更是内容散发的一个重要散发形式,同时,公司外部相干的直播需要也各式各样。 vivo 直播中台架构师李国林在《vivo直播利用技术实际与摸索》中大家一起探讨如何疾速地赋能业务相干的直播能力,为相干开发者提供定制化直播SDK和一站式直播解决方案。 (vivo 直播中台架构师李国林) vivo直播平台旨在给公司外部多部门相干开发者提供定制化直播SDK和一站式直播解决方案,最终为用户带来更好的产品体验。具备以下的技术劣势: 反对的直播形式多样    目前反对泛娱乐,低时延互动反对,反对转播,多平台同时推流直播,办公网直播。 接入成本低,定制化直播SDK    提供直播根底SDK,直播业务性能模块化,可插拔,升高业务接入难度和接入门槛。 提供丰盛的开播工具,反对丰盛的直播输出源    反对PC端,OBS,手机端等多个终端设备开播,反对第三方转推直播,灵活性高。 2021 vivo开发者大会 · 互联网技术专场已收官。将来,vivo互联网技术将继续一直输入技术内容,与行业交换切磋。 ...

December 17, 2021 · 1 min · jiezi

关于架构设计:应用不停机发布的思考与初识-IDCF

利用公布,简略来说就是将已开发实现的零碎性能部署到生产环境,并可失常对用户提供服务。 传统的利用公布步骤个别采纳“三步曲”: 第一步:进行利用第二步:更新利用第三步:启动利用那你必定会问,从进行利用始终到启动利用期间,零碎性能是不是无奈失常应用? 没错。在利用公布过程中,可能会呈现页面白屏、拜访超时等各种异样,而且个别会继续很久,所以公布工夫基本上都集中在凌晨,考究点的可能就配上一句敌对提醒“零碎正在保护,请稍后拜访!”。 这种状况大部分都呈现在传统行业,起因可能是感觉没有必要,因为: 传统行业的业务个别都集中的日间,也就是说凌晨根本没有业务,或者非重要业务就算凌晨无奈应用这些性能,感觉也没关系,第二天再来就是了,客户又不会跑了但真的是这样吗?现在越来越多的传统行业,都在向互联网服务模式转型,其服务次要特点:“全天”不间断为客户提供“优质”的“线上”服务,拆分一下关键词 “全天”代表着任何工夫“优质”代表着客户体验“线上”代表着线上自助所以说,一个优质的客户服务势必会对服务可用性提出更高的要求,而传统的停机公布岂但会对客户造成应用影响,还会变向对企业造成非间接经济损失。 例如:客户体验降落导致的客户散失 仅此而已?非也!作为已经也同样是一名运维工程师的我来说,凌晨公布粗茶淡饭,还时不时来一次长达8小时的“短途之旅”,身材就间接被掏空,加上第二天还在“补血”中,还会被各种骚扰电话轰炸,这几乎就是一场噩梦。 由此可见,利用不停机公布的重要性,通过它能够帮忙咱们:一是在利用公布过程中线上服务继续可用,晋升服务可用性,二是可在白天或是任何工夫公布,晋升运维人员的机动性。 那么咱们须要怎么做,能力实现利用不停机公布呢,那接下来就让咱们进入正题。 part 1利用不停机公布,从字面上很好了解,就是利用公布过程中服务不中断。 但认真回忆一下,原先利用公布过程中,反正服务会中断,那就在利用公布实现后,通过网络屏蔽内部流量的形式,先进行外围或罕用性能的外部验证,在确保没有问题后,再解除网络屏蔽,并对外提供服务。 那当初呢?利用公布后间接对外?不须要进行外部或小流量验证?想必每个人的答案都有所不同。对此,能够对利用不停机公布能力,简略定义三个成熟度。 成熟度成熟度能力成熟度一级利用公布过程服务不中断成熟度二级利用公布过程服务不中断,单利用性能可先进行外部/小流量验证成熟度三级利用公布过程服务不中断,多利用(联动)性能可先进行外部/小流量验证注:不同的成熟度对技术能力的要求会有所不同,倡议通过逐渐演进的形式来晋升成熟度,并在演进过程中对不同的技术能力进行验证,从而不断完善。 有人会说蓝绿公布,或有人会说滚动公布,灰度公布就能够实现以上能力。但其实,这些答案并不精确,或者说并不全面,它们虽有交加,但无奈涵盖。 既然提到公布模式,那咱们先来简略比拟一下几种公布模式的优缺点。 蓝绿公布滚动公布灰度公布资源老本生产等比例资源投入,老本较高根本无需额定资源投入,老本较低根本无需额定资源投入,老本较低回滚时长两套环境间接切换,时长较短依据滚动速率决定,时长较长灰度局部实例回滚,时长适中技术难点资源齐全隔离,技术难点较低需制订滚动策略,技术难点适中引入流量路由能力,技术难点较高影响范畴影响所有用户,影响面较大影响所有用户,影响面较大影响大量用户,影响面较小注:大部分的技术文章里都会提到,可通过以上任何一种公布模式,做到用户无感知的利用公布,但在理论状况下,并不齐全足够,还须要通过一些辅助伎俩组合在一起能力实现。 联合以上公布模式的优缺点,如果你的组织在基础架构技术能力上曾经十分成熟,那么灰度公布肯定是最佳之选,但如果还处于初级阶段,那可能并不是,而蓝绿公布的资源投入较高,也不是一种十分好的抉择。 剩下的只有滚动公布,但滚动公布的公布策略会比较复杂,特地在容器环境下,同一利用多个服务实例的滚动策略还须要独自来实现。 所以,后期能够抉择一种折中的形式,即:独自搭建一套预发验证环境,利用架构需对齐生产环境,但容量方面能够最小化,个别一个利用至多2个服务实例。 这样,咱们就能够在对生产环境做利用公布前,当时对生产预验证环境进行利用公布,公布后仅对外部用户可见,验证通过后,再对生产环境采纳全量利用公布。 part 2利用不停机公布是一项综合性能力,当明确好一种公布模式后,就须要逐渐辨认会波及到哪些技术组件,以及明确技术组件在整个解决方案中所负责的职责边界,从而使它们可能互相协同工作。 如下列举了一些次要的技术组件: 技术组件职责边界利用治理平台次要负责管制整个利用公布流程,以及集成并调度不同的技术组件,协同实现利用不停机公布负载平衡(4层)次要负责服务申请的流量接入,可依据所辨认的流量特色,负载散发到不同的负载平衡(7层)负载平衡(7层)次要负责服务申请的流量路由,可依据所辨认的流量特色,路由散发到同一利用的不同实例容器/虚拟机平台次要负责容器/虚拟机资源管理,包含容器/虚拟机的创立、更新、销毁等域名解析零碎次要负责域名地址治理,包含域名的注册、更新、解析等,以及提供用户拜访利用或利用间拜访等寻址能力注册核心次要负责服务资源管理,包含服务的注册、更新、登记等,以及提供服务申请方发现服务提供方的能力在明确技术组件后,还须要对技术组件进行正当的架构布局,以适配不同的网络架构要求。 本次次要将对负载平衡进行特地阐明,一方面它是负责解决流量的核心技术组件,另一方面网络架构的不同,对它的部署架构影响可能也是最大的。 在传统的网络架构环境中,出于对网络安全或其余思考因素,通常会划分出多个不同的网络区域,网络区域间的拜访须要通过开设防火墙拜访策略才能够进行互通。 但这种形式必然会对应用服务间间接进行点对点拜访的形式造成影响,次要起因是虚拟机或容器环境中,利用的IP地址可能会发生变化,导致无奈提前明确防火墙拜访策略。 所以,个别都会思考应用负载平衡(代理模式)来解决这个问题。 倡议后期优先选择计划三,尽管链路较长会小幅影响性能,但此部署计划绝对较为成熟,一方面能够防止流量负载不均的问题,另一方面对于利用的革新老本也会绝对较低。 注:除网络区域隔离会遇到这种状况外,在某些网络架构中,不同的容器集群间也同样无法访问,所以也同样实用。 另外,除必要状况下,也应尽量减少跨网络区域或跨容器集群间的拜访,例如:优先容器集群内路由拜访,跨网络区域频繁交互的应用服务倡议迁徙至同一网络区域等。 负载平衡通常能够分为4层模式和7层模式,其中4层更关注流量负载,而7层更关注流量路由。 个别倡议将负载平衡(4层)和负载平衡(7层)进行分层部署,以充分发挥它们的强项。 倡议后期优先选择计划二,尽管无奈实现多容器集群间的全局流量调度,但对于以后可观测性和排障能力还不够健全的组织,通过物理隔离升高运维难度也是一种不错的抉择。 综上架构决策,最终的全局流量链路大抵如下,默认状况下,数据中心间流量隔离,即:单数据中心流量收敛,但可依据理论状况进行选择性放行。 part 3利用不停机公布的根底是服务路由,在这里,咱们能够把应用服务分为两种角色,服务申请方或服务提供方,而服务申请方通过不同的寻址形式,最终拜访到服务提供方的模式,能够称之为服务路由。 服务路由能够分为南北向和东西向。 南北向:服务申请方—>负载平衡(4层)—>负载平衡(7层)—>服务提供方东西向:服务申请方—>服务提供方不难发现,其次要区别就是,南北向服务申请方需借助负载平衡(代理模式)拜访服务提供方,而东西向服务申请方间接拜访服务提供方。 注:域名解析后果会缓存在本地,可缓解域名解析服务压力,但缓存工夫应依据不同的服务水平进行评估,否则将会缩短解析地址切换及故障转移时长。有条件的话倡议采纳httpdns来解决本地缓存问题。 但不论是南北向还是东西向,服务提供方在被拜访前,得让服务申请方感知或可见,常见的形式次要有两种,一种是不依赖注册核心的,而另一种则是依赖注册核心的。 如果以后利用架构上暂未应用微服务框架,即:不依赖注册核心,服务提供方能够手动或主动将服务在负载平衡上进行服务注册,服务申请方间接调用负载平衡。 如果以后利用架构上曾经应用微服务框架,即:依赖注册核心,服务提供方能够在注册核心上进行服务注册,服务申请方在注册核心进行服务发现,或者由负载平衡在注册核心进行服务发现,服务申请方间接调用负载平衡。 注:在多注册核心的场景下,可通过对立注册核心实现异构注册核心的服务发现 另外,咱们还会对同一利用的不同服务实例进行分组,分组策略可依据不同的条件来决定,例如:不同环境、不同版本等。 假如依据不同环境(预生产环境和生产环境)这个条件,能够把部署在预发验证环境的应用服务分为预发组,把部署在生产环境的应用服务分为线上组。 而后通过配置路由策略,下发到负载平衡或应用服务,就能够实现简略的服务路由了。 例如:不同分组间默认状况下不容许服务路由,但非凡场景下容许预发组服务路由至线上组。 注:若服务申请方是前端页面或客户端,也能够对前端流量也进行分组,例如:依据网络环境,将接入公司WI-FI网络环境的流量辨认成预发组 part 4利用不停机公布的外围是利用如何优雅进行,光有服务路由可能还不够,它尽管曾经解决了大部分问题,但离胜利还差最初一步。 后面咱们提到过利用公布要做到用户无感知,那如果利用公布过程中呈现瞬断或短时间中断,而用户又正好在应用,那算不算用户就感知到了呢? 不过,如果你感觉线上服务中断5分钟也能够忍耐,那我只能呵呵了。但我置信大部分具备互联网服务模式的头部公司,别说公布一次服务进行5分钟,可能就连5秒钟也无法忍受。 那咱们先来剖析一下为什么会呈现瞬断或短时间中断: 服务申请解决还没实现,利用就被强行进行(例如:运维必备大招之kill -9 过程),导致解决中的申请无奈失常返回服务提供方尽管已进行,但未告诉服务申请方,服务申请方依然持续拜访已进行的服务提供方,导致出现异常 针对以上两种状况,还须要分南北向和东西向进行探讨。 ...

November 23, 2021 · 1 min · jiezi

关于架构设计:系统架构图-云架构案例

记录一个在线制图工具,通过浏览器拜访网址:https://www.freedgo.com 点击在线制图,进入图形设计工具页面即可在线制图.它领有超过10w个在线制图模板,以下摘录精选优质的云架构模板: 提供给零碎架构设计人员参考: 案例大型公司网络拓扑图点击进入 政务大数据共享平台框架图点击进入 微服务部署与监控运维架构图点击进入 微服务Docker部署图点击进入 大数据平台架构点击进入 微软云架构点击进入 性能架构图点击进入 集群架构点击进入 金融(保理业务)SOA类零碎架构图SOA类零碎架构图.png "金融(保理业务)SOA类零碎架构图")点击进入SOA类零碎架构图.html "金融(保理业务)SOA类零碎架构图") 技术架构点击进入 医疗云平台零碎架构图点击进入 中台服务点击进入 时间轴横向点击进入

August 31, 2021 · 1 min · jiezi

关于架构设计:技术白皮书现代企业架构设计

【注】本文节译自:APIs and microservices: How to create modern enterprise architectures (bitpipe.com)    创立和倒退现代化的企业架构并非易事:这意味着突破繁多的、集中的零碎,转而应用 API 和微服务等工具反对更多云性能和自适应环境。在本指南中,咱们钻研了这些类型的云连贯架构的要害属性,并提供了有助于造就以 API 为核心的古代架构的实用倡议。接下来,咱们来探讨一下渐进式 Web 应用程序的呈现。    云应用程序被认为是一种易于部署、批改、扩大和计量的服务。这为古代企业架构和利用程序设计须如何倒退提供了线索。这就是为什么,以及将来是什么样子。    云服务自身建设在高度分布式的基础架构上,旨在对故障具备弹性,并且在不影响用户的状况下轻松挪动和调整大小。应用利用程序接口或 API 拜访和管制形象服务,将用户与实现细节齐全隔离。用户简直不晓得或不关怀服务在哪里运行或在什么类型的零碎上运行。这些外围属性坚固了云服务绝对于传统单体软件的泛滥劣势。    然而,这些雷同的个性能够而且应该利用于构建在一个或多个云上的企业应用程序。事实上,应用共享、按需、可伸缩的云服务的细粒度微服务设计是任何古代企业架构的虚构需要,这些架构冀望满足数字业务的需要,服务于数百万挪动客户、智能机器和连贯的传感器。 互联的数字企业    企业架构必须扭转的起因是高速连贯和数十年来计算能力指数级摩尔定律改良的交融。这使得便宜智能手机市场趋于饱和,公用事业规模的 IT 服务提供商得以创立云服务。这些技术独特推动了业务的巨大变化。无论您将其称为“新连贯经济学 ”(Gartner) 还是“无界企业 ”(AT&T Bell Labs),它都意味着企业以及随之而来的 IT 零碎和应用程序将越来越多地与人交互,还将以自动化业务流程和智能设施的模式与设施、虚构对象和其他软件交互。这是一种交互的爆炸式增长,Gartner 称之为数字网格。    这对企业架构的影响变得更像是大型云服务——想想谷歌、Facebook 和 AWS——而不是应用单体的、集中的零碎来解决一直增长和越来越不可预测的工作负载。事实上,随着双模 IT、DevOps 和麻利开发等概念的引入以放慢数字业务翻新的步调,其影响将远远超出企业架构,深刻到 IT 如何开展业务的外围。然而咱们这里的重点是体系结构框架。 解决“连通性”    然而,如果组织抉择施行它,演进的古代企业架构将相似于云。应用程序是否最终运行在 AWS 和 Azure 等共享的公共服务上;基于 Azure Stack、OpenStack 或 vCloud 等软件构建的公有基础设施;或者两者联合,架构必须假设共享的可用性,即便仅在组织外部,计量软件服务也能够立刻实例化、批改、扩大和互连。随着组织构建的数字服务看起来更像 Facebook 和 Uber,利用架构必须相似于云原生服务,而不是隔离在单个盒子上的单体零碎。    古代架构应具备以下要害属性: 将客户端接口与业务服务拆散:应用程序将采纳挪动和浏览器设计范式,客户端专门用于 UI 和后端服务的业务解决。人造分布式:后端应用程序将可能运行多个实例,提供弹性和可扩展性,同时反对继续、麻利开发流程所需的无中断更新。应用微服务:后端服务将针对特定性能而设计。它还能够在许多消费者之间共享,并能够轻松链接到特定应用程序的服务链中。将微服务视为用于构建任意简单性能的构件。服务能够在本人的 VM 中隔离运行,也能够作为共享操作系统实例的容器运行。它们还具备固有的自计量性能,以反对基于生产的计费、细粒度的性能跟踪和主动扩大。异步服务间通信:服务将应用音讯总线替换信息,而不是到网络套接字和文件共享的长久连贯。丰盛的服务组合:服务将公开元数据,容许它们作为宽泛服务组合的一部分进行治理、应用和编排,包含挪动和物联网利用后端、数据存储和剖析、消息传递、监控和平安。应用程序模板和设计模式库:    该组合是模板的根底,这些模板将服务组合在一起,以解决各种利用开发需要和设计模式,比方 Azure 提供的。开发人员库还包含规范数据模型,用于抉择适合的数据服务,如对象存储、NoSQL、SQL、大数据,例如 Hadoop 和 Spark;以及满足特定需要的数据转换管道。以 API 为核心:API 是次要的,通常也是惟一的服务接口。 客户端拜访通常是无状态的,但任何状态都通过音讯总线和后端数据服务解决,并且只有起码的客户端反对。自动化基础设施:服务链能够从用于部署、扩大、挪动和停用云实例的基础设施模板中实例化。 服务计量和仪表用于对资源应用状况收回警报、流动、谬误状态、并触发主动修复,例如缩放、重启和人工告诉。细粒度的安全性:对单个服务的拜访通过基于角色的访问控制列表进行管制,策略定义为应用程序模板的一部分。 用户身份和角色被集中管理,并可能与来自业务合作伙伴或公共在线服务的内部身份管理系统联结。 待办事项清单    领有正确的企业架构可能是将来数字业务打算成败的要害。 对于 CIO 和 IT 高管来说,这意味着架构应该是执行层的优先级,它是通过 IT、应用程序开发人员和业务线经理之间的密切协作开发。 对于 IT 经理和技术专业人士来说,企业架构的重要性须要一个由多学科专家组成的专门团队——例如 IT 经营、AppDev、DevOps、云经营和数据科学家等——他们的重点是开发、改良、更新和施行架构。    一直倒退的企业架构是一直倒退的 IT 的一部分,它必须专一于灵便的服务翻新、开发和施行,以响应动静的数字业务需要。因而,它可能会随同 IT 外部的构造和文化变动,例如双模式和 DevOps 组织以及继续交付流程。对于 IT 业余人员来说,这是最具挑战性但又最激动人心的时刻之一。 ...

August 19, 2021 · 1 min · jiezi

关于架构设计:vivo-全球商城优惠券系统架构设计与实践

一、业务背景优惠券是电商常见的营销伎俩,具备灵便的特点,既能够作为促销流动的载体,也是重要的引流入口。优惠券零碎是vivo商城营销模块中一个重要组成部分,早在15年vivo商城还是单体利用时,优惠券就是其中外围模块之一。随着商城的倒退及用户量的晋升,优惠券做了服务拆分,成立了独立的优惠券零碎,提供通用的优惠券服务。目前,优惠券零碎笼罩了优惠券的4个外围要点:创、发、用、计。 “创”指优惠券的创立,蕴含各种券规定和应用门槛的配置。“发”指优惠券的发放,优惠券零碎提供了多种发放优惠券的形式,满足针对不同人群的被动发放和被动发放。“用”指优惠券的应用,包含正向购买商品及反向退款后的优惠券回退。“计”指优惠券的统计,包含优惠券的发放数量、应用数量、应用商品等数据汇总。vivo商城优惠券零碎除了提供常见的优惠券促销玩法外,还以优惠券的模式作为其余一些流动或资产的载体,比方手机类商品的保值换新、内购福利、与内部广告商单干发放优惠券等。 以下为vivo商城优惠券局部场景的展现: 二、零碎架构及变迁优惠券最早和商城耦合在一个零碎中。随着vivo商城的一直倒退,营销流动力度加大,优惠券应用场景增多,优惠券零碎逐步开始“力不从心”,裸露了很多问题: 海量优惠券的发放,达到优惠券单库、单表存储瓶颈。与商城零碎的高耦合,间接影响了商城整站接口性能。优惠券的迭代更新受限于商城的版本安顿。针对多品类优惠券,技术层面没有积淀通用优惠券能力。为了解决以上问题,19年优惠券零碎进行了零碎独立,提供通用的优惠券服务,独立后的零碎架构如下: 优惠券零碎独立迁徙计划 如何将优惠券从商城零碎迁徙进去,并兼容已对接的业务方和历史数据,也是一大技术挑战。零碎迁徙有两种计划:停机迁徙和不停机迁徙。 咱们采纳的是不停机迁徙计划: 迁徙前,经营进行与优惠券相干的后盾操作,防止产生优惠券静态数据。静态数据:优惠券后盾生成的数据,与用户无关。 动态数据:与用户无关的优惠券数据,含用户支付的券、券和订单的关系数据等。 配置以后数据库开关为单写,即优惠券数据写入商城库(旧库)。优惠券零碎上线,通过脚本迁徙静态数据。迁完后,验证静态数据迁徙准确性。配置以后数据库开关为双写,即线上数据同时写入商城库和优惠券新库。此时服务提供的数据源仍旧是商城库。迁徙动态数据。迁完后,验证动态数据迁徙准确性。切换数据源,服务提供的数据源切换到新库。验证服务是否正确,呈现问题时,切换回商城数据源。敞开双写,优惠券零碎迁徙实现。迁徙后优惠券零碎申请拓扑图如下: 三、零碎设计3.1 优惠券分库分表随着优惠券发放量越来越大,单表曾经达到瓶颈。为了撑持业务的倒退,综合思考,对用户优惠券数据进行分库分表。 关键字:技术选型、分库分表因子 分库分表有成熟的开源计划,这里不做过多介绍。参考之前我的项目教训,采纳了公司中间件团队提供的自研框架。原理是引入自研的MyBatis的插件,依据自定义的路由策略计算不同的库表后缀,定位至相应的库表。 用户优惠券与用户id关联,并且用户id是贯通整个零碎的重要字段,因而应用用户id作为分库分表的路由因子。这样能够保障同一个用户路由至雷同的库表,既有利于数据的聚合,也不便用户数据的查问。 假如共分N个库M个表,分库分表的路由策略为: 库后缀databaseSuffix = hash(userId) / M %N 表后缀tableSuffix = hash(userId) % M 3.2 优惠券发放形式设计为满足各种不同场景的发券需要,优惠券零碎提供三种发券形式:对立领券接口、后盾定向发券、券码兑换发放。 3.2.1 对立领券接口保障领券校验的准确性 领券时,须要严格校验优惠券的各种属性是否满足:比方支付对象、各种限度条件等。其中,比拟要害的是库存和支付数量的校验。因为在高并发的状况下,需保障数量校验的准确性,不然很容易造成用户超领。 存在这样的场景:A用户间断发动两次支付券C的申请,券C限度每个用户支付一张。第一次申请通过了领券数量的校验,在用户优惠券未落库的状况下,如果不做限度,第二次申请也会通过领券数量的校验。这样A用户会胜利支付两张券C,造成超领。 为了解决这个问题,优惠券采纳的是分布式锁计划,分布式锁的实现依赖于Redis。在校验用户领券数量前先尝试获取分布式锁,优惠券发放胜利后开释锁,保障用户支付同一张券时不会呈现超领。下面这种场景,用户第一次申请胜利获取分布式锁后,直至第一次申请胜利开释已获取的分布式锁或超时开释,不然用户第二次申请会获取分布式锁失败,这样保障A用户只会胜利支付一张。 库存扣减 领券要进行库存扣减,常见库存扣减计划有两种: 计划一:数据库扣减。 扣减库存时,间接更新数据库中库存字段。 该计划的长处是简略便捷,查验库存时间接查库即可获取到实时库存。且有数据库事务保障,不必思考数据失落和不统一的问题。 毛病也很显著,次要有两点: 1)库存是数据库中的单个字段,在更新库存时,所有的申请须要期待行锁。一旦并发量大了,就会有很多申请阻塞在这里,导致申请超时,进而零碎雪崩。 2)频繁申请数据库,比拟耗时,且会大量占用数据库连贯资源。 计划二:基于redis实现库存扣减操作。 将库存放到缓存中,利用redis的incrby个性来扣减库存。 该计划的长处是冲破数据库的瓶颈,速度快,性能高。 毛病是零碎流程会比较复杂,而且须要思考缓存失落或宕机数据恢复的问题,容易造成库存数据不统一。 从优惠券零碎以后及可预感将来的流量峰值、零碎维护性、实用性上综合思考,优惠券零碎采纳了计划一的改良计划。改良计划是将单库存字段扩散成多库存字段,扩散数据库的行锁,缩小并发量大的状况数据库的行锁瓶颈。 库存数更新后,会将库存平均分配成M份,初始化更新到库存记录表中。用户领券,随机选取库存记录表中已调配的某一库存字段(共M个)进行更新,更新胜利即为库存扣减胜利。同时,定时工作会定期同步已支付的库存数。相比计划一,该计划冲破了数据库单行锁的瓶颈限度,且实现简略,不必思考数据失落和不统一的问题。 一键支付多张券 在对接的业务方的领券场景中,存在用户一键支付多张券的情景。因而对立领券接口须要反对用户一键领券,除了支付同一券模板的多张,也反对支付不同券模板的多张。一般来说,一键支付多张券指支付不同券模板的多张。在实现过程中,须要留神以下几点: 1)如何保障性能 支付多张券,如果每张券别离进行校验、库存扣减、入库,那么接口性能的瓶颈卡在券的数量上,数量越多,性能直线降落。那么在券数量多的状况下,怎么保障高性能呢?次要采取两个措施: a. 批量操作。 从发券流程来看,瓶颈在于券的入库。领券是实时的(异步的话,不能实时将券发到用户账户下,影响到用户的体验还有券的转化率),券越多,入库时与数据库的IO次数越多,性能越差。批量入库能够保障与数据库的IO的次数只有一次,不受券的数量影响。如上所述,用户优惠券数据做了分库分表,同一用户的优惠券资产保留在同一库表中,因而同一用户可实现批量入库。 b. 限度单次领券数量。 设置阀值,超出数量后,间接返回,保证系统在平安范畴内。 2)保障高并发状况下,用户不会超领 如果用户在商城发动申请,一键支付A/B/C/D四张券,同时流动零碎给用户发放券A,这两个领券申请是同时的。其中,券A限度了每个用户只能支付一张。依照前述采纳分布式锁保障校验的准确性,两次申请的分布式锁的key别离为: 用户id+A\_id+B\_id+C\_id+D\_id 用户id+A_id 这种状况下,两次申请的分布式锁并没有发挥作用,因为锁key是不同,数量校验仍旧存在谬误的可能性。为防止批量领券过程中用户超领景象的产生,在批量领券过程中,对散布锁的获取进行了革新。上例一键支付A/B/C/D四张券,须要批量获取4个分布式锁,锁key为: 用户id+A_id 用户id+B_id 用户id+C_id ...

August 9, 2021 · 1 min · jiezi

关于架构设计:极客大学架构实战营第0期网盘分享

download:极客大学-架构实战营|第0期网盘分享!/usr/bin/env python-- coding: utf-8 --import osimport subprocessimport shutil def main(): sdk_path = os.getenv('ANDROID_HOME')ndk_path = os.getenv('NDK_HOME')standalone_path = os.getenv('NDK_STANDALONE')directory = build_directory(sdk_path, args.output.filestem_str , native_shared_libs)# // Copy the additional native libs into the libs directory.for name, path in native_shared_libs.items(): shutil.copy( path, os.path.join( directory, "libs/", "armeabi/",name)# compile android_native_app_glue.ccmd = os.path.join( standalone_path , "bin/" , "arm-linux-androideabi-gcc ")arg1 = os.path.join( ndk_path, "sources/" , "android/" ,"native_app_glue/", "android_native_app_glue.c ")arg2 = " -c "arg3 = " -o "arg4 = directory + "android_native_app_glue.o"os.system(cmd + arg1 + arg2 + arg3 + arg4)"""calling gcc to link a shared object"""cmd = os.path.join(standalone_path , "bin/", "arm-linux-androideabi-gcc ")arg1 = passthrougharg2 = os.path.join( directory , "android_native_app_glue.o")arg3 = " -o " + os.path.join( directory ,"libs", "armeabi", "libmain.so")arg4 = " -shared"arg5 = " -Wl,-E"os.system(cmd + arg1 + arg2 + arg3 + arg4 + arg5 )"""call ant debug"""ant_command = "ant debug"os.system(ant_command )#copy apk file to required destshutil.copy( os.path.join( directory, "bin/", "rust-android-debug.apk"), output)def find_native_libs(args: &Args) -> HashMap<String, Path> { ...

August 3, 2021 · 2 min · jiezi

关于架构设计:谈谈代码降低复杂度从放弃三层架构到DDD入门

本文首发于泊浮目标简书:https://www.jianshu.com/u/204...版本日期备注1.02021.8.1文章首发1.前言最近我发现团队我的项目中的某个利用复杂度越来越高,具体表现为: 代码可读性较差:各个服务之间调用简单,流程不清晰批改局部业务导致大量测试用例失败,但很难疾速的寻找出这些测试用例失败的根因基于这些状况,我开始寻找升高复杂度的计划,于是就有了这篇再谈DDD的文章。 1.1 具体问题1.1.1 宏观角度从宏观来说,软件架构模式演进经验了三个阶段。 第一阶段是单机架构:采纳面向过程的设计办法,零碎包含客户端 UI 层和数据库两层,采纳 C/S 架构模式,整个零碎围绕数据库驱动设计和开发,并且总是从设计数据库和字段开始。第二阶段是集中式架构:采纳面向对象的设计办法,零碎包含业务接入层、业务逻辑层和数据库层,采纳经典的三层架构,也有局部利用采纳传统的 SOA 架构。这种架构容易使零碎变得臃肿,可扩展性和弹性伸缩性差。第三阶段是散布式微服务架构:随着微服务架构理念的提出,集中式架构正向散布式微服务架构演进。微服务架构能够很好地实现利用之间的解耦,解决单体利用扩展性和弹性伸缩能力有余的问题。咱们晓得,在单机和集中式架构时代,系统分析、设计和开发往往是独立、分阶段割裂进行的。比方,在零碎建设过程中,咱们常常会看到这样的情景:A 负责提出需要,B 负责需要剖析,C 负责零碎设计,D 负责代码实现,这样的流程很长,经手的人也很多,很容易导致信息失落。最初,就很容易导致需要、设计与代码实现的不统一,往往到了软件上线后,咱们才发现很多性能并不是本人想要的,或者做进去的性能跟本人提出的需要偏差太大。 而且在单机和集中式架构这两种模式下,软件无奈疾速响应需要和业务的迅速变动,最终错失倒退良机。此时,散布式微服务的呈现就有点恰逢其时的意思了。 下面这部分来自于极客工夫,这外面指出个别DDD是应用在微服务设计与拆分上,但我认为在单体利用中做模块的拆分也是能够并举荐的,这能够让你的模块在须要时能够即刻拆分进来——变成一个独立的微服务。相干能够参考【ZStack】4.过程内服务,这是一个开源,并施行于生产中很好的一个案例。 1.1.2 宏观角度这个问题很简略,service的代码必然会越堆越多,而且聚拢越来越多的业务。 2.DDD入门咱们先来看一张图: 从最外层开始——什么是畛域?大白话来说就是一系列问题的聚合。举个例子: 电商平台中的电商域,你要解决的一系列问题有: 用户认证挪动收付订单报价...能够看到,域是出现进去的是一系列的业务畛域问题。 在不同域中,同一个数据实体的形象状态往往是不同的。比方,Bookstore 利用中的书本,在销售畛域中关注的是价格,在仓储畛域中关注的是库存数量,在商品展现畛域中关注的是书籍的介绍信息。 2.1 上下文边界往里面,咱们应该看到的是限界上下文。其实这个翻译并不好,原文叫bounded context,叫做上下文边界更为得当。实质上来说,它定义了边界。再具体点,即:用来封装通用语言和畛域对象,提供上下文环境,保障在畛域之内的一些术语、业务相干对象等(通用语言)有一个确切的含意,没有二义性。 2.2 聚合接下来,咱们看到了聚合。聚合就是由业务和逻辑严密关联的实体和值对象组合而成的,聚合是数据批改和长久化的根本单元,每一个聚合对应一个仓储,实现数据的长久化。 聚合有一个聚合根和上下文边界,这个边界依据业务繁多职责和高内聚准则,定义了聚合外部应该蕴含哪些实体和值对象,而聚合之间的边界是松耦合的。依照这种形式设计进去的微服务很天然就是“高内聚、低耦合”的。 那聚合根是什么呢? 聚合根的次要目标是为了防止因为简单数据模型短少对立的业务规定管制,而导致聚合、实体之间数据不一致性的问题。 传统数据模型中的每一个实体都是对等的,如果任由实体进行无管制地调用和数据批改,很可能会导致实体之间数据逻辑的不统一。而如果采纳锁的形式则会减少软件的复杂度,也会升高零碎的性能。 如果把聚合比作组织,那聚合根就是这个组织的负责人。聚合根也称为根实体,它不仅是实体,还是聚合的管理者。 首先它作为实体自身,领有实体的属性和业务行为,实现本身的业务逻辑。 其次它作为聚合的管理者,在聚合外部负责协调实体和值对象依照固定的业务规定协同实现独特的业务逻辑。 最初在聚合之间,它还是聚合对外的接口人,以聚合根 ID 关联的形式承受内部工作和申请,在上下文内实现聚合之间的业务协同。也就是说,聚合之间通过聚合根 ID 关联援用,如果须要拜访其它聚合的实体,就要先拜访聚合根,再导航到聚合外部实体,内部对象不能间接拜访聚合内实体。 2.3 实体与值对象在 DDD 中有这样一类对象,它们领有惟一标识符,且标识符在历经各种状态变更后仍能保持一致。对这些对象而言,重要的不是其属性,而是其延续性和标识,对象的延续性和标识会逾越甚至超出软件的生命周期。咱们把这样的对象称为实体。其实很像数据库里自带不变id的一行行业务数据。 值对象绝对不是那么重要,因为它是用来形容实体的一组属性集。很多零碎中的实现会以json来实现,比方【ZStack】7.标签零碎。 为了不便了解,这边做个小结。实体和值对象的目标都是形象聚合若干属性以简化设计和沟通,有了这一层形象,咱们在应用人员实体时,不会产生歧义,在援用地址值对象时,不必列举其全副属性,在同一个限界上下文中,大幅升高误会、放大偏差,两者的区别如下: 两者都通过属性聚类造成,实体有唯一性,值对象没有。在本文案例的限界上下文中,人员有唯一性,一旦某个人员被零碎纳入治理,它就被赋予了在事件、流程和操作中被惟一辨认的能力,而值对象没有也不用具备唯一性。实体着重唯一性和延续性,不在意属性的变动,属性全变了,它还是原来那个它;值对象着重描述性,对属性的变动很敏感,属性变了,它就不是那个它了(意味着不可变性,它可能是从内部查问来的)。策略上的思考框架稳固不变,战术上的模型设计却灵便多变,实体和值对象也有可能随着零碎业务关注点的不同而更换地位。比方,如果换一个非凡的限界上下文,这个上下文更关注地址,而不那么关注与这个地址产生分割的人员,那么就应该把地址设计成实体,而把人员设计成值对象。3. DDD上手3.1 从三层模型到DDD这里先简略介绍一下三层模型到DDD对应的一个变动。 能够的看得出来,次要是对service进行了拆分。个别能够拆成三层: 应用服务层:多个畛域服务或内部应用服务进行封装、编排和组合,对外提供粗粒度的服务。应用服务次要实现服务组合和编排,是一段独立的业务逻辑。畛域服务层:由多个实体组合而成,一个办法可能会跨实体进行调用。在代码过于简单的时候,能够将每个畛域服务拆分为一个畛域服务类,而不是将所有畛域服务代码放到一个畛域服务类中。实体:是一个充血模型。同一个实体相干的逻辑都在实体类代码中实现。3.2 建模简介咱们能够用三步来划定畛域模型和微服务的边界。 第一步:在事件风暴中梳理业务过程中的用户操作、事件以及内部依赖关系等,依据这些因素梳理出畛域实体等畛域对象。第二步:依据畛域实体之间的业务关联性,将业务严密相干的实体进行组合造成聚合,同时确定聚合中的聚合根、值对象和实体。在第二章的图里,聚合之间的边界是第一层边界,它们在同一个微服务实例中运行,这个边界是逻辑边界,所以用虚线示意。第三步:依据业务及语义边界等因素,将一个或者多个聚合划定在一个限界上下文内,造成畛域模型。在下面的图里,限界上下文之间的边界是第二层边界,这一层边界可能就是将来微服务的边界,不同限界上下文内的畛域逻辑被隔离在不同的微服务实例中运行,物理上互相隔离,所以是物理边界,边界之间用实线来示意。3.3 实际:设计一个MiniStack为了便于大家了解,我在这里会设计一个很简略的Iaas平台,并在外面代入最根本的DDD概念。 3.3.1 产品愿景为了:企业的外部的开发者、运维人员他们的:计算、存储、网络资源管理这个:MiniStack是一个:公有云平台它能够:治理计算、存储、网络资源管理,帮用户简略疾速的创立虚拟机而不像:OpenStack咱们的产品:简略、强壮、智能串起来就是:为了满足企业的外部的开发者和运维人员,他们的硬件资源管理,咱们建设里这个MiniStack,它是一个公有云平台,它能够治理计算、存储、网络资源管理,帮用户简略疾速的创立虚拟机,而不像OpenStack,咱们的产品简略、强壮、弹性。 3.3.2 场景剖析因篇幅起因,咱们来聊个最典型的场景——创立虚拟机,以便理出相干的畛域模型。 在这里咱们须要留神,咱们要尽可能的梳理整个零碎产生的操作、命令、畛域工夫以及依赖变动等。 3.3.2.1 创立虚拟机用户登陆零碎:从数据库中对信息进行校验,实现登陆认证创立虚拟机:填写虚拟机名、集群、计算规格、L3网络以及镜像。如果需要的话(简略的体现),能够指定所在的物理机、以及网段。 VM服务须要提供创立虚拟机接口提交至MiniStack引擎,引起开始做相干调度: ...

August 2, 2021 · 1 min · jiezi

关于架构设计:架构之路数据库基础3-设计的等级规范化

上一课:【架构之路】数据库根底(2)- 函数依赖与Armstrong公理 定义:数据库设计的等级规范化,即设计满足适当范式的过程。对于范式:一共有六级范式。能够将其了解为环保规范或认证体系,像金字塔构造,即高层的实现中肯定合乎底层的准则。(即一系列的蕴含关系)。在理论中,依据关系模式(表构造)达到了第几范式来示意其规范化水平形式:通过拆分数据库表(解耦、重组)来实现降级。范式体系:第一范式:属性字段(列)的原子性——字段不可再分。第二范式:表的原子性——每一个非主属性齐全依赖主键(表只笼罩本人性能,留神齐全依赖的概念)。第三范式:打消非主属性对主键的传递依赖。字段冗余性。如:学号、姓名、年龄、学院名称、学院电话。姓名可通过学号推导进去。(留神传递依赖的概念)BC范式: 去掉耦合度——参考[三大范式和BC范式 - widy - 博客园 (cnblogs.com)](https://www.cnblogs.com/awidy...)

July 26, 2021 · 1 min · jiezi

关于架构设计:云基础设施架构设计

前言随着AWS、阿里云、Azure、腾讯云等私有云的蓬勃发展,越来越多的企业开始在思考上私有云了。 这些年做架构征询,发现很多传统的公司在基础设施上云的过程中没有明确的设计思路,只是一通购买云产品,而后应用云产品,认为这样就是上云了。 但其实,如果没有一个很好的云基础设施架构设计,会使后续的云应用变得难以保护,达不到预期的成果,同时成本上升。 这篇文章外面,我会分享一些过来我的项目中的私有云设计教训和思路,给大家提供一些基于微服务的场景下如何设计云基础设施架构的参考。其中这里的云指的是如阿里云,AWS的私有云。 为什么要上云上云的益处或价值在各大文章外面曾经说得十分多了。 我这里也搪塞的列举几个益处和价值吧。 降低成本可伸缩性业余的运维速度降低成本 降低成本次要是升高了两类老本。 公司不再须要招聘业余的运维人员专门负责保护服务器。(大型公司除外,他们通常须要大量的运维人员对立保护全公司的云资产或者自建云计算)公司不再须要专门的人员来针对运维开发各类工具,现在常见的云计算平台都蕴含丰盛的性能,以及欠缺的售后体系。可伸缩性 可伸缩是传统的服务器无奈做到的,这也正是现在云计算越来越火的一个很大的起因。 咱们能够依据业务的须要,扩大服务性能,不仅如此,而且还能做到放大服务性能,以节约老本。 业余的运维 上云之后不是没有运维了,而是把运维交给了云计算平台的业余的人来做了。而你只须要关怀如何基于这些云基础设施构建本人的产品了。 速度 速度是指各方面的速度都晋升了。比方,你只须要花1分钟工夫就能创立一台新的服务器,你只须要花1分钟工夫就能扩容某个服务。因为缩小了各种搭建配置工夫,开发工夫因而也缩短了。缩短了试验和测试的工夫,更快的为客户提供可用性。 云基础设施架构成熟度评估那么上云之后咱们如何晓得咱们的云基础设施架构是足够优良的呢? 这里就须要有一套云基础设施架构成熟度评估模型。 我依据这些年的架构征询工作,联合多个我的项目总结了这套云基础设施架构成熟度评估模型。它 次要分为8个模型,5种等级。 这8个模型是: 可伸缩性 - 云基础设施能依据业务须要自在伸缩可复制性 - 云基础设施能依据业务须要疾速复制可恢复性 - 云基础设施挂了之后能主动或疾速复原可用性 - 云基础设施的设计能保障服务的高可用性安全性 - 云基础设施的设计能有十分高的平安设计可量化治理 - 云基础设施应该能够被量化治理以优化老本可维护性 - 云基础设施应该具备更简略的可维护性可组合性 - **云基础设施会依据业务须要组合应用这5种等级是: 原始级 - 齐全没有应用云基础设施根底级 - 尝试了一些根本的云基础设施标准级 - 所有基础设施都上云了成熟级 - 所有基础设施都上云了并且把握云基础设施架构的最佳实际当先级 - 自建云计算联合下面的模型,咱们就能够得出如下的打分。 基于这个打分,咱们就能够失去如下的评估图。 那么接下来,咱们就把这个架构设计开展来说一说。 次要说一说VPC设计,访问控制设计,平安设计和数据库设计。 VPC设计VPC全称是Virtual Private Cloud,是云上的一个逻辑隔离的专有网络。 应用VPC次要是为了平安隔离,把不同的环境隔离开来。一是防止环境污染,二是保障安全性。 因而,如下图所示,通常一个企业都会设计以下几个VPC环境: 产品环境测试环境开发环境UAT环境产品环境是咱们线上所有产品运行的VPC环境,只有用户能接触到的一个环境。 测试环境是做测试用的,也是大部分公司开发人员和测试人员能接触的一个环境。 开发环境则是日常工作所在的环境,它通常与办公网络是连通的,这里会放咱们的git,pipeline,镜像仓库,制品库等。 UAT环境通常是给客户做验证的,比方上线前,须要让客户去验证是否合乎预期了,这个环境之所以不能应用测试环境是因为通常客户须要导入一些实在数据做测试,须要保障UAT环境的洁净。 另外,如果有多地区部署零碎的要求,就须要应用多个VPC,因为VPC是地区级别的资源,是不能跨地区的。 访问控制设计咱们的云资源不是对所有人凋谢的,特地是对于产品环境的访问控制应该尤其严格,一是避免外部人的误操作,二是避免黑客的入侵。 但我在很多客户那里都遇到过,他们没有任何访问控制设计,所有的开发人员都共用一个或几个账号。这是十分危险的应用形式,不利于治理,也有诸多危险。 当初的专用云都有访问控制性能,通常叫做Resource Access Management。 ...

June 7, 2021 · 1 min · jiezi

关于架构设计:请立刻停止使用-JWT-进行会话管理

引言近来发现,不少 WEB 利用零碎应用 JWT 进行会话治理,原因居然是为了防止服务端存储会话,或者谋求可自主管制,实不知应用 JWT 进行会话治理有微小的安全隐患! HTTP 会话治理先说说 HTPP 协定,家喻户晓, HTTP 协定的特点就是一问一答(一次申请一次响应)。那么基于 HTTP 协定,做个购物网站,要实现用户登录,增加商品到购物车,最终买单的性能。为了实现以上性能,辨认出一系列操作都是同一个用户,最为简略的形式就是每次操作浏览器都发送账户和明码,这样服务端晓得是哪个用户增加商品到购物车和最终买单。这样看起来很简陋,而且在每次申请中携带账户和明码将大大增加泄露危险。 为了缩小账户明码在申请中携带的次数,咱们引入一个 session-id 的货色。在你携带账户明码登录购物网站(第一次申请),服务端验证通过后返回一个 session-id 。尔后你增加商品到购物车也好,最终下单也好,反正后续的每次申请都携带好这个 session-id 即可。为什么携带 session-id 就能够辨认出这是哪个客户的操作呢?因为服务端将客户的账户信息和本次会话发送给客户端的 session-id 关联了起来,那么这个session-id 和账户的关联信息就是 session-data。 在以上例子里,session-data 是存储在服务端的。其实,session-data 也能够存储到客户端。那么依据 session-data 存储的地位不同,分为 Server Side Session 和 Client Side Session 两种模式。 Server Side SessionServer Side Session 模式是最为常见的,如后面购物网站的例子。在此模式中,客户端(浏览器)将 session-id 存储到 本地 cookies 中。其典型实现如下图所示:上图中 User A 是个曾经建设会话的老用户,他的 Cookies 中存储了 Session_id,值为“AA01”,在申请中携带这个 Session_id,服务端收到后通过 Session_id 查问到 Session Database 中对应的数据,并在程序中应用。New User是个刚开始会话的新用户,他的 Cookies 中还没有 Session_id,于是服务端生成一个新的 session_id 返回给他,并在返回中应用401状态码,告知他重定向到登录页,进行登录。后续如果这个 New User 登录胜利,服务端将会把他的身份信息存储到 Session Table中,并与会话初生成的 session_id 关联,这样后续的申请就如同 User A 这个老用户。 ...

May 14, 2021 · 3 min · jiezi

关于springboot:业务团队如何统一架构设计风格

简介: 首次上线利用,面对业务框架搭建你是否曾感到无从下手?保护线上利用,面对大量历史包袱你是否正避坑不迭深陷泥潭?为何同样是业务利用,不同人的设计格调千差万别?为何最后的设计通过多个迭代后总是面目全非?新人来到团队,怎样才能疾速理解业务,不被大量技术细节折磨?如果你也有这些困扰,心愿本文能提供些许帮忙。 作者 | 木沉起源 | 阿里技术公众号 首次上线利用,面对业务框架搭建你是否曾感到无从下手?保护线上利用,面对大量历史包袱你是否正避坑不迭深陷泥潭?为何同样是业务利用,不同人的设计格调千差万别?为何最后的设计通过多个迭代后总是面目全非?新人来到团队,怎样才能疾速理解业务,不被大量技术细节折磨?如果你也有这些困扰,心愿本文能提供些许帮忙。 一 初衷 1 细节割裂架构 业界的成熟利用框架有很多。无论是SpringMVC/SpringBoot还是SofaBoot,都对工程构造给出了明确的标准约定,职责边界看似十分清晰。但在实践中,再简略的业务利用都防止不了业务逻辑扩散各处,突破module边界呈现隐式耦合的景象。扩散的业务细节必然导致利用架构的割裂,如果没有继续的重构调整,最终总会变得复杂臃肿(当然,是继续有新需要的前提下),老人缄默新人流泪,只能依附天降猛男重做2.0。究其原因,集体认为次要在于: 框架灵活性过高:利用框架给出的是工程标准,而非业务设计规范,为开发者保留了十分大的灵活性,一个业务性能能够有很多种实现形式。 架构约束力有余:业务架构的搭建和保护是在不同时段由不同人别离投入的后果,设计思维的不同,自我要求的不同,我的项目进度压力的不同,都会对利用的现状产生影响。 若以法律和道德的关系做类比,通用框架束缚了技术编码的“法律”底线,而设计准则就是开发人员对本身的“道德”要求。在简略的业务场景下,满足需要是第一优先级,设计能力的诉求并不突出。但在多方合作的业务团队下(真实情况大多如此),没有对立的“道德规范”,将很难造成合力实现简单我的项目。《Java开发手册》(阿里巴巴Java开发规约)在推动编码标准的路线上迈出了很大一步,极大晋升了工程人员的业余素质,大大提高了“道德共识”。那么在业务架构设计的畛域里,是否至多能在某个问题域内,也建设一套面向业务研发同学的“设计规约”。 2 技术积淀散失 另一方面,进入阿里巴巴后,本身研发经验尽管并不多,但接触过不少优良设计。这些产出无论是否最优计划,都体现出了技术同学对优良设计的美好愿望和弱小落地能力,也的确在肯定的历史期间内高效地保障了业务倒退。然而,令我困惑的是,只管每个业务我的项目和业务产品都能积淀出一些可复用的组件或框架,参加研发的同学也能总结出一套面向未来需要的设计准则和实践经验,但这些财产始终难以保护和传承。可能的起因有(对前端/测试/数据/平台等研发经验不太理解,这里仅针对一线业务研发): 保持设计成绩而非设计准则:有成功经验的研发同学,偏向于用已经的架构设计来套用当下的业务场景。这种思路自身没有对错,但如果钉不配锤,往往会在短期内引入大量额定老本,反倒丢失了本来的设计劣势。面对具体问题域,只有保持一贯的设计准则,在需要剖析的过程中联合诸多因素进行动静衡量,能力打造真正合乎当下和将来需要的设计。 喜爱造新轮子而非继续重构:研发同学的设计准则和代码洁癖可能是一种“玄学”,对前人代码的不待见倒是更具确定性的常态,其实这不难理解。即便都是DDD流派,计划沟通时也未必相互认可;即便通过退让对架构设计达成统一,编码实现的格调也是各领风骚。了解前人的设计思路和代码嗜好更重要,还是按时实现业务需要更重要?按本人善于的设计格调重写更简略,还是在别人的“过期”设计上继续重构优化更简略? 靠文档传承而非工具化复用:对新人来说,文档里的再多倡议和疾速上手指南,都比不上一个开箱即用的工程DEMO;在成熟利用上继续开发的人,不会因为历史文档上大写的注意事项就抵制住长期代码换取早点上班的事实引诱,除非利用工程中有编译/部署失败的强制束缚让你不得不放弃。 相比于短少“设计规约”导致的低效合作,曾经积淀的“规约原型”被轻易摈弃更加令人惋惜。业务研发的日常工作,实质上是拆解问题域的复杂性,用分层解耦/工具化/平台化/业务形象的多种思路将子问题一一击破。如果局部子问题已被很好解决,为何不站在前人肩上?放弃造不造新“轮子”的纠结心态吧,或者咱们更须要搭“积木”的心态。 二 思路:业务架构设计规约 联合蚂蚁链-利用技术团队近年来的技术实际,咱们试图从本身需要登程,搭建一套或者能满足更多业务场景的业务架构设计规约。重点阐明下,本文是从无限的问题域登程提出的解决思路,不奢求成为通用解决方案。如果其余业务线也有相似的痛点,心愿能有些许借鉴。 规范:对立业务设计框架,用标准化架构简化技术细节积淀:从业务场景中继续积淀“积木”重构:继续重构“积木”,缩小反复建设集成:基于业务服务编排引擎疾速集成 1 规范——缩小细节 现实状况下,业务技术只需关注领域建模,但事实中却不得不思考更多通用的技术细节。以供应链金融场景下简化版的应收账款发行流程为例,须要思考的有: 领域建模:应收账款畛域模型及其行为的设计流程编排:流程模型的设计及发行流程的状态机设计数据转换:畛域模型<->数据模型及流程模型<->数据模型的双向转换并发管制:业务锁机制的设计业务幂等:流程中各业务环节的幂等管制异样解决:异样捕获,错误码约定监控报警:摘要日志,异样日志,边界日志 其余 在以上未齐全列举的几项中,除了“领域建模”以外,根本都是与具体业务无关,但对于一个稳固牢靠的业务利用不可缺失的局部。如果能建设一套标准化的框架计划,用对立的标准解决掉业务无关的大量细节,是否就能让业务技术同学真正的专一于“领域建模”? 2 积淀——能力复用 积淀和复用是技术群最常出圈的几个词,可见认同度之高。能力复用不局限于模式和粒度,可能切实升高技术老本,进步业务扩展性,就是不错的积淀,可作为“积木”供后续应用。以蚂蚁链利用技术团队场景为例,近年来积淀的能力包含但不局限于: 技术类 工程标准系列:束缚编码标准和边界接口定义格调,日志打印,异样解决,仓储行为,状态机等等 读写拆散机制:屏蔽交易类需要与查问类需要对数据模型的设计抵触,升高设计复杂性,晋升查问性能和灵活性业务类 网银核身:进步网银核身签名在不同业务流程中的扩展性合约上链:进步智能合约对接在不同业务流程中的扩展性平台类 配置核心:灵便定义和治理业务流程须要的各类配置项产品核心:平台性能打包和隔离,实现业务流程的全局视图 3 重构——继续优化 积淀来源于业务需要,却经常落后于新需要。对于设计者以外的人来说,保护别人的“积木”经常会踩到不少坑,反倒不如本人重写。这也是为何每个团队都在说积淀,但可能横向复用,甚至在同一个团队内继续复用的能力都少之又少。尽管这个景象没有完满解法,但集体倡议采取以踊跃的心态对待这些“积木”: 剖析历史背景,理解“积木”呈现的技术和业务背景明确该能力可能解决的问题,和不实用的场景剖析当下业务需要,是否能够重构该能力后间接复用与创作者沟通,评估重构落地计划 这里没有强调重构复用和重写这两种计划的ROI比照,是因为集体看来,即便前者老本更高,重构的过程对集体技术成长和团队文化对立都是无利的。绝对于一直颠覆和创造新“积木”,继续优化的过程,是对本人和别人教训的一直回顾和反思,看清历史的坑,能力防止新危险的呈现。 4 集成——灵便搭建 规范可能落地,除了有足够趁手的“积木”库外,更重要的一点,是要有灵便便捷的“粘合剂”,以实现业务性能的疾速搭建和灵便调整。在供应链金融的场景下,业务需要次要体现为各种各样的业务流程,比方发行/转让/清分等等。为了简化“积木”搭建,灵便复用底层能力,咱们基于以下指标,设计了面向业务的服务编排引擎: 标准化:遵循设计规约,将业务无关的通用技术细节屏蔽插件化:对“积木”敌对,可继续积淀和复用新能力业务化:面向业务,有业务形容能力的流程编排配置化:通过配置即可实现流程编排,最好能做到可视化配置 5 产品——业务大图 “积木”+“粘合”可能满足技术落地的低成本高扩大,但从业务视角,还须要一个全局大图来描述业务线的全域能力和性能流程。本文中暂不波及。 三 实际——业务架构规范计划 如前所说,只靠文档造成的共识,对技术没有足够的束缚,极难维持。因而,咱们基于上述规约的各项准则,搭建了一套标准化的业务架构设计计划,通过组件化工具化的形式束缚业务利用,造成团队共识。一个规范的业务利用架构如下: 1 组件——标准技术细节 通过组件化约定,束缚通用技术细节的行为,包含但不局限于: 交易模型 形容业务流程的外围交易模型,用于管控状态推动,维持与业务模型的关联。 仓储行为 数据长久层的通用行为,包含锁定查问/插入/更新/一般查问等。 事务模板 定义事务边界,确保模版内业务逻辑的事务一致性;反对幂等能力。 通用业务模板 定义业务逻辑边界,无事务性保障,但蕴含了异样解决/日志埋点等通用能力。 ...

April 22, 2021 · 1 min · jiezi

关于微服务:事务消息应用场景实现原理与项目实战附全部源码

简介:从利用场景登程,给出解决方案与实现原理,并提供整套工业级实现源码。 作者:丁威 活动中心场景介绍 在电商零碎上线初期,往往会进行一些“拉新”流动,例如流动部门提出新用户注册送积分、送优惠券流动。 基于分布式、微服务的设计理念,通常的架构设计(子系统交互)如下图所示: 其外围零碎介绍如下: • 账户核心提供用户登录、用户注册等服务,一个新用户注册时,向 MQ 服务器中的 USER_REGISTER 主题发送一条音讯,主流程完结,与送积分,送优惠券等过程解耦。• 优惠券(券零碎)提供发放优惠券、应用优惠券等与券相干的根底服务。• 积分核心提供积分相干的服务,例如积分赠送、积分生产、积分查问等根底服务。• 送积分服务(消费者)订阅 MQ,依照规定决定是否须要赠送积分,如果须要则调用积分相干的根底接口,实现积分的发放。• 送优惠券(消费者)订阅 MQ,依照规定决定是否须要赠送优惠券,如果须要则调用券零碎相干的根底接口,实现优惠券的发放。下面的架构设计十分优雅,但并不是无懈可击,如果新用户注册胜利,但音讯发送到 MQ 失败,或者音讯胜利发送到 MQ,但发送完 MQ 后零碎出现异常导致用户注册失败又该如何呢?下面的问题其实就是典型的分布式事务问题:即如何保障用户注册(数据库操作)与 MQ 音讯发送这两个分布式操作的一致性。RocketMQ 事务音讯闪亮退场。 事务音讯实现原理 一言以蔽之:RocketMQ 事务音讯要解决的问题是音讯发送与业务的一致性,其解决思路:二阶段提交与事务状态回查,其具体实现流程如下图所示: 其外围设计理念:• 应用程序开启一个数据库事务,进行数据库操作,并且在事务中发送一条 PREPARE 音讯,PREPARE 音讯发送胜利后告诉应用程序记录本地事务状态,而后提交本地事务。• RocketMQ 在收到类型为 PREPARE 的音讯时,首先备份音讯的原主题与原音讯生产队列,而后将音讯存储在主题为 RMQ_SYS_TRANS_HALF_TOPIC 的音讯队列中,故 PREPARE 的音讯是不会被客户端生产的。• Broker 音讯服务器开启一个定时工作解决 RMQ_SYS_TRANS_HALF_TOPIC 中的音讯,会每隔指定工夫向音讯发送者发动事务状态查问申请 ,询问音讯发送者客户端本地事务是否胜利,而后依据回查状态决定是提交还是回滚,即对处于 PREPARE 状态进行提交或回滚操作。• 发送者如果明确得悉事务胜利,则能够返回 COMMIT,服务端会提交该条音讯,具体操作是恢复原音讯的主题与队列,从新发送到 Broker,生产端感知后生产。• 发送者如果无奈明确得悉事务状态,则返回 UNOWN,此时服务端会期待肯定工夫后再次向发送者询问,默认询问 15 次。• 发送者如果十分明确得悉事务失败,则能够返回 ROLLBACK。在具体实际中,音讯发送者在无奈获取事务状态时不要果断的返回 ROLLBACK,而是要返回 UNOWN,让服务端定时重试回查,阐明如下: 在将 PREPARE 音讯发送到 Broker 后,服务端发动事务查问时本地事务可能还未提交,为了防止有效的事务回查机制,RocketMQ 通常至多在收到 PREPARE 音讯 6s 后才会发动第一次事务回查,可通过 transactionTimeOut 配置。故客户端在实现事务回查时无奈证实事务状态时不应该返回 ROLLBACK,而是返回 UNOWN。 ...

April 16, 2021 · 1 min · jiezi

关于微服务:微服务与-DevOps实践技术架构与组织架构-IDCF

一、概述首先,咱们来看看微服务的定义:微服务是一个界线明确、高度封装、松耦合、能够独立部署和独立扩大的服务利用组件。如图所示。微服务架构基于 SOA 和畛域驱动设计(DDD)构建,其次要目标蕴含以下三个方面:开发的敏捷性、部署的便利性及明确的可扩展性。 其次,微服务和传统的 SOA 有什么异同: 从设计原则上来讲,微服务架构遵循 SOA 的设计准则。小的、可重用的服务并不一定是微服务,微服务架构强调麻利、独立开发、独立部署、独立扩大,重用在某种程度上会影响敏捷性。微服务架构为了实现其麻利个性,在 SOA 架构束缚的根底之上又增加了新的束缚,微服务之间不能相互依赖,因而要求微服务可能独立部署、独立扩大,微服务之间的依赖越少越好。 微服务中的一个服务只实现一个独立的个性。 对于微服务而言,尽量不要为内部利用公布代码级 API,能够通过服务调用或者事件解决依赖问题。 微服务中的服务之间最好通过异步事件交互。 微服务中的每个服务都领有本人独立的数据。 另外,微服务架构的长处有很多: 敏捷性:微服务不仅能够进步开发的敏捷性,还能够减速继续部署(CD),从而使开发团队可能尽快部署新的性能。缩小危险:因为每个微服务都是比拟玲珑并且独立部署的,因而能够缩小每次部署的危险。适宜分布式开发:微服务之间依赖水平低,因而能够更加灵便地独立开发。技术灵活性:微服务之间的耦合水平低,因而技术团队能够依据不同的特点抉择最合适的技术栈,例如利用不同的编程语言解决不同的畛域问题。可扩展性:一个利用有许多微服务组成,每个微服务能够依据须要独立扩大,而无须对整个利用做整体扩大。鉴于以上长处,咱们来看一下微服务的实质。微服务在实质上是一种服务实现模式,微服务能够实现一个利用中独立的业务性能,而不是整个利用或者模块,因而,微服务其实是将单体利用的复杂性从程序外部转移到了服务组件之间,这就对微服务形象的粒度有一个比拟高的衡量要求。 对于微服务的粒度,大家探讨的最多,这也是实际过程中常常遇到的令人纠结的问题。实际上,如果形象粒度太细,就须要大量的服务编排来满足业务场景,而大量应用服务编排就可能会导致微服务退回到 SOA 模式(服务编排是相似 BPM 或者 ESB 的零碎);而如果服务粒度太粗,则不利于开发的敏捷性和部署的便利性。 微服务的次要目标是实现麻利,微服务架构的次要构建形式是采纳畛域驱动设计,而畛域驱动设计次要包含如下五个概念: Bounded ContextContext MapEvent SourcingCQRSBASE微服务的粒度并没有一个明确的界线,也就是说“尺寸”是绝对的。通常,微服务的粒度和对敏捷性的要求密切相关,往往粒度越细其麻利度也越高,然而并不是所有的利用对麻利的要求都那么高,也就是说在微服务的设计和实现过程中,对于粒度的大小能够做适当的调整。对于想要采纳微服务架构的团队,首先要思考如下几个前提条件: 现有软件架构是否曾经服务化或者依照零碎性能做了模块化切分。团队的麻利成熟度如何,是否有足够的 DevOps 教训。开发团队是否有足够的架构设计能力来适应采纳微服务所带来的设计办法、模式以及技术架构上的微小差别。DBA 团队是否有能力和志愿制订新的数据管理模式——将数据管理的形式由原来的集中管理转变为去中心化治理。运维团队是否有足够的能力为微服务提供全新的环境管理工具、部署工具和监控工具。综上所述,咱们倡议微服务的演进线路如图所示。 从单体利用或者传统分层架构的利用向服务化过渡,通过封装和组合等形式提供对外公布接口的能力,从而晋升利用的可拜访性。通过重构将 Domain-Level(畛域层面)的功能模块转变为能够独立部署的服务,从而晋升整个利用的敏捷性。咱们将这种可独立部署的服务称为 MiniService,其粒度比微服务粗,因此形象难度比拟低,然而也能在肯定水平上取得微服务所带来的敏捷性晋升的益处,然而对 DevOps 的基础设施等要求没有微服务高,因而倡议没有微服务教训的团队能够从 MiniService 开始尝试。通过 Feature-Level(个性层面)的形象,依据繁多职责准则将 MiniService 拆分成微服务,从而取得更高的扩展性和敏捷性。二、融数数据微服务的架构选型咱们在构建微服务体系的过程中,经验了技术选型、技术验证、引入开源实现及齐全自研等一系列的过程,其中也走过不少弯路,当初回想起来,感触良多,在这里跟大家分享一下,心愿可能有所帮忙。对于技术选型,咱们不心愿反复创造轮子,也不心愿齐全受制于开源的实现,所以在技术选型时遵循如下准则: 考查社区热度、架构成熟度、学习曲线、可维护性,如图所示。 尽量关照现有服务的开发方式和框架的应用习惯,不对目前的研发团队造成太大的冲击。可能给程序员提供何种能力?咱们的冀望是: 不便开发不便迁徙多协定反对多语言反对不便监控不便运维咱们比拟了可能用到的一些开源服务框架,并对它们的性能点进行了评估,如图所示。 因为之前团队采纳 RESTEasy + Spring Boot 的形式实现服务,不心愿对现有的零碎和产品产生太大的影响,因而决定服务框架首先须要反对 REST 服务,又因为 Netflix 提供了比拟全面的解决方案,并且 Spring Cloud 在遵循 cloud-native 准则的根底上对 Netflix 进行了比拟敌对的封装,因而初步的论断是能够基于 Spring Cloud 进行二次开发,封装咱们本人的微服务框架。 ...

April 7, 2021 · 2 min · jiezi

关于架构设计:架构设计策略之寻找够用的设计

要想开发胜利的软件,开发者必须依据设计策略去做最优的解决方案。只管有时候,比较简单的问题,毋庸思考太多,“梭哈”就完了,既疾速又无效。然而,随着业务的变动和零碎复杂性的减少,设计上的问题始终会呈现的,就像不标准的代码会带来很多隐患和技术债权,这些都是要还的。凡事预则立,没有架构设计策略的开发,很容易陷入谬误凌乱中,开发工作难以进行上来。因而,要学会使用思维模式(见《架构设计思维模式》)和思维积淀循环(见《架构设计思维模式实际流程》),去制订最优的设计策略。 找到够用的设计最优的设计策略不是谋求让架构设计达到完满的状态,应该分明这是不可能,因为在事实开发中会有工夫、资金老本、技术、常识、业务变动等限度导致架构设计不可能做到完满。 因而,咱们的指标是找到一个够用的设计,这个架构设计能适应以后企业环境(满足利益相干方的需要等)和灵便应答业务变动。 寻找够用的架构设计,能够参考如下策略: 疾速验证解决方案:解决方案验证的速度越快,就越快找到适合的架构设计,我的项目就能越快受害。设法升高危险:架构设计失败是很重大的问题,必须时刻思考可能呈现的危险,并依据危险来进行设计。致力简化问题:使用分治、常识和形象等办法,去了解和简化复杂性一直增长的问题。疾速迭代学习:使用思维积淀循环疾速学习,疾速积攒常识,就能疾速实现目标。同时思考问题的解法和证法:能解答问题的设计方案可能有很多,但能证实实用无效的设计方案,可能寥寥无几。因而,须要同时思考问题的解法和证法,以便高效地找到够用的设计。以上策略可能了解起来有点难度,上面就集体了解再次一一阐明下。 疾速验证解决方案要想能疾速验证解决方案,必须要建设一套疾速验证解决方案的机制。尽管架构师不是什么技术先知,但能够使用以下机制来疾速验证解决方案:能够先“夸夸其谈”(头脑风暴、参考过来教训、决策矩阵等)来疾速确定待验证的解决方案,再以“胜兵先胜后求战”的思维来优先验证最可能无效的解决方案,最初再使用各种试验的办法去验证解决方案。 设法升高危险这里要援用下工程学历史学家Henry Petroski的话: 失败的概念是设计过程的外围,正所谓“失败乃胜利之母”,通过打消失败,可达致胜利之设计。 做架构设计是肯定要设法打消失败的危险,但现在“伟人的肩膀”(各种打消危险的设计技术)切实太多了,很容易陷入了抉择艰难的泥沼里。 因而,这里的“设法升高危险”应该是依据危险驱动的,即思考危险大小和解决的优先级、抉择适合的技术去口头、评估升高危险的水平再决定下一步设计,这里其实就是使用思维积淀循环的思考、口头、查看步骤。 致力简化问题简化问题不单单是为了应答日益增长的复杂性和规模,还有开发成本和保护老本等问题。如果把问题想得过于简单也是不行的,那就可能适度设计了。为什么会这样?往往是因为咱们对问题了解的不够深刻,这时候应该使用思维积淀循环去了解问题,积攒常识,再使用循环去把问题形象或者分而治之。 疾速迭代学习疾速迭代学习,这也是麻利开发的准则。如果一次迭代学习的工夫过长,首先很可能满足不了业务的时效性,其次工夫长无奈灵便应答变动,最初可能会导致保护的代价很高。因为个别周期长的迭代,实现的性能多,依赖多,复杂度高,一旦呈现问题,纠正问题的老本和代价就很高了。因而,架构设计必须疾速迭代学习,保障灵活性和一直进化的个性。 同时思考问题的解法和证法问题的解法是很多的,越成熟的技术,越多成熟的解决方案,但并不是都适合的。因为每个我的项目和技术团队是有差别的,并不能“一招鲜,吃遍天”,还须要依据本身的领有的条件去证实某个解决方案的确是最优的。这是十分符合思维积淀循环的,因为思考了问题口头后必定是须要进行查看的。 总结尽管现实的架构设计是不可能的,然而也不能没有理论实用谋求的。寻找够用的设计其实是强调架构设计的度,要使用高效设计策略去寻找恰到好处的架构设计。因为适度或者过简的架构设计是不行的,适度必然浪费资源,过简必然无奈躲避危险。

April 5, 2021 · 1 min · jiezi

关于springboot:第三篇-跟我学习SpringCloudSpring-Cloud和Dubbo的区别及各自的优缺点

咱们先从 Nginx 说起,理解为什么须要微服务。最后的服务化解决方案是给雷同服务提供一个对立的域名,而后服务调用者向这个域发送 HTTP 申请,由 Nginx 负责申请的散发和跳转。这种架构存在很多问题:Nginx 作为中间层,在配置文件中耦合了服务调用的逻辑,这减弱了微服务的完整性,也使得 Nginx 在肯定水平上变成了一个重量级的 ESB。图中标识出了 Nginx 的转发信息流走向。 服务的信息扩散在各个系统,无奈对立治理和保护。每一次的服务调用都是一次尝试,服务生产方并不知道有哪些实例在给他们提供服务。这带来了一些问题: 无奈直观地看到服务提供方和服务生产方以后的运行状况与通信频率;生产方的失败重发、负载平衡等都没有对立策略,这加大了开发每个服务的难度,不利于疾速演变。为了解决下面的问题,咱们须要一个现成的核心组件对服务进行整合,将每个服务的信息汇总,包含服务的组件名称、地址、数量等。服务的调用方在申请某项服务时首先通过核心组件获取提供服务的实例信息(IP、端口等),再通过默认或自定义的策略抉择该服务的某一提供方间接进行拜访,所以思考引入 Dubbo。Dubbo 是阿里开源的一个 SOA 服务治理解决方案,文档丰盛,在国内的应用度十分高。图 2 为 Dubbo 的根本架构图,应用 Dubbo 构建的微服务曾经能够较好地解决下面提到的问题。 从图 2 中,能够看出以下几点: 调用中间层变成了可选组件,生产方能够间接拜访服务提供方;服务信息被集中到 Registry 中,造成了服务治理的核心组件;通过 Monitor 监控零碎,能够直观地展现服务调用的统计信息;服务消费者能够进行负载平衡、服务降级的抉择。然而对于微服务架构而言,Dubbo 并不是美中不足的,也有一些缺点,比方: Registry 重大依赖第三方组件(ZooKeeper 或者 Redis),当这些组件呈现问题时,服务调用很快就会中断。Dubbo 只反对 RPC 调用。这使得服务提供方与调用方在代码上产生了强依赖,服务提供方须要一直将蕴含公共代码的 Jar 包打包进去供生产方应用。一旦打包呈现问题,就会导致服务调用出错。笔者认为,Dubbo 和 Spring Cloud 并不是齐全的竞争关系,两者所解决的问题域并不一样。Dubbo 的定位始终是一款 RPC 框架,而 Spring Cloud 的指标是微服务架构下的一站式解决方案。如果非要比拟的话,Dubbo 能够类比到 Netflix OSS 技术栈,而 Spring Cloud 集成了 Netflix OSS 作为分布式服务治理解决方案,但除此之外 Spring Cloud 还提供了配置、音讯、平安、调用链跟踪等分布式问题解决方案。以后因为 RPC 协定、注册核心元数据不匹配等问题,在面临微服务根底框架选型时 Dubbo 与 Spring Cloud 只能二选一,这也是大家总是拿 Dubbo 和 Spring Cloud 做比照的起因之一。Dubbo 曾经适配到 Spring Cloud 生态,比方作为 Spring Cloud 的二进制通信计划来施展 Dubbo 的性能劣势,Dubbo 通过模块化以及对 HTTP 的反对适配到 Spring Cloud。 ...

March 30, 2021 · 1 min · jiezi

关于springboot:第二篇跟我学习SpringCloudSpring-Cloud是什么Spring-Cloud版本介绍

Spring Cloud 是一系列框架的有序汇合。它利用 Spring Boot 的开发便利性,奇妙地简化了分布式系统基础设施的开发,如服务注册、服务发现、配置核心、音讯总线、负载平衡、断路器、数据监控等,这些都能够用 Spring Boot 的开发格调做到一键启动和部署。艰深地讲,Spring Cloud 就是用于构建微服务开发和治理的框架汇合(并不是具体的一个框架),次要奉献来自 Netflix OSS。 Spring Cloud 模块介绍Spring Cloud 模块的相干介绍如下: Eureka:服务注册核心,用于服务治理。Ribbon:基于客户端的负载平衡组件。Hystrix:容错框架,可能避免服务的雪崩效应。Feign:Web 服务客户端,可能简化 HTTP 接口的调用。Zuul:API 网关,提供路由转发、申请过滤等性能。Config:分布式配置管理。Sleuth:服务跟踪。Stream:构建音讯驱动的微服务应用程序的框架。Bus:音讯代理的集群音讯总线。除了上述模块,还有 Cli、Task等。教程中只介绍一些罕用的模块。Spring Cloud 是一个十分好的框架汇合,它蕴含的功能模块十分多,不可能一一解说到,但凡在教程中呈现的模块都是实在开发中用失去的。 Spring Cloud 版本介绍置信大家跟笔者一样,在第一次拜访 Spring Cloud 官网时肯定会有一个纳闷那就是版本太多了,到底哪个是稳固版本?哪个才是本人须要的版本?接下来就给大家简略介绍一下版本的问题。拜访官网 https://spring.io/projects/spring-cloud 能够看到网页右侧的版本列表,如图 1 所示。 从图 1中能够看到 Spring Cloud 不是像别的我的项目那样,版本号采纳 1.1、1.2、1.3 这种的格局。因为 Spring Cloud 是一个领有诸多子项目的大型综合我的项目,能够说是对微服务架构解决方案的综合套件组件,其中蕴含的各个子项目都独立进行着内容的迭代与更新,各自保护着本人的公布版本号。至于怎么抉择适宜本人的版本,笔者认为,大家能够在接触的时候间接选最新的稳固版本。新版本中的 Bug 必定要少,并且更稳固。本教程的案例都是基于 Finchley SR2 进行解说的。不同的版本有不同的性能,对应的每个子模块的版本也不一样,那么如何晓得每个大版本上面具体的子模块是什么版本呢?答案就在官网的首页下面,在页面的最下方有一个表格(见表 1 ),通过这个表格咱们能够分明地晓得 Finchley SR2 对应的 Spring Boot 版本是 2.0.6.RELEASE,Spring-Cloud-Bus 是 2.0.0.RELEASE。 举荐布式架构源码 表 1 Spring Cloud版本列表

March 30, 2021 · 1 min · jiezi

关于架构设计:成为架构师

大家什么时候成为架构师的?置信要么企业外部降职、要么跳槽新公司。那是架构师了,公司和招聘要求定义的职责到底该怎么能力做好?如何开始架构师的职业生涯?如何均衡业余技术谋求和企业赚钱第一位的谋求? 架构师要做什么对于合格架构师的职责如下: 设计软件系统架构;零碎合成成为多个可实现的模块;兼顾大局、确保零碎整体稳固无效;衡量品质属性(非功能性需要);管控不可避免的技术债权;锤炼和晋升整个团队的架构设计能力。简而言之就是在兼顾零碎全局、躲避零碎危险、形象等的常识下,做设计、合成零碎,分配任务,保障系统顺利开发和上线,并利用这些常识来晋升团队能力。 何为软件架构软件架构是对于如何组织软件的一零碎重大设计决策和用意的汇合,旨在实现冀望的品质属性和其余指标。 以上的定义有点形象,以下援用卡内基梅隆大学软件工程研究院(SEI)的定义:计算机系统的软件架构是解释零碎所需的构造体的汇合,其中包含:软件元素、元素之间的互相关系,以及二者各自的属性。 该定义阐明了组成软件架构至关重要的因素:元素、关系及属性。即:元素(属性) + 关系 (属性)= 架构。简略来说就是将多个有某些属性的元素以有某些属性的关系连贯在一起,就组成了架构。你能够把元素和关系设想成建筑工地的砖块和水泥,砖块和水泥有很多品种和属性。元素是软件的根本组成(类、包、层、数据库表等),关系则形容了元素如何合作实现工作(调用、依赖、运行于等)。 然而,并不能简略地认为就是这些构造体组成了架构,而是说架构为了解释零碎所需的构造体而整合在一起来阐明,因为架构还蕴含了设计的决策和用意。就像JavaBean的命名标准,蕴含的用意就是代码的规范化、晋升代码的可维护性等。 总结下来,软件架构应该是:元素(属性) + 关系 (属性)+ 决策 + 用意= 架构 成为团队架构师大体来说,成为架构师之前应该至多参加过三到五个零碎的开发,而且承当的技术职责应该一直减少,但最重要的是要总结经验造成全面的常识体系。 从程序员向架构师转变,首先应该要记录和总结你在开发过程中学到的常识。针对每一个我的项目,做以下几点记录和总结: 记录利益相干方和次要业务指标。记录和总结我的项目的整体解决方案。记录波及的技术以及选用的起因。记录最大的危险和克服过程。剖析我的项目存在的有余,总结改良的办法。无论你心愿外部降职,还是跳槽降职,都要有急躁来晋升业余程度。机会是留给有筹备的人的。 记住,架构师不仅仅是团队中的角色,更是一种思维形式。就算你是程序员,每天写代码也会做出很多设计决定的,这其中必定有些决定是具备架构意义的。不想做将军的士兵都不会是好的士兵,所以无论你的头衔是什么,你都应该使用架构设计的思维做出失当的决策,让架构向着健全的方向倒退,那你实际上就是架构师。 开发杰出的软件开发软件系统要尽量躲避危险,佛祖保佑永无bug那种,而架构是软件胜利的根底。 优良的软件架构应该是这样的: 架构将问题分而治之。架构准确地解释了如何将零碎划分为独立笨重且易于解决的小模块,同时还能保障整个零碎协同工作,让零碎的总价值高于各模块的价值之和,即1+1大于2。架构提供了协同工作的指导方针。软件开发不单单是技术,也是以人为本的艺术。软件架构形容了整个零碎如何组成和用意。把握了架构也就分明了大家该怎么分工合作进行软件开发。架构为简单设计提供了常识。提供对立的词汇、术语、概念等等常识,都为沟通和了解带来了极大的便当。常识是随工夫而积攒和晋升的,利用常识,反复的问题的产生就能防止。架构是最优决策的成绩。架构不单单思考性能的根本实现,还要思考老本、束缚、进度、危险、团队的交付能力,以及最重要的品质属性。衡量这些进行恰到好处的架构设计,才是最优的决策。架构让你防止犯重大谬误。架构设计并非万能,但至多要能躲避重大的、常见的危险。预防大于医治,因而架构是能够帮忙咱们去预防今后可能呈现的危险和问题,而不是佛祖保佑就能够的。架构让零碎更灵便。业务是一直地随工夫而变动的,相应的零碎也应该随之变动,而不是推倒重来。因而架构须要为软件开发提供灵活应变的构造。总结头衔和职称并不是架构设计的实质所在,必须专一于架构设计的外围职责,逐渐学习和积攒相应的架构设计常识,并使用这些常识去开发杰出的软件,这就真正成为了架构师。

March 29, 2021 · 1 min · jiezi

关于架构设计:不止中台全面的架构演进趋势和方法-IDCF

小编按:付老师这篇一万四千字的长文,有不少独创性的远见卓识。比方中台施行组合拳,不拘泥一家;EBA vs DDD等。在十万加爽文式快餐浏览更容易被follow的时代,本文重发,谨以此献给能读懂或者打算读懂的读者们。毕竟业余畛域是有浏览门槛的。应技术琐话之约,试图写一篇探讨架构方法论的文章,然而动笔之后,才发现,本人仿佛陷入了Frederick P. Brooks学生在《设计本来》一书中指出的问题:“设计中最艰难的局部在于决定要设计什么”。 2020年1月18日,有人戏称是“中台”历史上最“艰难”的一天,一篇炸圈的文章将对“中台”的探讨又一次推向高点,尽管“泼冷水”的象征十足。其实笔者之前也谈到过,“中台”自诞生伊始就非一个谨严的定义,而是一种比喻,比喻当然也就容易导致争论不休,“中台”当初面临的问题其实也和笔者入手写这篇文章面对的问题差不多。然而,将“中台”实践一直明晰化的尝试仍是个好事件,毕竟,这是国内企业掀起的一次对架构设计办法的无益摸索。 笔者在2019年11月南京中台大会上也曾讲到,现在很多畛域都在谈国产化、自主可控,架构畛域难道不须要吗?架构畛域方法论的继续欠缺、国产实践的继续翻新,是驾驭技术组合的要害,底层技术的一直自主化并不会必然带来顶层设计能力的自主化,而数字化转型,除了须要底层技术的撑持外,卓越的下层设计更是重中之重。走出有中国特色的数字化路线,底层技术能力与下层设计能力缺一不可。 对企业级软件架构设计办法的钻研须要所有人独特关注,它是在继续进化的,也是将来企业走向数字化过程中,实现业务与技术深度交融的必经之路。Brooks学生在同一本书还提到:“好的设计者应该投入大量精力来学习判例……但古代设计匆忙的节奏却对这种实现十分不利”,他写下此语是在10年前,明天,这种状况只能说是有过之而无不及吧。 探讨架构问题永远是艰难的,尽管笔者能力无限,然而出于对架构实践的喜好,还是尝试通过本文与各位读者独特探讨架构办法的演进与改进。 一、软件工程与企业架构1.1 糊涂的晚期:没有工程、没有架构架构设计是随着软件复杂度的回升而真正受到人们器重的。1946年,微小的电子管计算机ENIAC诞生,软件行业的帷幕拉开,然而尔后十几年的工夫里,软件设计都只是多数人的事件,这个行业大部分工夫都在实验室中倒退。尽管高级语言呈现,然而大多数程序设计人员的次要武器是汇编语言。模块化的思路逐步呈现,然而软件过程治理是很原始的,也没有所谓的架构设计办法,风行的就是“先写了再说”。 1.2 办法的开始:瀑布模型和Zachman模型凌乱的治理形式引发了60-70年代的软件危机,于是,1968年NATO会议上,“软件工程”的概念首次被提出,其核心思想就是建设并应用欠缺的工程化准则,通过一系列办法,以较经济的伎俩取得能在理论机器上无效运行的牢靠软件。这个“奢侈”的指标,反映了软件行业晚期存在的工夫不可控、品质不可控、估算不可控等诸多问题造成的困扰。 1970年,Winston Royce在《大型软件系统开发的治理》一文中,提出了“瀑布模型”,将开发分成如图1所示的7个明确的阶段: 图1 瀑布模型 Royce其实认为这是一个有危险的开发过程,并提出了5个批改倡议,包含在分析阶段之前减少一个在信息有余条件下的预设计、开发过程中减少客户参加等,然而大家却把这个被他列为批评对象的“瀑布模型”作为开发的规范过程,包含美国国防部,他的倡议却鲜为人知了。其中的分析阶段也就包含了架构设计工作,逐步又被细分为概要设计和具体设计。然而这个期间的架构设计次要还是针对软件设计,还没有倒退出成形的企业架构实践。 随着人们对软件设计工作意识的不断深入,大型软件设计与企业治理的关系越来越严密,这也体现了人们对软件设计的本质性指标——为企业服务的认知。 基于此,1987年Zachman提出了首个较为残缺的企业架构模型,该模型依照“5W1H”,即What(数据)、How(性能)、Where(网络)、Who(角色)、When(工夫)、Why(动机)6个维度,联合指标范畴、业务模型、信息系统模型、技术模型、具体展示、性能零碎6个档次,将企业架构分成36个组成部分,形容了一个残缺的企业架构要思考的内容,如表1-1所示。 表1 Zachman模型简介 这个架构设计方法论曾经将零碎设计应反对企业经营治理指标的要求表达出来,然而该模型的一个有余是Zachman并没有给出一个具体的构建办法。 1.3 成熟的提高:螺旋模型和TOGAF1988年,软件工程上又一个里程碑式的办法诞生了,Barry Boehm提出了“螺旋模型”,该模型如图2所示: 图2 螺旋模型 螺旋模型通过继续对原型进行验证式、增量交付的形式,补救“瀑布模型”在需要治理方面有余,是一种对需要的渐进式摸索,也增强了对项目风险的治理。Brooks在2010年著书时仍对该模型赞叹有加。 随着信息化水平的加深,企业越发意识到将IT融入企业治理的重要性,IT人员也意识到与业务联合的重要性,于是,1995年TOGAF(The OpenGroup Architecture Framework ,凋谢组体系结构框架)应运而生,业务架构的概念也被明确提出来。 TOGAF认为企业架构分为业务架构和IT架构两大部分,业务架构是把企业的业务策略转化为日常运作的渠道,业务策略决定业务架构,它包含业务的经营模式、流程体系、组织构造、地区散布等内容,业务架构再作用于IT实现。TOGAF的设计交付物如表2所示: 表2 TOGAF交付物示意 能够看出,到TOGAF时代,在内容上,企业架构和业务架构倒退的曾经较为欠缺了;在工艺上,TOGAF也有明确的操作要求,也正是因为有具体的要求,TOGAF被公认的毛病之一就是太“重”,有点像是架构畛域的“瀑布模型”。 从Zachman到TOGAF,只管实践日臻成熟,然而企业架构设计与理论开发过程之间的联合始终不是很好,更像是在两条线上倒退,外表看起来,Zachman模型仿佛还能跟“瀑布模型”走失去一起,毕竟二者都被认为是“漫长”的,但大部分开发实际上在这个期间都是沿着“竖井式”的路线在走,仍旧不足对企业级设计的关怀。至于TOGAF,它跟螺旋模型、迭代模型之间在实操上有不易联合之嫌,恐怕不少企业承受了利用TOGAF思路的征询计划,却在施行过程中将其束之高阁了。尽管如此,TOGAF对推动企业架构倒退的作用仍是十分大的。 1.4 对更快的摸索:麻利开发、DDD和微服务对效率的摸索涌现出了更多的软件工程办法、设计办法,不同办法间逐步造成组合,从繁多办法到“组合拳”也是一个很有意思的过程。 不满足于软件工程的提高,90年代,麻利开发的思路开始呈现。2001年,在美国犹他州雪鸟滑雪胜地,麻利办法发起者组织麻利团聚并起草赫赫有名的《麻利宣言》,“麻利”开发也在这次团聚上正式定名。尽管目前对麻利开发的意识还不是很统一,但大体上的开发流程,能够在网上找到很多相似图3的介绍: 图3 麻利开发流程(来自互联网) 麻利开发的锋芒堪称直指“瀑布模型”,大多数讲麻利开发的书简直都以此结尾。笔者并非一个麻利实践者,因而也无奈深刻探讨这一办法的优缺点,然而从对其实现过程的介绍来看,企业架构的设计显然没有蕴含在麻利过程中,麻利强调的是产品和用户维度,而且麻利的“轻文档”理念与企业架构已有的“重文档”办法之间也是有矛盾的。 因为钻研的人很多,麻利开发在软件过程治理和软件设计方面都有较快倒退。只管有人质疑其成果,然而据称全球排名第11的资产治理公司——荷兰国内团体(ING)是在全公司推广麻利开发的,该公司领有员工113,000人,在寰球50个国家为6千多万客户提供金融服务。 除了对过程的减速,架构设计办法自身也有翻新。2003年,Eric Evans提出了DDD,也即畛域驱动设计办法,该办法的特点是在需要剖析、软件设计方面的一体化实现,通过畛域模型间接造成能够领导到“类”设计的软件架构模型。然而DDD显著只是一个软件架构设计办法,而非企业架构设计,并且,DDD畛域的大师级人物Vaughn Vernon认为企业级是无奈从顶层间接设计的,只能在领域建模实现后,一一畛域地进行尝试性交融。Eric Evans也在其书的结尾对“总体规划”办法示意了一种婉转的不信赖。DDD最经典的架构图如图4和图5所示: 图4 六边形架构(来自互联网) 图5 畛域模型示例(来自互联网) EricEvans曾提出该办法次要面向麻利过程,二者其实在办法层面有相似之处,都强调疾速由需要进入开发过程,也都重视对模式的使用。然而因为DDD办法把握起来有肯定难度,因而并没有真的随着麻利开发“火”起来,倒是借了另一种架构格调的“东风”,微服务。 微服务最早由Martin Fowler与James Lewis于2014年独特提出,微服务架构格调重视用具备独立数据库的微服务来代替原有的单体利用设计形式,每个微服务运行在本人的过程中,并应用轻量级机制通信,通常是Restful API。这些服务基于业务能力构建,并可能通过自动化部署机制来独立部署,服务能够应用不同的编程语言实现,以及不同数据存储技术,并放弃最低限度的集中式治理。从理念上看,极具灵活性、疾速响应能力、可复用性和扩展性,案例上更是有传奇公司Netflix做标杆。 然而这种架构格调并没有很好地解决它的前身SOA遗留的问题,就是如何确定服务的颗粒度,于是,不温不火快10年的DDD派上用场了。DDD这种能够间接依照限界上下文导出数据和行为相结合的设计后果的办法,很适宜推微服务一把。Chris Richardson在其著述《微服务架构设计模式》一书中就专门花了两章来介绍DDD与微服务的联合。 在对更快的摸索中,麻利开发、DDD和微服务提供了一种包含软件过程、架构设计和工程实现在内的“组合拳”,当然,这并不意味着所有企业都要这么用,只是一种参考而已。此外,求快的同时,这些办法也都欠缺对企业架构的关注,它们都是能够晋升IT开发效力的无力工具,然而,在To B端,仍须要一种能够面向企业级能力建设的办法作为总体导引。 ...

March 29, 2021 · 1 min · jiezi

关于im:一套亿级用户的IM架构技术干货下篇可靠性有序性弱网优化等

本文内容和编写思路是基于邓昀泽的“大规模并发IM服务架构设计”、“IM的弱网场景优化”两文的提纲进行的,感激邓昀泽的自私分享。 1、引言接上篇《一套亿级用户的IM架构技术干货(上篇):整体架构、服务拆分等》,本文次要聚焦这套亿级用户的IM架构的一些比拟细节但很重要的热门问题上,比方:音讯可靠性、音讯有序性、数据安全性、挪动端弱网问题等。 以上这些热门IM问题每个话题其实都能够独自成文,但限于文章篇幅,本文不会一一问题具体深刻地探讨,次要以抛砖引玉的形式疏导阅读者了解问题的要害,并针对问题提供专项钻研文章链接,不便有选择性的深刻学习。心愿本文能给你的IM开发带来一些好处。 本文已同步公布于“即时通讯技术圈”公众号,欢送关注。公众号上的链接是:点此进入。 2、系列文章为了更好以进行内容出现,本文拆分两了高低两篇。 本文是2篇文章中的第2篇: 《一套亿级用户的IM架构技术干货(上篇):整体架构、服务拆分等》《一套亿级用户的IM架构技术干货(下篇):可靠性、有序性、弱网优化等》(本文)本篇次要聚焦这套亿级用户的IM架构的一些比拟细节但很重要的热门问题上。 3、音讯可靠性问题音讯的可靠性是IM零碎的典型技术指标,对于用户来说,音讯能不能被牢靠送达(不丢音讯),是应用这套IM的信赖前提。 换句话说,如果这套IM零碎不能保障不丢音讯,那相当于发送的每一条音讯都有被失落的概率,对于用户而言,肯定会不会“释怀”地应用它,即“不信赖”这套IM。 从产品经理的角度来说,有这样的技术阻碍存在,再怎么费劲的推广,最终用户都会很快散失。所以一套IM如果不能保障音讯的可靠性,那问题是很重大的。 PS:如果你对IM音讯可靠性的问题还没有一个直观的映象的话,通过《零根底IM开发入门(三):什么是IM零碎的可靠性?》这篇文章能够通俗易懂的了解它。 如上图所示,音讯可靠性次要依赖2个逻辑来保障: 1)上行音讯可靠性;2)上行音讯可靠性。1)针对上行音讯的可靠性,能够这样的思路来解决: 用户发送一个音讯(假如协定叫PIMSendReq),用户要给这个音讯设定一个本地ID,而后期待服务器操作实现给发送者一个PIMSendAck(本地ID统一),通知用户发送胜利了。 如果期待一段时间,没收到这个ACK,阐明用户发送不胜利,客户端SDK要做重试操作。 2)针对上行音讯的可靠性,能够这样的思路来解决: 服务收到了用户A的音讯,要把这个音讯推送给B、C、D 3集体。假如B长期掉线了,那么在线推送很可能会失败。 因而确保上行可靠性的外围是:在做推送前要把这个推送申请缓存起来。 这个缓存由存储系统来保障,MsgWriter要保护一个(离线音讯列表),用户的一条音讯,要同时写入B、C、D的离线音讯列表,B、C、D收到这个音讯当前,要给存储系统一个ACK,而后存储系统把音讯ID从离线音讯列表里拿掉。 针对音讯的可靠性问题,具体的解决思路还能够从另一个维度来思考:即实时音讯的可靠性和离线音讯的可靠性。 有趣味能够深刻读一读这两篇: 《IM音讯送达保障机制实现(一):保障在线实时音讯的牢靠投递》《IM音讯送达保障机制实现(二):保障离线音讯的牢靠投递》而对于离线音讯的可靠性来说,单聊和群聊又有很大区别,无关群聊的离线音讯牢靠投递问题,能够深刻读一读《IM开发干货分享:如何优雅的实现大量离线音讯的牢靠投递》。 4、音讯有序性问题音讯的有序性问题是分布式IM零碎中的另一个技术“硬骨头”。 因为是分布式系统,客户端和服务器的时钟可能是不同步的。如果简略依赖某一方的时钟,就会呈现大量的音讯乱序。 比方只依赖客户端的时钟,A比B工夫晚30分钟。所有A给B发消息,而后B给A回复。 发送程序是: 客户端A:“XXX”客户端B:“YYY”接管方的排序就会变成: 客户端B:“YYY”客户端A:“XXX”因为A的工夫晚30分钟,所有A的音讯都会排在前面。 如果只依赖服务器的时钟,也会呈现相似的问题,因为2个服务器工夫可能也不统一。尽管客户端A和客户端B时钟统一,然而A的音讯由服务器S1解决,B的音讯由服务器S2解决,也会导致同样音讯乱序。 为了解决这种问题,我的思路是通过能够做这样一系列的操作来实现。 1)服务器工夫对齐: 这部分就是后端运维的锅了,由系统管理员来尽量保障,没有别的招儿。 2)客户端通过工夫调校对齐服务器工夫: 比方:客户端登录当前,拿客户端工夫和服务器工夫做差值计算,发送音讯的时候思考这部分差值。 在我的im架构里,这个能把工夫对齐到100ms这个级,差值再小的话就很艰难了,因为协定在客户端和服务器之间传递速度RTT也是不稳固的(网络传输存在不可控的提早危险嘛)。 3)音讯同时带上本地工夫和服务器工夫: 具体能够这样的解决:排序的时候,对于同一个人的音讯,依照音讯本地工夫来排;对于不同人的音讯,依照服务器工夫来排,这是插值排序算法。 PS:对于音讯有序性的问题,显然也不是下面这三两句话能讲的分明,如果你想更艰深一了解它,能够读一读《零根底IM开发入门(四):什么是IM零碎的音讯时序一致性?》。 另外:从技术实际可行性的角度来说,《一个低成本确保IM音讯时序的办法探讨》、《如何保障IM实时音讯的“时序性”与“一致性”?》这两篇中的思路能够借鉴一下。 实际上,音讯的排序问题,还能够从音讯ID的角度去解决(也就是通过算法让音讯ID产生程序性,从而依据音讯ID就能达到音讯排序的目标)。 无关程序的音讯ID算法问题,这两篇十分值得借鉴:《IM音讯ID技术专题(一):微信的海量IM聊天音讯序列号生成实际(算法原理篇)》、《IM音讯ID技术专题(三):解密融云IM产品的聊天音讯ID生成策略》,我就不废话了。 5、音讯已读同步问题音讯的已读未读性能,如下图所示: 上图就是钉钉中的已读未读音讯。这在企业IM场景下十分有用(因为做领导的都喜爱,你懂的)。 已读未读性能,对于一对一的单聊音讯来说,还比拟好了解:就是多加一条对应的回执息(当用户浏览这条音讯时发回)。 但对于群聊这说,这一条音讯有多少人已读、多少人未读,想实现这个成果,那就真的有点麻烦了。对于群聊的已读未读性能实现逻辑,这里就不开展了,有趣味能够读一下这篇《IM群聊音讯的已读回执性能该怎么实现?》。 回归到本节的主题“已读同步”的问题,这显示难度又进一级,因为已读未读回执不只是针对“账号”,当初还要细分到“同一账号在不同端登陆”的状况,对于已读回执的同步逻辑来说,这就有点复杂化了。 在这里,依据我这边IM架构的实践经验,提供一些思路。 具体来说就是:用户可能有多个设施登录同一个账户(比方:Web PC和挪动端同时登陆),这种状况下的已读未读性能,就须要来实现已读同步,否则在设施1看过的音讯,设施2看到仍然是未读音讯,从产品的角度来说,这就影响用户体验了。 对于我的im架构来说,已读同步次要依赖2个逻辑来保障: 1)同步状态保护,为用户的每一个Session,保护一个工夫戳,保留最初的读音讯工夫;2)如果用户关上了某个Session,且用户有多个设施在线,发送一条PIMSyncRead音讯,告诉其它设施。6、数据安全问题6.1 根底IM零碎架构中的数据安全比个别零碎要简单一些,从通信的角度来说,它波及到socket长连贯通信的安全性和http短连贯的两重安全性。而随着IM在挪动端的风行,又要在安全性、性能、数据流量、用户体验这几个维度上做衡量,所以想要实现一套欠缺的IM平安架构,要面临的挑战是很多的。 IM零碎架构中,所谓的数据安全,次要是通信安全和内容平安。 6.2 通信安全所谓的通信安全,这就要了解IM通信的服务组成。 目前来说,一个典型的im零碎,次要由两种通信服务组成: 1)socket长连贯服务:技术上也就是少数人耳熟能详的网络通信这一块,再细化一点也就是tcp、udp协定这一块;2)http短连贯服务:也就是最罕用的http rest接口那些。对于晋升长连贯的安全性思路,能够深刻浏览《通俗易懂:一篇把握即时通讯的音讯传输平安原理》。另外,微信团队分享的《微信新一代通信安全解决方案:基于TLS1.3的MMTLS详解》一文,也十分有参考意义。 如果是通信安全级别更高的场景,能够参考《即时通讯平安篇(二):探讨组合加密算法在IM中的利用》,文中对于组合加密算法的应用思路十分不错。 至于短连贯安全性,大家就很相熟了,开启https少数状况下就够用了。如果对于https不甚了解,能够从这几篇开始:《一文读懂Https的安全性原理、数字证书、单项认证、双项认证等》、《即时通讯平安篇(七):如果这样来了解HTTPS,一篇就够了》。 6.3 内容平安这个可能不太好了解,下面既然实现了通信安全,那为什么还要纠结“内容平安”? 咱们理解一下所谓的密码学三大作用:加密( Encryption)、认证(Authentication),鉴定(Identification) 。 具体来说就是: 加密:避免好人获取你的数据。认证:避免好人批改了你的数据而你却并没有发现。鉴权:避免好人混充你的身份。在上节中,歹意攻击者如果在通信环节绕开或冲破了“鉴权”、“认证”,那么依赖于“鉴权”、“认证”的“加密”,实际上也有可有被破解。 ...

March 22, 2021 · 1 min · jiezi

关于研发管理:研发管理101军规002特种部队更符合不确定业务的组织架构设计-IDCF

拓展浏览:研发治理101军规#001 两周迭代,造成团队继续习惯 | IDCF 这是研发治理的第2条军规,我急不可待地将组织架构的设计作为根底理念举荐给尽可能多的研发管理者。 在阿里有个习惯性的动作,策略调整的第一步是组织架构的调整,可见组织如何排列组合是个极其重要的事件。让张飞去负责后勤,就和安顿孙悟空挑扁担一样,对团队都是负价值,进而让西天取经这件事变得更难了。 因而,研发治理的002篇,咱们优先谈谈更合乎不确定业务的组织架构设计,我称之为特种部队。当初治理思维,很多来源于军队的组织建设,从过来100年的战争史来看,以美军建制为例,从一战二战,到越南战争,再到海湾战争,几十万人死磕的堡垒时代完结了,当初更多是特种部队编制,十几个人的海豹突击队就能发动忽然的小型战斗,并可能管制和平输赢的走向。 回到研发团队的现实情况,通常在组织架构上的不认真,会带来治理上无比简单的麻烦,而且往往粗率的组合会拼凑出乌合之众,而不是能战之师。如何设计研发团队的组织架构,是个大大的思考题。Worktile 团队经验过好几次不同的组织状态,也经常性的将研发团队进行组织调整,简略说,一个研发团队的角色次要是以下几类: 产品经理设计师服务端工程师前端工程师测试工程师运维工程师其余对于研发治理来说,高效团队的第一步是设计适当和适度的组织架构,将适合的人排列组合,能力造成有战斗力的团队。那么什么是特种部队,其实唐僧师徒就是特种部队,念经的是精神领袖,拿金箍棒的火眼金睛扫清妖怪,还得有个好逸恶劳的沉闷氛围,苦活累活须要沙和尚默默担着,而整个团队的能力实现了真正的1 + 1 > 2的效力,历经九九八十一难修成正果。 以什么样的组织形式调配以上资源,是个十分考验团队治理的事件,例如很多公司会将设计团队作为齐全独立的部门,其余团队和我的项目按需调配设计资源,设计团队就像公司的乙方角色,通过资源调配来匹配执行。 而另一种状态则是宽泛存在于Facebook、谷歌、小米、阿里、头条等互联网公司,设计、产品经理、开发、测试组成短小精悍的特种部队,在研发团队中以小组状态组合,就像一个研发业务的接口一样,有清晰的输出和清晰的输入,有清晰的指标和清晰的边界。 Facebook的数万名工程师并不是像集团军一样制作Facebook,更多的反而是十几个人的小团队造成自组织单元,信息流、音讯、账户治理、广告零碎、群组、图片分享,被切分成有数可大可小的业务单元,每个业务单元由残缺编制的开发者团队负责,产品经理、设计师、前端、服务端、测试组成残缺精悍的特种部队,向一个业务单元的指标和后果负责,又能灵便聚焦的驱动业务迭代。 在Worktile研发团队,咱们依据本身业务个性,组成了数十个不同的研发特种部队,例如基础架构组、凋谢API组、麻利产品组(Agile)、测试产品组(Testhub)、Wiki产品组(Wiki)、我的项目集产品组(Plan)、后盾服务组、客户研发组、增长组等等,每个小虎队跟进业务复杂度通过以下的根本配置来组织开发工程师。 (ps:小虎队是咱们外部对特种部队的称呼) 显然,打起仗来,特种部队形式的小组,从执行到指标都是超级强悍的,也同时能不便研发组织绩效考核的落地与激励。新业务成立时,咱们通常从其余小组提拔优良的工程师来当唐僧,领导和开辟新的业务组,他须要本人去五指山找孙悟空,去高老庄救猪八戒,去通天河招沙和尚,而不影响其余业务的资源占用。 因为不同的特种小虎队有清晰的指标、职责和边界,因而不同小组之间的配合与合作将变得清晰无效,基础架构层的问题将天然由基础架构组负责和解决,而Plan产品和Agile产品间接的高密度数据买通,则在两个小组之间进行接口协调即可。 特种部队的组织文化,适配业务疾速迭代和不确定性加剧的时代,一个特种部队有全副武装的能力,有聚焦的方向和指标,有自组织和自驱动的文化,而特种小虎队也齐全匹配了奖罚分明的研发绩效治理逻辑。干得好的唐僧会迅速失去更多真经的激励,而没用后果的业务会疾速撤掉重组。 总结来说,特种部队式的组织架构设计,价值在体现在: 适应需要的变更和业务的不确定能够聚焦业务和指标继续配合的团队更默契,组织更无效不便绩效考核跨团队的配合,可能不便定义清晰的边界,进而实现对业务无效的组织和宰割不同的特种部队,能主动造成竞争机制培训和成长,会在一个特种部队单元里造成残缺的闭环一直扩大的小虎队,也天然造成了开发工程师的回升通道,为有后劲的孙悟空提供了在新业务单元施展的空间和可能还有一部分和组织架构相干的是正在流行的中台,和始终在风行的阿米巴,我会在其余的军规中尝试探讨这两个话题。 高效研发的第一步是从组织架构的设计开始的,尝试思考将团队朝着特种部队的方向打造,会有N多播种。 这是第002条军规:打造特种部队。 内容起源:PingCode作者:Anytao研发治理101军规——PingCode(Worktile)CEO王涛

March 22, 2021 · 1 min · jiezi

关于架构设计:一套亿级用户的IM架构技术干货上篇整体架构服务拆分等

1、引言经验过稍有些规模的IM零碎开发的同行们都有领会,要想实现大规模并发IM(比方亿级用户和数十亿日音讯量这样的规模),在架构设计上须要一些额定的思考,尤其是要解决用户高并发、服务高可用,架构和实现细节上都须要不短时间的打磨。 我在过往的工作经验里,亲手设计和实现了一套亿级用户量的IM,平台上线并通过6年多的验证,稳定性和可用性被验证齐全达到预期。 这套IM零碎,从上线至今已6年无余,自己也曾经到职守业近2年,但当初设计和开发这套零碎时积攒和播种了大量的第一手实践经验和技术心得。 因而,想借本文把过后的架构设计经验记录下来,作为同行交换和参考,心愿能提供一些启发,少走弯路。 本文已同步公布于“即时通讯技术圈”公众号,欢送关注。公众号上的链接是:点此进入。 2、系列文章为了更好以进行内容出现,本文拆分两了高低两篇。 本文是2篇文章中的第1篇: 《一套亿级用户的IM架构技术干货(上篇):整体架构、服务拆分等》(本文)《一套亿级用户的IM架构技术干货(下篇):可靠性、有序性、弱网优化等(稍后公布...)》本篇次要总结和分享这套IM架构的总体设计和服务拆分等。 3、原作者本文基于邓昀泽的“大规模并发IM服务架构设计”一文进行的扩大和订正,感激原作者的分享。 邓昀泽:毕业于北京航空航天大学,现蓝猫微会创始人兼CEO,曾就任于美团、YY语音、微软和金山软件等公司,有十多年研发治理教训。 4、技术指标在这套IM零碎的架构上,技术上咱们保持高要求,通过数年的验证,也的确达到了设计预期。 这4大技术指标是: 具体解释就是: 1)高牢靠:确保不丢音讯;2)高可用:任意机房或者服务器挂掉,不影响服务;3)实时性:不论用户在哪里,在线用户音讯在1秒内达到(咱们理论是75%音讯能够做到120ms);4)有序性:确保用户音讯的有序性,不会呈现发送和承受的乱序。5、架构拆分从整体架构上来说,亿级用户量的IM架构整体上偏简单。 传统开源的IM服务喜爱把所有服务做到1-2个服务里(Connector+Service模型),这样带来的问题比较严重。 传统开源的IM的问题次要体现在: 1)服务代码简单,难以继续开发和运维;2)繁多业务逻辑出问题,可能会影响到其它逻辑,导致服务的全面不可用。因而,我在做架构设计的时候尽量谋求微服务化。即把整体架构进行分拆为子系统,而后子系统内依照业务逻辑分拆为微服务。 零碎拆分如下图: 4个子系统的职责是: 1)IM业务零碎:服务IM相干的业务逻辑(比方好友关系、群关系、用户信息等);2)信令零碎:负责用户登录,用户在线状态的保护,以及在线用户的上行推送;3)推送零碎:负责音讯的在线推送和离线推送;4)存储系统:负责音讯和文件的存储和查问;其中:信令零碎和推送零碎是基础设施,不只是能够为IM业务服务,也能够承载其它相似的业务逻辑(比方客服零碎)。 在部署层面:采纳存储3外围机房,信令和推送节点按需部署的形式(国内业务举荐8-10个点)。实际上咱们只做了了北京3个机房,上海1个机房和香港一个机房的部署,就基本上满足了大陆+香港的业务需要。 上面将一一介绍这4个子系统的细节方面。 6、IM业务零碎一说到IM,很多人脑海里跳出的第一个要害就是“即时通信”,技术上天经地义的联想到了socket,也就是大家成天嘴上说的:“长连贯”。换句话说,很多对IM不理解或理解的不多的人,认为IM里的所有数据交互、业务往来都是通过“长连贯”来实现的,这样话,对于本文章中拆分出的“IM业务零碎”就有点不了解了。 实际上,晚期的IM(比方20年前的QQ、MSN、ICQ),的确所有数据根本都是通过“长连贯”(也就是程序员所说的“socket”)实现。 但现在,挪动端为主端的IM时代,IM零碎再也不是一个条“长连贯”走天下。 当初,一个典型的IM零碎数据往来通常拆分成两种服务: 1)socket长连贯服务(也就是本文中的“推送服务”);2)http短连贯服务(就是最罕用的http rest接口那些,也就是本文中的“IM业务零碎”)。艰深一点,也也就当初的IM零碎,通常都是长、短连贯配合一起实现的。  比方论坛里很多热门技术计划都是这样来做的,比方最典型的这两篇:《IM单聊和群聊中的在线状态同步应该用“推”还是“拉”?》、《IM音讯送达保障机制实现(二):保障离线音讯的牢靠投递》,文记里提到的“推”其实就是走的“长连贯”、“拉”就上指的http短连贯。 对于socket长连贯服务就没什么好说,就是大家最常了解的那样。 IM业务零碎具体来说,就是专一解决IM相干的业务逻辑,比方: 1)保护用户数据:用户根本信息等;2)保护好友关系:好友申请、好友列表、好友信息等;3)保护群组信息:群创立、遣散、成员治理等;4)提供数据:离线拉取、历史记录同步;5)其它逻辑:比方通过存储和推送零碎,存储音讯和发送告诉;依照微服务的准则,IM业务零碎也被分拆为多个服务,比方: 1)GInfo服务:群组信息保护;2)IM服务:解决1V1音讯;3)GIM服务:解决群组音讯。7、信令零碎7.1 根本状况信令零碎主要职责是3局部:  1)保护用户在线状态: 因为用户规模宏大,必然是多个集群,每个集群多台服务器为用户提供服务。 思考到服务器运维的复杂性,咱们要假设任何一个集群,任何一个服务器都可能会挂掉,而且在这种状况下要可能持续为用户提供服务。 在这种状况下,如果用户A给用户B发消息,咱们须要晓得用户B在哪个服务器上,能力把音讯正确推送给用户B。用户在哪个信令服务,这个信息就是在线状态数据。 2)上行音讯推送: 跟上一个职责无关,用户在线的时候,如果有其它用户给他发消息,那就最好不要走离线推送,而是走在线推送。 在线推送的最初一个环节,是把用户音讯推送给用户设施,因为就须要晓得用户登录到哪个服务器上。 3)业务散发: 信令服务不只能够解决IM申请,也能够解决其它类型的业务申请。为了解决不同的业务,就须要有散发能力。 具体做法是通过一个SVID(service id)来实现,不同的业务携带不同的SVID,信令服务就晓得如何散发了。 用户通过登录服务把数据(比方IM音讯)发送到信令零碎,信令零碎依据SVID转发给IM零碎。不论后盾有多少个业务,用户只须要一条链接到信令。 7.2 服务拆分信令零碎为了实现以上这3个职责,同时要确保咱们服务可平行扩大的能力和稳定性,在理论的技术实现上,咱们实际上把信令服务分拆为3个服务模块。 如下图所示:  上面将一一介绍这3个子服务。 7.3 Login服务Login服务次要负责保护用户长链接: 1)每个用户一条链接到Login服务,并按工夫发心跳包给Login服务;2)服务定时检查用户链接状态和心跳包,比方发现2个心跳周期都没收到心跳,就认为用户掉线了(有假在线问题,有趣味同学可回贴探讨)。Login服务收到用户登录申请当前,验证uid/cookie,如果胜利就把这个用户的登录信息发送给online。 此过程次要记录的信息蕴含: 1)uid(用户id);2)Login服务器IP/Port;3)Route服务器的IP/Port。如果用户发送IM音讯,先发送到Login,Login转发给Route,Route依据服务的类型(SVID),发现是IM协定就发送给后端的IM服务。 Login对并发要求比拟高,个别要反对TCP+UDP+Websocket几种形式,单服务能够做到10-250万之间。从服务稳定性角度触发,倡议是管制VM的CPU/内存,单服务器以20-50万为适合。 Login服务器自身没有状态,任何一个Login服务断掉,用户端检测到当前重连另一个Login服务器就能够了,对整体服务可靠性根本没有影响。 7.4 Online服务Online服务次要负责保护用户的在线信息: 1)如果用户掉线,Online服务里信息就是空;2)如果用户在线,Online就能找到用户登录在哪个集群,哪个Login服务器上。Online业务绝对简略:多个Login服务器会连贯到Online,定期同步用户登录和离线信息。 Online主要职责是:把用户状态信息存储在Redis集群里。因而也是无状态的,任何一个Online服务挂掉,不影响整体服务能力。 如果集群规模不大,用户规模也不大,Online服务也能够收到Login服务里去。 如果规模比拟大,倡议分拆进去,一方面简化Login的逻辑复杂度,同时防止写Redis的慢操作放在Login服务里。因为Login要同时解决50万以上的并发链接,不适宜在循环里嵌入慢操作。 ...

March 15, 2021 · 1 min · jiezi

关于架构设计:亿级用户中心的设计与实践

用户核心是互联网最为根底的外围零碎,随着业务和用户的增长,势必会带来一直的挑战。如何在亿级的状况下保证系统的高可用,高性能以及高平安,本文可能给你一套实际计划。注1:本文探讨的是微服务框架下的用户核心,不波及受权等性能; 注2:本文所波及的用户核心设计与vivo本身业务无关。 用户核心,顾名思义就是治理用户的中央,简直是所有互联网公司最为外围的子系统之一。它的外围性能是登录与注册,次要性能是批改明码、换绑手机号码、获取用户信息、批改用户信息和一些延长服务,同时还有登录之后生成Token以及校验Token的性能。上面咱们从几个维度来拆解用户核心。 一、服务架构用户核心既须要为用户提供服务,也会承当其余业务的频繁调用;既然须要为用户提供服务,它就会自带一些业务逻辑,比方用户在登录过程中须要风控或短信的校验,那么就会存在不可用的危险。而比方获取用户信息的接口,则没有那么多的依赖,可能只须要调用数据库或者缓存就能够。获取用户信息接口要求稳固,而外围的登录注册接口也须要稳固,然而当咱们在接口层面加一些策略或者批改的时候,不心愿因为上线问题导致整个服务不可用,而且上线后,须要对整个服务性能做全量的回归,导致资源重大节约。 因而,基于业务个性,咱们能够将用户核心拆成3个独立的微服务: 网关服务,外围服务,异步消费者服务。网关服务,提供http服务,聚合了各种业务逻辑和服务调用,比方登录时候须要校验的风控或者短信;外围服务,解决简略的业务逻辑以及数据存储,外围服务处在调用链路的终端,简直不依赖调用其余服务,比方校验Token或者获取用户信息,他们就只依赖于redis或者数据库;而异步消费者服务,则解决并生产异步音讯。下文会具体介绍。 这样的设计之后,当有新性能上线时,外围服务和异步生产服务简直不须要从新公布,只须要公布网关服务,依赖咱们外围服务的第三方十分释怀,层级也十分的清晰。当然,这样做的代价就是服务的调用链路变长了。因为波及到网关和外围服务,就须要公布两个服务,而且要做兼容性测试。 二、接口设计用户核心的接口波及到用户的外围信息,安全性要求高;同时,承接了较多第三方的调用,可用性要求也高。因而,对用户核心的接口做以下设计: 首先,接口能够拆分为面向Web和面向App的接口。Web接口须要做到跨域状况下的单点登录,加密、验签和token校验的形式也同App端的不一样。 其次,对外围接口做非凡解决。比方登录接口,在逻辑和链路上做了一些优化。为什么要对这些接口做非凡解决呢?如果用户不能登录,用户会十分恐慌,客诉量会立马上来。 那怎么做呢?一方面,咱们将用户外围信息表做简略。用户的信息当中会蕴含userId、手机号码、明码、头像、昵称等字段,如果把用户的这些所有信息都保留在一张表中,那么这张表将会异样宏大,变更字段变得异样艰难。因而,须要将用户表拆分,将外围的信息保留在用户表中,比方userId、username、手机号码、明码、盐值(随机生成)等;而一些如性别,头像,昵称等信息保留在用户材料表中。 另一方面,咱们须要将登录的外围链路做短,短到只依赖于读库。个别状况下,用户登录后,须要记录用户登录信息,调用风控或者短信等服务。对于登录链路来说,任何一个环节呈现问题都有可能导致用户无奈登录,那么怎么样能力做到最短的链路呢?办法就是依赖的服务可主动降级。比如说反欺诈校验出问题了,那么它主动降级后应用它的默认策略,极其状况下只做明码校验,主库挂了之后还能到从库读取用户信息。 最初就是接口的安全性校验。对App接口咱们须要做防重放和验签。验签可能大家比拟相熟,然而对防重放这个概念可能绝对生疏。防重放,顾名思义就是避免申请反复发送。用户申请在特定时间段内只能申请一次。即便用户申请被攻击者挟持,在一段时间内也无奈反复申请。如果攻击者想要篡改用户申请再发送,对不起,申请不会通过。得益于大数据的反对,联合终端,咱们还能够把每个用户行为画像存储在零碎中(或者调用第三方服务)。用户发动申请后,咱们的接口会依据用户画像对用户进行诸如手机号码校验、实名认证、人脸或者活体校验。 三、分库分表随着用户的增长,数据超过了1亿,怎么办?常见的方法就是分库分表。咱们来剖析一下用户核心常见的一些表构造:用户信息表,第三方登录关联表,用户事件表。从上述表中能够看进去,用户相干的数据表增长绝对迟缓,因为用户增长是有天花板的。用户事件表的增长是呈指数级增长,因为每个用户登录、变更等明码及变更手机号码等操作是不限次数。 因而,首先咱们能够先把用户信息表垂直切分。正如下面说的,将用户ID、明码、手机号、盐值等常见字段从用户信息表中拆分,其余用户相干的信息用独自一张表。另外,把用户事件表迁徙至其余库中。相比于程度切分,垂直切分的代价绝对较少,操作起来绝对简略。用户外围信息表因为数据量绝对较少,即便是亿级别的数据,利用数据库缓存的机制,也可能解决性能问题。 其次,咱们能够利用前后台业务的个性采纳不同的形式来区别对待。对于用户侧前台拜访:用户通过username/mobile登录或者通过uid来查问用户信息。用户侧信息的拜访通常是单条数据的查问,咱们能够通过索引屡次查问来解决一致性和高可用问题。对于经营侧后盾拜访:依据年龄、性别、登录时间段、注册时间段等来进行查问,基本上都是批量分页查问。然而因为是外部零碎,查问量低,对一致性要求低。如果用户侧和经营侧的查问采纳同一个数据库,那么经营侧的排序查问会导致整个库的CPU回升,查问效率降落,影响到用户侧。因而,经营侧应用的数据库能够是和用户侧同样的MySQL离线库,如果想要减少经营侧的查问效率,能够采纳ES非关系型数据库。ES反对分片与复制,不便程度宰割和扩大,复制保障了ES的高可用与高吞吐,同时可能满足经营侧的查问需要。 最初,如果还是要程度切分来保证系统的性能,那么咱们采取什么样的切分形式呢?常见的办法有索引表法和基因法。索引表法的思路次要是UID可能间接定位到库,然而手机号码或者username是无奈间接定位到库的,须要建设一个索引表来记录mobile与UID或者username与UID的映射关系的形式来解决这个问题。通常这类数据比拟少,能够不必分库分表,然而相比间接查问,多了一次数据库查问的同时,在新增数据的时候还多了一次映射关系的插入,事务变大。基因法的思路是咱们将username或者mobile融入到UID中。具体做法如下:、 用户注册时,依据用户的手机号码,利用函数生成N bit的基因mobile\_gen,使得mobile\_gen=f(mobile);生成M bit全局惟一的id,作为用户标识;拼接M和N,作为UID赋给用户;依据N bit来取余来插入到特定数据库;查找用户数据的时候,将用户UID的后N bit取余来落到最终的库中。从上述过程中看,基因法只实用于某类常常查问的场景,比方用手机号码登录,如果用户应用username登录就比拟麻烦了。因而大家以依据本人的业务场景来抉择不同的形式程度切分。 四、Token之柔性降级用户登录之后,另一个重要的事件就是Token的生成与校验。用户的Token分为两类, 一类是web端登陆生成的Token, 这个Token能够和Cookie联合, 达到单点登陆的成果,在此不细说了。另外一类就是APP端登录生成的Token。用户在咱们的APP输出用户名明码之后,服务端会对用户的用户名明码进行校验,胜利之后从系统配置核心获取加密算法的版本以及秘钥,并依照肯定的格局排列用户ID,手机号、随机码以及过期工夫,通过一系列的加密之后,生成了Token之后并将其存入Redis缓存。而Token的校验就是把用户ID和Token组合并校验是否在Redis中存在。那么如果Redis不可用了怎么办呢?这里有一个高可用和主动降级的设计。当Redis不可用的时候, 服务端会生成一个非凡格局的Token。当校验Token的时候,会对Token的格局进行一个判断。 如果判断为Redis不可用时生成的Token,那么服务端会对Token进行解密,而Token的生成是由用户ID,手机号、随机码和过期工夫等数据依照特定顺序排列并加密而来的, 那么解密进去的数据中也蕴含了ID,手机号码,随机码和过期工夫。服务端会依据获取到的数据查询数据库, 比对之后通知用户是否登录胜利。因为内存缓存redis和数据库缓存性能的差距,在redis不可用的状况下,降级有可能会导致数据库无奈及时响应,因而须要在降级的办法上退出限流。 五、数据安全数据安全对用户核心来说十分重要。敏感数据须要脱敏解决,对明码更是要做多重的加密解决。利用尽管有本人的安全策略,但如果把黑客限度在登录之前,那利用的安全性将失去大幅度的晋升。互联网上用户明文数据受到泄露的案件每每产生,因而各大企业对数据安全的意识也提到了前所未有的高度。而即便应用了MD5和salt的加密形式,仍然能够应用彩虹表的形式来破解。那么用户核心对用户信息是怎么保留的呢? 首先,正如上文中提到的用户明码、手机号等登录信息和其余的信息拆散,而且在不同的数据库中。其次,对用户设置的明码进行了黑名单校验,只有符合条件的弱明码,都会回绝提交,因为不论应用了什么加密形式的弱明码,都极其容易破解。为什么呢?因为人的忘性很差,大部分人总是最偏向于抉择生日,单词等来当明码。6位纯数字能够生成100万个不同的明码,8位小写字母和数字的组合大略能够生成2.8万亿个不同的明码。一个规模为7.8万亿的明码库足以笼罩大部分用户的明码,对于不同的加密算法都能够领有这样一个明码库,这也就是为什么大部分网站都倡议用户应用8位以上数字加字母明码的起因。当然,如果一方面加了盐值,另一方面对密钥离开保存,破解难度会指数级减少。 最初,能够用bcrypt/scrypt的形式来加密。bcrypt算法是基于Blowfish块密钥算法来实现的,bcrypt外部实现了随机加盐解决,应用bcrypt之后每次加密后的密文都不一样,同时还会应用内存初始化hash过程。因为应用内存,尽管在CPU上运行很快,然而在GPU上并行运算并不快。随着新的FPGA集成了大型RAM,解决了内存密集IO的问题,然而破解难度仍然不小。而scrypt算法补救了bcrypt算法的有余,它将CPU计算与内存应用开销都指数级晋升了。bcrypt和scrypt算法可能无效抵挡彩虹表,然而安全性的晋升带来了用户登录性能的降落。用户登录注册并不是一个高并发的接口,所以影响并不会特地大。因而在平安和性能方面须要根据业务类型和大小来做均衡,并不是所有的利用都须要应用这种加密形式来爱护用户明码。 六、异步生产设计此处的异步生产,就是上文提到的异步生产服务。用户在做完登录注册等操作后,须要记录用户的操作日志。同时,用户注册登录结束后,上游业务须要对用户减少积分,赠送礼券等处分操作。这些零碎如果都同步依赖于用户核心,那么整个用户核心将异样宏大,链路十分简短,也不合乎业内的“大零碎做小“的准则。依赖的服务不可用之后将会造成用户无奈登录注册。因而,用户核心在用户操作完之后,将用户事件入库后发送至MQ,第三方业务监听用户事件。用户核心和上游业务解耦,同时用户操作事件入库后,在MQ不可用或者音讯失落的时候可做弥补解决。用户的画像数据也在很大水平上来源于此处的数据。 七、灵活多样的监控用户核心波及到用户的登录注册更改明码等外围性能,是否及时发现零碎的问题成为要害指标,因而对业务的监控显得尤为重要。须要对用户核心重要接口的QPS、机器的内存使用量、垃圾回收的工夫、服务的调用工夫等做具体的监控。当某个接口的调用量降落的时候,监控会及时发出报警。除了这些监控之外,还有对数据库Binlog的写入,前端组件,以及基于ZipKin全链路调用工夫的监控,实现从用户发动端到完结端的全面监控,哪怕呈现一点问题,监控随时会通知你哪里出问题了。比方经营互动推广注册量降落的时候,用户核心就会发出报警,能够及时告诉业务方改过问题,挽回损失。 八、总结本文从服务架构设计,接口设计,token降级,数据安全和监控等方面介绍了亿级用户核心的设计,当然用户核心的设计远不止这些,还会蕴含用户数据的分库分表,熔断限流,第三方登录等,在本文中就不一一赘述。只管本文中设计的用户核心可能满足大部分公司的需要,然而还存在一些比拟大的挑战:在鉴权服务增长的状况下,如何平滑的从用户核心剥离;监控的侵入性以及监控的粒度的欠缺;另外服务的安全性、可用性、性能的晋升永远都没有止境,也是咱们孜孜追求的指标。在将来的日子里,心愿可能通过大家的致力,使用户核心的技术体系更上一层楼。 作者:vivo 游戏技术团队

March 8, 2021 · 1 min · jiezi

关于架构设计:数据中心架构设计比较

交换机的互联和数据通信的保障是设计一个数据中心的根本方面。当今的数据中心都是由1RU或者2RU的设施组成。因而能够将1RU或者2RU的交换机放到racks外面能够大大的节俭空间,简化布线。典型的,ToR(Top of Rack)和EoR(End of Rack)是以后比拟常见的数据中心架构设计。这篇文章次要探讨这两种架构的差别。 ToR & EoR综述什么是ToR?ToR就是将网络接入交换机放在一个服务器机架的下面。服务器间接连到接入交换机。每个服务器机架往往有一个或者两个接入交换机。而后所有的接入交换机都会连到机架外面的汇聚交换机。只须要大量的线缆从服务器机架连到汇聚层机架。 下面是EoR?在EoR架构中,每个机架内的服务器间接连到汇聚层机架的交换机。这缩小了网络设备的数量,进步了网络设备的端口利用率。然而须要大量的程度布线。和EoR同时存在的是MoR(Middle of Row),次要的差别是交换机放在一排机架的两头,线缆长度缩短了。 ToR和EoR的比拟长处对于ToR来说,布线老本降落了,因为所有服务器只须要连贯到它本人的机架,网络设备机架和服务器机架之间的线缆变少了。同时,线缆治理也变得简略了。技术人员增加,缩小线缆变得简略。 对于EoR来说,设施数量缩小了,因为不是所有的机架都有交换机了。因而所需的机架空间也变少了。数据中心的设施越少,对制冷设施的要求越低,能耗更少了。 毛病绝对的,每个架构都有他们的毛病。对于ToR来说,尽管布线变少了,然而所需的机架空间增大了。交换机的治理可能有一点简单。 对于EoR,它的二层替换效率比ToR差,因为当同一个机架同一个VLAN上的两个服务器之间想要通信的时候,流量会先流到汇聚层交换机,而后再流回来。同时,因为EoR设计的时候只有大量交换机,须要在机架之间部署更多的线缆,从而更有可能造成线缆凌乱。须要更加优良的技术人员来做线缆治理。 ToR和EoR的物理部署ToR部署一个是冗余接入交换机的部署,这往往须要两个高速ToR交换机连贯到核心网。服务器连贯到机架上的接入交换机。还有一个是服务器连贯汇聚。两个高速ToR交换机是在一个虚构的chassis下面。服务器能够连贯到任意一个交换机(连贯汇聚技术)。 EoR部署EoR接入交换机部署到整排服务器机架的尾部。如果部署须要反对现有的布线,也能够用虚构chassis。 论断ToR和EoR是常见的数据中心架构设计。抉择一个适合的网络架构能够晋升数据中心的效率。从这篇文章,你能够对支流数据中心架构有一个大抵的理解。 关注公众号:网络技术平台,回复 “ 材料 ” 获取视频、培训教程、试验手册、电子书。

February 24, 2021 · 1 min · jiezi

关于架构设计:网关现有架构及优化

网关技术实现如图: 网关初始化时,从redis获取配置,包含路由信息,机构的密钥(用于业务数据加解密),平台对机构的公私钥(用于签名验签),机构可拜访api的权限,机构黑白名单。并将这些配置信息保留至内存。这些信息在治理端配置。通过redis对配置变动进行监听,如果有变动则更新内存或重建路由路由信息包含后端对接形式,后端地址,依照api名称和版本进行断言与后端对接形式目前有三种: http:惯例的gateway转发性能lb:gatewa转发到注册至eureka的服务,利用场景为适配器,如果网关输入的参数格局和后端须要的不相符,须要裁剪参数mq:异步调用http的反对: 增加path断言,裸露同一对外入口增加apiName和apiVersion断言,找到须要转发的后盾路由,进入对应过滤器重写path,改为自定义的后盾服务地址。如果通过一系列过滤器,则转发至相应服务lb的反对: 增加path断言,裸露同一对外入口增加apiName和apiVersion断言,找到须要转发的后盾路由,进入对应过滤器后盾地址命名规定为/service-name/url,解析后盾地址,设置route的uri为service-name即注册至eureka的服务名称,rewritepath为url,即理论调用的后盾地址。addRequestHeader增加申请头,设置明码,标记为gateway转发来的申请。Lb的后盾服务对header进行校验。mq的反对: 增加path断言,裸露同一对外入口增加apiName和apiVersion断言,找到须要转发的后盾路由,进入对应过滤器配置后端scheme为mq定义全局过滤器:如果scheme为mq,则为mq类的路由。 新建uuid,将(uuid, rsp)放入map中,而后将蕴含uuid的申请发送至mq。网关收到mq响应时,同样会失去uuid,再从map中获取rsp进行响应。将(uuid, rsp)放入map的同时,也会将(uuid,curenttime)放入exceedMap中,网关会定时查看mq类的交易是否超时。(exceedMap革新为linkedHashMap)mqfilter的isAlready。。因为是全局路由,解决mq/http协定的最初的filter;对于http,防止走了nettyroute又走forward技术演进: 最开始只有互联网网关,对接的是内部机构,须要对参数进行加解密,签名验签。后续有了新的需要:开发外部网关:公司外部的零碎做为调用方,走的内网不须要加密,只进行md5验证即可。互联网网关和外部网关有共用的filter,也有各自独有的filter。与后端的对接形式也有所不同,外部网关没有lb的对接模式。 提取公共filter,定义共性filter,可自由组合filter和predicate进而构建网关按需配置:有时须要在内网环境部署网关进行功能测试,只须要配置一条http路由即可,没必要部署redis和mq,因而配置信息应反对从配置文件中读取,并且不去监听配置的变动。路由信息的读取也应按对接形式分为http,lb和mq类,依据网关须要按需配置。 路由配置化移除对redis的依赖网关性能按需组合全局与部分filter:原架构filter均为全局filter,由map决定交易是否走这个路由。现改为部分路由,创立路由addCommonFilter的时候增加。(未实现,因为须要改路由模型,比拟麻烦)对于同一类网关,断言形式和公共过滤器是雷同的,而不同的对接模式有各自的filter。为了实现filter的复用及灵便配置,定义了GatewayRouteDynamicService类,其中RouteUpdate办法创立一类路由的流程模板: 从数据源获取路由信息apiPlan增加网关公共断言(实现addCommonPredicate接口)增加公共过滤器(实现addCommonFilter)增加特定断言/过滤器(实现addSpecificDynamicRoute)公布路由扩展性的实现: 不同的网关实现各自的addCommonPredicate,addCommonFilter接口,可增加该类网关的共有断言及接口。如果token校验,加解密有不同的实现形式,重写filter增加到CommonFIlter里即可不同的路由类型实现addSpecificDynamicRoute接口,如http,mq,lb数据源可选redis和配置文件可选是否监听数据源的变动,如果监听,须要应用redis后续数据源和监听反对抉择zk等中间件目前断言为apiName+version对应一条路由。也反对依据传入的机构号,银行号进行路由,继承predicateFactory类,实现addCommonPredicate即可。gateway几大功能模块: 加载并初始化路由: 次要是按与后端的对接形式划分,如果有新的对接形式,实现addSpecificDynamicRoute接口如果有mq的路由: 配置mq响应监听:因为有多个gateway实例,同一交易的申请和响应应该由同一个gateway解决。不同gateway的申请queue地址一样,但响应queue不同。响应queue地址在申请交易jms信息的reply字段,因而后盾服务只需配置申请queue,响应queue蕴含在申请的jms信息中。这里响应queue地址为service_name + docker.slot(1, 2, 3…)。这样服务每次重启时,响应queue地址不会变动。如果gateway弹性扩大,slot+1,不必改变配置文件,实现主动扩容。如果响应queue为docker容器虚构ip,服务每次都会新建queue,会非常凌乱。超时mq音讯解决:在exceedMap中查看是否有超时交易读取配置: 去除对redis的依赖,可抉择从redis或者配置文件。注入redis或配置文件的实现类。实现配置的获取和实现的拆散,配置批改监听和配置获取的拆散监听配置批改: 能够抉择不去监听,或者通过redis,zk监听监听新的配置,如某个api的限流大小,监听某个key如change,如果变动值为value,就从spring中找到名字为value的bean,调用run办法。如果减少新配置,不必再if else或switch地改变代码,新建类即可,实现对扩大凋谢,批改敞开。劣势: 更加形象,扩展性更强,劣势: 架构更加简单,调试不便,学习曲线平缓网关搭建好之后,须要欠缺对网关交易的监控性能。咱们须要实时(准实时)把握交易状况和网关的运行状况,如: 交易监控统计: 交易总比数随工夫的变动过来一段时间哪些机构调用哪个银行的哪些api,哪些api被调用的次数最多有没有异样交易,如超时,后盾服务挂掉等引起的失败交易交易告警: 配置告警规定,如果有异样交易,及时发出通知交易链路日志查看: 通过流水号查看网关链路的日志出报表: 过来一段时间机构,银行,api级别的调用统计状况,便于统计免费网关服务监控: 过来一段时间网关内存应用,gc,沉闷线程数等jvm信息,如果有异样及时告警异样解决: 网关转发申请到后盾的异样: 无奈连贯后盾连贯超时自定义异样: filter未通过的异样,如参数校验失败,token校验失败,加解密失败等;断言异样,网关未匹配到路由未知异样: 运行时异样等这些异样在对立的中央由handler解决。对于mq类交易异样,个别只有响应超时异样,由守护线程AutoGcFlux解决。

February 21, 2021 · 1 min · jiezi

关于架构设计:一些代码开发的感受

什么是好的代码: 复用性强,高可扩大,易保护,可读性强面向接口编程高内聚低耦合配置化,做不到动静失效起码应做到配置化,不要硬编码灵活性,模块化架构及代码层面的简洁和优雅利用类的封装性、继承性和多态性,灵活运用接口组合思考这样写好不好扩大,有没有裸露不必要的接口设计模式六大准则: 繁多职责凋谢关闭里氏替换:对扩大的凋谢,对批改的敞开成果依赖倒置:模块间依赖通过形象产生,实现类之间不产生间接依赖关系,其依赖关系是通过接口或者抽象类产生的。如果类与类间接依赖细节,那么久会间接耦合。接口隔离:建设繁多接口,不要建设宏大臃肿接口;尽量细化接口,接口中办法尽量少。迪米特

February 17, 2021 · 1 min · jiezi

关于架构设计:HDFS架构演变之路

前言Hadoop到目前为止倒退曾经有10余年,版本通过了无数次的更新迭代,目前业内大家把Hadoop大的 版本分为Hadoop1,hadoop2,Hadoop3三个版本。 1 hadoop1hadoop1版本刚进去的时候是为了解决两个问题: 海量数据如何存储的问题海量数据如何计算的问题Hadoop1的外围设计就是HDFS和Mapreduce。 2 HDFS1架构HDFS1是一个主从式的架构,主节点只有一个叫NameNode。从节点有多个叫DataNode。 2.1 NameNode治理元数据信息(文件目录树):文件与Block块,Block块与DataNode主机的关系。NameNode为了疾速响应用户的操作申请,所以把元数据加载到了内存外面。2.2 DataNode存储数据,把上传的数据划分成为固定大小的文件块。(Hadoop1,默认是64M。Hadoop2,128M)为了保障数据安全,每个文件块默认都有三个正本。3 HDFS1的架构缺点尽管HDFS1当初设计进去能够解决海量数据存储的问题,但在应用的过程中缓缓的呈现了一些缺点,其中次要为以下两点: 单点故障问题内存受限问题3.1 单点故障单点故障顾名思义就是单个节点产生了问题,导致HDFS呈现了致命的缺点。咱们都晓得HDFS集群是有多个节点组成的,其中最为重要的节点就是NameNode所在的节点。NameNode主持着所有数据存储的元数据信息。一旦NameNode产生故障则整个HDFS就不可用了。 3.1.1 高可用那么HDFS为了解决这个问题,就提出了高可用的计划,意思就是多一个NameNode,当其中一个挂了或失去通信的时候,另外一个能够代替,从而维持HDFS的可用性,实现主动容灾的性能。 为了实现主动容灾,能够引入第三方框架集群,这里zookeeper就退场了。zookeeper在与NameNode进行通信的时候会创立一把锁,持有这把锁的NameNode则被当作active NameNode,另外备份的NameNode被当作standby NameNode。同时后盾还会起一个监听的线程ZKFC来监测NameNode。一旦监测到active NameNode呈现问题,则standby NameNode主动切换。 3.1.2 数据一致性问题引入另外一个NameNode就要思考数据一致性的问题。以后的NameNode挂掉状况下,高可用的NameNode顶上的时候若是与之前挂掉的NameNode元数据信息保留不统一的话,则会产生一些申请找不到对应数据的状况。会让咱们从主观意识的数据缺失了。 3.1.3 JournalNode那么为了防止这一景象的产生就要保持数据的一致性。这里HDFS引入了共享文件系统的概念,它会在后盾启动肯定数量的JournalNode过程(同步存储元数据,压力较小),组成一个共享的文件系统,存储元数据(editlog)。当然journalNode自身也是实现高可用的。active NameNode将元数据实时写入JournalNode,standby NameNode实时读取元数据信息,从而维持active NameNode,standby NameNode两者元数据统一。 3.2 内存受限高可用计划让单点故障问题得以解决。也让咱们晓得了NameNode的重要性,咱们之所以能这么快的通过NameNode检索到存储在DataNod的数据,是因为NameNode将元数据都读取到内存中,检索效率大大超于磁盘。 那么随着数据的与日俱增,元数据的越来越宏大,NameNode的内存是否够存在受限。答案是肯定存在的,NameNode自身也是一台服务器,拆卸的内存必定是受限的。那么当内存受限的时候,增加这台的内存也是能够长期解决当务之急的。但却治标不治本。咱们自身集群由这么多台服务器组成,一台节点的内存不够用,能够利用其余的服务器内存来实现这数据的检索。 所以,这里HDFS就使用了联邦机制(Federation)。 3.2.1 联邦机制(Federation)联邦机制的原理就是将NameNode划分为不同的命名空间并进行编号(这里能够想像成计算机中的C,D,E盘等)。不同的命名空间之间互不烦扰。在DataNode中创立目录,此目录对应命名空间的编号。由此,编号雷同的数据由对应的命名空间进行治理。当然为了防止单点故障问题,仍旧采纳高可用计划。 HDFS2架构由此,HDFS解决了单点故障和内存受限的问题,HDFS1也进入了HDFS2的时代,这也是咱们当初常常应用的版本,也是绝对稳固版本。 HA计划(High Available)解决HDFS1 NameNode单点故障问题。联邦计划解决了HDFS1 内存受限问题。HDFS3架构至于HDFS3是在HDFS2的根底上优化了HA计划,并退出了纠删码的技术。 HA计划反对多个NameNode引入纠删码技术(EC)HA计划的优化次要是反对了多个NameNode,使得生产环境更加牢靠一些。纠删码技术诞生的背景是因为HDFS中3个正本的存储开销在某些场景下过大。例如一些冷数据的存储3份正本对于老本来说就显得有些节约了。因而,一个天然的改良是应用纠删码(EC)来代替正本,它提供了同等级别的容错能力,而且存储空间大大减少。在典型的纠删码(EC)设置中,存储开销不超过50% 。EC 文件的复制因子是无意义的。它总是1,不能通过 -setorp 命令更改。 有了纠删码技术的退出,故而HDFS3既进步了存储效率的同时又放弃住了数据的持久性的特点。

February 5, 2021 · 1 min · jiezi

关于架构设计:DDD分层架构最佳实践

还在单体利用的时候就是分层架构一说,咱们用得最多的就是三层架构。而当初曾经是微服务时代,在微服务架构模型比拟罕用的有几个,例如:整洁架构,CQRS(命令查问拆散)以及六边形架构。每种架构模型都有本人的利用场景,但其外围都是“高内聚低耦合”准则。而使用畛域驱动设计(DDD)理念以应答日常减速的业务变动对架构的影响,架构的边界越业越清晰,各施其职,这也合乎微服务架构的设计思维。以畛域驱动设计(DDD)为理念的分层架构曾经成为微服务架构实际的最佳实际办法。 一、什么是DDD分层架构1. 传统三层架构要理解DDD分层架构,首页先理解传统的三层架构。 传统三层架构流程: 第一步思考的是数据库设计,数据表如何建,表之间的关系如何设计第二步就是搭建数据拜访层,如选一个ORM框架或者拼接SQL操作第三步就是业务逻辑的实现,因为咱们先设计了数据库,咱们整个的思考都会围绕着数据库,想着怎么写能力把数据正确地写入数据库中,这时CRUD的规范作法就呈现了,也就没有太多思考面向对象,解耦的事件了,这样的代码对日常的保护天然是越来越艰难的第四步表示层次要面向用户的输入2. DDD分层架构 为了解决高耦合问题并轻松应答当前的零碎变动,咱们提出了使用畛域驱动设计的理念来设计架构。 此段落局部总结来源于欧翻新《DDD实际课》的《07 | DDD分层架构:无效升高层与层之间的依赖》读后感1)畛域层首先咱们抛开数据库的困扰,先从业务逻辑动手开始,设计时不再思考数据库的实现。将以前的业务逻辑层(BLL)拆分成了畛域层和应用层。 畛域层聚焦业务对象的业务逻辑实现,体现事实世界业务的逻辑变动。它用来表白业务概念、业务状态和业务规定,对于业务剖析可参照:《应用畛域驱动设计剖析业务》 2)应用层应用层是畛域层的下层,依赖畛域层,是各聚合的协调和编排,原则上是不包含任何业务逻辑。它以较粗粒度的关闭为前端接口提供反对。除了提供下层调用外,还能够包含事件和音讯的订阅。 3) 用户接口层用户接口层面向用户拜访的数据入向接口,可按不同场景提供不一样的用户接口实现。面向Web的可应用http restful的形式提供服务,可减少平安认证、权限校验,日志记录等性能;面向微服务的可应用RPC形式提供服务,可减少限流、熔断等性能。 4) 基础设施层基础设施层是数据的出向接口,封装数据调用的技术细节。可为其它任意层提供服务,但为了解决耦合的问题采纳了依赖倒置准则。其它层只依赖基础设施的接口,于具体实现进行拆散。 二、DDD分层代码实现1. 构造模型 2. 目录构造.├── pom.xml└── src ├── main │   ├── java │   │   └── fun │   │   └── barryhome │   │   └── ddd │   │   ├── WalletApplication.java │   │   ├── application │   │   │   ├── TradeEventProcessor.java │   │   │   ├── TradeMQReceiver.java │   │   │   └── TradeManager.java │   │   ├── constant │   │   │   └── MessageConstant.java │   │   ├── controller │   │   │   ├── TradeController.java │   │   │   ├── WalletController.java │   │   │   └── dto │   │   │   └── TradeDTO.java │   │   ├── domain │   │   │   ├── TradeService.java │   │   │   ├── TradeServiceImpl.java │   │   │   ├── enums │   │   │   │   ├── InOutFlag.java │   │   │   │   ├── TradeStatus.java │   │   │   │   ├── TradeType.java │   │   │   │   └── WalletStatus.java │   │   │   ├── event │   │   │   │   └── TradeEvent.java │   │   │   ├── model │   │   │   │   ├── BaseEntity.java │   │   │   │   ├── TradeRecord.java │   │   │   │   └── Wallet.java │   │   │   └── repository │   │   │   ├── TradeRepository.java │   │   │   └── WalletRepository.java │   │   └── infrastructure │   │   ├── TradeRepositoryImpl.java │   │   ├── WalletRepositoryImpl.java │   │   ├── cache │   │   │   └── Redis.java │   │   ├── client │   │   │   ├── AuthFeignClient.java │   │   │   └── LocalAuthClient.java │   │   ├── jpa │   │   │   ├── JpaTradeRepository.java │   │   │   └── JpaWalletRepository.java │   │   └── mq │   │   └── RabbitMQSender.java │   └── resources │   ├── application.properties │   └── rabbitmq-spring.xml └── test └── java此构造为繁多微服务的简略构造,各层在同一个模块中。 ...

January 21, 2021 · 4 min · jiezi

关于架构设计:基于-DDD-的微服务设计和开发实战

你是否还在为微服务应该拆多小而争论不休?到底如何能力设计出收放自如的微服务?怎样才能保障业务畛域模型与代码模型的一致性?或者本文能帮你找到答案。 本文是基于 DDD 的微服务设计和开发实战篇,通过借鉴畛域驱动设计思维,领导微服务项目团队进行设计和开发(实践篇详见《当中台遇上 DDD,咱们该如何设计微服务?》)。本文包含三局部内容:第一局部讲述畛域驱动设计基本知识,包含:分层架构、服务视图、数据视图和畛域事件公布和订阅等;第二局部讲述微服务设计办法、过程、模板、代码目录、设计准则等内容;最初局部以一个我的项目为例讲述基于 DDD 的微服务设计过程。 一、指标本文采纳 DDD(畛域驱动设计)作为微服务设计指导思想,通过事件风暴建设畛域模型,正当划分畛域逻辑和物理边界,建设畛域对象及服务矩阵和服务架构图,定义合乎 DDD 分层架构思维的代码构造模型,保障业务模型与代码模型的一致性。通过上述设计思维、办法和过程,领导团队依照 DDD 设计思维实现微服务设计和开发。 通过畛域模型和 DDD 的分层思维,屏蔽内部变动对畛域逻辑的影响,确保交付的软件产品是边界清晰的微服务,而不是外部边界仍然凌乱的小单体。在需要和设计变动时,能够轻松的实现微服务的开发、拆分和组合,确保微服务不易受内部变动的影响,并稳固运行。 二、适用范围本文实用于依照 DDD 设计办法进行微服务设计和开发的我的项目及相干人员。 以下状况不实用: “咱们的指标是按期盖出一栋大楼来,不要跟我提什么办法,有这啰嗦的工夫,还不如放松点工夫搬砖,把楼给我快点盖好!”。“我的工作就是让软件运行起来,能工作所有就 OK!我不须要那么多束缚,什么设计办法、扩展性、业务变动、畛域模型、响应能力与我无关。别耽搁工期啦!先上线再说!”。“好的软件是本人演进进去的,咱们不须要设计!”。哈哈,开个玩笑啦!其实设计不会花太多工夫的! 不耽搁大家工夫了,言归正传。 三、DDD 分层架构视图DDD 分层架构包含:展示层、应用层、畛域层和根底层。 DDD 分层架构各层职能如下: 展示层展示层负责向用户显示信息和解释用户指令。 应用层应用层是很薄的一层,次要面向用户用例操作,协调和指挥畛域对象来实现业务逻辑。应用层也是与其余零碎的应用层进行交互的必要渠道。应用层服务尽量简略,它不蕴含业务规定或常识,只为下一层的畛域对象协调工作,使它们相互合作。应用层还可进行平安认证、权限校验、分布式和长久化事务管制或向内部利用发送基于事件的音讯等。 畛域层畛域层是软件的外围所在,它实现全副业务逻辑并且通过各种校验伎俩保障业务正确性。它蕴含业务所波及的畛域对象(实体、值对象)、畛域服务以及它们之间的关系。它负责表白业务概念、业务状态以及业务规定,具体表现形式就是畛域模型。 根底层根底层为各层提供通用的技术能力,包含:为应用层传递音讯、提供 API 治理,为畛域层提供数据库长久化机制等。它还能通过技术框架来反对各层之间的交互。 四、服务视图微服务内的服务视图微服务内有 Facade 接口、应用服务、畛域服务和根底服务,各层服务协同配合,为内部提供服务。 1、接口服务接口服务位于用户接口层,用于解决用户发送的 Restful 申请和解析用户输出的配置文件等,并将信息传递给应用层。 2、应用服务应用服务位于应用层。用来表述利用和用户行为,负责服务的组合、编排和转发,负责解决业务用例的执行程序以及后果的拼装。 应用层的服务包含应用服务和畛域事件相干服务。 应用服务可对微服务内的畛域服务以及微服务外的应用服务进行组合和编排,或者对根底层如文件、缓存等数据间接操作造成应用服务,对外提供粗粒度的服务。 畛域事件服务包含两类:畛域事件的公布和订阅。通过事件总线和音讯队列实现异步数据传输,实现微服务之间的解耦。 3、畛域服务畛域服务位于畛域层,为实现畛域中跨实体或值对象的操作转换而封装的服务,畛域服务以与实体和值对象雷同的形式参加施行过程。 畛域服务对同一个实体的一个或多个办法进行组合和封装,或对多个不同实体的操作进行组合或编排,对外裸露成畛域服务。畛域服务封装了外围的业务逻辑。实体本身的行为在实体类外部实现,向上封装成畛域服务裸露。 为暗藏畛域层的业务逻辑实现,所有畛域办法和服务等均须通过畛域服务对外裸露。 为实现微服务内聚合之间的解耦,原则上禁止跨聚合的畛域服务调用和跨聚合的数据互相关联。 4、根底服务根底服务位于根底层。为各层提供资源服务(如数据库、缓存等),实现各层的解耦,升高内部资源变动对业务逻辑的影响。 根底服务次要为仓储服务,通过依赖反转的形式为各层提供根底资源服务,畛域服务和应用服务调用仓储服务接口,利用仓储实现长久化数据对象或间接拜访根底资源。 微服务外的服务视图1. 前端利用与微服务微服务中的应用服务通过用户接口层组装和数据转换后,公布在 API 网关,为前端利用提供数据展现服务。 2. 微服务与内部利用跨微服务数据处理时,对实时性要求高的场景,可抉择间接调用应用服务的形式(新增和批改类型操作需关注事务一致性)。对实时性要求不高的场景,可抉择异步化的畛域事件驱动机制(最终数据一致性)。 五、数据视图DDD 分层架构中数据对象转换的过程如下图。 数据视图应用服务通过数据传输对象(DTO)实现内部数据交换。畛域层通过畛域对象(DO)作为畛域实体和值对象的数据和行为载体。根底层利用长久化对象(PO)实现数据库的替换。 DTO 与 VO 通过 Restful 协定实现 JSON 格局和对象转换。 ...

January 19, 2021 · 1 min · jiezi

关于架构设计:vivo-全球商城订单中心架构设计与实践

一、背景随着用户量级的快速增长,vivo 官网商城 v1.0 的单体架构逐步暴露出弊病:模块愈发臃肿、开发效率低下、性能呈现瓶颈、系统维护艰难。 从2017年开始启动的 v2.0 架构降级,基于业务模块进行垂直的零碎物理拆分,拆分进去业务线各司其职,提供服务化的能力,独特撑持主站业务。 订单模块是电商零碎的交易外围,一直累积的数据行将达到单表存储瓶颈,零碎难以撑持新品公布和大促流动期间的流量,服务化革新势在必行。 本文将介绍 vivo 商城 订单零碎建设的过程中遇到的问题和解决方案,分享架构设计教训。 二、零碎架构将订单模块从商城拆分进去,独立为订单零碎,应用独立的数据库,为商城相干零碎提供订单、领取、物流、售后等标准化服务。 零碎架构如下图所示: 三、技术挑战3.1 数据量和高并发问题首先面对的挑战来自存储系统: 数据量问题随着历史订单一直累积,MySQL中订单表数据量已达千万级。 咱们晓得InnoDB存储引擎的存储构造是B+树,查找时间复杂度是O(log n),因而当数据总量n变大时,检索速度必然会变慢, 不论如何加索引或者优化都无奈解决,只能想方法减小单表数据量。 数据量大的解决方案有:数据归档、分表 高并发问题商城业务处于高速发展期,下单量屡翻新高,业务复杂度也在晋升,应用程序对MySQL的访问量越来越高。 单机MySQL的解决能力是无限的,当压力过大时,所有申请的访问速度都会降落,甚至有可能使数据库宕机。 并发量高的解决方案有:应用缓存、读写拆散、分库 上面对这些计划进行简略形容: 数据归档订单数据具备工夫属性,存在热尾效应,大部分状况下检索的都是最近的订单,而订单表里却存储了大量应用频率较低的老数据。 那么就能够将新老数据离开存储,将历史订单移入另一张表中,并对代码中的查问模块做一些相应改变,便能无效解决数据量大的问题。 应用缓存应用Redis作为MySQL的前置缓存,能够挡住大部分的查问申请,并升高响应时延。 缓存对商品零碎这类与用户关系不大的零碎成果特地好,但对订单零碎而言,每个用户的订单数据都不一样,缓存命中率不算高,成果不是太好。 读写拆散主库负责执行数据更新申请,而后将数据变更实时同步到所有从库,用多个从库来分担查问申请。 但订单数据的更新操作较多,下单顶峰时主库的压力仍然没有失去解决。且存在主从同步提早,失常状况下提早十分小,不超过1ms,但也会导致在某一个时刻的主从数据不统一。 那就须要对所有受影响的业务场景进行兼容解决,可能会做一些斗争,比方下单胜利后先跳转到一个下单胜利页,用户手动点击查看订单后能力看到这笔订单。 分库分库又蕴含垂直分库和程度分库。 ① 程度分库:把同一个表的数据按肯定规定拆到不同的数据库中,每个库能够放在不同的服务器上。 ② 垂直分库:依照业务将表进行分类,散布到不同的数据库下面,每个库能够放在不同的服务器上,它的核心理念是专库专用。 分表分表又蕴含垂直分表和程度分表。 *① 程度分表:*在同一个数据库内,把一个表的数据按肯定规定拆到多个表中。 *② 垂直分表:*将一个表依照字段分成多表,每个表存储其中一部分字段。 咱们综合思考了革新老本、成果和对现有业务的影响,决定间接应用最初一招:分库分表 3.2 分库分表技术选型分库分表的技术选型次要从这几个方向思考: 客户端sdk开源计划中间件proxy开源计划公司中间件团队提供的自研框架本人入手造轮子参考之前我的项目教训,并与公司中间件团队沟通后,采纳了开源的Sharding-JDBC计划。现已更名为Sharding-Sphere。 Github:https://github.com/sharding-sphere/文档:官网文档比拟毛糙,然而网上材料、源码解析、demo比拟丰盛社区:沉闷特点:jar包形式提供,属于client端分片,反对xa事务   3.2.1 分库分表策略联合业务个性,选取用户标识作为分片键,通过计算用户标识的哈希值再取模来失去用户订单数据的库表编号. 假如共有n个库,每个库有m张表, 则库表编号的计算形式为: - 库序号:Hash(userId) / m % n- 表序号:Hash(userId) % m 路由过程如下图所示: 3.2.2 分库分表的局限性和应答计划分库分表解决了数据量和并发问题,但它会极大限度数据库的查问能力,有一些之前很简略的关联查问,在分库分表之后可能就没法实现了,那就须要独自对这些Sharding-JDBC不反对的SQL进行改写。 除此之外,还遇到了这些挑战: (1)全局惟一ID设计 分库分表后,数据库自增主键不再全局惟一,不能作为订单号来应用,但很多外部零碎间的交互接口只有订单号,没有用户标识这个分片键,如何用订单号来找到对应的库表呢? ...

December 28, 2020 · 2 min · jiezi

关于架构设计:OPPO互联网业务多活架构演进和实践

OPPO 是如何保障互联网业务的高可用?多活架构如何落地,如何依据业务需要继续演进?针对简单的零碎,如何提供牢靠的监控计划?......OPPO 尽管是一家手机公司,然而其互联网业务的规模十分宏大,月活用户数超过 3 亿,既有内容业务、散发业务,也有商业广告、金融等业务。整体上,用户的应用十分高频,来自客户端的申请和数据量十分宏大,并且这几年始终在继续高速倒退。 随着业务复杂度和并发量迅速减少,OPPO 面临的难题是如何保障互联网业务的高可用?多活架构如何落地,如何依据业务需要继续演进?针对简单的零碎,如何提供牢靠的监控计划?...... 带着这些疑难,InfoQ 记者采访了 OPPO 互联网服务零碎后端框架团队负责人罗工。 据悉,他于 2015 年退出 OPPO,有十余年的研发经验,并在高可用架构、PaaS 平台和根底框架研发等方面有丰盛的实践经验。罗工负责 OPPO 后端框架体系建设,包含 API 网关、微服务框架、服务网格等,且经验了 OPPO 从千万级用户到亿级用户的增长历程。 1. OPPO 业务多活的诉求据罗工介绍,OPPO 业务多活的三个外围诉求是老本、扩大、容灾。 具体说来,老本是指业务总体技术经营老本,包含基础设施的资源老本、研发老本,还包含业务中断的老本、品牌和口碑老本; 扩大是因为业务规模过大,一个服务须要调用数百个三方实例、一个数据库被数百个实例连贯、一个服务须要连贯几十个数据库,架构非常复杂。因而,这就须要对用户进行分片,放大业务规模,天然演进到单元化多活的架构; 容灾,一方面是极其状况下对用户数据可靠性保障的需要,另一方面,因业务过于简单、解决的链路很长,总会呈现一些意外状况,频率还挺高,而问题定位到复原的工夫超过公司 RTO 的要求。机房外部共享运营商线路、DNS、SNAT 防火墙、负载平衡、K8s 集群、注册核心、监控等资源,而机房之间是绝对隔离的环境,同时出问题的概率大幅升高。在业务呈现无奈主动复原的故障时,先切换机房复原业务,而后再从容定位问题根因。 2. 业务多活的两大挑战OPPO 互联网业务有两大特点:一是业务品种多,没有主线;二是十分高频,申请量大。 先说第一大特点:业务品种多,没有主线,很难制订对立的用户单元划分规定。对平台服务的提供方来说,比方流动、评论、账号、积分、内容中台等,所有机房都须要读写,都需全量的数据。因而,要设计一个 N 主全量数据的架构难度十分大。 以业务中台 - 评论零碎为例,多活架构如下: 评论以独立 SDK、独立域名提供服务。防止在业务部署的多个机房的外部调用,否则,评论服务就须要每个机房提供读写服务;记录日志、流水,比方点赞记录、勾销点赞记录,防止批改、计数操作;最终统一。通过订阅的形式更新元数据、缓存,防止双写造成的数据不统一,同时在数据谬误时更容易修复;按用户单元进行调度,用户只会拜访其中一个机房,感知不到两个机房独立更新的元数据的差别。通过以上措施,把平台业务和产品业务离开,防止机房外部调用。 第二大特点是十分高频,申请量大。罗工示意,“一方面,咱们提供的服务自身就是用户应用频率较高的,另一方面,还有一些常驻服务,比方天气、推送通道、软件自更新、手机云服务等。个别的开源技术计划无奈撑持集群的规模,比方 1000 个实例的 Redis 集群,并且运行的老本过高,自愈能力和可观测性有余等,因而须要自研或深度的掌控。这对技术上的挑战很大。” 以 Redis 为例,如上图所示,后端搭建多个 Redis Group,Proxy 实现 Redis 3.0 Cluster 协定,将一部分 slot 流量分发给 Redis Group,这样 Redis Group 的规模就能失去管制。 ...

December 18, 2020 · 2 min · jiezi

关于架构设计:带宽利用率提升50腾讯云联网架构方案解析

导语 | 企业 A 是一家互联网公司,以后在云上计算资源曾经靠近 10W 核,华东地区专线流量 24G+,资源部署以华东为主、华北、华南、东北等可用区为辅。该企业属于典型的混合云架构,本文次要分享企业A如何通过云联网架构优化实现带宽利用率晋升50%,心愿与大家一起交换。文章作者:李彬文,腾讯云售后架构师。一、云联网背景介绍1. 对等连贯概述对等连贯(Peering Connection)是一种大带宽、高质量的云上资源互通服务,能够帮忙买通腾讯云上的资源通信链路。对等连贯具备多区域、多账户、多种网络异构互通等特点,反对 VPC 间互通、VPC 和黑石公有网络互通,满足不同业务的部署需要。 2. 传统专线概述混合云架构后期都是应用传统的专用通道买通用户 IDC 与云上 VPC。如果一根物理专线须要买通多个 VPC,须要通过不同的 VLAN ID 别离创立专用通道来连贯多个VPC。 3. 云联网概述云联网(Cloud Connect Network,CCN)为用户提供云上不同 VPC间、VPC 与本地数据中心间(IDC)内网互联的服务。具备全网多点互联、路由自学习、链路选优及故障疾速收敛等能力。 云联网笼罩寰球 20+ 地区,反对 100+Gbps 带宽以及最高可达 99.99% 的可用性,为用户轻松构建极速、稳固、平安、灵便的寰球互联网络,典型利用场景如下: VPC 与 VPC 间高质量内网互联:在线教育多个地区的实时音视频零碎、游戏减速多地区内网互联、多地区容灾架构。VPC 与 IDC 间内网全互联:一个专用通道买通多个 VPC,实现单次接入全网互联,如混合云场景。 云联网比照对等连贯和传统专线的劣势如下图所示: 下文将从企业 A 的理论登程,介绍企业 A 采纳腾讯云联网的架构优化实际。 二、企业A架构现状介绍1. 企业A混合云背景介绍企业 A 外围业务位于华东地区,在上海有两个 VPC,一个自建 IDC。在北京、成都、广州、HK 各有一个 VPC,其中 HK 的 VPC 用于接入海内业务。 最终通过对等连贯以及传统专线通道实现所有云上 VPC 与自建 IDC 的互联互通(因为传统架构互联线路较多暂不提供具体拓扑,下文提供了合成拓扑)。 ...

December 1, 2020 · 2 min · jiezi

关于架构设计:前端架构学习

1、应用场景1.1、实用场景:本篇文章,实用于单个/多个大型项目、领有超过10个以上的前端开发的场景。前端我的项目的规模不同,老本收益比也会有所差异。通常来说,人员越多、我的项目复杂度越高,那么收益/老本的比值越大。对于人数较少、我的项目简略的开发团队,可能有局部措施不实用,因而应该依据具体情况来选用。 1.2、核心思想:【1】解决问题:前端架构的设计,应是用于解决已存在或者将来可能产生的技术问题,减少我的项目的可管理性、稳定性、可扩展性。【2】人效比:对于须要额定开发工作量的事务(本文中存在一些须要肯定开发量的内容),咱们在决定是否去做的时候,应该思考到两个因素:第一个是破费的人力老本,第二个是将来可能节约的工夫和金钱、防止的项目风险与资损、进步对业务的撑持能力以带来在业务上可掂量的更高的价值、以及其余价值。【3】定性和定量:架构里设计的内容,肯定要有是可掂量的意义的,最好是能够定量的——即能够掂量带来的收益或缩小的老本,至多是能够定性的——即尽管无奈用数字论述收益,但咱们能够明确这个是有意义的,例如减少安全性升高危险。【4】数据敏感:专门写这一条强调数据作为根据的重要性。当咱们须要压服其余部门/下级管理者,以推动咱们设计的内容时,只有数据——特地是跟钱无关的数据,才是最有说服力的证实。因为篇幅所限,本文很难间接给出定量的值,因而倡议架构设计者,先确保我的项目中设计应用2.7里的埋点零碎,依据埋点零碎获取的数据,对我的项目成果进行定量分析,并以此写成PPT和其余部门/下级管理者进行协调。 1.3、切入角度:分为根底层和应用层。根底层偏基础设施建设,与业务相关性较低。应用层更贴近用户,用于解决某一个问题。局部两个都沾边的,依据教训划分到其中一个。 1.4、其余因为曾经谈到架构层级,因而很多内容,并不仅仅只属于前端畛域,有很多内容是复合畛域(前端、后端、运维、测试),因而须要负责架构的人,技术栈足够全面,对将来倒退有足够的前瞻性。文章的内容构造为:【我的项目】—>【解决的问题和带来的益处】—>【我的项目的实际意义】 2、根底层设计2.1、自建Gitlab这个是根底的根底了。本不应该提的,不过思考到我最近面试的几家公司,有的公司(人数并不少)并没有应用Gitlab,因而专门提一下,并且应用这个的难度非常低。强烈建议应用Gitlab进行版本治理,自建Gitlab难度并不大,方便管理,包含代码治理、权限治理、提交日志查问,以及联动一些第三方插件。 意义:公司代码是公司的重要资产,应用自建Gitlab能够无效爱护公司资产。2.2、版本治理版本治理的几个关键点: 公布后分支锁死,不可再更改:指当例如0.0.1版本胜利公布后,不可再更改0.0.1分支上的代码,否则可能会导致版本管理混乱。全自动流程公布;指应防止开发者提交后,手动编译打包等操作,换句话说,开发人员公布后,将主动公布到预公布/生产环境。开发人员不和相干环境间接接触。实现这个须要参考上面的2.3。多版本并存;指当例如公布0.0.2版本后,0.0.1版本的代码应仍保留在线上(例如CDN),这样当呈现线上bug时,不便疾速回滚到上一个版本。意义:进步我的项目的可控性。2.3、主动编译公布Jenkins这个工具用于在代码公布后,执行一系列流程,例如主动编译打包合并,而后再从Gitlab公布到CDN或者动态资源服务器。应用这个工具,能够让个别研发人员不关怀代码传到Gitlab后会产生什么事件,只须要分心于开发就能够了。 意义:让研发人员分心于研发,和环境、运维等事件脱钩。2.4、纯前端版本公布纯前端版本公布分为两步: 前端公布到生产环境——此时能够通过外网链接加正确的版本号拜访到新版本的代码,但页面上的资源还是旧版本;前端通过配置工具(或者是间接更新html文件),将html中引入的资源,改为新版本。解决的问题是:以后端须要公布新版本时,能够不依赖于后端(依据理论状况,也能够不依赖于运维)。毕竟有很多需要并不需要后端染指,单纯改个前端版本后就要后端公布一次,显然是一件十分麻烦的事件。这个须要专门的工具,用于配置版本公布,我最近就在写这个。 意义:进步公布效率,升高公布带来的人员工夫损耗(这些都是钱),也能够在前端版本回滚的时候,速度更快。2.5、对立脚手架实用场景:有比拟多独立中小我的项目。益处: 能够缩小开发人员配置脚手架带来的工夫损耗(非凡性能能够fork脚手架后再自行定制);对立我的项目构造,方便管理,也升高我的项目交接时带来的须要相熟我的项目的工夫;不便对立技术栈,能够事后引入固定的组件库;意义:进步开发人员在多个我的项目之间的疾速切换能力,进步我的项目可维护性,对立公司技术栈,防止因为环境不同导致奇怪的问题。2.6、Node中间层实用场景:须要SEO且前端应用React、vue,或前端染指后端逻辑,间接读取后端服务或者数据库的状况。 SEO:仁者见仁智者见智,尽管很多公司曾经不做了,但通常认为,还是有肯定意义的(特地是须要搜索引擎引流的时候),因而React或者Vue的同构是必须的。并且同构还能够升高首页白屏工夫;前端读取后端服务/数据库:益处是进步前端的开发效率和对业务的反对能力,毛病是可能导致P0级故障。意义:让前端能够侵入后端畛域,质的晋升对业务的反对能力。2.7、埋点零碎强烈推荐前端做本人的埋点零碎。这个不同于后端的日志零碎。前端埋点零碎的益处: 记录每个页面的访问量(日周月年的UV、PV);记录每个性能的使用量;捕获报错状况;图表化显示,不便给其余部门展现;埋点零碎是前端高度染指业务,把握业务倒退状况的一把利剑,通过这个零碎,咱们能够比后端更粗浅的把握用户的习惯,以及给产品经理、经营等人员提供精确的数据根据。当有了数据后,前端人员就能够针对性的优化性能、布局、页面交互逻辑、用户应用流程。埋点零碎应和业务解耦,开发人员应用时注册,而后在我的项目中引入。而后在埋点零碎里查看相干数据(例如以小时、日、周、月、年为周期查看)。 意义:数据是money,数据是公司的生命线,数据是最好的武器。2.8、监控和报警零碎监控和报警零碎应基于埋点零碎而建设,在如以下场景时触发: 当访问量有比拟大的变动(比方日PV/UV只有之前20%以下)时,主动触发报警,发送邮件到相干人员邮箱;比方报错量大幅度回升(比方200%或更高),则触发报警;当一段时间内没有任何访问量(不合乎之前的状况),则触发报警;每过一段时间,主动汇总访问者/报错触发者的相干信息(例如零碎、浏览器版本等);建设这个零碎的益处在于,提前发现一些不容易发现的bug(须要埋点做的比拟扎实)。有一些线上bug,因为用户环境非凡,导致无奈被开发人员和测试人员发现。但其中一部分bug又因为不波及资金,并不会导致资损(因而也不会被后端的监控零碎所发现),这样的bug非常容易影响我的项目里某个链路的失常应用。 意义:进步我的项目的稳定性,进步对业务的把控能力。升高bug数,升高资损的可能性,提前发现某些性能的bug(在工单到来之前)。2.9、平安治理前端的平安治理,通常要依赖于后端,至于只跟单纯有关系的例如dom.innerHTML= 'xxx '这种太根底,就不提了。平安治理的很难从架构设计上完全避免,但还是有肯定解决方案的,常见平安问题如下: XSS注入:对用户输出的内容,须要转码(大部分时候要server端来解决,偶然也须要前端解决),禁止应用eval函数;https:这个显然是必须的,益处十分多;CSRF:要求server端退出CSRF的解决办法(至多在要害页面退出);意义:缩小安全漏洞,防止用户受到损失,防止遭逢歹意攻打,减少零碎的稳定性和安全性。2.10、EslintEslint的益处很多,强烈推荐应用: 升高低级bug(例如拼写问题)呈现的概率;减少代码的可维护性,可浏览性;硬性对立代码格调,团队合作起来时更轻松;总的来说,eslint举荐间接配置到脚手架之中,对咱们进步代码的可维护性的帮忙会很大。能够思考在上传到gitlab时,硬性要求eslint校验,通过的才容许上传。 意义:进步代码的可维护性,升高团队合作的老本。2.11、灰度公布灰度公布是大型项目在公布时的常见办法,指在公布版本时,初始状况下,只容许小比例(比方1~5%比例的用户应用),若呈现问题时,能够疾速回滚应用老版本,实用于主链路和访问量极大的页面。益处有以下几点: 生产环境比开发环境简单,灰度公布时能够在生产环境小范畴尝试察看新版本是否能够失常运行,即便出问题,也能够管制损失。对于大版本更新,能够先灰度一部分,察看埋点成果和用户反馈(即所谓的领先试用版)。如果成果并不好,那么回滚到老版本也能够及时止损;当咱们须要验证某些想法或问题的时候,能够先灰度一部分,疾速验证成果如何,而后查漏补缺或者针对性优化;灰度公布通常分为多个阶段:【1】1%;【2】5~10%;【3】30~50%;【4】全量推送(100%)。灰度公布肯定要容许配置某些IP/账号拜访时,能够间接拜访到灰度版本。 意义:升高危险,进步公布灵便度。2.12、前后端拆散这个并不是指常见的前后端拆散,而是指在调配前后端管控的畛域。中小我的项目常见的状况是后端只提供接口和让某个url指向某个html,前端负责html、css、js等动态资源。但大型项目并不倡议这么做,倡议前端负责除html以外的动态资源,而html交给后端解决,理由有很多: 后端进行渲染,不便对立插入一些代码和资源,例如埋点js,监控js,国际化文本资源,页面标识符等。这些通常是后端通过调用某些服务间接写入的;当页面须要对立的头尾时(参考淘宝里我的淘宝页面),前端不应该关注这些跟以后页面无关的货色;某些货色,如果通过html来治理,那么耦合度太高了,违反理解耦和拆散的准则;前端版本公布在后端引入某种功能模块后,能够从独自的页面管制前端公布内容,比更新html更不便,也利于灰度公布;意义:更标准的进行页面治理,升高页面和性能的耦合度,缩小简单页面的环境配置工夫。2.13、MockMock也是常见前端零碎之一,用于解决在后端接口未好时,生成返回的数据。我集体不太倡议开发一个专门的零碎来Mock,更好的Mock手法是间接嵌入到脚手架之中。思路如下: 当在开发环境下,拜访链接通常是localhost:8000/index.html,此时退出后缀 ?debug=true;封装好的异步申请在发现以后链接有以上标记时,认为是测试环境,拜访/userinfo 时,不去读取线上的数据(因为也读取不到),去本地环境读取 src/test_ajax/userinfo.json,并将内容返回给用户;异步申请失常拿到数据,在页面中显示;当线上接口能够获取到数据后,从network里找到返回的数据,放入/ src/test_ajax/userinfo.json中,此时再次本地调试的话,相当于应用的是线上的实在数据。 </li> 复制代码这种解决,能够升高mock的复杂度,随时更改mock时返回的数据,比独自开发一个mock零碎性价比更高。 意义:在前后端并行开发时,升高沟通交流老本,不便开发结束后间接对接。2.14、定期备份备份是常被疏忽的一件事件,但当咱们遇见毁灭性场景时,短少备份带来的损失是十分大的,常见场景: 服务器损坏,导致存在该服务器上的内容全副完蛋;触发某致命bug或者错误操作(例如rm -f),导致文件和数据全副隐没;数据库呈现错误操作或呈现问题,导致用户数据、公司资产蒙受严重损失;总的来说,没人想遇见这样的场景,但咱们必须思考这种极其状况的产生,因而须要从架构层面解决这个问题。常见办法是定期备份、多机备份、容灾零碎建设等。 意义:防止在遭逢极其场景时,给公司带来不可估量的损失。3、应用层设计3.1、多页和单页除了非凡场景,通常举荐应用多页架构。理由如下: 多页我的项目,页面和页面之间是独立的,不存在交互,因而当一个页面须要独自重构时,不会影响其余页面,对于有长期历史的我的项目来说,可维护性、可重构性要高很多;多页我的项目的毛病是不同页面切换时,会有一个白屏工夫,但通常来说,这个工夫并不长,大部分现有大公司的线上网页,都是这样的,因而认为是能够承受的;多页我的项目能够单次只更新一个页面的版本,而单页我的项目如果其中一个功能模块要更新(特地是公共组件更新),很容易让所有页面都须要更新版本;多页我的项目的版本控制更简略,如果须要页面拆分,调整局部页面的应用流程,难度也会更低;灰度公布更敌对;之前面试的一家,采纳了单页的模式,之前因为种种原因,同时采纳了ng和react。因为我的项目历史也比拟久(3年以上),后果导致目前持续保护更新的难度很大,即便想局部重构,也很麻烦。 意义:升高长期我的项目迭代保护的难度,3.2、以利用为单位划分前端我的项目在我的项目比拟大的时候,将所有页面的前端文件放入到同一个代码仓库里,我之前参加过一家企业的前端我的项目开发,发现其就是这么做的。依据应用教训来看,存在很多问题: 会极大的减少代码的保护难度;我的项目会变得很俊俏;不不便权限治理,容易造成页面误更改或代码泄密;任何人都有权力改任何他能看到的页面(在合并代码的时候,管理人员并不能确定他本次批改的页面是否是需要里他应该改的页面);公布老本高,即便改一个页面,也须要公布所有资源;因而,咱们应该防止这种景象的产生,集体举荐以利用为单位进行开发、公布。所谓利用即指一个业务波及到的前后端代码,益处很多: 不便进行治理,当某个业务有需要变更时,能够只给研发人员该业务前端利用的developer权限;在须要公布某业务时,只须要公布该业务的所属利用即可;意义:标准我的项目,减少代码的安全性,升高我的项目保护老本。3.3、根底组件库的建设这个蛮根底的,对于组件库的建设,不倡议研发人员较少时去做这件事件,专职前端开发人数少于10人时,倡议应用比拟靠谱的第三方UI库,例如Antd,这样性价比更高。设计根底组件库的前提,是要求对立技术栈,这样能力最大化根底组件库的效益。组件库倡议以应用以下参考规范: 应用ts;可扩展性强;实用水平高;文档分明具体;版本隔离,小版本优化加性能,大改须要大版本更新;和UI协调对立,要求UI交互参加进来;总的来说,建设起来后,利大于弊,然而须要专人保护,因而还是有肯定老本的。 意义:对立不同/雷同产品线之间的格调,给用户更好的体验,缩小单次开发中写UI组件时节约的工夫和人力,进步开发效率。3.4、技术栈对立前端有三大支流框架,还有兼容性最强jQuery,以及各种第三方库,UI框架。因而我的项目需要如果简单一些,很容易造成一个大杂烩。因而前端的技术栈必须对立,具体来说,倡议实现以下动作: 三大框架选型其一,团队程度个别举荐Vue、程度较好举荐React,对外我的项目选React或者ng;须要兼容IE8或更老版本时,倡议应用jQuery;组件库自建或者对立抉择一个固定的第三方;一些非凡第三方库对立应用一个版本,例如须要应用地图时,固定应用高德或百度或腾讯地图;基础设施建设应防止反复造轮子,所有团队尽量共用,并有专门的前端平_台负责对立这些货色,对于非凡需要,能够新建,但该当有说服力;总的来说,技术栈对立的益处很多,能够无效进步开发效率,升高反复造轮子产生的老本。 意义:不便招人,简化团队成员造就老本,以及进步我的项目的可持续性。3.5、浏览器兼容常见的问题是IE6、7、8,以及局部小众浏览器(PC和手机)产生的奇怪问题。因而应该思考对立解决方案,防止bug的反复产生。常见解决方案有: 配置postcss,让某些css减少兼容性前缀;写一个wepback的loader,解决某些非凡场景;标准团队代码,应用更稳固的写法(例如挪动端防止应用fixed进行布局);对常见问题、疑难问题,总结解决方案并团队共享;倡议或疏导用户应用高版本浏览器(比方chrome);意义:防止浏览器环境产生的bug,以及排查此类bug所节约的大量工夫。3.6、内容平台建设为了进步公司外部的沟通效率,总结经验,以及窃密起因。应建设一个外部论坛+博客站点。其具备的益处如下: 能够记录公司的历史;研发同学之间分享教训;总结转载一些外界比拟精品的文章,进步大家的眼界;减少公司外部同学的交换,有利于公司的团队和文化建设;对某些技术问题能够进行探讨,缩小因没有达成共识带来的沟通损耗;家喻户晓,大型互联网公司通常都有这样一个外部论坛和博客站点。其升高了公司的沟通和交换老本,也减少了公司的技术积攒。 意义:博客加强技术积攒,论坛加强公司外部沟通能力。3.7、权限治理平台当公司内部人员较多时,应有一个专门的平_台,来治理、标准用户的权限以及可拜访内容。权限治理平_台有几个特点: 必然和Server端人造高耦合度,因而须要有专门的管制模块负责解决权限问题(负责Server端开发解决,或者前端通过中间层例如Node层染指解决);自动化流程管制,即用户创立、申请、审批、到职主动删除,都应该是由零碎推动并揭示相干人士,必要时应能触发报警;权限应有时效性,缩小永久性权限的产生;审批流程应清晰可见,每一阶段流程应具体明确;应与公司流程紧密结合,并且进步可修改性,不便公司前期进行流程优化;意义:使得公司外部流程正规化、信息化。3.8、登录零碎设计(单点登录)当公司外部业务线比较复杂但相互之间的耦合度比拟高时,咱们应该思考设计增加单点登录零碎。具体来说,用户在一处登录,即能够在任何页面拜访,登出时,也同样在任何页面都失去登录状态。SSO的益处很多: 加强用户体验;买通了不同业务零碎之间的用户数据;不便对立治理用户;有利于引流;升高开发零碎的老本(不须要每个业务都开发一次登录零碎和用户状态管制);总的来说,大中型web利用,SSO能够带来很多益处,毛病却很少。 意义:用户体验加强,买通不同业务之间的距离,升高开发成本和用户治理老本。3.9、CDN前端资源的加载速度是掂量用户体验的重要指标之一。而事实中,因为种种因素,用户在加载页面资源时,会受到很多限度。因而上CDN是十分有意义的,益处如下: 用户来自不同地区,退出CDN能够使用户拜访资源时,拜访离本人比拟近的CDN服务器,升高拜访提早;升高服务器带宽应用老本;反对视频、动态资源、大文件、小文件、直播等多种业务场景;打消跨运营商造成的网络速度较慢的问题;升高DDOS攻打造成的对网站的影响;CDN是一种比拟成熟的技术,各大云平_台都有提供CDN服务,价格也不贵,因而CDN的性价比很高。 意义:减少用户访问速度,升高网络提早,带宽优化,缩小服务器负载,加强对攻打的抵抗能力。3.10、负载平衡目前来看,负载平衡通常应用Nginx比拟多,以前也有应用Apache。当遇见大型项目的时候,负载平衡和分布式简直是必须的。负载平衡有以下益处: 升高单台server的压力,进步业务承载能力;不便应答峰值流量,扩容不便(如举办某些流动时);加强业务的可用性、扩展性、稳定性;负载平衡曾经是蛮常见的技术了,益处不必多说,很容易了解。 意义:加强业务的可用性、扩展性、稳定性,能够反对更多用户的拜访。3.11、多端共用一套接口目前常见场景是一个业务,同时有PC页面和H5页面,因为业务是一样的,因而应防止同一个业务有多套接口别离实用于PC和H5端。因而解决方案如下: 后端提供的接口,应该同时蕴含PC和H5的数据(即独自对一个存在亢余数据);接口该当稳固,即当业务变更时,应尽量采取追加数据的模式;只有在独自一端须要非凡业务流程时,设计单端独有接口;多端共用接口,是缩小开发工作量,并且进步业务可维护性的重要解决方案。 意义:升高开发工作量,加强可维护性。

November 24, 2020 · 1 min · jiezi

关于架构设计:架构设计分布式结构下服务部署发布

本文源码:GitHub·点这里 || GitEE·点这里 一、服务公布简介分布式系统架构下,服务公布是一件很麻烦的事件,特地是在构建主动公布流程和灰度测试的策略两个外围方面。通常状况下如果不波及数据层面的灰度流程,服务能够灰度上线,或者滚动上线,这两种形式很罕用;如果波及到数据灰度,则可能须要两头服务做不同版本数据之间追平,或者停机保护一次性解决好数据和上线问题,不过前面这种形式危险较大。 二、蓝绿部署 新版本上线的时候,并不停掉老版本,新旧两个版本同时运行,通常还会在负载平衡的策略上偏向于旧版本服务解决申请,这样新版本就有一个执行的观察期过渡期,等到新版本安稳运行一段时间后,再把申请都发到新版服务上,旧版本服务实现下线。这种形式在分布式架构下很少应用,对服务器要求过高。 三、滚动公布 滚动公布能够防止蓝绿部署的服务器资源占用问,首先公布一台新版本服务,而后停掉一台老版本服务,新版服务通过察看之后,再逐渐替换掉所有老版本的服务,这样服务的环境变动比拟频繁,绝对不稳固。 四、灰度公布上述两种形式在一般业务场景下都还算好操作,分布式系统下的灰度公布简单程序绝对高很多,根底流程如下: 新版本上线,可能波及分布式下多个灰度服务,因而在服务在整个链路上散发时,都要判断下个申请是路由到失常服务还是灰度服务,还要对灰度服务做申请的权重管制,不能让灰度服务解决大量的申请。 理论策略:在理论的分布式系统灰度公布流程,通常会采纳如下一个策略: 配置一个灰度是否开启的标识;配置一批灰度账户,通常内部人员;配置灰度服务版本标识;申请在链路执行时,判断灰度是否开启;判断以后用户身份是否是灰度测试账号;获取以后能够申请的服务列表;依据灰度服务版本抉择申请的具体服务;这个流程十分的简单,须要很多自定义的策略,还要相熟分布式框架的底层API原理,要二次重写来适配灰度策略,设计重写原生API还容易触发一些惊喜问题。 五、数据库灰度如果说最难解决的灰度模式是什么,就是数据库的版本灰度问题,通常业务对数据库革新降级,理论都是通过停机保护来解决的,可能很多开发都经验过,公布停服布告,而后在指定工夫内把数据全副追平或者二次搬运,再从新提供服务。然而总有些业务场景是不能停机保护的,解决灰度数据的根本策略如下: 该模式中,除了失常的灰度流程之外,须要在灰度数据库和失常数据两头提供一个数据调配服务,用来解决如下问题:灰度数据库缺失数据,须要长期从失常库拉取,灰度版本失败,新数据须要从新整合写入本来失常库;灰度版本胜利,旧版数据迁徙等;最终保证数据的安稳降级。 六、源代码地址GitHub·地址https://github.com/cicadasmile/data-manage-parentGitEE·地址https://gitee.com/cicadasmile/data-manage-parent举荐浏览:编程体系整顿 序号项目名称GitHub地址GitEE地址举荐指数01Java形容设计模式,算法,数据结构GitHub·点这里GitEE·点这里☆☆☆☆☆02Java根底、并发、面向对象、Web开发GitHub·点这里GitEE·点这里☆☆☆☆03SpringCloud微服务根底组件案例详解GitHub·点这里GitEE·点这里☆☆☆04SpringCloud微服务架构实战综合案例GitHub·点这里GitEE·点这里☆☆☆☆☆05SpringBoot框架根底利用入门到进阶GitHub·点这里GitEE·点这里☆☆☆☆06SpringBoot框架整合开发罕用中间件GitHub·点这里GitEE·点这里☆☆☆☆☆07数据管理、分布式、架构设计根底案例GitHub·点这里GitEE·点这里☆☆☆☆☆08大数据系列、存储、组件、计算等框架GitHub·点这里GitEE·点这里☆☆☆☆☆

November 14, 2020 · 1 min · jiezi

关于架构设计:架构中台图

阿里巴巴数据中台全景图阿里是数据中台概念的首先提出者,其案例更具剖析意义。从阿里巴巴数据中台全景图能够看出,阿里的数据中台包含了计算与存储平台、数据资产治理、智能数据研发、对立数据中心中间件(OneService)四大模块,最上层撑持着阿里数据、数据大屏、生意顾问等大数据利用。 程序流程图程序流程图又称程序框图,是用对立规定的规范符号形容程序运行具体步骤的图形示意。程序框图的设计是在解决流程图的根底上,通过对输入输出数据和处理过程的详细分析,将计算机的次要运行步骤和内容标识进去。 程序设计流程图遵循这种办法的程序设计,就是结构化程序设计。相应地,只有规定好三种根本构造的流程图的画法,就能够画出任何算法的流程图。程序设计流程图,流程图是一款网络图绘制软件,新鲜玲珑,功能强大,能够很不便的绘制各种业余的业务流程图/程序流程图/数据流程图/网络拓扑图。 软件开发周期软件生命周期(Software Life Cycle,SLC)是软件的产生直到报废或停止使用的生命周期。软件生命周期内有问题定义、可行性剖析、总体形容、零碎设计、编码、调试和测试、验收与运行、保护降级到废除等阶段一个软件产品或软件系统也要经验孕育、诞生、成长、成熟、兴起等阶段。 零碎流程图零碎流程图(又称业务流程图)进行可行性剖析时,通常用零碎流程图来形容所要开发的零碎。用于 形容我的项目的解决流程、范畴、性能等。零碎流程图是概括的描述零碎物理模型的传统工具。它的根本思维是用图形符号以黑盒子模式描述零碎外面的每个具体部件(程序、文件、数据库、表格、人工过程等)。 网络组建拓扑图网络拓扑图是指用传输媒体互连各种设施的物理布局,即用什么形式把网络中的计算机等设施连接起来。拓扑图画出网络服务器、工作站的网络配置和相互间的连贯。网络的拓扑构造有很多种,次要有星型构造、环型构造、总线结构、分布式构造、树型构造、网状结构、蜂窝状构造等。 我的项目布局时间轴流程图我的项目布局时间轴流程图,对一个我的项目从开始到完工的整个过程进行总结演绎。工夫线图,又叫时间轴图,能以历史进程为载体,将过往的重要事项或者里程碑,标注在轴线上,并加以阐明。它的作用是可能可视化内容,以图文的模式出现进去。时间轴是一种表白事物倒退过程的可视化图示,被许多商业治理人士所应用。 产品开发流程图产品开发流程(Product Development Process)产品开发流程是指企业用于想像、设计和商业化一种产品的步骤或流动的序列。产品开发流程波及的人员从产品经理到设计师、前端、后端等等一系列人员,这篇文章次要对于产品开发的残缺流程,心愿对各个工作岗位上的人有借鉴意义。 产品经理工作流程图输入产品计划,每一位产品经理都应该有清晰、业余、残缺的流程意识,不能一上来就是原型或者需要文档。 作为一名产品经理,画业务流程图是一项必备技能。如何高效的井井有条的来推动,最重要的是有一套清晰的工作流程。 依照产品从需要到上线的线性门路来讲,这个门路就是产品经理的工作流程。 平台数据架构流程图规范大数据平台架构,规范大数据平台架构,大数据平台架构,数据仓库,数据集市,大数据平台层级构造,数据挖掘,举报,蕴含该模版的分享。数据架构设计(数据架构组) 概述 总体形容 绝对于业务架构和利用架构,数据架构在总体架构中处于根底和外围位置。

November 8, 2020 · 1 min · jiezi

关于架构设计:2020中国系统架构师大会活动回顾ZEGO实时音视频服务架构实践

10月24日,即构科技后盾架构负责人&高级技术专家祝永坚(jack),受邀加入2020中国零碎架构师大会,在音视频架构与算法专场进行了主题为《ZEGO实时音视频服务架构实际》的技术分享。 以下为演讲内容的节选: 作为一家业余的音视频云服务商,即构服务了泛娱乐、在线教育、金融、产业互联网、IoT等行业的多家头部公司,例如映客、花椒、微博、好将来等。往年上半年受疫情影响,即构所服务的多家教育、泛娱乐客户都呈现了流量暴增的景象。而即构提供的稳固后盾服务,保障了客户线上业务0故障经营,这离不开咱们成熟稳固、可用性高、能主动扩容的流媒体服务架构。 上面我从ZEGO流媒体服务简介、流媒体服务架构、调度逻辑设计和经营监控四局部进行分享: 一、ZEGO流媒体服务介绍以这张图为例,咱们来看ZEGO流媒体服务的全貌:假如图中有三位主播A,B,C和观众,主播A,B,C要进行连麦互动,他们别离通过浏览器、原生App和微信/QQ小程序来推流。因为主播应用了不同的终端模式来进行推流,那么底层应用的音视频协定也是不同的,别离对应着WebRTC,AVERTP(ZEGO的公有音视频协定),RTMP。 主播之间连麦互动须要相互拉流,为了取得良好的互动成果,须要很低的端到端拉流提早(<400ms)。因而,主播们能够到即构寰球实时网络来进行拉流,反对Web终端,和原生App拉流,国内的理论环境端到端提早能够做到150-400ms。 而观众,因为量比拟大,须要思考老本,同时他不须要互动,能够承受较高的提早。因而能够思考从即构寰球实时网络转推一路RTMP协定的码流到第三方CDN,观众再从CDN去拉流。 当然,如果观众也要很低的提早,那么也能够从咱们的实时网络拉流。此外,一些原来应用RTMP的客户,还能够通过第三方利用通过OBS来推流,很轻易的迁徙到即构寰球实时网络,用户就能够实现在寰球区域范畴内进行低提早的音视频互动。 介绍完次要流媒体服务的全流程后,咱们来看流媒体服务蕴含的具体职责: 调度:在用户推拉流前,须要发动调度申请,取得一个资源后才可能发动理论的码流推拉。用户体验的好坏,跟调度策略有很大关系。 理论推拉流:咱们适配了RTMP,WebRTC,AVERTP等多种协定的推拉流规范,提供了更优的流控等算法。 转推CDN:即构寰球实时网络和第三方的CDN须要进行合作来满足客户的多样化场景需要。 转码:RTMP应用的AAC音频编码,WebRTC应用的Opus音频编码,这两种格局互通,须要对音频进行转码。 转协定:咱们RTMP和WebRTC是以网关的模式存在的,两头的网络传输都是以咱们的AVERTP协定来进行。 目前咱们反对H264,H265,VP8 3种格局的视频编码转码;AAC, Opus,SILK 3种格局的音频转码;RTMP、WebRTC、AVERTP3种协定格局的转协定。 混流:当呈现多个主播连麦互动时,观众如果别离去拉主播的流,对带宽老本和用户的设施都有很高的要求。咱们会让服务器混合成一条流,观众只须要拉混合后的流即可。 流治理:推拉流鉴权,禁推治理,咱们提供了业务经营必须的多种流治理性能。 即构实时音视频服务的劣势体现在4个方面: 第一,多云商架构设计咱们设计之初就确定了反对多云商的架构设计。不同云商有着不同的劣势,他的数据中心和网络资源人造的存在着差异性,a云商在印度南部笼罩品质好,b云商在印度北部笼罩品质好。那么咱们就都用起来,让a云商笼罩印度南部,b云商笼罩印度北部,从而让整体取得更好的接入品质。 第二,高可用设计保障品质咱们架构设计上加进了许多高可用的计划,来保障稳固的服务质量,前面会开展。 第三,弱网下抗丢包能力强咱们自研的音视频引擎,在弱网下的体现更优异,能实现“上/上行70%丢包下,放弃10-15帧视频晦涩通话;上/上行80%丢包下,放弃音频晦涩通话”。 第四,低提早大规模散发利用ZEGO自研引擎,咱们做了低提早大规模散发的流媒体服务架构设计,能极大的进步后盾并发能力。 (未完待续……) 鉴于分享内容较丰盛,更多ZEGO实时音视频服务架构实际中的“流媒体服务架构设计、调度逻辑设计以及经营监控”等内容,能够扫描下方二维码获取演讲材料包,蕴含演讲文字稿、演讲PPT以及即构寰球次要国家的端到端提早实测数据。

October 30, 2020 · 1 min · jiezi

关于架构设计:降本提效贝壳搜索推荐架构统一之路

导语 | 搜寻和举荐是用户获取信息的两种次要形式,在贝壳也是帮忙客户找到房子的次要伎俩,那么二者都有哪些类似和不同之处?是否能够应用同一套架构来实现?对立架构之后又能带来哪些收益呢?本文是对贝壳搜寻举荐部平台架构负责人——低就在云+社区沙龙online的分享整顿,心愿与大家一起交换。 点击视频查看残缺直播回放 一、贝壳搜寻举荐应用场景1. 人、房、客匹配连贯贝壳为大家提供了找房、买房的一整套服务。因为买房是一个十分重要且简单的事件,它的流程很长,不可能像买书、买衣服一样,线高低单领取就实现了。买房的过程个别都会有一个线下的经纪人参加,就是咱们俗称的“中介”。 所以贝壳的次要业务场景是人、房、客三者的连贯匹配。人是指经纪人,房是房子,客就是咱们的 C 端用户。 这三者的连贯和匹配都是搜寻的几个外围场景,比方“人客”的连贯,咱们有客源检索系统(经纪人找客户)和经纪人检索系统(客户找经纪人)。 而“人房”连贯次要对应 B 端的房源搜寻,就是提供给经纪人应用的房源搜寻。比方当大家去线下的链家门店,通知经纪人想要什么样的房子后,经纪人个别就会通过 B 端房源搜寻零碎帮你到适合的房子。 B 端搜寻比 C 端搜寻更简单一些,是专门给有教训的经纪人应用的,是另一套搜寻零碎,包含新房、二手房、租房、链家直营、海内等各场景的B端房源检索,这些都属于“人房”连贯。 “房客”匹配就是大家比拟相熟的 C 端的搜寻举荐了。比方大家无论是上贝壳APP,还是PC站或者小程序,都会常常见到的二手房、新房、租房、海内、地图找房等各频道的搜寻。以及各种首页举荐、相干举荐、猜你喜爱等举荐页面。 对咱们来说,C 端目前是更外围的场景,因为 C 端的搜寻举荐会间接影响到公司的线上商机转化率,须要咱们继续一直的去优化搜寻举荐的成果,晋升点击率、转化率等,所以前面的介绍会次要围绕 C 端开展。 为了更好的撑持这些外围业务场景,作为搜寻举荐平台而言,咱们次要关注三个点:效率、老本和稳定性。效率包含“房客”匹配效率和研发迭代效率,老本包含人员老本和机器老本,稳固即是服务须要保障99.99%以上的高可用性。 2. 场景示例下图就是大家能够在贝壳 APP 上看到的,搜寻举荐的常见场景:贝壳 APP 首页中的主搜框、二手房、新房、租房、海内、必看好房、商业办公、查成交、找小区、地图找房等等。 顺手进入一个频道,比方二手房频道,在下面输出本人想要的小区名、商圈名等等,就会返回给你想要的后果。 如果不进入搜寻频道,在首页往下滑的话,会进入到举荐的首页。不须要任何关键词,间接给你举荐你可能感兴趣的小区、房子等等。 3. 场景概览作为平台,除了外围业务,咱们还赋能了很多其余场景,比方搜寻平台以后一共赋能了 500 多个场景。 C端搜寻包含下面提到的新二租等,目前承接了贝壳 60% 的线上商机。B 端的搜寻包含房源搜寻、客源搜寻、装修搜寻等等。除此之外,还反对了很多外部其余事业部须要用到搜寻的业务,比方签中平台、交易平台、人事行政等等。 举荐方面,目前赋能了 300 多个场景,次要是在C端,同样包含二手房、新房、租赁等等,承接了 15% 的线上商机。场景次要有首页的举荐、相干举荐、猜你喜爱、feed 流等等。 和很多公司一样,在贝壳,搜寻和举荐之前是分属于两个不同的团队各自倒退的,整体代码架构差别都很大,所以我上面会先别离介绍两个平台各自的演进过程,而后再介绍搜寻举荐架构对立的过程。 二、贝壳搜寻平台架构演进贝壳搜寻平台次要经验了四个阶段:搜寻服务、搜寻平台、搜寻云平台和搜寻中台。 2017 年时还只是一个简略的搜寻服务,次要用于链家二手房的搜寻。随着公司业务的疾速倒退,很多其余业务线也都须要搜寻能力。于是本着不反复造轮子的准则,咱们把搜寻服务进行平台化,凋谢它的能力,对各业务进行赋能,从而成为了搜寻平台。 搜寻平台到 2018 年的时候,曾经接入了 100 多个业务,日均有 5 个亿的流量。 成为搜寻平台之后,咱们发现接入的业务越接越多,每接一个业务都须要占用肯定的工夫,造成大家大部分的工夫都花在业务对接上,没有多少工夫能够用于自身平台的技术迭代,长此以往,将很难有技术晋升和积淀,无论是对平台还是团队的同学,都是极为不利的。 ...

October 19, 2020 · 2 min · jiezi

关于架构设计:优秀程序员如何提高架构能力

导语 | 成为架构师是程序员进阶不可或缺的一条门路,尤其在当今更加智能化的社会,对每位程序员的架构能力都提出了新的要求。本文是对腾讯云块存储与虚拟化总监马文霜、贝壳找房根底平台总经理&腾讯云最具价值专家「TVP」王超、同程艺龙机票事业群CTO&腾讯云最具价值专家「TVP」王晓波在云+社区沙龙online的分享整顿,心愿与大家一起交换。 点击视频查看残缺直播回放 01  畅谈架构演进史 王晓波:其实架构演进,这件事件在我看来正好是对本人职业生涯的一个总结,我之前是做基础架构、中间件等一系列的货色,这些年在做业务架构和利用架构。 从我的角度来看,架构技术演进史能够分成两个局部对待:一个是利用技术架构局部,一个是根底技术架构局部,两个演进形式和要害节点不太一样。但利用架构是建设在基础架构演进史根底之上的。 架构演进史能够分为三个阶段,首先是单体时代。在 2006 年左右,过后国内对架构师的定义还不是那么清晰,很多人不分明架构师是什么。刚开始咱们仅仅是把技术做得比拟好,可能布局框架开发标准的称之为架构师。 第一代的架构演进就是技术编程框架为外围开展的一系列布局和解耦局部或者一系列的模型建设局部。那个时代来看,很多开源次要的货色都是编程框架,更多的是单纯的编程。 第二代就进入了高并发、分布式,应答大流量的状态。这个时候的架构演进更加重视的是外围基础设施,也就是关系数据库是不是 OK、Cache 是不是 OK、整个负载是不是 OK,是不是能够做横向的扩大,是不是足够分布式,是不是足够领有对流量的管制,或者是不是有足够的稳定性、高可用的管制...... 这一代架构的演进特点是重视于根底建设,就是大量的资源变成了根底建设,利用在这个根底上更好地迭代。 第三阶段应该是基于数据的利用架构,利用架构到了当初这个状态更加重视数据驱动,也就是越来越多的基于数据的开掘产生新的利用。 或者能够这样说:当“机器学习”这一类的技术不再是作为一个广告词推出的时候,并且真正落到零碎的每一个角落的时候,那么咱们的架构新挑战也就来到了。 这一代的数据驱动的架构更加重视的是对于海量数据的开掘和实时利用,对于大量数据的疾速计算,甚至咱们要求做更快的利用开发部署,这个时候更多的特点就是延长,更多地做数据驱动等等一系列的货色,源源不断发明新的数据驱动架构理念。 王超:我从另一个层面来看,架构是随着整个行业的倒退和社会须要去倒退的。 首先是门户、社交时代,在 2000 年前后,过后是 PC 互联网蓬勃暴发的年代,有四大门户,互联网次要是新闻内容传递为主。所以那个年代分布式内容散发网络,也就是 CDN 蓬勃发展。再通过几年开始有 SNS 社交这一类的产品呈现,解决的是人和人之间信息传递的问题。 技术上从编译型语言,逐渐适度到动静解释性语言的广泛应用,便于编写一些简单的业务逻辑关系代码,同时像关系型数据库也开始被广泛应用。 除此之外,因为关系网络非常复杂,要满足性能要求,开始大量利用缓存,补救关系型数据库存取能力有余的一些场景需要。 过后还有一个疾速倒退的技术就是搜索引擎,综合搜寻解决的也是信息疾速被查找的需要和问题,但因为是全网检索,就对存储、计算有了十分高的要求,这个时候呈现出了分布式系统和 NLP 的雏形,进一步晋升工程能力。 第二阶段是是挪动互联网阶段,就是从 PC 到手机再到各种各样的端,大家对互联网的认知逐渐加深,流量开始指数级增长。 这个时候须要的是更强的存储和计算能力,所以云计算就被宽泛提出来,随之呈现了很多超大规模集群。 最初是生产互联网和产业互联网的高速发展期,工程能力在上个期间曾经被很好的解决了,在 IoT 广泛应用之前不会再有指数级终端设备联网,根底工程能力不再是问题,次要的技术倒退会聚焦在大数据、AI 架构方面。比方,如何用图数据库解决简单关系图谱的问题,GPU 集群、弹性计算、机器学习框架都越来越重要。 所以在我看来,架构技术的演进和倒退是因为社会倒退和用户须要发生变化的。 马文霜:晓波老师和王超老师对互联网的产品、技术架构演进做了十分好的演绎和总结。我想以云硬盘的技术演进给大家讲一讲咱们在这里的一些思考以及取得的经验教训。 2013 年咱们设计云硬盘的时候认为这是一个分布式的存储系统,腾讯在分布式系统是有着多年的积攒的,分布式文件系统 TFS、KV 存储、CKV 都是十分成熟的产品。用成熟稳固的产品去撑持云盘可靠性好,可能疾速上线,就集结了腾讯的三大明星产品TFS、TSSD 和 CKV,设计了云盘 1.0。 TFS、TSSD 和 CKV,这些零碎的可用性都十分好,而后用它们搭建进去的云硬盘可用性必定也是有保障的。冷热拆散,冷数据下沉到由 HDD 组成的 TFS 外面,热数据就上浮到由 SSD 组成的 TSSD 集群当中,既保证了性能,又关照了吞吐,还能够有限扩容、老本有劣势,各种长处堪称一应俱全。 ...

October 19, 2020 · 2 min · jiezi

关于架构设计:架构设计的本质

简介: 实际上架构只是零碎设计外面的一个重要环节,除了架构还蕴含了商业诉求,业务建模,系统分析,零碎设计等重要畛域。本文尝试从更高视角从新扫视架构设计的工作,把架构设计的回升到零碎设计的平面空间去摸索,最终勾画出零碎设计的全域常识体系。 作者 | 编程原理林振华 【问题】 什么是零碎设计,零碎设计的外围是什么?如何训练零碎设计的思维模式?有什么办法来帮忙咱们了解简单的零碎?如何进行系统分析?架构设计的实质是什么?如何进行架构设计?如何进行业务领域建模?模型如何推导出架构设计?架构设计须要遵循哪些标准?【关键词】 零碎思维,系统分析,零碎设计,架构元素,架构视图,架构模型,业务模型,概念模型,零碎模型,分析模型,设计模型,用例驱动,畛域驱动,物件,性能,物件构造,性能交互,利益,架构工具,决策抉择,架构师,架构图 全文概要软件从业人员的成长路线大体是在治理线和技术线上造成冲破,当然也有联合起来井水不犯河水的。而技术上的谋求,架构师则是一个重要的门槛,对于刚入行的程序员可能会认为架构师就是画架构图的,诚然架构师很重要的一个职责是绘制架构图,但这只是其中一个很小的环节而已。 实际上架构也只是零碎设计外面的一个重要环节,除了架构还蕴含了商业诉求,业务建模,系统分析,零碎设计等重要畛域。本文尝试从更高视角从新扫视架构设计的工作,把架构设计的回升到零碎设计的平面空间去摸索,最终勾画出零碎设计的全域常识体系。 思维剖析零碎总览人类社会活动中的不论大大小小的,简略抑或简单的事物,总要先呈现在咱们的脑海里,而后再投射到事实的物理空间来。咱们总是在手不释卷地谋求美妙的事物,但现实存在的问题就是,首先咱们的脑袋也了解不了太过简单的货色,其次脑海里的设想有时候也很难实在无损的映射成事实的零碎,再者因为总是资源无限的,咱们并没有花不完的估算。 归纳起来设计一个零碎,或者奢侈的说,做一件事件,咱们须要解决以下问题: 在解决以上提出的问题前,首先申明咱们要实现的是一个零碎,而不是随便混搭的一件物品,毕竟当初探讨的不是行为艺术。那么就须要先来理解零碎的定义: 零碎是由一组实体和实体之间关系形成的汇合,其性能大于各个实体性能之和。零碎能够分为天然零碎和人工零碎,然而本文特指须要人类参加的人工零碎。 天然零碎: 人体零碎生态系统大气零碎水源零碎人工零碎: 机械系统电子系统操作系统社会零碎零碎演变下面谈到在零碎设计流程次要是应用了剖析思维和零碎思维的联合,当然人类思维还有其余的运作模式,比方批评思维,翻新思维和发散思维等,以此衍生的又是另外一套截然不同的方法论。上面咱们次要剖析零碎设计过程中的思维流动。 通常谈起架构师就会联想到各式各样的架构图,谈架构图就要搞清楚什么是架构设计,那么架构设计之前是什么呢?架构设计是整个零碎建设的外围环节,犹如设计图纸之于修建那么重要,那架构设计之上应该就是零碎设计了。先搞清楚零碎设计的定义: 零碎设计是依据系统分析的后果,使用零碎迷信的思维和办法,设计出能最大限度满足所要求的指标零碎的过程。1)业务形容上节弄清楚零碎的概念,也就是先把边界框定下来,那么咱们要实现的无非就是以上类别的零碎。天然零碎是人造造成的,或者你违心的话也能够认为是盘古开天辟地造成的,那也能够归为人为零碎。我这么说的起因是尝试把视角从软件这个畛域往更加宏观的方向晋升,让咱们临时忘掉软件架构师这一积重难返的角色。 假如当初咱们想登上火星,言下之意是须要借助一套设施要把人类送到火星上,大胆一点,施展仅存那点为数不多的物理常识储备,要设计出一套零碎,可能把人类送到火星。这个时候老板就是违心出资去火星奢华 7 日游的金主,那么须要一个负责人来实现这趟旅程,咱们权且把这个负责人就称为登火旅行零碎架构师(叫总设计师也行,不须要在意这种细节)。那么这个零碎架构师的工作,就是把登陆火星的一系列需要和指标转化成为足于撑持登陆火星宏大工程的零碎架构。 依据零碎总览提到的问题,先一一作答。 因为人命关天,这项工作看起来是挺简单的,首次接到这个单子时我心田是徘徊的。然而答复了以上问题后,感觉清朗了不少,咱们在实现零碎性质,受众,利益和指标的剖析和解答后,能力进入到零碎的架构阶段。 首先对以上提到的需要,咱们先用动画片外面的简略画面为根底来描述咱们的设计,而后大抵依据能想到的过程实现首次业务流程的形容。 业务流程画图元素:火箭,机舱,地球,火星,来回,根底性能(平安,舒服,老本) 通过以上的形容,根本涵盖了火星旅程的四个阶段:登机,航行,下机玩耍,返程,这实质上跟咱们平时搭个飞的去趟浪漫的土耳其也是差不多的。而在此之前咱们脑海里可能还是一片混沌,沉溺在登陆火星这项浩瀚的工程而不晓得从而动手。 从混沌到开始有点脉络,其实无形中曾经实现了一次建模,咱们称为业务建模。翻回去查阅零碎总览的表格,其实咱们曾经把需要这个维度大抵列举进去了,把登陆火星的几大畛域给拆散开来了。那么接下来就是要把登陆火星这个我的项目的主线给阐明分明。 2)概念形象怎么把这件事的主线阐明分明?滔滔不绝的把一件事件讲完其实反而是很难讲明确,除非这件事件自身足够非常简单的。那么就须要抓重点的来说,这个时候就须要一个叫做“概念”的工具。 概念是形象的、广泛的想法,是充当指明实体、事件或关系的领域或类的实体。简略来说,概念就是用简略的一个词汇,就能够让在坐的大家都能准确无误的了解这个词汇所表白的含意。这个是语言独特的魅力,能够说有个概念这个武器,才有了人类屡次工业革命的文化大暴发。有了“概念”这个工具,再对概念进行组合,会暴发出无穷的生产力。 这里交叉讲一下概念的利用,比“傅立叶级数”这个概念,我敢打赌有 80% 的人不晓得所谓何物,然而没关系,咱们并不是要来科普这个概念,先依据百度百科来看看这个概念的形容: 先不要怕,我这么说的目标不是为了让大家搞懂什么是傅立叶级数,这里咱们能够看出即便这么鬼畜概念也是很一般的根底概念元素组成的,比方收敛公式,比方三角函数,比方 求和概念,甚至像 1,2,3 这些阿拉伯数字。这里不得不说学数学最外围的环节就是深刻理解概念,没有之一。 说回来,这里的语境就是在大家都独特了解承受这些根底概念后,通过一系列简单组合的高级概念,也仍然可能清晰谨严的表达出来,上面傅里叶级数的产生过程的动图看看就好。 好了,当初咱们晓得了概念这个工具的重要性和性能,后面咱们曾经列举了登陆火星要做的事件,那么当初就须要准确简洁的把这件事给说分明了,这个是个艰难的工作,因为如果主线没有梳理清晰,前面整个工程将万劫不复。 在业务建模后就是概念建模,作为架构设计的输出,这个阶段就须要对外围业务的充沛了解,同时在基础性和通用性方面的性能也须要同时思考,这个阶段须要大量的业务专家和各个领域的科学家通力协作,保障对系统的了解没有偏差。通过一系列的概念形象和组合,最终输入登陆火星工程的架构图,这里只是用于阐明登陆火星我的项目同样遵循这业务-概念-架构-设计的流程,不要在意架构图自身合不合理。 3)零碎落地当然这还远远不够,零碎之所以简单,就是咱们对系统总有有数更多的要求,更多的性能,更好的性能,那么接下来就是对各个模块进行剖析,细化,设计和施行。当然咱们不会班门弄斧真的在这里去剖析登陆火星的理论流程,以上这个例子尽管比拟粗旷,然而根本也描述了一个简单零碎建设的过程,也就是从需要,建模到架构的思维过程,是从最原始的登火需要一步步扩大的过程。 其实咱们还能够举个小一点的案例,比方一个乏味的需要“赚钱”,引申进去就是做一个能盈利商业我的项目架构,有趣味的同学能够依据这个思维模式一步一步勾画出整个流程进去,置信这也是一个不错的办法,兴许还真能解决些许困惑。上面演示的就是登月过程宏观层面落地的步骤。 架构思维1)架构指标始终以来我听过很多人在讲架构,有些人在做架构,然而很难探讨出一个大家都称心的定义,什么是架构师,架构师须要做哪些工作?或者说很少有往深的去思考,只晓得被称为架构师阐明这个人很厉害。在我毕业的时候有个同学打趣的跟我说,你们做程序的无非就是增删改查,过后我竟无言以对,过后脑海里浮现的是一系列工具的利用技巧,比方 tomcat,nginx 的应用,还有对业务的翻译。 随着对业务的贴近和对计算机技术的进一步意识,我从新扫视“这世上的零碎无非就是增删改查”,这句话说对也对也不对,这句话就跟计算机软件无非就是 0 和 1 的汇合,也对也不对。特地是对刚入行的人可能感觉设计离本人比拟远,因为习惯了关上 idea 才开始思考业务,写代码才开始思考畛域模型,这是十分不好的习惯,如同如果没有在 coding 状态下是无奈进行建模思考,这个很难,须要长久的训练能力达成设计阶段进行思考。 架构设计只是零碎设计外面的一个阶段,而零碎设计是利用建设外面的外围环节,有一些简略的利用建设是不须要零碎设计的,当然有一些简单的利用,在能力超强的工程师团队,有足够的默契后,也能够间接进行建设。 软件架构之道最外围的问题是解决复杂性的问题,并且在解决问题的过程中找到最佳的平衡点,既要简略又能满足倒退。形容零碎设计的实质,就是实现纵向上的工夫,横向上的空间进行思考,布局出决策门路,最终拿到指标后果。 架构师眼里第一件事不是多风行的技术,多高性能的框架,或者多欠缺的业务模型,而应该聚焦在利益之上。对,这个可能会颠覆一些认知,当咱们真正把利益放在首位后,再去思考接下来要实现的事件,咱们的工作能力称得上架构。也就是说,架构师的天职就是最大限度地实现客户的利益,这里的客户能够是市场客户,也能够是合作团队,还能够是同一个团队的我的项目成员。 再直白的说,架构师就是负责把老板画的饼给实现了,在相当长的一段时间内保障产物有足够的利益回报。有人会说那咱们做的就是公益我的项目,就不思考利益,我补充一下,这里说的利益不止是经济收益,还有零碎带来的社会价值。那么又有人会说,架构是谋求利益回报,那老板的指标就是炒股发大财,请架构师你给我选几支股票吧,那我会说其实优良的基金经理也能够称为狭义上的架构师。 2)架构过程天然在增熵,而零碎架构过程其实就是减熵的过程,一个架构的诞生始于指标的确立,而后是对需要的刻画,继而是落地办法的抉择。 所谓条条大路通罗马,有的是一路平川而有的则是崎岖不平,那么架构过程就是一直归类合并同类项,力求最合适的决策抉择来实现咱们所要达成的欲望。在面对简单业务的场景下,咱们须要做出如下的思考: ...

October 12, 2020 · 2 min · jiezi

关于架构设计:架构设计-基于消息中间件图解柔性事务一致性

简介: 分布式事务基于可靠消息最终一致性的实现计划,既然是可靠消息,则要求MQ必须反对事务管理,这样能力保障业务前后一致性。 一、最大致力告诉TCC分段提交实用分布式架构中对一致性、实时性要求较高的业务场景,在理论业务中也存在实时性比拟低的业务,例如常见的短信告诉,客户端音讯,经营体系更新等业务,这时候为了加重外围流程的复杂度和压力,能够采取最大致力告诉形式实现柔性事务的治理。 例如常见的第三方领取业务中,本地业务和领取端业务解决实现之后都会生成音讯告诉,根本流程如下: 本地业务预处理实现之后;申请第三方领取服务;领取操作胜利对该账号发送音讯;领取服务回调本地业务;本地业务生成零碎告诉音讯;上述流程的音讯场景中有一些根底特点,在外围业务解决实现之后,发送音讯告诉,容许失败,在指定时间段内或者指定重试次数之后,容许音讯失落状况存在,即音讯的不可靠性。 在理论的领取零碎中,启动每日对账校验时会对当日的流水做校验,如果发现领取流水有未实现的流程,会有状态补救,后续能够持续解决,这种伎俩在对账中很罕用。 二、可靠消息分布式事务基于可靠消息最终一致性的实现计划,既然是可靠消息,则要求MQ必须反对事务管理,这样能力保障业务前后一致性。 1、RocketMQ事务音讯RocketMQ在4.3版中开始反对分布式事务音讯,采纳2PC的思维来实现了提交事务音讯,同时减少一个弥补逻辑来解决二阶段超时或者失败的音讯,如下图所示: 上图阐明了事务音讯的大抵计划,其中分为两个流程:失常事务音讯的发送及提交、事务音讯的弥补流程。 1.1 发送及提交 (1)发送音讯(half音讯,即发送但不被生产); (2)服务端响应音讯写入后果; (3)依据发送后果执行本地事务,如果写入失败,此时half音讯对业务不可见,本地逻辑不执行; (4) 依据本地事务状态执行Commit或者Rollback(Commit操作生成音讯索引,音讯对消费者可见) 1.1 弥补流程 (1)对没有Commit/Rollback的事务音讯(pending状态的音讯),从服务端发动一次“回查”; (2)Producer收到回查音讯,查看回查音讯对应的本地事务的状态; (3)依据本地事务状态,从新Commit或者Rollback; 其中,弥补阶段用于解决音讯Commit或者Rollback产生超时或者失败的状况。 1.3 设计原理 在RocketMQ事务音讯的次要流程中,一阶段的音讯如何对用户不可见。其中,事务音讯绝对一般音讯最大的特点就是一阶段发送的音讯对用户是不可见的。那么,如何做到写入音讯然而对用户不可见呢?RocketMQ事务音讯的做法是:如果音讯是half音讯,将备份原音讯的主题与音讯生产队列,而后扭转主题为RMQ_SYS_TRANS_HALF_TOPIC。因为生产组未订阅该主题,故生产端无奈生产half类型的音讯,而后RocketMQ会开启一个定时工作,从Topic为RMQ_SYS_TRANS_HALF_TOPIC中拉取音讯进行生产,依据生产者组获取一个服务提供者发送回查事务状态申请,依据事务状态来决定是提交或回滚音讯。 2、最终一致性基于上述RocketMQ事务音讯可靠性的特点,即能够实现某类业务下事务的最终一致性。音讯发送一致性是指产生音讯的业务动作与音讯发送统一,也就是说如果业务操作胜利,那么由这个业务操作所产生的异步音讯肯定要发送进来,否则就业务失败回滚,音讯也会抛弃。 流程根本如下: 发送half事务音讯,无奈被生产;本地业务代码逻辑解决实现;发送确认音讯,标识该音讯能够生产;如果音讯生产方异样,勾销整体动作;该流程次要针对音讯生产方,在理论开发中,音讯的生产方也一样很难解决,要保障最终一致性,必然会面对一个问题,生产方异样,音讯一直的重试,可能存在局部业务解决胜利,局部业务解决失败的状况,这时候就要解决服务接口的幂等性问题。 三、幂等接口1、幂等简介编程中一个幂等操作的特点是其任意屡次执行所产生的影响均与一次执行的影响雷同。就是说,一次和屡次申请某一个资源会产生同样的作用影响。 在简单的异步流程中,尤其留神失败重试问题,通常领取流程中,每次接口被申请,对每一步数据更新的操作,都会前置一步状态查问的流程,用来判断下一步的数据更新是否该执行。 2、幂等接口在零碎服务接口申请中,任何明确的接口响应,例如失败或胜利,这样业务流程都好解决,然而例如领取场景如果申请超时,如何判断服务的后果状态:客户端申请超时,本地服务超时,申请领取超时,领取回调超时,客户端响应超时等,或者基于MQ的一直重试机制,在局部业务异样状态下,始终没有返回胜利,则音讯会始终重试。 这就须要设计流程化的状态治理,尤其在音讯重试机制下,很少会再次对重试的业务接口应用重度的事务管制,有些业务被执行结束,只须要判断一个状态,下次音讯重试跳过即可,只须要把未解决的业务弥补解决即可,在重试机制下,在局部业务没有全副执行胜利之前,音讯会始终重试,直到最终全副实现。 四、源代码地址GitHub·地址https://github.com/cicadasmile/data-manage-parentGitEE·地址https://gitee.com/cicadasmile/data-manage-parent

September 8, 2020 · 1 min · jiezi

关于架构设计:你的业务是可变的吗

请不要跟我说用ES或者其余,其实很多中小公司的业务就是如此,就是基于mysql或者sqlserver 来搞这样的业务业务场景不晓得通过D妹子的论述,大家理解状况了没。这里菜菜再具体说一下。D妹子的程序记录了订单的log来供其余业务(比方统计)应用,这里就以统计业务来说,OrderLog表设计如下: 列名数据类型形容OrderIdnvarchar(100)订单号,主键UserIdint下单用户idAmountint订单的金额其余字段省略... 除此之外还有一个用户信息表UserInfo,设计如下: 列名数据类型形容UserIdint用户id,主键ProvinceIdint用户省的idCityIdint用户市的idCountyIdint用户区县的id波及到拆单等简单的订单操作,表的设计可能并非如此,然而不影响菜菜要说的事变数的业务当初如果要统计某个省的订单总数,sql如下: select count(0) from OrderLog o inner join UserInfo u on o.UserId=u.UserId where ProvinceId=@ProvinceId有问题吗,sql没问题,这时候用户A的省市区县信息忽然变了(兴许是在其余地区买房,户口迁徙了),也就是说UserInfo表里的信息变了,那用以上的sql统计用户A以前省市区县的订单信息是不是就会出错了呢?(产品狗说在哪下的订单就属于哪的订单) 业务的定位以上的问题你感觉是不是很简略呢?只有略微批改一下表兴许就够了。然而,菜菜要说的不是针对这一个业务场景,而是所有的业务场景的设计。那你有没有想过为什么D妹子的设计会呈现这样的问题呢? 深刻理解业务能力防止以上相似的谬误产生,肯定要深刻理解不变和可变的业务点。 拿D妹子的统计来说,你的业务是统计区域的订单数,这个业务在产品设计上定义的是不变性,也就是说在行为产生的那个工夫点就确定了业务性质,这个业务的性质不会随着其余变而变。具体到以后业务就是:用户在X省下的订单不会随着用户区域信息的变动而变动,说白了就是说用户在X省生成的订单永远属于X省。 谈到业务性质的不变性,对应的就有业务的可变性。如果你开发过相似于QQ空间这样的业务,那必定也做过相似访客的性能。当要显示访客记录的时候,访客的名称在少数状况的设计中属于可变性的业务。什么意思呢?也就是说一个用户批改了姓名,那所有显示这个用户拜访记录的的中央姓名都会同时扭转。 说到这里,各位再回头看一下D妹子的业务,这里又牵扯到一个零碎设计的问题,家喻户晓,一个好的零碎设计须要把业务的变动点形象提取进去,D妹子订单统计的业务变动点在于用户的省市区县会变动,订单的金额、订单号等信息不会变动。所以你们感觉是不是D妹子的数据表能够批改一下呢? 数据表的改良改良用户信息依照以上的论述,D妹子业务的变动点在于用户的省市区域信息,所以能够把用户信息的表形象提取进去,主键不再是用户id 列名数据类型形容Idint主键Id,主键UserIdint用户idProvinceIdint用户省的idCityIdint用户市的idCountyIdint用户区县的id这样的话用户订单log表中就变为 列名数据类型形容OrderIdnvarchar(100)订单号,主键UserBIdint对应用户表中的主键idAmountint订单的金额其余字段省略... 这样设计的话,如果用户的省市区县信息有变动,相应的用户信息表中会存在多条用户省市区县数据 这里的用户信息表并非是用户对象的主表,而是依据订单业务衍生进去的表改良业务数据表依据业务的变性和不变性,既然把订单区域统计的业务定义为不变的业务性质,那订单的log表齐全能够这样设计 列名数据类型形容OrderIdnvarchar(100)订单号,主键UserIdint下单用户idProvinceIdint用户省的idCityIdint用户市的idCountyIdint用户区县的idAmountint订单的金额其余字段省略... 写在最初各位读到这里,可能会感觉菜菜这次写的其实很鸡肋,然而,D妹子的场景却是实在环境中遇到的问题。问题的实质还是变性业务和非变性业务的定义和划分,和架构设计一样,数据库的设计其实也须要把变动的业务存储点进行形象,其实应该说是抽离进去。 心愿大家有所播种 --菜菜 支付架构师进阶材料大礼包

August 26, 2020 · 1 min · jiezi

A计划基础架构软件创业之道分享实录

刘超: A计划是Atypical Ventures为创业者们举办的系列圆桌活动,邀请每个行业独角兽企业创始人为创业者们分享洞见与经验。今天到场嘉宾是Atypical Ventures最喜欢的一群人之一:会做管理并有商业头脑的极客。Geek不只局限技术,他们往往深入研究问题到极致、优化解决方案到极致并以此为乐。一旦Geek插上商业视野与管理能力的双翼,将可能成为最出色的CEO。在座四位嘉宾是真·Geek,他们做云计算、大数据、AI平台、存储系统,他们的产品一定程度上也体现了程序员的情怀,同时具备巨大商业价值。上个世纪80年代开始,基础架构软件领域已经群雄逐鹿,Oracle依靠基础架构上的创新成长为超级独角兽。新世纪后的Amazon和阿里巴巴也依靠Iass、Pass为公司带来第二、第三的成长曲线。近十年来我们耳熟能详的ElasticSearch、Spark、MongoDB、Kafka等开源架构软件背后都有很成功的商业洞见。因此本次Atypical Ventures组织的A计划活动将请各位和观众一起围绕计算、存储、数据以及他们所蕴含的商业价值展开讨论。接下来把时间交给他们。 分享人: 季昕华,UCloud创始人。历任华为公司安全团队负责人、腾讯公司安全中心副总经理、盛大在线首席安全官、盛大云计算公司CEO等职务,具有多年的安全管理、产品研发、企业运营工作经验。UCloud在2013年首轮融资时获得Atypical Ventures创始合伙人投资人卢蓉支持。2020年1月,UCloud成功上市成为科创板云计算第一股。 季昕华: 谢谢Ruby,谢谢刘超。非常开心有机会能和大家交流。Ruby是我的贵人。Ruby一直说让我来给大家做个分享。但是她说大家都知道创业非常辛苦,让我不要讲一些大的东西,更多让我讲讲我不开心的事,让大家开心。所以我想讲讲我整个创业过程中的困难和挑战。其实我想可能大部分软件创业者不管在跟投资人沟通、客户沟通,还是跟记者沟通时,都会被问到一个灵魂拷问的问题:如果阿里、腾讯、百度做了你的事,你怎么办? 其实我也是一样。最初我出来做云计算的时候,那时阿里腾讯都已在做了。所以我比大家更惨。结果是什么?我最初去融资时大概见过一千多个投资人,他们觉得团队不错,但问我如何能够和BAT竞争?我当时一直没有很好的答案,所以导致了什么?我喝了1000多杯咖啡都没融到资,只好把自己的房子卖了,自己做自己的天使投资人,史上第一傻卖房创业的典型。中间幸好遇到Ruby。2012年成立公司后,2013年我们产品面世接了不少游戏客户。Ruby常说自己是技术小白,但却能透过技术底层看到我们。我记得很清楚,当时在上海,Ruby没让我喝咖啡,我就点了一杯Mojito。这杯Mojito让我遇到Ruby,遇到我的第一个投资机构。特别感谢当初的相遇,有了今天的UCloud。 今天我想主要给大家讲如何和阿里、腾讯、百度去PK。可能在座很多创业者都会遇到同样问题,会和我一样被灵魂拷问。经过这么多年的尝试和摸索,我也做了一些总结。我希望把这些思考分享给大家,希望各位在过程中能够给我更多的指导和帮助。 我们认为创业公司和BAT其实有三种关系,分别是独立的发展模式、从属的发展模式、竞争的发展模式。在这里借用知名科幻小说《三体》的比喻:三体里面有三颗非常大的恒星。其实互联网行业也一样,有阿里、腾讯、百度这三大恒星。创业公司很容易被恒星吸引或灭掉。 创业公司在做的时候首先要分析BAT的战略。我这里列出了阿里、腾讯、百度的生态体系和他们的整个模式。 阿里围绕“让天下没有难做的生意”,从电商开始扩展到广告支付、物流、运算及金融。需要流量、市场、技术、数据、行业模式。刘超很幸运,当初打造的乐动力有一百多万日活,这部分是阿里非常喜欢的流量,所以进行了投资并购。百度其实相对来说比较不同,先从搜索进入移动市场、收购了91,后面做糯米、O2O,再到今天转向AI。腾讯战略很清晰,从社交获取流量,通过内容变现,所以由游戏、文学、视频拓展到支付和云计算,也需要流量、内容、市场、技术和模式。 有了这个图,我们就知道阿里、腾讯、百度都需要什么。这让创业者可以用非常好的模式去站队、被收购或利用竞争关系获取生存空间,类似三国杀。三国杀局势下如何生存发展,就有可以讲的故事了。 创业公司开始创业首先要需要找到新的机会,这里面有七种模式。 1.新的人群。比如快手。 2.新的市场。比如海外市场,其实BAT发展得不是特别好的。 3.新的技术。比如AI、PingCap为代表的数据库等。 4.新的模式。比如拼多多。 5.新的行业。比如无人机。 6.离互联网较远的行业。比如农业的褚橙。 通过把握这种新的机会点,容易得到快速发展,从天使到A轮、B轮都比较容易实现。因为这是新的市场,很容易拿到资本支持。但当你拿到B轮之后就会遇到一个挑战—— 一般在B轮之前创业公司是可以充分竞争的,但是当B轮之后就进入了BAT视野中。这时候BAT就会问你一个问题:你要不要被我投资?如果要,我可以把各种资源给你。但如果你不要,那么我就投你的竞争对手。 所以这时候创业公司就面临选择:到底是想做从属发展还是选择竞争发展?目前的情况来看,大部分公司都会选择从属发展模式,而很少公司能够进入竞争发展模式。那么接下来我会详细介绍的这两种模式。第一种模式要从属发展,它的核心是认清定位,获取资源协同发展。 这里我把从属发展分为四种模式。 第一种模式叫做顺合模式,就是围绕着BAT生态做BAT生态链的补充。比如如涵是围绕淘宝来做的,就可以迅速做起规模。但是遇到的挑战是规模很难做得更大,会有天花板。从我们过去的经验来看,一般能做到200亿人民币左右市值,再往上就有难度。因为BAT作为大恒星不希望你做大,特别是不希望你跳出它的生态圈,走到另外一个生态圈里去。这种模式我们称之为顺合模式,它的优点是非常快速、可以非常好地利用整个BAT资源,但发展的空间会遇到瓶颈。 第二种也很有意思,叫做逆合模式。做BAT一方中的对手,然后获取另一方的支持和合作。比如我们知道阿里是做电商的,腾讯自己做电商做得不好,所以创业者做一个好的电商就可以被腾讯投资去跟阿里PK。比如说像唯品会、京东、拼多多这种都能够获取腾讯投资。而如果创业者想获取阿里投资,可以比如做好一个社交软件、做好一个搜索引擎。我们称这种为逆合模式。逆合模式的好处是你的投资方会把你当作打手,会给你很多弹药作支持,但是你的生存或者死亡不是他的事。投资方的目标是通过你来打对手。 第三种竞合模式,难度比较大,是吸引BAT两方或者三方的参与,然后从而获得支持。滴滴就获得了阿里投资和腾讯投资,是因为是双方都需要通过滴滴来发展移动支付的业务,所以它的规模就会大很多。但难点是你要协调关系,同时引入两方或多方的整个支持。 第四种我们称为流浪模式,类似于《流浪地球》。典型是美团。美团最初被阿里投资,但是随着美团快速扩大,王兴想拓展更大的业务比如支付。阿里不想他做支付,所以美团就从阿里星球,逃出来进入了腾讯星球,所以现在美团规模就非常大了。那么这种模式难度非常大,只有王兴这种厉害人物才有可能做起来,而且获得很大支持。 这四种我称之为从属模式发展。它的好处是可以快速发展起来,但困难是可能会遇到瓶颈。当然如果你要有流浪、竞合模式可能会好很多,所以各位如果要创业,可以仔细分析一下阿里、腾讯、百度生态,进行合作的把握和竞争的把握。 比如说像阿里需要的是市场,如果有创业项目海外市场做得非常好的话,完全具备被投资的可能。如果你做社交做得非常好,阿里也可能会投你。所以选择一个好的切入点,很容易获取了投资或者并购机会,实现快速套现。像我们成功的刘超刘总通过乐动力,快速被阿里投资并购,所以他现在成功地成为一名投资者,而不像我们很多创业者还是苦哈哈做创业。 第二种我们称之为竞争发展模式,这种难度比较大,需要具备强大的战略,组织、投融资、国际化和品牌能力。非常典型的就是头条,头条通过它非常强的战略、特别强的组织能力以及投资关系能力,成为现在BAT之外一股不可忽视强大力量;或者说由字节跳动取代了百度的B,成为新的BAT。大家可以深入去研究一下。 最后,我们是怎么做的呢?一个我们坚持中立,不被BAT投资。带来什么好处?比如说做电商的不太敢用阿里云,做游戏的不太敢用腾讯云,做手机的不太敢用华为云,就可能选择我们。第二是一家公司如果需要多个云来做支持,就是我们的机会。因此我们内部自诩为我们叫“云备胎”。各位如果不敢用阿里腾讯用百度的,那么用我们UCloud是一个好选择。第三是我们深入行业来提供更好的支持和帮助,这是我们简单的、也是最好的一个策略。 总结下来我们认为创业公司要和腾讯阿里百度竞争的话,各位可以从新人群、新市场、新技术、新模式或者新行业,这五个方向或以一个比较远的行业切入进去,通过前期市场化的充分竞争成为领头羊之后,进入到B轮。这时候阿里腾讯百度找到你,你会选择从属发展或者是竞争发展。如果选择从属发展就要去分析整个战略需求,决定是用顺合模式、逆合模式、竞合模式还是流浪模式。当然这和你的选择相关,如果你想快速套现、快速上市,顺合模式最好的,但规模有瓶颈。逆合模式帮BAT当打手套现较方便,但上市有难度。竞合模式规模很大,需协调多家关系。流浪模式难度很大,只有美团较成功。 除此之外,竞争发展模式是难度很大的路径。但好处是只要做出来就是下一个BAT。就是《三体》里面的下一个恒星。它需要有刚强的战略、组织、投融资、国际化等能力。经过八年的努力,我们在2020年1月20号上市,成为全世界第一个独立上市的云计算公司,也是中国A股市场第一个同股不同权的公司。想和大家分享三点。 1.创业公司很辛苦。技术创业很辛苦。感谢有Ruby这样的投资人,能有Atypical Ventures这样的投资机构支持。我们的上市给大家一个信心:即使大家像我一样做技术出身,在有投资人支持下,只要坚持做,在中国,特别是科创板的机会下,做科技公司还是有机会上市的。 2.我想特别跟大家讲,我是一个农民出身的孩子,我的父亲在我很小的时候去世了,我没有任何背景。我想说在像我这样一个没有任何背景、家庭情况非常不好的一个苦孩子,在中国,只要我们努力做好技术、做好服务,也是有机会上市的。 3.我也特别想跟大家分享是什么,虽然在中国BAT三座大山的压力下,只要我们努力去做真正的价值,不断为用户创造价值,也是有机会逐步发展起来、不会死的。就是说在BAT竞争下,我们也有机会活下来。 我觉得上次说明这三点,虽然创业过程很苦,技术人员创业更苦,但是我觉得核心是抓住自己的优势来为用户创造价值,在困难情况下能咬牙坚持下来,在优秀的投资机构的不断支持下,我们还是有机会发展很好的。这就是我们公司的一个文化叫做优秀是刻苦努力得来的,这也是我们公司优刻得三个字的寓意。谢谢大家! 分享人: PingCAP联合创始人黄东旭。黄东旭曾就职于微软亚洲研究院、网易有道和豌豆荚,是开源项目 Codis 作者、TiDB设计者。除了PingCAP CTO的身份外,他是一位黑客、摇滚乐手和程序员。PingCAP致力于探索并逐步解决分布式数据库领域问题,曾获得云启、复星、晨兴、华创、经纬等机构总计超过7600万美元的融资。 黄东旭: 听完老季的分享真是感触颇多。作为前辈,老季的故事给我们所有人带来鼓舞。其实PingCAP属于一家新生代的公司。在过去的中国很少有这样的公司出现。PingCAP是一家做开源分布式数据库的公司,主要和唯一的产品就是TiDB。从公司诞生到现在正好5年。整个公司260个员工分散在全球各地,是比较典型的开源软件公司。 其实在5年前我们刚开始创业时候,中国应该说还没有任何一家成规模或者体系完整的开源软件公司出现。我们应算国内最早一波去用开源软件做创业的公司,这个过程中也摸索了一些如何在中国做世界级开源软件的打法、策略,会跟大家分享。 然后其实刚才我看到老季talk里面有一点,我觉得说的特别好:如果想把这个公司做大,我个人觉得不要去害怕跟BAT去做直接竞争。PingCAP或TiDB在领域里主要的竞争对手其实也是阿里、腾讯等国内巨头企业。我个人的经验就是当评断一家公司或者说一个产品实力,有时候并非由你本人说辞决定,别人会去看你的竞争对手是谁。如果你的竞争对手都是BAT,其实你自己某个程度上也就是“巨头”。所以有时我会觉得你的竞争对手定义了你。对于新一代基础软件创业者来说,不要去害怕,反而说在如果你发现你的竞争对手已经没有创业公司,全都是巨头了,说明可能你自己已经挺厉害的。 TiDB是一个数据库。今天很多听众是工程师,所以大家可能用过。MySQL是全球最流行的开源项目之一,大家在自主架构里面使用MySQL的很多。但数据量大了以后,它的扩展能力就变成问题。所以过去在TiDB出现之前,大家可能经常会使用分库分区、MySQL中间件等方案。5年前我出来创业前在豌豆荚,当时我们也是重度MySQL用户,遇到一个问题就是MySQL分表业务层面非常不灵活,很多功能包括跨分片做join或transaction没法搞。我们当时就在想能不能从零开始去设计一个数据库像MySQL这样易用,对于用户来说使用友好,同时又拥有像NoSQL那样无限的水平拓展能力。这样对于用户来说,既保持了业务快速开发,同时又能承受各种scale,这是TiDB的初衷。 当时我们也看了谷歌的一些paper,觉得这个方向还没有一个开源软件做,而这项技术可能会开启未来的数据库市场。所以我们就跳出来说:我们要去做这个方向的开源软件,去解决程序员们的问题。它并不是MySQL或者基于一个MySQL的封装,它是从零开始的新东西。它并不是一个MySQL的分支,并不是类似像HaSQL、Hadoop的分析平台,而是一个分布式数据库。而且它是百分之百的交易型、分布式分析的、实时分析的数据库。 对于一些没有听说过TiDB的小伙伴,我简单说几点优点。 第一点这个系统能够水平的无限扩展。对于你的业务来说,无论你的业务的复杂性有多大,或者数量有多大,你只需要往集群里面简单加机器,就可以无限扩展。整个过程你不需要人工去做重新分布或者重调整的。 第二点在大规模的集群下,通过先进分布式算法让系统拥有自我恢复、高可用能力。就是说当系统节点出现故障时,业务层完全透明,可以自我恢复。 第三点是支持强一致特性,简单来说就是它可以用来做银行核心的交易。其实这也就是为什么TiDB的大绝大多数商业客户都来自金融银行这样行业,这也是过去像MongoDB、NoSQL没办法去触碰的市场。 第四点是业务层MySQL协议兼容。如果已经是依赖MySQL代码的场景,基本不用改任何一层代码就可以去直接migrate到TiDB,数据迁移成本几乎是零。本身TiDB就是一个混合负载型的数据库。 其实我们的数据库主要有两种应用场景。 第一种当核心的MySQL数据库出现了性能、并发、数据量瓶颈时,可以无缝迁移到TiDB去支撑业务快速增长。比如TiDB早期第一个大规模商业客户其实是MoBike,MoBike在他们公司很小的时候就选用了TiDB,在他们业务高速飞速增长的时候,他们的基础架构数据库层面上基本没做太大的变化,就帮他们一步步地从思路上解决了scale困境。 第二就是TiDB本身是一个分布式的架构,所以可利用整个集群计算资源去做数据实时分析。这个在银行对账实时风控场景应用很多,是一个 general purpose的 database。 ...

July 1, 2020 · 2 min · jiezi

设计模式之备忘录模式

0x01.定义与类型定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。该模式又叫快照模式。类型:行为型UML类图 基本代码实现/** * 发起人类 */public class Originator { /** * 状态编码 */ private String status; public Originator(String status) { this.status = status; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } /** * 创建备忘录 * @return */ public Memento createMemento() { return new Memento(this); } /** * 回滚 * @param memento */ public void restoreMemento(Memento memento) { this.status = memento.getStatus(); }}/** * 备忘录类 */public class Memento { private String status; public Memento(Originator originator) { this.status = originator.getStatus(); } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; }}/** * 备忘录管理类 */public class Caretaker { /** * 备忘录记录栈 */ private Stack<Memento> MEMENTO_STACK; public Caretaker() { MEMENTO_STACK = new Stack<>(); } /** * 添加一个备忘录 * @param memento */ public void addMemento(Memento memento) { MEMENTO_STACK.push(memento); } /** * 获取一个备忘录 * @return */ public Memento getMemento() { return MEMENTO_STACK.pop(); }}测试与应用/** * 测试与应用 */public class Test { public static void main(String[] args) { //备忘录管理 Caretaker caretaker = new Caretaker(); //发起人 Originator originator = new Originator("1"); //创建备忘录1 Memento memento1 = originator.createMemento(); caretaker.addMemento(memento1); //修改并创建备忘录2 originator.setStatus("2"); Memento memento2 = originator.createMemento(); caretaker.addMemento(memento2); //修改状态3 originator.setStatus("3"); System.out.println(originator.getStatus()); //回滚上一次 originator.restoreMemento(caretaker.getMemento()); System.out.println(originator.getStatus()); //回滚上一次 originator.restoreMemento(caretaker.getMemento()); System.out.println(originator.getStatus()); }}输出结果321备忘录模式角色介绍 ...

November 5, 2019 · 3 min · jiezi

设计模式之代理模式

代理模式0x01.定义与类型定义:为其他对象提供一种代理,以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介的作用,可去掉功能服务或增加额外的服务。类型:结构型几种代理方式: 远程代理--为不同地理的对象,提供局域网代表对象---通过远程代理来模拟各个店铺的监控虚拟代理--根据需要将资源消耗很大的对象进行延迟-真正需要的时候进行创建--比如说先加载文字-图片是虚拟的-再加载保护代理--控制一个对象的访问权限--权限控制智能引用代理--火车票代售处0x02.适用场景保护目标对象增强目标对象0x03.优缺点优点代理模式能将代理对象与真实被调用的目标对象分离一定程度上降低了系统的耦合度,扩展性好保护目标对象增强目标对象缺点代理模式会造成系统设计中类的数据增加在客户端和目标对象增加一个代理对象,会造成请求处理速度缓慢增加了系统的复杂度0x04.扩展1.静态代理定义:通过在代码中显示定义了一个业务实现类的代理,在代理类中实现了同名的被代理类的方法,通过调用代理类的方法,实现对被代理类方法的增强。代理和被代理对象在代理在代理之前是确定的,他们都是实现的相同的接口或者继承相同的抽象类静态代理UML类图 代码实现/** * 被代理的接口类 * @author zhiyuan.shen */public interface Subject { /** * 具体方法 */ void doAction();}/** * @author zhiyuan.shen */public class RealSubject implements Subject { @Override public void doAction() { System.out.println("service impl class."); }}/** * 代理类 * @author zhiyuan.shen */public class Proxy implements Subject { private Subject subject; public Proxy(Subject subject) { this.subject = subject; } @Override public void doAction () { System.out.println("before"); subject.doAction(); System.out.println("after"); }}测试与应用类/** * @author zhiyuan.shen */public class Test { public static void main(String[] args) { //创建服务类 RealSubject realSubject = new RealSubject(); //自己执行方法 realSubject.doAction(); System.out.println("----------"); //创建代理类 Proxy proxy = new Proxy(realSubject); //代理执行 proxy.doAction(); }}输出结果service impl class.----------beforeservice impl class.after静态代理角色介绍 ...

October 16, 2019 · 3 min · jiezi

拿起键盘就是干跟我一起徒手开发一套分布式IM系统

1、引言老读者应该还记得我在去年国庆节前分享过一篇《技术干货:从零开始,教你设计一个百万级的消息推送系统》,虽然我在文中有贴一些伪代码,依然有些朋友希望能直接分享一些可以运行的源码。好吧,质疑我穷我无话可说(因为是真穷。。),怀疑我撸码的能力那是绝对不行,所以这次准备拉起键盘大干一场——徒手撸套分布式IM出来!^_^! 本文记录了我开发的一款面向IM学习者的 IM系统——CIM(全称:CROSS-IM),同时提供了一些组件帮助开发者构建一款属于自己可水平扩展的 IM。 通过学习本文和CIM代码,你可以获得以下知识: 1)如何从头开发一套IM(CIM的客户有点弱,见谅见谅);2)如何设计分布式的IM架构;3)如何将你的分布式IM架构用代码和相关技术实现出来。本文配套的CIM源码地址: 主要镜像:https://github.com/crossoverJie/cim备用镜像:https://github.com/52im/cim以下文章与本文类似或相关,同样有助于您的IM开发入门: 《自已开发IM有那么难吗?手把手教你自撸一个Andriod版简易IM (有源码)》《适合新手:从零开发一个IM服务端(基于Netty,有完整源码)》《拿起键盘就是干:跟我一起徒手开发一套分布式IM系统》《浅谈IM系统的架构设计》《简述移动端IM开发的那些坑:架构设计、通信协议和客户端》《一套海量在线用户的移动端IM架构设计实践分享(含详细图文)》《一套原创分布式即时通讯(IM)系统理论架构方案》《一套高可用、易伸缩、高并发的IM群聊、单聊架构方案设计实践》* 友情提示:阅读本文和CIM源码,需要您具备一定的网络编程、IM理论等知识等,如果您还不具备这些,请先阅读《新手入门一篇就够:从零开发移动端IM》,完全来的及! 学习交流: - 即时通讯/推送技术开发交流5群:215477170[推荐]- 移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM》(本文同步发布于:http://www.52im.net/thread-2775-1-1.html) 2、关于作者 crossoverJie(陈杰): 90后,毕业于重庆信息工程学院,现供职于重庆猪八戒网络有限公司。 3、运行演示本次特地录了两段视频演示(群聊、私聊),点击下方链接可以查看视频版 Demo。 CIM 私聊视频演示:https://www.bilibili.com/video/av39405821CIM 群聊视频演示:https://www.bilibili.com/video/av394055014、架构设计下面来看看具体的架构设计: 架构说明: 1)CIM 中的各个组件均采用 SpringBoot 构建;2)采用 Netty + Google Protocol Buffer 构建底层通信;3)Redis 存放各个客户端的路由信息、账号信息、在线状态等;4)Zookeeper 用于 IM-server 服务的注册与发现。整体主要由以下模块组成: 1)cim-server——IM 服务端:用于接收 client 连接、消息透传、消息推送等功能。支持集群部署;2)cim-forward-route——消息路由服务器:用于处理消息路由、消息转发、用户登录、用户下线以及一些运营工具(获取在线用户数等);3)cim-client——IM 客户端:给用户使用的消息终端,一个命令即可启动并向其他人发起通讯(群聊、私聊);同时内置了一些常用命令方便使用。5、逻辑流程图整体的流程也比较简单,流程图如下: 流程解释如下: 1)客户端向 route 发起登录;2)登录成功从 Zookeeper 中选择可用 IM-server 返回给客户端,并保存登录、路由信息到 Redis;3)客户端向 IM-server 发起长连接,成功后保持心跳;4)客户端下线时通过 route 清除状态信息。所以当我们自己部署时需要以下步骤: 1)搭建基础中间件 Redis、Zookeeper;2)部署 cim-server,这是真正的 IM 服务器,为了满足性能需求所以支持水平扩展,只需要注册到同一个 Zookeeper 即可;3)部署 cim-forward-route,这是路由服务器,所有的消息都需要经过它。由于它是无状态的,所以也可以利用 Nginx 代理提高可用性;4)cim-client 真正面向用户的客户端;启动之后会自动连接 IM 服务器便可以在控制台收发消息了。更多使用介绍可以参考快速启动。 ...

October 15, 2019 · 2 min · jiezi

Nebula-架构剖析系列零图数据库的整体架构设计

Nebula Graph 是一个高性能的分布式开源图数据库,本文为大家介绍 Nebula Graph 的整体架构。 一个完整的 Nebula 部署集群包含三个服务,即  Query Service,Storage Service 和 Meta Service。每个服务都有其各自的可执行二进制文件,这些二进制文件既可以部署在同一组节点上,也可以部署在不同的节点上。 Meta Service上图为 Nebula Graph 的架构图,其右侧为 Meta Service 集群,它采用 leader / follower 架构。Leader 由集群中所有的 Meta Service 节点选出,然后对外提供服务。Followers 处于待命状态并从 leader 复制更新的数据。一旦 leader 节点 down 掉,会再选举其中一个 follower 成为新的 leader。 Meta Service 不仅负责存储和提供图数据的 meta 信息,如 schema、partition 信息等,还同时负责指挥数据迁移及 leader 的变更等运维操作。 存储计算分离在架构图中 Meta Service 的左侧,为 Nebula Graph 的主要服务,Nebula 采用存储与计算分离的架构,虚线以上为计算,以下为存储。 存储计算分离有诸多优势,最直接的优势就是,计算层和存储层可以根据各自的情况弹性扩容、缩容。 存储计算分离还带来的另一个优势:使水平扩展成为可能。 此外,存储计算分离使得 Storage Service 可以为多种类型的个计算层或者计算引擎提供服务。当前 Query Service 是一个高优先级的计算层,而各种迭代计算框架会是另外一个计算层。 ...

October 14, 2019 · 1 min · jiezi

我在极客时间的首次分享

文章首发于公众号 松花皮蛋的黑板报作者就职于京东,在稳定性保障、敏捷开发、高级JAVA、微服务架构有深入的理解 当时我将自己的文章投稿到InfoQ,然后总编辑郭总邮件邀请我来分享,于是有了这次值得纪念的演讲。欢迎朋友们前往极客时间App观看。 主题为:如何利用有效的资源抗住618大促流量 大概内容如下: 性能测试 性能优化 硬件优化可包括配置升级比如使用支持NIO的Tomcat版本代替低版本、集群水平扩展、摘取集群短板。 软件优化包括代码审查然后优化SQL和低性能代码。 扩展点 一、开发语言基础知识 数据结构中各种集合间的区别,包括适用场景、CRUD复杂度、线程安全性、有序性、快速失败特性。 并发当中的四种设计模式,包括Future模式、Master-Slave模式、保护暂停模式、不可变模式、生产消费者模式等。 IO当中的零拷贝技术、序列化和反序列化。 内存管理中的内存模型、垃圾回收策略。 使用连接池减少管理的开销。 二、程序设计 SOLID原则,具体为单一职责原则、开闭原则、里氏替换原则、接口隔离原则、依赖倒置原则。 设计模式,常见的有单例模式、工厂模式、策略模式、责任链模式。 接口设计,比如借鉴组合模式减少过多的重载。 避免过度设计,不要过早关注安全性、可配置性、可扩展性、可维护性、可继承性。 三、数据库 理解好索引和锁。 四、中间件 利用好缓存,但是要注意缓存和源数据同步的一致性问题。 利用好消息引擎,但是要注意幂等性、有序性、数据冗余复制的问题。 五、分层 理解好领域驱动设计,按业务划分限界上下文、消除隐匿数据依赖、明确定义依赖方向。 六、高可用 服务降级、服务限流、依赖熔断、队列、超时和重试机制、数据一致性。 文章来源:www.liangsonghua.me作者介绍:京东资深工程师-梁松华,在稳定性保障、敏捷开发、JAVA高级、微服务架构方面有深入的理解

October 1, 2019 · 1 min · jiezi

微服务化

问题服务如何定义服务如何发布和订阅服务如何监控服务如何治理(熔断机制等)故障如何定位基本组件服务描述: RESTful API, 性能差XML, java平台, 一般内部使用IDL, interface description language, 用作跨语言平台的服务之间的调用, 修改或者删除PB字段不能前向兼容 gRPC(google)Thrift(facebook)注册中心 服务提供者在启动时进行注册服务消费者在启动时进行订阅注册中心返回提供者的地址列表给消费者当提供者发生变化, 注册中心通知消费者服务框架 服务通信采用什么协议?数据传输采用什么方式?数据压缩采用什么格式?服务监控 指标收集数据处理数据展示服务追踪 消费者调用生成一个requestId提供者接到请求后记录requestId, 如果需要调用其他服务, 再生成一个requestId, 两个id一起往下传服务治理 单机故障单IDC故障依赖服务不可用注册中心注册中心需要提供哪些接口 服务注册接口服务注销接口心跳汇报接口服务订阅接口服务变更查询接口服务查询接口服务修改接口集群部署zookeeper目录存储, 区分版本号服务健康状态监测服务状态变更通知(zookeeper的watcher机制)白名单机制RPC客户端和服务端如何建立网络连接 HTTPSocket 链路存活检测断连重试服务端如何处理请求: 使用成熟开源方案, 如Netty、MINA等 同步阻塞方式(BIO)同步非阻塞方式(NIO)异步非阻塞方式(AIO)数据传输采用什么协议 HTTPDubbo数据改如何序列化和反序列化 支持数据结构类型的丰富度跨语言支持性能监控监控内容 用户端监控: 业务直接对用户提供的功能的监控接口监控: 业务提供的功能锁依赖的具体RPC接口的监控资源监控: 某个接口依赖的资源的监控基础监控: 对服务器本身的健康状况的监控监控指标 请求量 实时请求量, QPS统计请求量响应时间错误率监控维度 全局维度分机房维度单机维度时间维度核心维度: 核心业务和非核心业务监控系统原理 数据采集 服务主动上报代理收集数据传输 UDP传输Kafka传输数据处理 接口维度聚合机器维度聚合数据展示追踪微服务调用作用 优化系统瓶颈优化链路调用生成网络拓扑透明传输数据原理 核心就是调用链: 通过一个全局唯一的ID将请求串起来traceId: 用于标识某一次具体的请求ID, 在第一层生成一个全局唯一的id, 随着调用往后传递.spanId: 用于标识调用在分布式请求中的位置. 第一层是0, 进入下一层则是0.1, 0.2, 再下一层是0.1.1、0.1.2, 以此类推. 可以清晰查看上下游依赖.annotation, 用于业务自定义埋点数据, 可以是业务感兴趣的想上传到后端的数据, 比如一次请求的UID.服务追踪系统 数据采集层, 负责数据埋点并上报给数据处理层. 1次RPC请求可以分为四个阶段 CS(Client Send): 生成调用上下文SR(Server Received): 生成服务端上下文SS(Server Send): 服务端上下文数据上报CR(Client Received): 将客户端上下文数据上报数据处理层, 负责数据的存储与计算 ...

September 6, 2019 · 4 min · jiezi

如何设计一个秒杀系统

开篇词 | 秒杀系统架构设计都有哪些关键点?秒杀主要解决两个问题,一个是并发读,一个是并发写秒杀的整体架构需要做到:稳、准、快。01 | 设计秒杀系统时应该注意的5个架构原则架构原则:“4 要 1 不要” 数据要尽量少请求数要尽量少路径要尽量短依赖要尽量少不要有单点架构是一种平衡的艺术,而最好的架构一旦脱离了它所适应的场景,一切都将是空谈。 02 | 如何才能做好动静分离?有哪些方案可选?那到底什么才是动静分离呢?所谓“动静分离”,其实就是把用户请求的数据(如HTML页面)划分为“动态数据”和“静态数据”。 简单来说,“动态数据”和“静态数据”的主要区别就是看页面中输出的数据是否和URL、浏览者、时间、地域相关,以及是否含有Cookie等私密数据。你应该把静态数据缓存到离用户最近的地方。静态数据就是那些相对不会变化的数据,因此我们可以把它们缓存起来。缓存到哪里呢?常见的就三种,用户浏览器里、CDN上或者在服务端的Cache中。你应该根据情况,把它们尽量缓存到离用户最近的地方。如何做动静分离的改造 我们如何把动态页面改造成适合缓存的静态页面呢? URL唯一。商品详情系天然h就j以做到URL唯一化,比如每个商品都由ID来标识,那么 http://item.xxx.com/item.htm?... 就可以作为唯一的URL标识。分离浏览者相关的因素。浏览者相关的因素包括是否已登录,以及登录身份等,这些相关因素我们可以单独拆分出来,通过动态请求来获取。分离时间因素。服务端输出的时间也通过动态请求获取。异步化地域因素。详情页面上与地域相关的因素做成异步方式获取,当然你也可以通过动态请求方式获取,只是这里通过异步获取更合适。去掉Cookie,服务端输出的页面包含的Cookie可以通过代码软件来删除,如Web服务器Varnish可以通过unset req.http.cookie命令去掉Cookie.动态内容如何处理? ESI方案(或者SSI):即在Web代理服务器上做动态内容请求,并将请求插入到静态页面中,当用户拿到页面已一个完整的页面了。这种方式对服务端性能有些影响,但是用户体验较好。CSI方案。即单独发起一个异步JavaScript请求,以向服务端获取动态内容。这种方式服务端性能更佳,但是用户端页面可能会延时,体验稍差。03 | 有针对性地处理好系统的热点数据发现热点数据 通过卖家报名的方式提前筛选出来,通过报名系统对这些热点商品进行打标。通过大数据分析来提前发现热点商品,比如我们分析历史成交记录、用户的购物车记录,来发现哪些商品可能更热门、更好卖,这些都是可以提前分析出来的热点。怎么优化 优化热点数据最有效的办法就是缓存热点数据,如果热点数据做了动静分离,那么可以长期缓存静态数据。但是,缓存热点数据更多的是"临时”缓存,即不管是静态数据还是动态数据,都用一个队列短暂地缓存数秒钟,由于队列长度有限,可以采用LRU淘汰算法替换。再来说说限制。限制更多的是一种保护机制,限制的办法也有很多,例如对被访问商品的ID做一致性Hash,然后根据Hash做分桶,每个分桶设置一个处理队列,这样可以把热点商品限制在一个请求队列里,防止因某些热点商品占用太多的服务器资源,而使其他请求始终得不到服务器的处理资源。最后介绍一下隔离。秒杀系统设计的第一个原则就是将这种热点数据隔离出来,不要让1%的请求影响另外的99%,隔离出也更方便对这1%的请求做针对性的优化。04 | 流量削峰这事应该怎么做?对秒杀这个场景来说,最终能够抢到商品的人数是固定的,就说100人和10000人发起请求的结果都一样,并发度越高,无效请求也越多。 但是从业务上来说,秒杀活动是希望更多的人来参与的,也就是开始之前希望有更多的人来刷页面,但真正开始下单,秒请求并不是越多越好。因此我们可以设计一些规则,让并发的请求更多地延缓,而且我们甚至可以过滤掉一些无效请求。 有损方案 ip过滤,随机过滤,百分比过滤无损方案 排队消息队列线程池加锁等待把请求序列化到文件中,然后再顺序地读文件(例如基于MySQL binlog的同步机制)来恢复请求秒杀系统中的常用削峰方法 答题 这个重要的功能就是把峰值的下单请求拉长,从以前的1s之内延长到2s-10s。还能防止机器抢单。分层过滤 对请求进行分层过滤,从而过滤掉一些无效的请求。浏览器层面:秒杀是否已经结束,答题是否正确缓存:商品状态是否正常,用户是否具有秒杀资格,库存判断数据:扣减库存05 | 影响性能的因素有哪些?又该如何提高系统的性能?减少编码 那么如何才能减少编码呢?例如,网页输出是可以直接进行流输出的,即用resp.getOutputstream() 函数写数据,把一些静态的数据提前转化成字节,等到真正往外写的时候再直接用OutputStream() 函数写,就可以减少静态数据的编码转换。减少序列化 序列化大部分是在RPC中发生的,因此避免或者减少RPC就可以减少序列化,当然当前的序列化协议也已经做了很多优化来提升性能。有一种新的方案,就是可以将多个关联性比较强的应用进行"合并部署",而减少不同应用之间的RPC也可以减少序列化的消耗。所谓"合并部署",就是把两个原本在不同机器上的不同应用合并部署到一台机器上,当然不仅仅是部署在一台机器上,还要在同一个Tomcat容器中,且不能走本机的Socket,这样才能避免序列化的产生。并发读优化 需要划分成动态数据和静态数据分别进行处理:像商品中的“标题"和"描述"这些本身不变的数据,会在秒杀开始之前全量推送到秒杀机器上,并一直缓存到秒杀结束;像库存这类动态数据,会采用"被动失效"的方式缓存一定时间(一般是数秒),失效后再去缓存拉取最新的数据。06 | 秒杀系统“减库存”设计的核心逻辑下单减库存,即当买家下单后,在商品的总库存中减去买家购买数量。下单减库存是最简单的减库存方式,也是控制最精确的一种,下单时直接通过数据库的事务机制控制商品库存,这样一定不会出现超卖的情况。但是你要知道,有些人下完单可能并不会付款。付款减库存,即买家下单后,并不立即减库存,而是等到有用户付款后才真正减库存,否则库存一直保留给其他买家。但因为付款时才减库存,如果并发比较高,有可能出现买家下单后付了款的情况,因为可能商品已经被其他人买走了。预扣库存,这种方式相对复杂一些,买家下单后,库存为其保留一定的时间(如10分钟),超过这个时间,库存将会自动释放,释放后其他买家就可以继续购买。在买家付款前,系统会校验该订单的库存是否还有保留:如果没有保留,则再次尝试预扣;如果库存不足(也就是预扣失败)则不允许继续付款;如果预扣成功,则完成付款并实际地减去库存。针对“库存超卖”这种情况,在10分钟时间内下单的数量仍然有可能超过库存数量,遇到这种情况我们只能区别对待:对普通的商品下单数量超过库存数量的情况,可以通过补货来解决;但是有些卖家完全不允许库存为负数的情况,那只能在买家付款时提示库存不足。 实际使用方案目前来看,业务系统中最常见就是预扣库存方案,像你在买机票、买电影票时,下单后一般都有个“有效付款时间”,超过这个时间订单自动释放,这都是典型的预扣库存方案。而具体到秒杀这个场景,应该采用哪种方案比较好呢?由于参加秒杀的商品,一般都是“抢到就是赚到”,所以成功下单后却不付款的情况比较少,再加上卖家对秒杀商品的库存有严格限制,所以秒杀商品采用“下单减库存”更加合理。另外,理论上由于“下单减库存”比“预扣库存”以及涉及第三方支付的“付款减库存”在逻辑上更为简单,所以性能上更占优势。“下单减库存” 在数据一致性上,主要就是保证大并发请求时库存数据不能为负数,也就是要保证数据库中的库存字段值不能为负数,一般我们有多种解决方案: 一种是在应用程序中通过事务来判断,即保证减后库存不能为负数,否则就回滚;另一种办法是直接设置数据库的字段数据为无符号整数,这样减后库存字段值小于零时会直接执行SQL语句来报错;再有一就 用CASE WHEN判断语句,例如这样的SQL语句: UPDATE item SET inventory= CASE WHEN inventory >= xxx THEN inventory-xxx ELSE inventory END类似 update order set inventory = inventory - xxx where inventory >= xxx07 | 准备Plan B:如何设计兜底方案?具体来说,系统的高可用建设涉及架构阶段、编码阶段、测试阶段、发布阶段、运行阶段,以及故障发生时。 ...

September 6, 2019 · 1 min · jiezi

专访宜信梁鑫回归架构本质重新理解微服务

本期专访宜信开发平台(SIA)负责人梁鑫,与大家一起聊聊微服务架构及其在企业落地应用的策略。 第一部分:微服务的诞生、演变以及应用策略 记者:近几年来,微服务架构设计方式被提出并在越来越多的企业中得以实践和落地,但对于刚开始接触微服务的人来说,还是不知道要从哪些方面开始了解。您能否结合软件架构的发展历史,聊聊微服务的发展与特征。 梁鑫:微服务本质上是一种架构的风格,如果要了解微服务,我认为需要先了解整个架构的发展脉络。 软件架构,总是在不断的演进中。如果把时间退回到二十年前,当时企业级领域研发主要推崇的还是C/S模式,PB、Delphi这样的开发软件是企业应用开发的主流。 随着时间的推移,我们发现标准化的客户端存在一些弊病,比如我有一千个终端,升级版本需要每一台终端都升级,这是非常麻烦的。然后,企业应用研发开始向互联网学习,把浏览器作为客户端来使用,就可以避免这个问题。因此,基于浏览器的B/S架构开始渐渐流行起来。 刚开始的时候是ASP,之后又出现了JSP,因为Java的预编译模式,让性能有了非常大的提升,随后基于Java语言的J2EE架构就变得越来越流行。至此,架构经历了从传统的C/S模式到B/S模式的转变。 B/S架构初期基本都是单体架构,各个系统比较独立,他们之间往往不需要进行交互,即使存在一些交互,也大多是数据层面的。那个阶段ETL工具发展得很快,就是为了解决这样的数据孤岛问题。 随着企业应用越来越多,系统之间相互的关系也越来越密切,系统之间实时交互访问的需求也越来越多。这个时候工程师们发现,不管是什么语言开发的软件,基本都支持一种叫做XML的语言,于是提出一种实时交互的技术解决方案:通过XML语言来进行企业应用系统之间的远程调用。由此,SOA的概念被提了出来,WebService开始流行。 当第二波互联网浪潮来临后,很多公司为了适应更加灵活的业务发展,用基于HTTP协议和Restful的架构风格替代了原先笨重的WebService,简洁清晰的JSON替代了XML。同时SOA架构中常常采用服务总线技术,无疑是给系统架构增加了一个异常麻烦的瓶颈。如果使用注册和发现的机制,让服务进程之间直接进行调用,更适合企业应用的发展。这就是微服务架构从技术方面来说的历史脉络。 在《微服务设计》中界定微服务有两个基本原则:松耦合&高内聚。即“把因相同因素变化的事情聚集在一起,把因不同因素变化的事情区隔开来。”至于微服务大小的划分并没有统一的标准,通俗地说,就是你觉得它的大小差不多,同时符合“松耦合&高内聚”的原则就可以。 微服务有很多的好处,大致列举一些。 异构:微服务可以帮助我们轻松采用不同的技术,并且理解这些新技术的好处。尝试新技术通常伴随着风险,但如果把服务切得很小了,总会存在一些点让你可以选择一个风险最小的服务采用新技术,并降低风险。弹性:很明显,微服务可以很好地处理服务不可用和功能降级的问题,因为它可以形成很多个节点。隔离:微服务架构将系统分解为独立运行单元,给系统带来更好的隔离性,独立的微服务在发生异常时更容易定位和隔离问题,隔离性也是服务扩展性的基础。扩展:庞大的单体服务只能作为一个整体进行扩展,即使系统中只有一小部分模块存在性能问题,也需要对整个系统进行扩展。而微服务架构可以根据性能需要对不同的模块进行水平扩展。部署简单:在微服务架构中,各个服务的部署是独立的,这样就可以更快地对特定部分的代码进行部署。服务出现问题也更容易快速回滚,同时敏捷的交付和部署带来了更好的业务需求响应体验。灵活:在微服务架构中,系统会开放很多接口供外部使用,当情况发生改变时,可以使用不同的方式构建应用。把单体应用分解成多个微服务,可以达到可复用、可组合的目的。记者:据悉,您之前发表过一篇文章“公司为什么需要建立一套统一的开发框架?”,您认为公司建立统一开发框架是为了解决什么问题? 梁鑫:这是一个仁者见仁智者见智的问题,每个人的出发点都不一样,有的人可能主张需要统一,有的人则可能排斥统一,结合我的经历和实践来看,我认为公司是需要建立统一开发框架的。 近十年,互联网的发展颠覆了很多传统行业,很多新兴公司如雨后春笋般的冒了出来,它们的业务增长非常快,公司规模也越来越大。这得益于中国经济的高速增长和互联网的快速发展。但这种高速的发展过程中伴随而来的是不可忽视的弊端: 弊端一:自我繁衍在公司快速的发展过程中,往往会出现这样一个链条。新增一块业务 —> 招聘一位高级技术人员 —> 围绕这位同事组建一支技术团队 —> 该业务基本由这只团队负责,然后就形成了一个闭环。当需要跟其他业务进行交互时,经常是技术负责人之间自行决定。这就形成了自我繁衍的状态。 弊端二:管控壁垒随着业务规模的快速发展,这个团队很快形成了一个部门,团队决策者通常会从自身利益考量,希望尽量减少对外部门的依赖,无论是技术选型、规范建立、组件选取、运行环境都能够自行掌控。 弊端三:断崖效应当这样的技术氛围一旦形成,单个员工对单个项目的影响就会变的非常巨大。一个产品经常会因为一两个核心员工的离职难以为继,最后不得不重新开发新的产品。 弊端四:资源浪费当每个团队都在试图构建自己完整的研发流程时。中间的技术研究、产品研发、运维管理就会出现非常多的资源浪费。 弊端五:难以考核怎么衡量一个川菜厨师和一个鲁菜厨师谁更优秀?当每个团队都是一个闭环,采用不同技术栈、不同的技术组件、不同的维护方式和规范时,已经无法从产出效率来判断一个团队的绩效,KPI 指标也就非常难以设立。 建立一套公司级的统一的开发平台可以有效解决上述问题。从技术层面来讲,如果可以形成公司级别的统一开发平台,会在实际的生产过程中带来非常大的收益。 首先,避免了重复性技术研究,节约了人力成本。在项目组之下构建一个基础的开发架构平台,把技术共性问题提炼出来,交给一个专门团队负责处理,让项目组把精力投入到业务中。其次,标准化了技术规范,提升了产品项目质量。做工程要千人一面,而不要千人千面。采用统一的开发平台后,在技术栈、技术组件、技术实现方案,甚至在代码规范上,就能形成标准化的技术输出模式,标准化带来的效果不仅仅是开发效率的快速提升,还有产品质量的大幅提升。再次,可以进行技术沉淀,提升公司整体的技术能力,避免陷入一个人的能力决定一个项目。技术的进步来源于不断的技术积累和沉淀,建立公司级别的统一开发框架(平台),项目团队基于该平台进行自身项目的研发,不再需要关注于底层技术实现,只需要关注业务即可。而且,专注于平台的同事为了更好地满足项目组的技术需求,对平台进行不断的改进,从而达到技术积累和沉淀的目标。最后,可以对研发的投入和产出进行衡量,对研发团队进行有效管理和考核。当基于同一开发平台的标准化技术规范建立起来后,对业务功能的代码实现就可以进行相对有效的评估和考量,可以避免因为技术实现差异而出现的种种问题。这对KPI的制定和考核是一个巨大的帮助。我从前年提出这样的一个思想,通过一年多的努力,已经在公司有了一定的成果。我们的统一开发平台定位于技术层面,其主要目的是为统一公司内相关产品研发和项目实施使用的技术架构和开发工具,有效提高统一技术支持力度,形成持续的技术积累手段,提升技术人员的利用率并降低对人员的依赖性,最终提升软件的规模化、流水线式的生产能力。 记者:最近“Spring Boot”、“Spring Cloud”等词总被提及,这些新的框架集合方案与传统的微服务框架相比有哪些优势?结合您的经验来看,您认为微服务未来的发展走向可能是什么? 梁鑫:我是公司内部较早研究Spring Cloud 技术栈的人,也是Spring Cloud中国社区的成员。Spring Cloud是在2017年一跃成为最流行的微服务开发框架。但是,这里有一个需要辩证看待的问题。“不是说使用了Spring Cloud框架就实现了微服务架构,具备了微服务架构的优势”,正确的理解应该是“使用Spring Cloud框架开发微服务架构系统,使系统具备微服务架构的优势。”Spring Cloud之所以能从其他框架中脱颖而出成为最火的框架,得益于其本身体系的完整性。这一点通过下图Spring Cloud、Dubbo和ServiceComb的对比可以比较直观地了解到。 另外,Spring在中国有广泛的群众基础,我也比较推崇这种“约定大于配置”的研发思想,不需要完全依赖标准化的东西。 我不敢妄谈微服务架构的未来走向。立足当下,我认为目前Spring Cloud+Docker容器化的技术是用于微服务架构的一个比较好的选择。我比较认可一个很有趣的说法是“基因架构”,意思是:架构从诞生之初就是为了改变的,所以你的架构越容易改变就越好。我觉得架构的未来会向这条路发展。 我们的统一开发平台的建设就是基于Spring Cloud技术栈。 记者:今年在软件研发行业比较热门的话题是“中台”,在架构层面也有人提出来要做微服务中台,对此您怎么看? 梁鑫:去年一个综艺节目带火了一句话,“盘它”。节目里有一句 “干干巴巴的,麻麻赖赖的,一点都不圆润,盘他!”。 后来说到什么就盘什么,也不管是什么东西,能不能握在手中,反正盘就是了。听起来是不是特别有魔性,然后就有了“万物皆可盘”这个段子。这本身其实只是一种调侃的讲法,也并不会真的有人看到什么就盘什么。有意思的是任何事情都可以再认真往深处想一想,你会不会也犯一些看似荒唐的错误呢?今年技术圈最火的一个名词就是“中台”,套用到这儿就变成了“万物皆可中台”,一个名词到处套,我认为很多公司应该避免盲目跟风,让“中台”成为名词陷阱。 面对一个新的技术或趋势,我们要先了解其来源和根本。中台的来源需要回溯到阿里。2015年阿里巴巴集团启动了中台战略,目标是要构建符合互联网大数据时代的,具有创新性、灵活性的‘大中台、小前台’的机制,即作为前台的一线业务会更敏捷、更快速地适用瞬息万变的市场,而中台将集合整个集团的运营数据能力、产品技术能力,对各前台业务形成强有力的支撑. 那阿里集团为什么要建立一个‘大中台、小前台’的架构呢?《企业IT架构转型之道——阿里巴巴中台战略思考与架构实战》一书对此有详细介绍。从阿里共享业务事业部的发展史说起,起初,阿里只有一个淘宝事业部,后来成立了天猫事业部,此时淘宝的技术团队同时支撑着这两个事业部。当时的淘宝和天猫的电商系统像我们很多大型企业的一样是分为两套独立的烟囱式体系,两套体系中都包含的有商品、交易、支付、评价、物流等功能。因为上述原因,阿里集团又成立了共享业务事业部,其成员主要来自之前的淘宝技术团队,同时将两套电商业务做了梳理和沉淀,将两个平台中公共的、通用的业务功能沉淀到共享事业部,避免重复建设和维护。 作为一个拥有10多年编程经验的老兵,我经常思考的一个问题就是系统发展的规律,透过其形领会其意,回顾架构的发展,我认为可以总结出一点:“快”。当然这个快是有前提的,比如正确率、资源限制,要在稳定、尽量减少资源消耗的情况下求快。 “快”可以再次分解,从开发的角度来看,编写代码要快、开发要快、功能测试要快、环境部署要快、服务启停要快;从生产的角度来看,程序运行的速度要快、高并发之下还是要快等。 微服务架构之所以流行,因为把服务拆小了,可以高度复用,不用经常编写和修改代码,节省了非常多的时间;容器化技术之所以流行,因为容器化技术可以使得生产环境和测试环境一致,节省了大量的环境部署时间、减少了出错的可能性,还可以随意增加容器节点,增强业务处理能力,保证高并发下的快速响应。分布式架构也是如此,微服务架构其实就是分布式架构的一种演化。万变不离其宗,都是追求“快”。 回到“中台”这个话题,建设中台的目标是避免重复建设和维护,快速响应需求。后台和平台的系统比较稳定,一般不轻易发生变化,而且从稳定性考虑,应该尽量减少后台和平台系统更新的次数,前端系统因为要适用用户的需求而不断变化,这样前台和后台在对接时就产生了一个求变一个求不变的矛盾,这时我们希望在两者之间建立一个中间平台,把前端后台可重复利用的东西集中到这个中间平台来,重新封装组合对外提供服务,这是符合“快”的思想的。 这是中台的来源和根本,企业在建设中台之前,一定要先了解这些,看所要建设的中台是否符合“避免重复建设和维护”的思想,是否符合“快”的原则。 第二部分:微服务在业务中的应用需要解决的关键问题 记者:宜信在今年开源了微服务任务调度平台SIA-TASK,这个平台在宜信技术团队内部有广泛的应用,开源后也得到了很多开发者的支持。您能否介绍一下这个平台的设计思路以及核心功能?(设计开发这个平台想要解决什么问题) 梁鑫:前面谈到中台,其实我认为“中台”只是一个名称而已,只要符合“避免重复建设和维护”和“快”两个原则,叫什么都可以,比如我们的微服务调度平台SIA-TASK,就是一个很像中台的系统。 介绍SIA-TASK的设计思想之前,我先介绍一下它的背景。无论是互联网应用或者企业级应用,都充斥着大量的批处理任务。常常需要一些任务调度系统帮助开发者解决问题。随着微服务化架构的逐步演进,单体架构逐渐演变为分布式、微服务架构。很多原先的任务调度平台已经不能满足业务系统的需求,于是出现了一些基于分布式的任务调度平台。这些平台各有其特点,也各有不足之处,比如不支持任务编排、与业务高耦合、不支持跨平台等问题,不符合新一代微服务架构的需求,因此我们开发了微服务任务调度平台(SIA-TASK)。 SIA-TASK 使用 SpringBoot 体系作为架构选型,基于Quartz及Zookeeper进行二次开发,支持相应的特性功能,SIA-TASK 的逻辑架构图如下图所示: ...

August 20, 2019 · 1 min · jiezi

面向对象设计的SOLID原则

1、单一职责原则考虑下面这个类 class Animal { constructor(name: string){ } getAnimalName() { } saveAnimal(a: Animal) { }}它实际上违背了单一职责原则SRP。上面的类其实有两个职责,一为动物实体的持久化管理,另外一个为动物的属性管理。那我们应该如何设计避免这种错误呢?我们可以新建另外一个类,它负责将实体对象存储到数据库上。如下所示: class Animal { constructor(name: string){ } getAnimalName() { } } class AnimalDB { getAnimal(a: Animal) { } saveAnimal(a: Animal) { } }当我们设计类时需要注意的一点是,如果功能因不同原因而发生变化,我们应该尝试将功能分开。2、开闭原则这个原则强调现有接口规范可以通过继承重用,不要修改现有已完成的接口。我们继续以动物这个类说明 class Animal { constructor(name: string){ } getAnimalName() { }}我们的需求是让列表中每个动物发出不同的声音,如下所示//... const animals: Array<Animal> = [ new Animal('lion'), new Animal('mouse')];function AnimalSound(a: Array<Animal>) { for(int i = 0; i <= a.length; i++) { if(a[i].name == 'lion') log('roar'); if(a[i].name == 'mouse') log('squeak'); }}AnimalSound(animals);上面的示例违背了开闭原则,当有新的类型需要处理时,将不得不在原有代码上进行修改,导致大量的阅读性差的IF条件语句。那我们应该怎么设计避免这种错误呢?我们可以定义一个有makeSound方法的共同类比如说Animal类,然后每个具体动物类继承并重写makeSound方法,完成个性化处理。另外真正的处理业务的AnimalSound类遍历Animal列表然后调用makeSound方法即可。当新扩展一个具体动物类时,AnimalSound类无须做任何修改。代码如下: ...

August 20, 2019 · 2 min · jiezi

设计模式之桥接模式

0x01.定义与类型定义:将抽象部分与它的具体实现部分分离,使它们都可以独立地变化。桥接模式将继承关系转化成关联关系,它降低了类与类之间的耦合度,减少了系统中类的数量,也减少了代码量。桥接模式中的所谓脱耦,就是指在一个软件系统的抽象化和实现化之间使用关联关系(组合或者聚合关系)而不是继承关系,从而使两者可以相对独立地变化,这就是桥接模式的用意。类型:结构型UML类图 Java实现/** * 主类抽象类 */public abstract class Abstraction { /** * 桥接组合对象 */ protected Implementor implementor; public Abstraction(Implementor implementor) { this.implementor = implementor; } /** * 操作类 */ public abstract void operation();}/** * 抽象接口 */public interface Implementor { void operationImpl();}/** * 实现类 */public class RefinedAbstraction extends Abstraction { public RefinedAbstraction (Implementor implementor) { super(implementor); } @Override public void operation() { System.out.println("操作"); implementor.operationImpl(); }}/** * 接口抽象实现1 */public class ConcreteImplementorA implements Implementor { @Override public void operationImpl() { System.out.println("桥接A"); }}/** * 接口抽象实现2 */public class ConcreteImplementorB implements Implementor { @Override public void operationImpl() { System.out.println("桥接B"); }}测试与应用/** * 测试与应用 */public class Test { public static void main(String[] args) { Abstraction abstraction1 = new RefinedAbstraction(new ConcreteImplementorA()); Abstraction abstraction2 = new RefinedAbstraction(new ConcreteImplementorB()); abstraction1.operation(); abstraction2.operation(); }}输出结果操作桥接A操作桥接B角色介绍 ...

August 18, 2019 · 2 min · jiezi

领域驱动设计在马蜂窝优惠中心重构中的实践

前言正如领域驱动设计之父 Eric Evans 所著一书的书名所述,领域驱动设计(Domain Driven Design)是一种软件核心复杂性应对之道。 在我们解决现实业务问题时,会面对非常复杂的业务逻辑。即使是同一个事物,在多个子业务单元下代表的意思也是不完全一样的。比如「商品」这个词,在商品详情页语境中,是指「商品基本信息」;在下单页语境中,是指「购买项」;而在物流页面语境中,又变成了「被运送的货物」。 DDD 的核心思想就是让正确的领域模型发挥作用。所谓「术业有专攻」,DDD 指导软件开发人员将不同的子业务单元划分为不同的子领域,在各个子领域内部分别对事物进行建模,来应对业务的复杂性。 一、重构优惠中心的背景我们在实际的开发过程中都遇到过这种情况,最初因为业务逻辑比较单一,为了快速实现功能, 以及对成本、风险等因素的综合考虑,我们会为业务统一创建一个大的模型,各个模块都使用这同一个模型。但随着业务的发展,各子领域的逻辑越来越复杂,对这个大模型的修改就会变成一种灾难,有时明明是要改一个 A 子领域的逻辑,却莫名其妙影响到了 B 或者 C 子领域的线上功能。 优惠中心就是一个例子。优惠中心主要负责马蜂窝各业务线商品的优惠活动管理,以及计算不同用户的优惠结果。「商品管理」和「优惠管理」作为两个不同的业务单元,在初期被设计为共用一个商品模型,由商品模块统一管理。 <center>图1 :初期商品模型</center> 出现的问题随着业务的发展,优惠的形式不断推陈出新,业务形态逐渐多样,业务方的需求也越来越个性化,导致后期的优惠中心无论从功能上还是系统上都出现了一些具体的问题: 1. 功能上来说,不够灵活 优惠信息是作为商品信息的一个属性在商品管理模块配置的。比如为了引导用户使用 App 需要设置 A 类型优惠,就通过在商品信息的编辑页面增加一个 A 类型优惠配置项实现;如果某个商品的 A 类型优惠需要在 0:00 分生效,业务同学就必须在电脑前等到 0:00 更新商品信息来上线优惠活动。 另外,如果想要创建针对所有商品都适用的优惠,按照之前的模式,所有的商品都要设置一遍,这几乎是不可接受的。 2. 从系统层面看,不易扩展 优惠信息存储在商品信息中,优惠信息是通过商品管理模块的接口输出的。如果要新增一种优惠类型,商品信息相关的表就要增加字段,商品的表会越来越大;如果要迭代一个优惠的逻辑,就有可能影响到商品管理模块的功能。 3. 不利于迭代 由于优惠信息仅仅作为商品的一个属性,没有自己的生命周期,所以很难去统计某一次设置的优惠的投入产出比,从而指导后续的功能优化。 重构优惠中心的预期系统层面上,要把优惠相关的业务逻辑独立出来,单独设计和实现;应用层面上,优惠中心会有自己的独立后台,负责管理优惠活动;也会有独立的优惠计算接口,负责 C 端用户使用优惠时的计算。二、分什么选择 DDD避免贫血模型基于传统的 MVC 架构开发功能的时候,Model 层本质上是一个 DAO 层,业务逻辑通常会封装在 Service 层,然后 Controller 通过调用 Service 层来完成对外的功能。这种模式下,数据和行为分别被割裂到了 Model 和 Service 两层。我们把这种只承载数据,但没有业务行为的 Model 称为「贫血模型」。 ...

July 12, 2019 · 1 min · jiezi

马蜂窝支付中心架构演进

为了更好地支持交易业务的快速发展,马蜂窝支付中心从最初只支持基础支付和退款的「刀耕火种」阶段,经历了架构调整的「刮骨疗伤」阶段,完成了到实现综合产品平台形态的「沉淀蓄力」阶段的演进。 目前,马蜂窝支付中心集成了包括基础订单、收银台、路由管理、支付通道、清算核对、报表统计等多种能力,为马蜂窝度假(平台、定制)、交通(机票、火车票、用车)、酒店(开放平台、代理商)等近 20 条业务线提供服务。本文将围绕支付中心整体演变过程中不同阶段的核心部分进行简要介绍。 一、支付中心 1.0初期为快速响应业务的支付、退款以及一些基础需求,支付中心主要负责接入支付通道(支付宝、微信、连连等),由各业务线分别实现收银台,然后调用支付中心进行支付。业务系统、支付中心和第三方通道的交互流程图如下: 各系统交互流程为: 业务线将订单信息封装后请求到支付中心支付中心对订单信息简要处理后增加支付信息请求到第三方支付通道第三方支付通道将支付结果异步回调到支付中心支付中心将第三方响应的数据简易处理后同步通知到各业务系统业务系统进行逻辑处理、用户通知及页面跳转等业务发展初期,业务量较小,交易场景也比较单一,这样的设计可以快速响应业务需求,实现功能。但当业务复杂性不断提高,接入的业务也越来越多时,该架构就显得力不从心了。各业务线需要重复开发一些功能,并且支付中心不具备整体管控能力,开发维护成本越来越大。主要的问题包括: 维护成本高:各业务线需单独维护收银台,调用支付系统完成支付,需分别保证幂等、安全等问题容灾能力差:所有功能集中在一个大模块里,某个功能出问题,直接影响全部结构不合理:架构单一,不能满足复杂业务场景系统职责乱:收银台维护了收款方式及部分业务路由,缺乏统一的管控为了兼顾对快速发展中的业务的需求响应和系统的高可用性,保证线上服务的质量,我们快速进行了架构调整,开始了向支付中心 2.0 的演进。 二、支付中心 2.02.0 架构将各业务的公共交易、支付、财务等沉淀到支付中心,并主要解决了以下三个主要问题: 建立基础订单、支付、财务统一体系,抽象和封装公共处理逻辑,形成统一的基础服务,降低业务的接入成本及重复研发成本;构建安全、稳定、可扩展的系统,为业务的快速发展和创新需求提供基础支撑,解决业务「快」和支付「稳」之间的矛盾;沉淀核心交易数据,同时为用户、商家、财务提供大数据支撑。2.1 核心能力支付中心 2.0 是整个交易系统快速发展的重要时段。在此过程中,不仅要进行架构的升级,还要保证服务的稳定。 目前支付中心对业务提供的主要能力包括: 平台支付:用户可以使用微信、支付宝等第三方平台来完成支付快捷支付:用户提供银行卡信息,进行便捷支付协议支付:用户完成授权后,可以在不打断用户体验的场景下进行便捷支付信用支付:用户可以选择花呗等分期产品进行透支支付境外支付:用户可以选择境外支付通道完成境外产品的购买线下支付:用户可以选择 ToB 通道完成特定场景的支付针对马蜂窝业务的特点,目前支持的核心交易场景包括: 支付和退款:适用于普通商品的购买及退款拆分支付:适用于限额或金额较大场景合单支付:适用于保险等分账到不同收款账号的场景2.2 架构设计演进过程中,首先是对相对独立,同时作为统一体系基础的网关进行模块化。支付网关对外抽象出支付、退款、查询这些标准请求,然后在网关基础上逐步梳理各支付通道,并逐步抽取出基础订单模块,解耦业务功能与支付功能,同时可支持复杂的业务场景。目前的系统功能整体架构如下: 如图所示,从架构上主要分为三个层次: 产品层:组合核心层提供的支付能力,对终端用户提供收银台、对运营财务人员提供运营财务系统核心层:支付中心核心模块,包括基础订单、支付路由、支付通道等支撑层:用来支撑整个系统的基础设施,包括监控报警、日志、消息队列等2.2.1 产品层产品层主要包含消费者可见的收银台、支付管理后台和财务核算、对账的财会系统。本文重点介绍收银台的设计思路。 收银台收银台包含 H5 收银台和 PC 收银台两部分: 移动端: PC端: 如上图所示,收银台主要由三部分组成:订单基本信息(含订单号及支付金额)、订单详情(含日期信息、商品信息及基础信息)、支付方式(平台支付、信用支付等)。 由于收银台是整个支付中心面向用户的唯一入口,用户体验及安全性至关重要。为同时支持业务个性化和用户的一致性体验,收银台主要是通过定制化和配置化的方式实现。对业务同学来讲接入也非常简单,仅需通过订单号跳转至收银台页面,后续流程均由支付中心完成。  用户下单后到达收银台页面,收银台通过订单所属业务线、支付金额、是否合单等信息,展示可用的支付通道。同时风控系统会从商品、订单、用户行为等维度进行监控,屏蔽高风险的支付渠道。支付渠道出现故障时可在收银台暂停展示。 (1)定制化 为支持统一收银台下各业务线不同模式、不同展示的特性,使用工厂类继承的模式实现各业务数据及展示样式。收银台主要属性分为展示模块和通道路由,其中重复及默认功能的模块由抽象类用模板的方式实现,子类使用默认方法或者重写父类方法即可达到自定义的实现。收银台展示实现类已经实现了一套默认的收银台,其中包含大多数必须的组件(如倒计时,头部定制,订单详情等)。一般情况下,各个业务线仅需简单添加特定的实现类,即可生成一个清晰又丰富的页面(2)配置化 收银台的配置化主要根据各业务的属性(业务类型、品类等)对后续操作做一定的流程处理配置化,比如: 基于后端路由对收银台展示层做不同的处理,用户看到的可支持的通道列表(微信、支付宝等),以及排序置顶打标记等满足不同场景、不同业务在同一种支付方式下收款到不同的收款账号根据场景不同,走不同的结算方式,以及结算渠道等2.2.2 核心层支付中心中的核心模块,包括基础订单、支付路由、支付通道等。 基础订单基础订单系统是连接交易业务线、支付中心和结算系统的桥梁,实现了业务和支付结算解耦。主要涵盖了业务创建订单、关单、支付、退款、回调通知等 API 模块。基础数据支持普通支付、合单支付、拆分支付、保险支付等多种场景的支付功能,各个系统的交互流程如下: 目前基础订单系统可支持如下两种特殊场景: (1)一订单 VS 多商品 创建一个基础订单可以包含 N 个商品(商品信息包含商品名称、商品 ID、单价、数量、折扣等,订单信息包含用户 UID、手机号、支付金额、订单折扣等汇总基础信息),N 个商品对应 M 个业务子订单 (M≦N),所有业务子订单的业务类型若一样则为普通模式,否则为搭售模式;每个业务订单对应一个对账单元(支付成功后会将支付信息同步给对账系统),一订单 VS 多商品的创单模式基本支持目前所有场景,包括未来可能的购物车模式。 (2)一订单 VS 多支付单 ...

July 5, 2019 · 1 min · jiezi

前端架构有什么能做的

前端有架构吗?前端有架构模式吗? 架构是什么?软件架构,是一种为了解决复杂问题的通用模式。软件架构,是关于软件系统的一系列有层次的技术决策的集合。换句话来说,当我们讨论架构的时候,不能只讨论某某架构,而是要包含其实施,以及后期的维护。 因为: 一个无法上线的应用架构,算不上是好的软件架构一个没有人能完成开发的软件架构,算不上是可行的软件架构一个在现有的技术上不可行的架构,算不上是合理的软件架构诸如微服务,对于复杂的后端系统来说,是一种不错的『低耦合,高内聚』的实施。但是,它并不适合于大部分的小公司——复杂的架构不适合于简单的应用。而小公司也缺乏足够的人才,来实施一个复杂的系统,与此同时还需要有人能维护这个系统。 所以,当我们谈及软件架构的时候,说的是:有这么一些人,他/她们能按时、高质量(或者说有质量)完成这一个系统的设计——即有能力的个人。 PS:对于前端架构来说,这些人大概率会来自于看了本书的人,笑~ 前端架构拆解:四层次设计从笔者的角度来看,架构设计本身是分层级的,面向不同级别的人时,所展示的内容也是不一样的。如面对的是同一级别、更高一级别的架构师、技术人员,说的便是形而上学的东西,如微前端、前后端分离,并通过各种概念,如构建系统拆份,以抽象的方式介绍如何去设计。这些概念,对于接触过的程序员来说,也是相当好理解的。而当我们面对的是,经验略微丰富的程序员的时候,说的可就不是:去实现微前端这样的东西。而是需要落实到怎样去做这样的一件事。 在不同的时期,不同的阶段,我们考虑的架构相关的因素是不同的。按照这个思想,笔者将架构的设计分为了四个层级: 系统级,即应用在整个系统内的关系,如与后台服务如何通讯,与第三方系统如何集成。应用级,即应用外部的整体架构,如多个应用之间如何共享组件、如何通信等。模块级,即应用内部的模块架构,如代码的模块化、数据和状态的管理等。代码级,即从基础设施来保障架构实施。 对应的层级与实施模式,如下图所示: ![前端四个层级]() 系统内架构在设计前端架构的时候,首先考虑的是应用在整个系统中的位置——它与系统中的其它子系统是怎样的。这种关系包含了架构上的关系、业务上的关系,以及它们之间的协作机制。对于前端应用来说,这一部分的子系统包含了: 其它前端应用。侧重于关注如何与这些应用交互,诸如交互、通讯等。对接的后台服务。关注于如何与后台服务进行通信,诸如权限、授权、API 管理等。若是系统间的数据通信,如与后台服务之间的交互,那么只需要规定好数据通信、数据传递的机制即可。这一类的通讯机制,不仅仅包含了前后端分离架构的 API 设计,还包含了各类的数据传递,诸如 OAuth 跳转的 Token 验证。除此,对于传统的多页面应用来说,也需要关注于其中的数据传递,如 Cookie 作为用户凭据等等。 为此,对于前端开发人员来说,关于与后端间的关系,我们所要考虑的主要因素是前后端分离架构的设计。 前后端分离架构。(详见《前端架构:从入门到微前端》)微前端架构。(详见《前端架构:从入门到微前端》)而后,我们还需要考虑到前端的客户端展现形式。在大前端的背景之下,它可能是以 PC Web 应用、移动 Web 应用、混合移动应用(结合 Cordova 构架)、混合桌面应用(结合 Electron 框架)、原生移动应用(结合 React Native)等,具体选择何一种技术,取决于我们在之前调查的利益相关者的需求。 当我们做完上述的三个核心的架构决策之后,就需要考虑一下应用的部署架构。不同的客户端形式,或者需要服务端渲染,会在某种程度上影响到前端应用的部署,但是总的影响并不是太大。往往只需要通过反向代理的配置,就可以完成部署的配置。若是与后台服务不在一个域,则需要考虑支持跨域请求或者是后台做一层代码。 在有了这些基本的架构设定,便可以往下继续设计下一层级的应用架构。 应用级架构应用级架构,指的是单个应用与外部应用的关系,如微服务架构下的多个应用的协作。它可以是一个团队下的多个前端应用,又或者是一个组织内的前端应用。其在组织中所处的位置,也进一步决定了我们所需要设计的架构方案。 若是从相关的定义上来看,它与系统级应用存在一定的交集。但是,笔者将其视之为系统级架构的进一步细化。如在系统内架构的层级里,我们定义了微前端架构,而具体的实施细则会放在各个应用中实现的。而诸如应用间的数据如何交换,而不同的应用又有各自不同的实现,则会在这个层级里定义了相应的接口。 与此同时,当我们维护了多个前端应用,必然会去考虑在这些应用之间,复用代码、共享组件库、统一设计等,以减少相应的工作量。为此,在这个层级里,我们会考虑下面的一些架构相关的设计内容: 脚手架。(详见《前端架构:从入门到微前端》)模式库。(详见《前端架构:从入门到微前端》)设计系统。(详见《前端架构:从入门到微前端》)与此同时,在这个层级里,我们决定选择什么前端框架,进行相关的技术选型。 模块级架构模块级架构,便是深入单个应用内部,更细致的设计应用内部的架构。它所涉及的部分,便是在日常开发中,我们经常接触到的主要部分。我们所做的便是制定一些规范,又或者是更细致的架构设计。这部分的内容,会在我们开始业务编码之前进行设计,在敏捷软件开发中,它称之为 迭代 0/Sprint 0/Iteration 0。相关的内容有: 模块化。(详见《前端架构:从入门到微前端》)组件化。(详见《前端架构:从入门到微前端》)除此,对于不同的框架,还涉及到一些框架特定的模式与架构设计,它们会在一定程度上影响单个应用的架构。对于不同的框架来说,所需要涉及的范围都有所不发。如在 Angular 框架中,不需要操心相关的模式,只需要掌握框架定义的规范即可,如使用 Service 来保存应用的状态,使用 Pipe 来处理数据等。而在 React 框架中,则需要设计状态和数据流的管理方式,为此便需要诸如 Flux 或者 Redux 这样的状态管理方案。 代码级:规范与原则当我们真正编码的时候,考虑的架构因素便是更低层级的内容。这部分的架构设计,便称为代码级的架构设计,它关注于实践过程中的相关规范和原则。这部分的内容相当的多,并且繁琐。它包含了以下的内容,但是又不限于下述的部分: 开发流程。(详见《前端架构:从入门到微前端》)代码质量及改善。(详见《前端架构:从入门到微前端》)规范而非默契。(详见《前端架构:从入门到微前端》)除此,在日常的开发中,还需要注重代码的可维护——简单的代码更容易读性和维护。笔者维护一个 Scala 项目的过程中,便是深有体会——越是写得越抽象的代码,越难以维护。诸如函数式编程是一个好的东西,但是好的东西也容易被烂用,导致人们不喜欢这个东西。 小结买, 买,买 ——节选自《前端架构:从入门到微前端》 ...

July 5, 2019 · 1 min · jiezi

分布式系统设计模式

layout: posttitle: 分布式系统设计模式category: 技术keywords: 架构,分布式,微服务,后端,分布式系统,设计模式 comments: true概述这篇文章是对于【分布式系统设计模式】的个人理解和部分翻译。 文章探讨了关于《基于容器化软件组件的微服务架构》。 其实容器化编程的发展路径和面向对象编程有异曲同工之妙--都是将复杂的系统进行抽象、解耦,然后通过一定的方式组合起来。 既然我们要组合,肯定会有面对不同情况的不同组合方式。所以,这些不同的组合方式也会有几个常用的固定模式。而这个正式我们要探讨的--分布式系统设计模式。 说到分布式,第一个联想到的应该就的容器化。为什么?其实容器化和分布式本没有交集,只是因为我们发现容器化是一个实现分布式的高效的方法。 容器化设置了一个天然的边界,边界之外用接口进行通信。有了这个边界的好处就是,任何意料之外的情况都可以被限制在最小的影响范围,毕竟我们构建的是一个大型的复杂系统。 我认为,用FMEA模型能很好的描述为什么会采用容器化去解构分布式系统。(FMEA,可以理解为:失控的状态一定会发生,我们要做的是控制失控的范围) 所以,我们接下来要说的设计模式基本上都是和容器相关,我们需要把容器作为一等公民去看。毕竟这是写 Kubernetes 的哥们写的。 单容器管理者模式 (Single-container management patterns)我们为容器增加一些可控接口,比如 run(), stop(), pause(),使得容器对外来说是可控的。 也正是因为广泛的 http 协议支持,你完全可以通过 http 和 JSON这样的序列化方式去构造你应用的对外的 API。 一般来说我们的设计方针都是一个容器提供一种服务。同时容器会为其上下游提供接口。 什么接口? 向上,提供容器本身丰富的信息接口。能够为特定的监控容器运行状态的应用提供信息。 向下,提供了控制容器本身的接口。使得分布式系统能够更有效的管理整个应用的生命周期,以及应用的优先级。 比如,一个集群的管理系统,能够设置集群处理任务的优先级。(比如 K8s 中的抢占式调度) 所以一旦采用这种模式的话,你会需要一个统一的管理平台,通过接口去管理(组管理)单个容器。 单节点-多容器应用模式 (Single-node, multi-container application patterns)这种模式比较好理解,有些容器应用是需要“共生”的,所以我们会将其放在同一个节点上。一旦这样,分布式系统会对容器组做联合调度。比如 K8s 里将调度单位描述成了 Pods(一个 Pod 可能包含多个容器),Nomad 则称其为 task groups。下面几个就是常用的单节点多容器的设计模式: 副载模式(Sidecar pattern)多容器部署最通用的一种模式,就是 sidecar 模式。其实大家都直接称呼 Sidecar 模式,不会翻译成副载。 那 Sidecar 是个啥样子呢? 举个例子吧:我们有一个主容器是 Web Server,我们需要收集 Web Server 所产生的日志。所以我们会有一个专门的 sidecar 容器,负责收集日志并把日志存储到集群的存储系统。 ...

June 27, 2019 · 1 min · jiezi

指尖前端重构React技术调研分析

一、为什么选择ReactReact是当前前端应用最广泛的框架。三大SPA框架 Angular、React、Vue比较。 Angular出现最早,但其在原理上并没有React创新的性能优化,且自身相对来说显得笨重。Vue出现最晚,其核心原理学习了React,只是语法形式的变化,关系上来说React是开拓者,Vue是学习者。React社区有强大活力与创新能力,不断涌现革命性的创新产品,其中包括可以使用JS操作原生控件的React Native,Vue后来跟进学习出了类似的Weex,但两者成熟度差很多。目前来看React的生态系统要比Vue大的多,在github、stackoverflow等最大的技术社区搜索两者,React的搜索结果是Vue的十倍左右,另外据近期统计使用React的站点是Vue的几百倍以上。更大的生态意味着更多可用的资源,以及遇到问题可以得到更多的有效参考与帮助,这也是除了性能之外选择React的核心原因。 选择React之后,应用会在以下几个方面有提升。 第一,原先的html间跳转会有短暂的白屏现象,这一点在安卓性能较差的机器上尤为明显,而React作为单页应用没有这个问题。第二,React 提供的虚拟DOM包含Diff算法,即将原dom copy一份,与改动后的dom对比,只渲染不同的dom节点,实现最小代价渲染,vdom创新的性能优化方式对性能的提升毋庸置疑。第三,React中核心组件化技术,更加容易的绑定事件行为,动态更新特定的dom,代码更加模块化,重用代码更容易,结构清晰易维护。二、在移动端使用React三大框架在移动端分别有自己的东西。Angular的ionic,React的React Native,Vue的Weex。其中ionic 是基于cordova技术,依然是浏览器应用。而后两者已上升到操作原生控件的层面,做出来的是原生界面,其中React Native的成熟度远高于Weex,已经被很多公司使用,而Weex使用者很少。 综合来看选择React 生态明显最佳,由当前的cordova过渡为cordova+Reactjs,然后可以平滑地过渡到React Native,媲美原生性能的最优混合开发方式。之所以说平滑是因为React Native中近90%的代码(JS)可以在IOS和Android端使用,剩余的涉及原生的代码也基本可以找到可用的资源,就像cordova 的插件一样。毕竟如果需要同时掌握JS, OC(或swift),java(或kotlin)才能开发React Native的话,那这门技术不会有人用;当然反过来如果有原生开发知识的话会对开发React Native有一定帮助。 直接转型为React native的话涉及了应用底层架构的变动,有比较大的跨度,而转为cordova+Reactjs相对容易,而由cordova+Reactjs到React Native同样容易不少,因为其中大部分Reactjs代码可以重用。 三、Reactjs开发工具的选择首先开发脚手架官方出了Create-react-app,集成了webpack-当前最流行的打包工具,babel-提高js版本兼容性的转码器,以及ESLint-代码检测工具和其它一些常用工具,同时对这些工具进行了比较优的配置。值得一提的是该脚手架将这些工具的配置文件进行了隐藏,本意是让使用者专注于编码即可,但实际使用时通常会有自己配置的需求,此时执行npm run eject即可出现被隐藏配置文件。 React-router 是官方推荐的路由管理工具,由于是单页应用区别于原先的html界面间跳转,跳转实质是在组件间进行,所以需要有路由管理工具来统一化管理。这里值得一提的是,React-router配合webpack可以实现代码的按需加载。 一般来说,webpack打包后会在生成一个压缩的js文件,在单页应用打开会整体加载这个文件,由于该js文件包含之前所有的js代码,虽然进行了压缩,一般仍至少有几百kb,当应用稍微复杂点,打包后文件会相应变大。而加载的时候,不管那些代码有没有执行到,都会下载下来并进行加载,造成性能浪费,这一点在显然在web端很重要,而在cordova中是将js代码直接打包在本地,等于跳过了下载步骤但仍然会有加载过程。通过在router中写require.ensure代码并在webpack中相应地修改配置即可将js分成多个文件,在需要时加载对应的js文件,实现按需加载。 Redux 是应用最广泛的第三方状态管理工具,其作用是当应用中多数据状态交互时,可以更有方便且代码结构清晰地统一管理状态,下图给出了形象的阐释。由于在实际开发中一般是分人员/分功能模块独立开发,考虑引入redux的成本(redux本身略复杂),可以在没有多数据交互的模块不使用redux,而在类似涉及增删改查的表单以及即时通讯websocket等契合redux的模块使用。 为项目选取合适UI组件库,一定程度上简化UI样式的开发并且考虑使用其提供的过渡动画效果。这方面有比较多的选择,Google Material Design 风格的Material-UI在github上最受欢迎,但其设计语言与我们当前APP截然不同,腾讯的weui和阿里的antd-mobile 较为相近,其中antd-mobile与create-react-app脚手架配合使用时配置项比较繁杂,因为阿里本意是用来配合自己的脚手架dva(封装了react-router和redux),因此暂时选择weui,后期开发有特定组件需求可结合其他ui库使用。 至于页面跳转时的过渡动画,有些UI库给出了一些过渡样式,比如touchstone。但该库已不再维护,文档不佳,且与新版本的react-router配合使用有不兼容情况。后来浏览官方文档发现官方有动画库react-addons-css-transition-group,使用该库结合css3的动画三件套animation,transition,transform即可实现各种动画效果包括基本的过渡效果,比如渐进平移等。 另外关于css,因为是单页应用,所以如果不加处理,直接import css文件的话最终打包生成一个css文件会导致样式应用到全局,造成同类名样式相互污染影响。解决这个问题有很多种方案。Facebook积极探索css in js方式,但直接写内联样式代码可读性太差。目前解决方案中应用最广泛的是css-modules,即在webpack配置中开启module选项,使用styles对象来写样式。 解决的原理是将css类名在打包后编译成哈希字符串,保持其唯一性。但当想要使用全局样式时要再配置,稍显繁杂,且它类名编写的方式为对象的方式,需要整体修改,另外在使用它时,发现不支持-横线的类命名方式,支持下划线方式,推荐驼峰式,而我们之前html中的样式类名大多是横线命名,这意味着原html和css中的类名都要对应修改,考虑到样式类名非常多,这一方式舍弃。 另外有基于css-modules使用高阶组件的react-css-modules使用人数也比较多,允许横线命名方式且全局本地样式区分简单,但有benchmark测试表明其会较大程度拖累性能,所以也舍弃。解决这个问题要最大程度兼容原先css的写法,即改动最小,因为之前的css类样式数量庞大。 Webpack css-loader 有个属性 :local 加上之后类会变成局部作用域,即webpack会对该类型的类进行自动哈希转码处理,但显然类名一个个加:local 是有些呆板的工作,于是想到可以利用scss的嵌套属性将:local在一个css文件中统一加到类名前。这里涉及到在脚手架create-react-app 添加对scss的支持,在命令行执行安装,并在package.json的scripts中添加watch-css指令,将原css文件改为scss文件,然后在最外层添加:local,执行watch-css命令,即可在scss文件旁自动产生css文件,且类名前自动添加:local 前缀,这种方法实践中发现并非所有类的样式都与:local 兼容良好,相应的可以使用文件名代替:local,要做的就是保持文件名的唯一性,这一点原工程下的文件名已满足。这样原先文件中引入css的方式,全局css引入的方式都不需要变化,做到最小代价。 scss 是 sass 3 引入新的语法,其语法完全兼容 css3,并且继承了 sass 的强大功能,sass和less是前端扩充css常用的方式,添加了嵌套,变量,继承等语法,但需要编译成css来最终使用(稳定性考虑)。 四、Reactjs 和cordova结合有哪些需要注意的开发Reactjs使用官方提供的脚手架Create-react-app,最终通过npm run build生成一个单页网页应用,放入cordova的www目录下即可。由于这两部分开发时独立,而原先开发是在含www目录的cordova工程目录下直接开发,这种不同会产生一些问题。比如cordova中某些插件安装后export函数或者变量供引入使用,因为一开始是分离的,在create-react-app中并找不到这些变量,就造成在build的时候产生变量undefined的错误,尽管最终放到cordova工程中后可以找到变量并正常运行,但在第一步react开发时控制台报一堆error会妨碍调试,影响开发体验。 在github上有一些react cordova 库,但实质上它们都需要通过npm run build来打包,所以并没有解决引入插件变量的问题,且会与create-react-app 有相斥的地方。所以要想办法使插件提供的变量在React中不报错,这里在不影响ESLint 检错机制的情况下可以采取迂回的方式。Build时控制台报错仅针对src文件夹下的代码,而在public文件夹下还有个index.html这个文件会最终被打包放到www目录下,因此可以在这个文件中deviceready时添加全局的插件变量(注意该类全局变量的唯一性,可以添加plugin前缀或使用命名空间等方式保证),并将值传给src目录下的代码中,这样即可绕过控制台build以及调试时的报错。 ...

June 26, 2019 · 1 min · jiezi

Design-Review-架构规范

Design Review 是 TTM 过程中至关重要的一环,优秀的 Design review 不但能让技术方案的考虑更加周全,更多意义是避免潜在的线上 Bug 以及不必要的反复。 下面是我经常思考的一些问题,虽然不是每个项目都会涉及到这些点,而且也不应该被这些问题所局限,但作为一个参考,依然希望能给团队提供一个好的思考框架。 可用性外部依赖有哪些?如果这些外部依赖崩溃了我们有什么处理措施?我们 SLA 是什么?主要是指可用性目标几个 9? 50/90/99 分位数的响应时间是多少?QPS 是多少?我们的超时、重试、过载保护、服务降级机制是什么?如何避免雪崩我们的调用方有哪些?分别有什么服务配额?是否需要对关键的服务调用方单独部署?运维我们都有配置了哪些监控?如果出现问题,我们需要查看哪些信息?这些信息是否都有记录?报警的处理流程是什么?系统上线流程和步骤是什么,出了问题后是否可以回滚,以及怎么回滚?安全XSS,CSRF,SQL 注入这些是否需要处理?3 防怎么搞:防抓,防 DDOS,防恶意访问是否有请安全团队 review是否有风控的需求?信息存储时是否设计到密码、信用卡、身份证等敏感信息,这些信息是怎么存储和访问的?扩展性分层,分模块怎么拆分比较合理?拆分出来的模块可以搞成服务单独部署吗?应用层可以水平扩展吗?有用 session 吗?可以去掉 session 吗?如果系统的负载提升到以前的 3 到 10 倍,当前系统是否依然可用存储层面如果需要扩展存储怎么做?系统中有哪些上下依赖的节点 / 系统 / 服务?这些依赖是否会导致无法并行开发?能否去掉这些依赖?是否有数据访问 API? 数据 API 的设计对性能的考虑是什么?数据 API 对异常数据 (超大数据集、空数据集、错误数据、schema 异常...) 的处理是什么?存储数据计划怎么存储?会有可能的性能瓶颈吗?需要考虑一些缓存方案吗?有什么复杂 SQL 可能会导致慢查询吗?数据库的操作什么地方用了事务?什么情况会导致锁竞争?我们的锁策略是什么?一致性和可用性如何平衡?未来如果分库分表会有什么影响?缓存失效会有什么影响?缓存大量失效会有什么影响?冷启动有问题吗?有热点数据吗?多个缓存节点需要权衡可用性和一致性吗?存储时,是否需要分库,分表,选择的理由是什么?技术选型开发语言是什么,框架是什么为什么用他们?缓存用什么(tair/medis/redis/memached),web server 用什么?(nginx+php fpm/ apach php 扩展/jetty/tomcat/jboss),消息队列用什么 (rebbitmq/beanstalk/kafka/mafka/metaq/notify)?为什么用它们?DB 是否可以用、以及用哪种 no sql (hbase/tair/mangodb/redis) 来优化?业界或者其他团队是否有处理过类似问题?他们是怎么处理的?是否可以 copy 或者借鉴?服务调用和服务治理请求同步处理还是异步队列处理比较好?服务接口的 URI 设计合理吗?可以向下兼容吗?服务间的调用协议是什么(dubbo/hsf/thrift) ?有公司标准的调用协议可以用吗(hession/protobuffer)?客户端和服务端的调用协议是什么(http/ws/私有)?有公司标准的调用协议可以用吗?有什么服务治理相关的要考虑的吗?能否接入 SLA 服务治理?业务监控正常的业务逻辑外,可能会有哪些奇葩或者恶意的操作?我们应该怎么处理?除了系统上的监控外,需要什么业务维度的监控吗?log 是怎么记的?如果要 debug 能有什么开关迅速打开吗?log 怎么 rotate?log 会影响性能吗?复用项目中有用什么新技术吗?为什么要用新技术?未来其他人接手容易吗?项目中有什么复杂计算的地方吗?这些计算可以用什么算法优化吗?这个项目可以抽象出来什么可以复用的东西吗?项目中的什么可以不用自己做,调用现成服务吗?测试新的系统设计是否容易独立测试兼容性新的系统是否和已有系统冲突,怎么融进去

June 24, 2019 · 1 min · jiezi

程序员过关斩将你的业务是可变的吗

请不要跟我说用ES或者其他,其实很多中小公司的业务就是如此,就是基于mysql或者sqlserver 来搞这样的业务业务场景不知道通过D妹子的阐述,大家了解情况了没。这里菜菜再详细说一下。D妹子的程序记录了订单的log来供其他业务(比如统计)使用,这里就以统计业务来说,OrderLog表设计如下: 列名数据类型描述OrderIdnvarchar(100)订单号,主键UserIdint下单用户idAmountint订单的金额其他字段省略... 除此之外还有一个用户信息表UserInfo,设计如下: 列名数据类型描述UserIdint用户id,主键ProvinceIdint用户省的idCityIdint用户市的idCountyIdint用户区县的id涉及到拆单等复杂的订单操作,表的设计可能并非如此,但是不影响菜菜要说的事变数的业务现在假如要统计某个省的订单总数,sql如下: select count(0) from OrderLog o inner join UserInfo u on o.UserId=u.UserId where ProvinceId=@ProvinceId有问题吗,sql没问题,这时候用户A的省市区县信息突然变了(也许是在其他地区买房,户口迁移了),也就是说UserInfo表里的信息变了,那用以上的sql统计用户A以前省市区县的订单信息是不是就会出错了呢?(产品狗说在哪下的订单就属于哪的订单) 业务的定位以上的问题你觉得是不是很简单呢?只要稍微修改一下表也许就够了。但是,菜菜要说的不是针对这一个业务场景,而是所有的业务场景的设计。那你有没有想过为什么D妹子的设计会出现这样的问题呢? 深刻理解业务才能避免以上类似的错误发生,一定要深刻理解不变和可变的业务点。 拿D妹子的统计来说,你的业务是统计区域的订单数,这个业务在产品设计上定义的是不变性,也就是说在行为产生的那个时间点就确定了业务性质,这个业务的性质不会随着其他变而变。具体到当前业务就是:用户在X省下的订单不会随着用户区域信息的变化而变化,说白了就是说用户在X省生成的订单永远属于X省。 谈到业务性质的不变性,对应的就有业务的可变性。假如你开发过类似于QQ空间这样的业务,那肯定也做过类似访客的功能。当要显示访客记录的时候,访客的名称在多数情况的设计中属于可变性的业务。什么意思呢?也就是说一个用户修改了姓名,那所有显示这个用户访问记录的的地方姓名都会同时改变。 说到这里,各位再回头看一下D妹子的业务,这里又牵扯到一个系统设计的问题,众所周知,一个好的系统设计需要把业务的变化点抽象提取出来,D妹子订单统计的业务变化点在于用户的省市区县会变化,订单的金额、订单号等信息不会变化。所以你们觉得是不是D妹子的数据表可以修改一下呢? 数据表的改进改进用户信息按照以上的阐述,D妹子业务的变化点在于用户的省市区域信息,所以可以把用户信息的表抽象提取出来,主键不再是用户id 列名数据类型描述Idint主键Id,主键UserIdint用户idProvinceIdint用户省的idCityIdint用户市的idCountyIdint用户区县的id这样的话用户订单log表中就变为 列名数据类型描述OrderIdnvarchar(100)订单号,主键UserBIdint对应用户表中的主键idAmountint订单的金额其他字段省略... 这样设计的话,如果用户的省市区县信息有变动,相应的用户信息表中会存在多条用户省市区县数据 这里的用户信息表并非是用户对象的主表,而是根据订单业务衍生出来的表改进业务数据表根据业务的变性和不变性,既然把订单区域统计的业务定义为不变的业务性质,那订单的log表完全可以这样设计 列名数据类型描述OrderIdnvarchar(100)订单号,主键UserIdint下单用户idProvinceIdint用户省的idCityIdint用户市的idCountyIdint用户区县的idAmountint订单的金额其他字段省略... 写在最后各位读到这里,可能会感觉菜菜这次写的其实很鸡肋,但是,D妹子的场景却是真实环境中遇到的问题。问题的本质还是变性业务和非变性业务的定义和划分,和架构设计一样,数据库的设计其实也需要把变动的业务存储点进行抽象,其实应该说是抽离出来。 希望大家有所收获 --菜菜 添加关注,查看更精美版本,收获更多精彩

June 14, 2019 · 1 min · jiezi

可用性高达5个9支付系统高可用架构设计实战

一、背景对于互联网应用和企业大型应用而言,多数都尽可能地要求做到7*24小时不间断运行,而要做到完全不间断运行可以说“难于上青天”。为此,对应用可用性程度的衡量标准一般有3个9到5个9。 可用性指标计算方式不可用时间(分钟)99.9%0.1%*365*24*60525.699.99%0.01%*365*24*6052.5699.999%0.001%*365*24*605.256对于一个功能和数据量不断增加的应用,要保持比较高的可用性并非易事。为了实现高可用,宜信支付系统从避免单点故障、保证应用自身的高可用、解决交易量增长等方面做了许多探索和实践。 在不考虑外部依赖系统突发故障,如网络问题、三方支付和银行的大面积不可用等情况下,宜信支付系统的服务能力可以达到99.999%。 本文重点讨论如何提高应用自身的可用性,关于如何避免单点故障和解决交易量增长问题会在其他系列讨论。 为了提高应用的可用性,首先要做的就是尽可能避免应用出现故障,但要完全做到不出故障是不可能的。互联网是个容易产生“蝴蝶效应”的地方,任何一个看似很小的、发生概率为0的事故都可能出现,然后被无限放大。 大家都知道RabbitMQ本身是非常稳定可靠的,宜信支付系统最开始也一直在使用单点RabbitMQ,并且从未出现运行故障,所以大家在心理上都认为这个东西不太可能出问题。 直到某天,这台节点所在的物理主机硬件因为年久失修坏掉了,当时这台RabbitMQ就无法提供服务,导致系统服务瞬间不可用。 故障发生了也不可怕,最重要的是及时发现并解决故障。宜信支付系统对自身系统的要求是,秒级发现故障,快速诊断和解决故障,从而降低故障带来的负面影响。 二、问题以史为鉴。首先我们简单的回顾一下,宜信支付系统曾经碰到的一些问题: (1) 新来的开发同事在处理新接入的三方通道时,由于经验不足忽视了设置超时时间的重要性。就是这样一个小小的细节,导致这个三方队列所在的交易全部堵塞,同时影响到其他通道的交易; (2) 宜信支付系统是分布式部署的,并且支持灰度发布,所以环境和部署模块非常多而且复杂。某次增加了一个新模块,由于存在多个环境,且每个环境都是双节点,新模块上线后导致数据库的连接数不够用,从而影响其他模块功能; (3) 同样是超时问题,一个三方的超时,导致耗尽了当前所配置的所有worker threads, 以至于其他交易没有可处理的线程; (4) A三方同时提供鉴权,支付等接口,其中一个接口因为宜信支付系统交易量突增,从而触发A三方在网络运营商那边的DDoS限制。通常机房的出口IP都是固定的,从而被网络运营商误认为是来自这个出口IP的交易是流量攻击,最终导致A三方鉴权和支付接口同时不可用。 (5) 再说一个数据库的问题,同样是因为宜信支付系统交易量突增引发的。建立序列的同事给某个序列的上限是999,999,999,但数据库存的这个字段长度是32位,当交易量小的时候,系统产生的值和字段32位是匹配的,序列不会升位。可是随着交易量的增加,序列不知不觉的升位数了,结果导致32位就不够存放。 类似这样的问题对于互联网系统非常常见,并且具有隐蔽性,所以如何避免就显得非常重要了。 三、解决方案下面我们从三个方面来看宜信支付系统所做的改变。 3.1 尽可能避免故障3.1.1 设计可容错的系统 比如重路由,对于用户支付来说,用户并不关心自己的钱具体是从哪个通道支付出去的,用户只关心成功与否。宜信支付系统连接30多个通道,有可能A通道支付不成功,这个时候就需要动态重路由到B或者C通道,这样就可以通过系统重路由避免用户支付失败,实现支付容错。 还有针对OOM做容错,像Tomcat一样。系统内存总有发生用尽的情况,如果一开始就对应用本身预留一些内存,当系统发生OOM的时候,就可以catch住这个异常,从而避免这次OOM。 3.1.2 某些环节快速失败“fail fast原则”Fail fast原则是当主流程的任何一步出现问题的时候,应该快速合理地结束整个流程,而不是等到出现负面影响才处理。 举个几个例子: (1)支付系统启动的时候需要加载一些队列信息和配置信息到缓存,如果加载失败或者队列配置不正确,会造成请求处理过程的失败,对此最佳的处理方式是加载数据失败,JVM直接退出,避免后续启动不可用; (2)支付系统的实时类交易处理响应时间最长是40s,如果超过40s前置系统就不再等待,释放线程,告知商户正在处理中,后续有处理结果会以通知的方式或者业务线主动查询的方式得到结果; (3)宜信支付系统使用了redis做缓存数据库,用到的地方有实时报警埋点和验重等功能。如果连接redis超过50ms,那么这笔redis操作会自动放弃,在最坏的情况下这个操作带给支付的影响也就是50ms,控制在系统允许的范围内。 3.1.3 设计具备自我保护能力的系统系统一般都有第三方依赖,比如数据库,三方接口等。系统开发的时候,需要对第三方保持怀疑,避免第三方出现问题时候的连锁反应,导致宕机。 (1)拆分消息队列 宜信支付系统提供各种各样的支付接口给商户,常用的就有快捷,个人网银,企业网银,退款,撤销,批量代付,批量代扣,单笔代付,单笔代扣,语音支付,余额查询,身份证鉴权,银行卡鉴权,卡密鉴权等。与其对应的支付通道有微信支付,ApplePay,支付宝等30多家支付通道,并且接入了几百家商户。在这三个维度下,如何确保不同业务、三方、商户、以及支付类型互不影响,宜信支付系统所做的就是拆分消息队列。下图是部分业务消息队列拆分图: (2)限制资源的使用 对于资源使用的限制设计是高可用系统最重要的一点,也是容易被忽略的一点,资源相对有限,用的过多了,自然会导致应用宕机。为此宜信支付系统做了以下功课: 限制连接数随着分布式的横向扩展,需要考虑数据库连接数,而不是无休止的最大化。数据库的连接数是有限制的,需要全局考量所有的模块,特别是横向扩展带来的增加。 限制内存的使用内存使用过大,会导致频繁的GC和OOM,内存的使用主要来自以下两个方面: A:集合容量过大; B:未释放已经不再引用的对象,比如放入ThreadLocal的对象一直会等到线程退出的时候回收。 限制线程创建线程的无限制创建,最终导致其不可控,特别是隐藏在代码中的创建线程方法。 当系统的SY值过高时,表示linux需要花费更多的时间进行线程切换。Java造成这种现象的主要原因是创建的线程比较多,且这些线程都处于不断的阻塞(锁等待,IO等待)和执行状态的变化过程中,这就产生了大量的上下文切换。 除此之外,Java应用在创建线程时会操作JVM堆外的物理内存,太多的线程也会使用过多的物理内存。 对于线程的创建,最好通过线程池来实现,避免线程过多产生上下文切换。 限制并发做过支付系统的应该清楚,部分三方支付公司是对商户的并发有要求的。三方给开放几个并发是根据实际交易量来评估的,所以如果不控制并发,所有的交易都发给三方,那么三方只会回复“请降低提交频率”。 所以在系统设计阶段和代码review阶段都需要特别注意,将并发限制在三方允许的范围内。 我们讲到宜信支付系统为了实现系统的可用性做了三点改变,其一是尽可能避免故障,接下来讲后面两点。 3.2 及时发现故障故障就像鬼子进村,来的猝不及防。当预防的防线被冲破,如何及时拉起第二道防线,发现故障保证可用性,这时候报警监控系统的开始发挥作用了。一辆没有仪表盘的汽车,是无法知道车速和油量,转向灯是否亮,就算“老司机”水平再高也是相当危险的。同样,系统也是需要监控的,最好是出现危险的时候提前报警,这样可以在故障真正引发风险前解决。 3.2.1 实时报警系统如果没有实时报警,系统运行状态的不确定性会造成无法量化的灾难。宜信支付系统的监控系统指标如下: 实时性-实现秒级监控;全面性-覆盖所有系统业务,确保无死角覆盖;实用性-预警分为多个级别,监控人员可以方便实用地根据预警严重程度做出精确的决策;多样性-预警方式提供推拉模式,包括短信,邮件,可视化界面,方便监控人员及时发现问题。报警主要分为单机报警和集群报警,而宜信支付系统属于集群部署。实时预警主要依靠各个业务系统实时埋点数据统计分析实现,因此难度主要在数据埋点和分析系统上。 3.2.2 埋点数据要做到实时分析,又不影响交易系统的响应时间,宜信支付系统在各个模块中通过redis实时做数据埋点,然后将埋点数据汇总到分析系统,分析系统根据规则进行分析报警。 3.2.3 分析系统分析系统最难做的是业务报警点,例如哪些报警只要一出来就必须出警,哪些报警一出来只需要关注。下面我们对分析系统做一个详细介绍: (1)系统运行架构 (2)系统运行流程 ...

June 12, 2019 · 1 min · jiezi

我对支付平台架构设计的一些思考

微信公众号「后端进阶」,专注后端技术分享:Java、Golang、WEB框架、分布式中间件、服务治理等等。 老司机倾囊相授,带你一路进阶,来不及解释了快上车!我在前一家公司的第一个任务是开发统一支付平台,由于公司的业务需求,需要接入多个第三方支付,之前公司的支付都是散落在各个项目中,及其不利于支付的管理,于是聚合三方支付,统一支付平台的任务就落在我手上,可以说是完全从 0 开始设计,经过一翻实战总结,我得出了一些架构设计上的思考,之前就一直很想把自己的架构设计思路写出来,但一直没动手,前几天在技术群里有人问到相关问题,我觉得有必要把它写出来,以帮助到更多需要开发支付平台的开发人员。 组件模式由于公司业务在很多地区都有,需要提供多种支付途径,以满足业务的发展,所以设计的支付平台需要接入多种第三方支付渠道,如:微信支付、支付宝支付、PayPal、IPayLinks 等等,我们都知道,每个第三方支付,都有自己一套对外 API,官方都有一套 SDK 来实现这些 API,我们应该如何组织这些 API 呢? 由于第三方支付渠道会随着业务的发展变动,所以组织这些 SDK 就需要在不影响支付平台整体架构的前提下可灵活插拔,这里我使用了组件的思想,将支付 API 拆分成各种组件支付组件、退款组件、订单组件、账单组件等等,那么这样就可以当引入一个第三方支付 SDK 时,可灵活在组件上面添加需要的 API,架构设计如下: 通过 Builder 模式根据请求参数构建对应的组件对象,将组件与外部分离,隐藏组件构建的实现。组件模式 + Builder 模式使得支付平台具备了高扩展性。 多账户体系在接入各种第三方支付平台,我们当时又遇到一个账户的问题,原因是公司当时的小程序与 APP 使用的是不同的微信账号,因此会出现微信支付会对应到多个账户的问题,而我当时设计支付平台时,没有考虑到这个问题,当时第三方支付只对应了一个账户,而且不同的第三方支付的账户之间相互独立且不统一。 于是我引入了多账户体系,多账户体系最重要的一个核心概念是以账户为粒度,接入多个第三方支付,统一账户的参数,构建了统一的支付账户体系,支付平台无需关心不同支付之间的账户差异以及第三方支付是否有多少个账户。 此时我在支付平台架构图加上账户层: 前端只需要传递 accountId,支付平台就可以根据 accountId 查询出对应的支付账户,然后通过 Builder 模式构建支付账户对应的组件对象,完全屏蔽不同支付之间的差异,在多账户体系里面,可以支持无限多个支付账户,完全满足了公司业务的发展需求。 统一回调与异步分发处理做过支付开发的同学都知道,目前的第三方支付都有一个特点,就是支付/退款成功后,会有一个支付/退款回调的功能,目的是为了让商户平台自行校验该笔订单是否合法,比如:防止在支付时,客户端恶意篡改金额等参数,那么此时支付成功后,订单会处于支付中状态,需要等待第三方支付的回调,如果此时收到了回调,在校验时发现订单的金额与支付的金额不对,然后将订单改成支付失败,以防止资金损失。回调的思想是只要保证最终的一致性,所以我们调起支付时,并不需要在此时校验参数的正确性,只需要在回调时校验即可。 讲完了回调的目的,那么我们如何来设计支付平台的回调呢? 由于支付平台接入了多个第三方支付,如果此时每个第三方支付设置一个回调地址,那么将会出现多个回调地址,由于回调的 API 必须是暴露出去才能接受第三方的回调请求,所以就会有安全问题,我们必须在 API 外层设置安全过滤,不然很容易出现一些非法暴力访问,所以我们需要统一回调 API,统一做安全校验,之后再进行一层分发。 分发的机制我这里建议用 RocketMQ 来处理,可能有人会问,如果用 RocketMQ 来做分发处理,此时怎么实时返回校验结果到第三方支付呢?这个问题也是我当时一直头疼的问题,以下是我对回调设计的一些思考: 公司的系统是基于 SpringCloud 微服务架构,微服务之间通过 HTTP 通信,当时有很多个微服务接入了我的支付平台,如果用 HTTP 作分发,可以保证消息返回的实时性,但也会出现一个问题,由于网络不稳定,就会出现请求失败或超时的问题,接口的稳定性得不到保障。由于第三方支付如果收到 false 响应,就在接下来一段时间内再次发起回调请求,这么做的目的是为了保证回调的成功率,对于第三方支付来说,这没毛病,但对于商户支付平台来说,也许就是一个比较坑爹的设计,你想一下,假设有一笔订单在支付时恶意篡改了金额,回调校验失败,返回 false 到第三方支付,此时第三方支付会再重复发送回调,无论发送多少次回调,都会校验失败,这就额外增加了不必要的交互,当然这里也可以用幂等作处理,以下是微信支付回调的应用场景说明: 基于以上两点思考,我认为返回 false 到第三方支付是没必要的,为了系统的健壮性,我采用了消息队列来做异步分发,支付平台收到回调请求后直接返回 true,这时你可能会提出一个疑问,如果此时校验失败了,但此时返回 true,会不会出现问题?首先,校验失败情况,订单必定是处于支付失败的状态,此时返回 true 目的是为了减少与第三方支付不必要的远程交互。 ...

June 6, 2019 · 1 min · jiezi

势高则围广TiDB-的架构演进哲学

本文根据我司 CEO 刘奇在第 100 期 Infra Meetup 上的演讲整理,预计阅读时间为 30 分钟。 大家可能知道我是 PingCAP CEO,但是不知道的是,我也是 PingCAP 的产品经理,应该也是最大的产品经理,是对于产品重大特性具有一票否决权的人。中国有一类产品经理是这样的,别人有的功能我们统统都要有,别人没有的功能,我们也统统都要有,所以大家看到传统的国内好多产品就是一个超级巨无霸,功能巨多、巨难用。所以我在 PingCAP 的一个重要职责是排除掉“看起来应该需要但实际上不需要”的那些功能,保证我们的产品足够的专注、足够聚焦,同时又具有足够的弹性。一、最初的三个基本信念本次分享题目是《TiDB 的架构演进哲学》,既然讲哲学那肯定有故事和教训,否则哲学从哪儿来呢?但从另外的角度来说,一般大家来讲哲学就先得有信念。有一个内容特别扯的美剧叫做《美国众神》,里面核心的一条思路是“你相信什么你就是什么”。其实人类这么多年来,基本上也是朝这条线路在走的,人类对于未知的东西很难做一个很精确的推导,这时信念就变得非常重要了。 <center>图 1 最初的基本信念</center> 实际上,我们开始做 TiDB 这个产品的时候,第一个信念就是相信云是未来。当年 K8s 还没火,我们就坚定的拥抱了 K8s。第二是不依赖特定硬件、特定的云厂商,也就是说 TiDB 的设计方向是希望可以 Run 在所有环境上面,包括公有云私有云等等。第三是能支持多种硬件,大家都知道我们支持 X86、AMD64、ARM 等等,可能大家不清楚的是 MIPS,MIPS 典型代表是龙芯,除此之外,TiDB 未来还可以在 GPU 上跑(TiFlash 的后续工作会支持 GPU)。 二、早期用户故事2.1 Make it work有一句话大概是“眼睛里面写满了故事,脸上没有一点沧桑”,其实现实是残酷的,岁月一定会给你沧桑的。我们早期的时候,也有相对比较难的时候,这时候就有一些故事关于我们怎么去经历、怎么渡过的。   首先大家做产品之前肯定先做用户调研,这是通用的流程,我们当初也做过这个事,跟用户聊。我们通常会说:“我们要做一个分布式数据库,自动弹性伸缩,能解决分库分表的问题,你会用吗?”用户说“那肯定啊,现在的分库分表太痛苦了。”这是最初我们获取需求最普通的方式,也是我们最容易掉入陷阱的方式,就好像“我有一百万,你要不要?肯定要。”“我有一瓶水,喝了之后就健康无比,延年益寿你要不要?肯定要。”很容易就得到类似的结论。 所以这个一句话结论的代价是我们进行了长达两年的开发。在这两年的时间里,我们确定了很多的技术方向,比如最初 TiDB 就决定是分层的。很显然一个复杂的系统如果没有分层,基本上没有办法很好的控制规模和复杂度。TiDB 分两层,一层是 SQL 层,一层是 key-value 层,那么到底先从哪一个层开始写呢?其实从哪层开始都可以,但是总要有一个先后,如何选择? 这里就涉及到 TiDB 的第一条哲学。我们做一个产品的时候会不断面临选择,那每次选择的时候核心指导思想是什么?核心思想是能一直指导我们持续往前去迭代,所以我们第一条哲学就是:永远站在离用户更近的地方去考虑问题。 为什么我们会定义这样一条哲学?因为离用户越近越能更快的得到用户的反馈,更快的验证你的想法是不是可行的。显然 SQL 层离用户更近,所以我们选择从 SQL 层写起。其实一直到现在,绝大多数用户用 TiDB 的时候根本感受不到 KV 层的存在,用户写的都是 SQL,至于底层存储引擎换成了别的,或者底层的 RocksDB 做了很多优化和改进,这些变化对于用户关注的接口来说是不可见的。 ...

May 31, 2019 · 4 min · jiezi

这3个关键指标直接决定了缓存的命中率

缓存是架构设计中一个重要的手段,它的技术比较简单,同时对性能提升又有特别显著的效果,在很多地方都会用到。使用缓存需要注意3个关键因素,它们决定了缓存的有效性、缓存的使用效率、缓存实现的效果: 1、缓存键集合大小 2、缓存空间的大小 3、缓存的使用寿命 阅读本篇文章将使用5分钟的时间,帮你提升缓存命中率。 0.什么是缓存的命中率? 缓存的主要特点是一次写入多次读出,通过这种手段减少对数据库的使用,尽快从缓存中读取数据,提高性能。所以缓存是否有效,主要就是看它一次写进去的缓存能不能够多次去读出来响应业务的请求,这个指标就叫做缓存的命中率。缓存命中率怎么算呢?查询得到正确缓存结果去比上总的查询次数,得到的指标就是缓存命中率,比如说十次查询九次都能够得到缓存的正确结果,他的命中率就是90%。 影响缓存命中率的主要因素有三个,分别是缓存键集合的大小、内存空间大小和缓存的寿命。 1.缓存键的集合大小。 缓存中的每个对象都是通过缓存键进行识别的。比如我们拿到key、value结构,key是字符串abc,value是字符串hello,abc就是其中的一个缓存键。键是缓存中唯一的识别符,定位一个对象的唯一方式就是对缓存键进行精确的匹配。 比如我们想缓存每个商品的在线商品信息,就需要使用商品ID作为缓存键。换句话说,缓存键空间是你的应用能够生成的所有键的数量。从统计数字上看,应用生成的唯一键越多,重用的机会越小。比如说根据IP地址缓存天气数据,可能需要40多亿个键。但是如果基于国家缓存天气数据,那么只需要几百个缓存键就够了,全世界也不过就几百个国家。 所以要尽可能减少缓存键的数量,键的数量越少,缓存的效率越高。设计缓存的时候要关注缓存键是如何进行设计的,它的整个的集合范围,限定在一个既能够高效使用,又可以减少它的数量,这个时候缓存的性能是最好的。 2.缓存可用空间的内存大小 缓存可以使用的内存空间决定了缓存对象平均大小和缓存对象的数量。因为缓存通常是存储在内存中的,缓存对象可用的内存空间相对来说比较昂贵,而且受到严格限制。 如果想缓存更多的对象,就需要先删除老的对象,再添加新的对象。而这些老的对象被删除掉,就会影响到缓存的命中率。所以物理上缓存的空间越大,缓存的对象越多,缓存的命中率也就越高。 3.缓存对象的生存时间 缓存对象的生存时间称为TTL。 对象缓存的时间越长,被重用的可能性就越高。使缓存失效的方法有两种: 1)超时失效 超时失效是在构建缓存,也就是在写缓存的时候,每个缓存对象都设置一个超时时间,在超时之前访问缓存就会返回缓存的数据,而一旦超时缓存就失效了,这时候再访问缓存,就会返回空。 2)实时清除 而实时清除是说,当有缓存对象更新的时候,直接通知缓存将已经被更新了的数据进行清除。清除了以后,应用程序下一次访问这个缓存对象键的时候,因为缓存已经清除了,不得不到数据库中去查找读取,这个时候就会得到最新的数据。因为更新总是更新在数据库里的。 还有一种虽然时间上还没有失效,但是新的对象要写入缓存,而内存空间不够了,这个时候就需要将一些老的缓存对象清理掉,为新的缓存对象腾出空间。 内存空间清除主要使用的算法是LRU算法,LRU算法就是最近最久未用算法。清除的时候,去清除那些最近最久没有被访问过的对象,这个算法使用链表结构实现的。所有的缓存对象都放在同一个链表上。当一个对象被访问的时候,就把这个对象移到整个链表的头部。当需要通过LRU算法清除那些最近最久未用对象的时候,只需要从队列的尾部进行查找,越是在队列尾部的越是最近最久没有被访问过的,优先清除的,腾出的内存空间让新对象加入进来。 以上3个条件即为决定缓存命中率的关键要素,熟练掌握后,会对缓存有更深的理解。 以上内容摘取自拉勾《阿里前辈的架构经》 第02讲(上):分布式缓存 点击查看更多 主讲人:李智慧,前阿里巴巴技术专家,《大型网站技术架构》作者 加拉勾职场导师微信:lagouandy,可不定时参与简历1v1诊断抽奖活动,更有拉勾官方技术交流社群等你加入

May 30, 2019 · 1 min · jiezi

支撑亿级用户的架构从0到1演化全过程

本文从以下2个方向,对互联网系统架构演化进行了一个综述: 1.大型互联网架构目前面临的挑战及其解决思路2.大型互联网系统架构演化过程,包含了所有的现在主要的互联网架构的考量点、技术方案、要解决的问题等。 建议用10min阅读,可以了解互联网架构的全貌。 一、架构演进面临的挑战及解决思路 互联网主要面对的技术挑战,用一句话概括:就是用户不断上升产生的并发访问压力以及数据存储压力,所以系统需要更强的处理能力才能解决这些问题。 而系统处理能力提升,主要有两种途径: 1.垂直伸缩: 提升单台服务器的处理能力,比如用更快频率的cpu,用更多核的cpu,用更大的内存,用更快的网卡,用更多的磁盘组成一台服务器,使单台服务器的处理能力得到提升,通过这种手段提升系统的处理能力。 缺点如下: a.当垂直伸缩达到一定程度以后,继续增加计算需要花费更多的钱。 b.垂直伸缩是有物理极限的,即使是大型机,也有自己的物理极限,它不可能无限地伸缩下去的。 c.操作系统的设计或者应用程序的设计制约着垂直伸缩,最多只能达到一个点无法继续提高。 在大型互联网出现之前,传统的软件,比如银行、电信这些企业的软件系统,主要是使用垂直伸缩这种手段实现系统能力提升的,在服务器上增强,提升服务器的硬件水平。当某种类型的服务器能力提升到了瓶颈以后,就会用更强大的服务器,比如说从服务器升级到小型机,从小型机提升到中型机,从中型机提升到大型机,服务器越来越强大,处理能力越来越强大,当然价格也越来越昂贵,运维越来越复杂。 2.水平伸缩: 单机的处理能力并不提升,也不使用更昂贵的更快的更厉害的硬件,而是通过更多的服务器,将这些服务器构成一个分布式集群,通过这个集群,统一对外提供服务,以此来提高系统整体的处理能力。 水平伸缩优点: a.只要架构合理,能够添加服务器到集群中,你的系统就是永远可以正常运行。 b.它没有极限,它的成本也不会说到了某个临界点就突然增加。而且逐渐的增加服务器,获得相同的计算处理能力,只会比以前的服务器更便宜,不会更贵,因为硬件的价格总是在不断地下降的。 c.应用程序运行在一个服务器上,是为单一服务器而设计的,而增加服务器的话只是让程序部署在更多的服务器上,所以也不需要对应用程序进行太多的改变,应用程序不会受到硬件制约。 在互联网行业中多采用水平伸缩的手段。 二、大型互联网系统架构演化过程 要让更多的服务器构成一个整体,需要在架构上进行设计,让这些服务器成为整体系统中的一个部分,有效地组织起来,统一提升系统的处理能力。 以下将通过大型互联网系统架构的演进过程,来详细理解如何通过以上两种伸缩方式逐步提升系统处理能力的。 这个过程对外看起来是一个业务演进过程,也就是用户量不断增长的一个过程。 实际上大型互联网整个的技术驱动就是因为用户量不断地在增加,数据量不断增加,导致并发访问压力持续增大,产生了一系列技术挑战。为了应对这个挑战,要不断地增强系统的技术处理能力,优化系统的架构。 最早的时候是单机系统,这时候可以满足少量用户的使用; 随着数据量提升,需要进行应用服务器与数据库分离,这个时候可以满足万级用户的使用; 再然后需要通过分布式缓存和服务器集群提升系统性能,这时候可以满足10万级的用户,之后需要进行反向代理,CDN加速还需要数据库读写分离,以满足百万用户级的访问; 随着数据量爆发式增长,使用分布式文件系统和分布式数据库系统,以满足千万级用户的访问; 最后使用搜索引擎、NoSQL、消息队列、分布式服务等更复杂的技术方案,以满足亿级用户的访问。 1.单机系统 在最早的时候,系统因为用户量比较少,可能只是有限的几个用户,这个阶段系统主要是用来验证技术以及业务模式是否可行的,系统也不需要太复杂,有限的几个主要功能。 开发完应用程序以后,部署在应用服务器上,一个应用访问自己服务器上的数据库,访问自己服务器的文件系统,构成了一个单机系统,这个系统就可以满足少量用户使用了。 如果这个系统被证明是可行的,是有价值的,好用的,如Google 最早就是部署在斯坦福的实验室里面,给实验室的同学和老师使用的。这些同学和老师使用后发现Google的搜索引擎比以前的搜索引擎(比如像Yahoo这样的搜索引擎)要好用的多,很快这个消息就扩散出去了。整个斯坦福大学的老师同学可能都过来访问这个服务器。这个时候服务器就不能够承受访问压力了,需要进行第一次升级,数据库与应用分离。 2、数据库与应用程序分离 前面单机的时候,数据库和应用程序是部署在一起的。 进行第一次分离的时候,应用程序、数据库、文件系统分别部署在不同的服务器上,从1台服务器变成了3台服务器,那么相应的处理能力就提升了3倍。 这种分离几乎是不需要花什么技术成本的,只需要把数据库文件系统进行远程部署,进行远程访问就可以了,这个时候的处理能力提升了3倍。 3、使用缓存改善性能 随着用户进一步的增加,更多的用户过来访,3台服务器也不能够承受这样的压力了,那么就需要使用缓存改善性能。 缓存主要有分布式缓存和本地缓存两种。 分布式缓存可以构成一个集群,存储更多的缓存数据,通过使用缓存一则应用程序不需要去访问数据库,因为数据库的数据是存在磁盘上的,访问数据库需要花费更多的时间,而缓存中的数据只是存储在内存中的,访问时间更短。 另一方面,数据库中的数据是以原始数据的形式存在的,而缓存中的数据通常是以结果形式存在,如果说已经构建成某个对象,缓存的就是这个对象,不需要进行对象的计算,这样就减少了计算的时间,同时也减少了CPU的压力。 这样不管是对计算资源的节约,还是对访问时间的节约,都会得到比较大的提升。通过使用缓存可以极大的改善性能。 4、应用服务集群化 虽然通过数据库分离和使用缓存,加快了系统的响应时间,减少了系统的计算压力,但是随着用户的进一步增加,应用服务器可能会成为瓶颈,一台应用服务器连接大量的并发用户的访问可能会成为一个瓶颈点,这时候就需要对应用服务器进行升级。 解决办法就是通过负载均衡服务器,将应用服务器部署为一个集群,添加更多的应用服务去处理用户的访问。 5、数据库读写分离 虽然通过负载均衡可以不断的添加应用服务器,为更多的用户提供系统访问服务。但是这个时候数据库会再一次成为整个系统的瓶颈点。 因为大量的用户过来访问,他们的主要操作都需要落在数据库上。虽然缓存可以缓存一部分的数据库读操作,但是还是有一部分读操作在缓存中找不到,还需要访问数据库,而且所有的写操作几乎都要访问数据库,这时候数据库就会成为瓶颈。 单一的数据库不能够承受这么大的访问压力。 这时候的解决办法就是数据库的读写分离,将一个数据库通过数据复制的方式,分裂为两个数据库,主数据库主要负责数据的写操作,所有的写操作都复制到从数据库上,保证从数据库的数据和主数据库数据一致,而从数据库主要提供数据的读操作。 通过这样一种手段,将一台数据库服务器水平伸缩成两台数据库服务器,可以提供更强大的数据处理能力。 6、使用反向代理和CDN加速相应 在对数据库做读写分离以后,要想更进一步增加系统的处理能力,需要使用反向代理和CDN加速。 所谓的CDN是指距离用户最近的一个服务器,当访问一个互联网应用的时候,我们的访问请求并不是直接到达互联网站的数据中心的,而是通过运营服务商进行数据转发的。 那么在进行数据转发的时候,最好已经有我们想要访问的数据了,这样就不需要访问互联网数据中心了。这个服务就叫做CDN服务,CDN服务就是部署在网络运营商机房里的离用户最近的一个服务器,用户请求先到这里查询有没有用户需要的数据,如果有,就从CDN直接返回,如果没有,再通过CDN进一步访问网站的数据中心,得到数据后再缓存到CDN供其他用户访问或下一次访问,所以CDN的本质还是一个缓存。 用户请求到达网站的数据中心后,也不是直接请求应用服务器,依然是查找一次缓存,这个缓存叫做反向代理服务器。 ...

May 24, 2019 · 1 min · jiezi

如何提高开发者代码的创造力让开发者不在枯燥

作为一名JAVAEE开发者,你也许已经对web开发的模式非常的熟悉, 比如Controller/Service/Repository,模式化程度非常高,甚至业务也抽象为简单的CRUD。简单的严重的限制开发的思维方式,限制代码的创造力,同时也让开发变得枯燥无味。这当然是编程艺术家不能忍受的。 本文从19年03月读的其他领域的书中看到的等价变换思维和戈顿法启发,结合最近工作实际情况来探索怎样提高代码的创造力。 戈顿法(Synectice):这种方法的指导思想把问题抽象化,不具体摊开业务,避免思维受到限制。 主要指抽象功能的动词部分。例如在定义一个拆开快递的的业务,我们将此抽象为"开",发散就有撬开,拧开,断开,破开,撕开,剥开,翻开等。等价变换思维(Equivalent Transformationn Thought):个人理解为类比法。 在理解现实生活中的事物,往往比较简单,但开发者想抽象为软件领域模型就会费劲的多。 下图以我的开源项目([1]: https://github.com/x-seeing/enginerring)为例:让编程变得快乐有意思的同时也会创造出更多的业务场景,不仅可以精准的定义业务,让业务没有偏差,同时也让系统的耦合性非常低。国内人设计的系统往往越做越复杂,无非是对业务抽象设计时出现没有意识到的偏差,导致积重难返。如果我们将业务类比于相对真实的事物,就会让系统更加健壮和精准。当然也不能完全照搬其他模型,否则会陷入战争泥潭的。如果把创造力简单的理解为个人的经验,能力,认识方式,思维方式,这种想法过于传统,也无法将创造力传承。所以抽时间在此总结,希望能成为一种有效的创新工具或一种创新方法论。 Created by 苏亚强(sueeing@126.com) on 2019/5/18.

May 18, 2019 · 1 min · jiezi

Angular-架构设计

引言Alice测试上线,发现包体积太大,加载太慢。决定启用懒加载与预加载加速加载速度。 整三天,课也没去上。改得时候特别痛苦,哭了,为什么没有早点发现惰性加载这个东西。 星期一,重新设计前台架构,重构前台代码。 星期二,分模块加载,启用惰性加载与预加载。 星期三,修改单元测试,添加provide。 星期四,写PPT。 星期五,.NET考试。 重构前台之后,觉得自己当前设计的架构很合理,遂分享出来,供大家学习交流。 架构理论架构理论主要参考外国老哥的一篇文章,Angular (2+): Core vs Shared Modules CoreModule:核心模块,只被AppModule引用,保证全局单例。 ShareModule:共享模块,被各业务模块引用,存储各模块必备的组件、管道以及模板。 实践CoreModule核心Module,全局只导入一次。 称之为核心,因为没有它应用跑不起来。 核心模块存放拦截器和服务,不过与正常的有些区别。 拦截器 @Injectable()export class YunzhiInterceptor implements HttpInterceptor {}@NgModule({ imports: [ NgZorroAntdModule, RouterModule ], providers: [ {provide: HTTP_INTERCEPTORS, useClass: YunzhiInterceptor, multi: true} ]})export class CoreModule {}服务 @Injectable({ providedIn: CoreModule})export class CollegeService {}现在不往root里注入了,因为发现有的时候写root有人会搞不清楚模块的层级关系,然后就懵圈了。 为了规避这种问题,直接注入到核心模块中,防止有人误解。 norm其实是想起一个规范的英文的,但是spec却被测试给用了,所以就去百度翻译了个放这了。 这个包主要是存储数据规范的。 entity存储实体,对应后台实体。 target存储自定义的规范对象,历史的教训告诉我们,如果把所有都放到实体包里,这很糟糕。 page这个是向小程序抄来的,小组件可以复用,大组件就需要单建目录了,都放一起看着混乱。 分模块加载,每个功能一个单独的模块,模块职责划分清晰。 @NgModule({ declarations: [ SetupComponent ], imports: [ SetupRouteModule, ShareModule ]})export class SetupModule {}模块中就这几行,什么废话都不要写,就声明本模块的组件,并导入本模块的路由和Share模块。其他的都不要写,第三方的导入交给ShareModule去处理。本模块只负责业务,不负责代码。 ...

May 18, 2019 · 1 min · jiezi