架构设计的三个原则 作者: lovingyu_er 时间: 2019-05-02 01:17:00 分类: 架构学习笔记 评论 #####架构设计的最终目的:解决软件系统复杂度带来的问题 程序员->鸿沟->"不确定性"->架构师 面对不确定性时,架构设计的三个原则: **合适原则** **简单原则** **演化原则** ####1.合适原则: 合适原则,合适优先于业界领先. 根据公司的资源进行安排,看是否有必要采用业界领先.如果业务还没有起来,这个时候,找到比较适合当前公司的状况比较好,,资源有限,将资源用到刀刃上. "亿级用户平台"的失败的案例:2011年的时候,某几个人规模的业务团队,雄心勃勃的提出要做出一个和腾讯QQ一拼高下的"亿及用户平台",最后结果当然是不出所料的失败了. 案例总结: ######1)将军难打无兵之仗:如果团队的人手不多,没有那么多人,却想干那么多活,是失败的主要原因之一. ######2)罗马不是一天建成的:腾讯的QQ支付宝,也不是说一下子就变成现在的架构,跟着用户的数量增加,用户的需求也不一样.像阿里云的中间件团队,在2008年的时候,发展到现在已经有十年多 ,中间抗住了很多次的"双11"场景,做了很多优秀的系统,中间遇到的挑战和踩坑,都是架构设计非常关键的因素.没有那么多积累,却想一步登天,这是失败的第二个原因 ######3).冰山下面才是关键:业务发展到一定阶段,都是从量变导致质变,出现很多新的问题,已有的方式已经不能解决这些问题,需要一个新的方案来解决,这就是所说的系统架构升级.一些技术的诞生,比如:GFS为何出现在Google,而不是亚马逊?主要因素还是因为Google 的数据比较大.没有那么卓越的业务场景,但是想灵光一闪,想成为一个天才,这也是失败的第三个因素 分析"亿及用户平台"的案例, 1)没有腾讯那么多的人(资源),2)没有QQ那么多的海量用户积累.3)也没有那么大的业务需求.真正的架构是在根据企业当前的人力,条件,业务等各种约束下设计出来的,能够合理地将资源整合在一起并发挥最大的功效. ####2.简单原则: 简单优于复杂的原则. 架构设计是一门技术活儿,就像我们日常中使用的手机一样,从手机的发展历程来看,手机的从简单的通信,短信功能,到现在越来越多的功能,其复杂度越来越高,精细度也越来越高,架构设计一样,我们自然而然的将架构设计做精美,做复杂,这样才能体现出我们的技术实力,才能讲架构设计做成一件艺术品. 团队的压力有时也会有意无意地促进我们走向复杂的方向,因为大部分人在评价一个方案水平高低的时候,复杂性是其中一个重要的参考指标。例如设计一个主备方案,如果你用心跳来实现,可能大家都认为这太简单了。但如果你引入 ZooKeeper 来做主备决策,可能很多人会认为这个方案更加“高大上”一些,毕竟 ZooKeeper 使用的是 ZAB 协议,而 ZAB 协议本身就很复杂。其实,真正理解 ZAB 协议的人很少(我也不懂),但并不妨碍我们都知道 ZAB 协议很优秀。 刚才我聊的这些原因,会在潜意识层面促使初出茅庐的架构师,不自觉地追求架构的复杂性。然而,**“复杂”在制造领域代表先进,在建筑领域代表领先,但在软件领域,却恰恰相反,代表的是“问题”。** 软件领域的复杂度主要一下几个方面: ```1.结构的复杂性``` 结构的复杂性主要有两个特点:1)组件比较多;2)组件之间的关系比较复杂 两个组件的组成的系统: 三个组件组成的系统: 四个组件组成的系统: 五个组件组成的系统: **结构性复杂度存在的第一个问题是:组件越多,越有可能中间某个组件出问题,从而导致系统故障.**这个概率可以算出来的,假设组件的故障率是10%,也就是有10%的时间不可用,那么2个组件系统的可用性为(1-10%)*(1-10%)=81%,三个组件的系统可用性是(1-10%)*(1-10%)*(1-10%)=72.9%,根据小数计算的特点,组价越多,起可用性就会越低. **结构性复杂度存在的第二个问题:某个组件改动,会影响关联的所有组件**,这些影响的组件,很有可能会低递归影响别的组件.比如一五个组件组成的系统为例,组件A修改,或者异常的时候,会影响与其关联的组件B/C/E,而E又会影响D.这个问题会影响整个系统的开发效率,因为一旦变更涉及外部系统,需要协调各方同意进行方案评估,资源协调,上线配合 **结构性复杂度存在的第三个问题:定位一个复杂系统中的问题总是比简单系统更加困难***.组件多,每个组件都有嫌疑,要进行逐一排查,其次组件间的关系复杂,有可能表现故障的组件并不是真正的问题的根源. ```2.逻辑复杂性``` 根据结构复杂性中描述,我们想到第一个就是解决方案就是"降低组件的数量",毕竟组件越少,系统的结构越简单,也符合我们架构设计的简单原则,最简单的是,当然系统只有一个组件,也就是系统的本身.当然这是比较理想的情况,这样做是不可能的,想淘宝,腾讯这种,不可能用一个组件就完成了所有的需求,因为这里还是存在一个逻辑的复杂性,就是说,这样一个组件的系统,其会带来逻辑的复杂性.如果一个组件的逻辑功能太复杂,仍旧会带来很多各种各样的问题.逻辑复杂性存在的典型的特征就是:单个组件承担了太多的功能.比如:电商为例,所有的商品管理,商品搜索,商品展示,订单管理,用户管理,支付,发货,客服....把这些功能都在一个组件中实现,也就就是逻辑的复杂性.逻辑复杂几乎会导致软件工程的每个环节都有问题,假设现在淘宝将所有的功能在一个组件中实现,可以想想一下会有什么问题: 1)系统很庞大,代码多少行不知道,但是"clone"一次要30分钟可能都搞不定 2)维护人员多,代码review 复杂,某个"菜鸟"修改一行代码,导致整个网站崩溃 3)需求,修改很多的需求,开n个分支,各种分之合并和覆盖 4)产品研发测试项目管理不停的开发讨论版本计划,协调资源,解决冲突 5)版本太多,每天上线几十个版本,系统频繁重启,记住,是重启哦 6)系统故障,几十个人一起去定位和处理 7)...不知道还会出现什么鬼情况 与传统的电路板的架构设计不一样,根本原因在于电路一旦设计好后进入生产,就不会改变,复杂性只是在设计的时候带来影响.而软件存在一个问题是,投入使用以后,需要满足源源不断的需求,不断地修改系统和修复bug,复杂性在整个系统生命周期中都会受到影响. 功能复杂的组件,从另外一个典型的特征就是采用了复杂的算法,复杂的算法导致的问题就是难以理解,进而导致难以实现,难以修改,并且出了问题难以快速解决.Zookeeper 本身的功能就是选举,为了实现分布式下的选举,采用了ZAB协议,所以Zookeeper功能相对简单,但是系统的实现却比较复杂,相比之下,etcd就要简单一些,因为etcd采用的Rafd 算法,相比ZAB协议,Raft算法更加容易理解,更加容易实现. 综合分析,可以看到无论是结构的复杂和逻辑的敷在性,都会存在各种问题,所以架构设计时,如果简单的方案和复杂的方案都可以满足需求,那么最好选择简单的方案. ####演化原则 演化优先于一步到位 软件架构的维基百科的定义:从和目的,主题,材料和结构的联系上说,软件架构和建筑物的架构相比拟. 软件架构描述的是一个软件系统的结构,包括各个模块,以及这些模块之间的关系;建筑物架构描述的是一幢建筑物的结构,包括各个不见,以及这些部件是如何有机地组成一幢完美的建筑物的.但是有本质的差别:建筑一旦完成(开建)就不可以再变,而软件却会随着业务的需求而不断的变化. 建筑物的例子:埃及金字塔,中国明长城,美国白宫 软件的例子:window的系统,安卓系统的版本更迭. **对于建筑来说,永恒是主题;而对于软件来说,变化才是主题** 软件架构设计的过程: 1.设计的架构要满足当时的需求 2.架构在实际应用过程中,不断的迭代,保留优秀的设计,修复有缺陷的设计,改正错误的设计,去掉无用的设计,使得架构逐步完善 3.业务发生变化的时候,架构要扩展,重构,甚至重写;代码也许会重写,但有价值的经验教训,逻辑,设计等,在新的架构中继续延续.
(一)学会使用服务等级协议SLA来评估你的系统 作者: lovingyu_er 时间: 2019-05-01 22:42:00 分类: 大规模数据处理 评论 在现在的一些云服务器提供商,通常会提供一些可用性的参数: 比如google cloud platform 写着99.9% 的Availability 的承诺 阿里云的RDS 保证提供99.999%的Availability 的承诺 ####什么是SLA? SLA :Service Level Agreement ,服务等级协议 概括的来说就是: 指的是系统服务提供者(Provider)对客户(Customer)的一个服务承诺.这是衡量一个大型分布式系统是否"健康"的常见的方法,也是客户(Customer)评估服务提供的一个重要参考的依据 #### SLA的常用指标 1)可用性 2)准确性 3)系统容量 #####1. 可用性(Availability) 是指系统服务能正常运行所占的时间百分比.比如文章开头提到的99.9%,99.99%等等都是一种可用性的描述. Tips : 100%可用性的系统服务是不存在,这就是要求系统在任何时间都能正常的完美运行,,这种实现非常非常困难,并且成本是非常非常的昂贵.及时是比较有名的AWS云服务商,包括国内的腾讯云,阿里云,以及后起之秀华为云等,都不能提供100%而且也不能保证100%的可用性,也有过Service Outage的时刻. 下面我们从时间说一下,可用性的数字概念 假如一个系统的可用性为99.99% ,我们可以认为是属于**高可用性(High Availability)**, 那么可用性的99.99%到底是有什么真实的含义呢? 根据一些架构师对于这个理解,我们梳理为如下: 99.99% Availability 指的是系统在一天当中,大约有0.01%*24*60*60 =8.64 秒的service outage ,这个中断的原因可能会有多种,比如:软件升级,系统维护,更新系统,等等. 下面我们对比一下集中高可用性的service outage时间 99.9% Service outage 24*60*60*0.001=86.4s 99.99% Service outage 24*60*60*0.0001 = 8.64s 99.999% service outage 24*60*60*0.00001 = 0.864s 其他的6个9的SLA ,7个9的等级,对于架构的设计要求的比较苛刻,对于其一些资料可以参考: ```bash https://uptime.is/99.99999``` 其实对于很多云服务厂商来说,满足三个9已经是一个黄金分割线 ####2.准确性(Accuracy): 准确性,顾名思义,就是某些数据是否是不准确,或者说是丢失了之类的.如果出现这种情况,用户可以接受的概率,或者说是百分比大概是多少 **问题1** 如何衡量系统的准确性呢? 不同的系统平台可能会用不同的指标去定义准确性.很多时候,系统架构会以错误率(Error Rate) 来定义这个SLA指标 **错误率**如何进行错误率的计算呢? 根据用户的请求的次数和错误的次数来进行计算: 也就是 导致系统内部错误(Internal Error )的有效请求次数/ 这个期间的有效请求数 案例计算,一分钟内有100个有效请求,5个请求导致系统返回error ,那么我们可以说一分钟内,这个系统的错误率是5/100=5%; 对于国际云服务厂商大佬,他们对于准确性都有一个明确的定义: Google Cloud PlatForm 对于准确性的定义,每个月的系统的错误率超过5%的时间要小于0.01 ,以每分钟计算 AWS :以每5分钟为单位,错误率不会超过0.1%; 通过错误率,我们很方便的就可以来定义系统的准确性,但是问题来了,如何进行在进行验收的时候进行评估呢? **问题3** 如何评估某个项目的准确性 常用手段:```性能测试```或者是查看```系统日志``` ,这个后期会文章中会再提到 ####3.系统容量(Capacity) 这里的容量不是```磁盘容量```,而是```系统能够支持的预期负载量是多少``` ,也就是每秒的请求数为单位 架构师在对于系统的响应评估可以通过QPS(Queries Per Second),或者RPS(Requests Per Second)是多少来判断系统架构每秒可以响应多少个请求数. Twitter :30W 的QPS **问题1**如何定义出自己系统的准确的QPS ? 1. 第一种方式:使用限流(Throttling)的方式 Java 使用Google Guava 库的RateLimiter类赖定义每秒最多发送的请求书 设置的时候,要根据服务器的资源进行设置,过去的请求可能会导致```内存溢出```异常发生,也就是所有的请求占用的内存,超过服务器本身提供内存,导致整个服务器无内存可用或者内存不足(SWAP)出现服务器崩溃. 2.第二种:性能压力测试 比较常见的压力测试工具有APache JMeter 或者LoadRunner 这类工具,或者简易的ab等等,这些可以测试出系统的峰值.以及对应的QPS 注意缓存的问题,如果没有的请求都命中缓存,那么缓存的存在,会导致用户得不到一个比较准确的QPS值.因为缓存的存在,导致请求不能查询到后台数据库,因为缓存一般属于内存数据库或者是属于非关系性数据库,如果查询命中缓存,其返回的速度会很快,导致QPS会比直接从数据库中读的会高出N倍. 3. 分析系统在使用中产生的日志(LOG) 系统上线后,一般会得到日志文件.一般日志文件都有记录每个时刻产生的请求.我们可以根据系统最繁忙的时刻所有接受的请求书,赖计算系统可以承载的QPS,这个参数也不一定太靠谱.如果服务器能支撑最大3万的请求量,但是服务器在高分期最大才1W,那么这个时候,使用这个QPS是不准确的. ####4.延迟(Latency) 延迟:系统收到用户的请求到响应这个请求之间的时间间隔. 在定义系统延迟的时候,比较常见的SLA 介绍会有p95或者p99这样的延迟生命,注意,这里的p指的是percentile,也就是百分位的意思 p95 一个系统的延迟是p95,延迟是1s的话,那么100个请求哟95个请求是少于定义的1s延迟,剩下的5个请求会大于定义的1s的响应时间 那个案例进行说一下延迟指标在SLA的重要性 在社交系统中,软件在接受到用户的请求之后,需要读取数据库中的内容给用户,为了降低系统的延迟,我们可以考虑将数据库的内容放入到缓存(Cache )中,以此来减少数据库读取的时间,系统运行一段时间,会有一个缓存的命中率(Cache Hit Ratio ) 的信息,90%命中缓存的话,而剩下10%的要从数据库重新读取内容.p95和p99延迟就恒联的系统的最长时间,也就是从数据库读取数据的时间.如何改进缓存的命中率,这个是系统架构师要考虑的,比如:数据库中增加index,优化数据库的设计等等.p95和p99过高,总会有5%或者1%的人对产品的体验感很差.
使用命令行 将 Ubuntu 18.04 升级到Ubuntu 19.04版本方法 作者: lovingyu_er 时间: 2019-05-01 01:02:00 分类: 编程语言 评论 Ubuntu19.10版本最近发布了,作为一个偏爱linux系统迷,当然是手痒想体验一把,比较喜欢用ubuntu进行代码Coding或者Learning,因此,直接在自己的MACHENIKE 笔记本上体验了一般,将近8G的内存,各种嗨 Ubuntu 18.04 LTS 中的LTS代表是:Long Time Service也就是说,是长期支持的版本.拥有了五年的持续支持,关键维修,以及更新. 其他的版本升级到Ubuntu19.10 的方法没有试过, 步骤如下: #####1.运行命令,更新软件包并升级系统内核 ```bash sudo apt-get update && sudo apt-get dist-upgrade``` #####2. 安装update-manager-core 软件包 ```bash sudo apt-get install update-manager-core``` #####3. 修改release-upgrades ```bash sudo vim /etc/update-manager/release-upgrades``` 将```Prompt```的值从```lts```修改为```normal``` 保存 #####4.Ubuntu 19.04 开发代号是:```Disco Dingo``` ,在/etc/apt/sources.list 中,将Ubuntu 18.04开发代号替换为19.04版本的开发代号,我的系统中没有这个文件,所以我跳过了这一步,注意,查看系统的开发代号,可以使用以下命令: ```bash darrykinger@darrykinger-MACHENIKE:~$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 19.04 Release: 19.04 Codename: disco ``` #####5.注释4步骤中的文件.```/etc/apt/sources.list``` 的每一行,只需要在每行的前面添加#符号即可. #####6.更新apt源并对内核进行升级: ```bash sudo apt-get update && sudo apt-get upgrade``` #####7. 开始进行全面的升级,只需要运行: ``` bash sudo apt-get dist-upgrade``` 以上的步骤中,没有发现什么大的问题,中间会提示很多对于软件配置文件的修改的,提示你是重写覆盖什么的,大概有一个Default=N,我一路使用的是N,有进程Mysql ,nginx出现异常,强制杀死进程,修改响应的文件就可以了.
2019年04月25号 作者: lovingyu_er 时间: 2019-04-25 21:56:37 分类: 每日发呆 评论 #复仇者联盟4上映 无论你遇见谁,他都是你生命中该出现的人,绝非偶然,他一定会教会你一些什么。” 所以我也相信,无论我走到哪里,那都是我该去的地方,经历一些我该经历的事,遇见我该遇见的人。
以编程语言:C和PHP谈汇编语言和解释型语言的差别 作者: lovingyu_er 时间: 2019-04-23 15:52:00 分类: php7底层设计和源码实现 评论 初步了解PHP7核心源码中ext、main、sapi、TSRM、Zend目录下的文件,以及各自的功能。 ###PHP7语言的执行原理 接触的高级语言有C/c++、Python、PHP、Go/Pascal等,根据其运行的原理不同,我们可以将它们归结为两种语言:编译型语言和解释型语言。 #####编译型语言: 应用程序执行之前,就将程序源代码“翻译”成汇编语言,然后进一步根据软硬件环境编译成目标文件。完成编译工作的工具叫做编译器。 下面的一段C语言代码: ```c #include int main(){ printf("hello world"); return 1; } ``` main函数是程序的入口,实现打印“hello world”的作用。经过编译和执行的过程中,其中间会经过如下的步骤: ######第一步.预处理:将依赖处理、宏替换等包括上面代码中的#include都会在此阶段被替换掉 ######第二步.编译:将C语言编译成汇编语言程序,一条C语言会通常被编译为多条汇编代码。完成对目标程序的优化。 ######第三步.汇编器再汇编,现在已经是汇编代码,通过汇编器再会变成目标程序,比如hello.o ######第四步.链接:将一些共享的目标文件,比如printf()函数(来自于静态库),通过链接器(如Unix链接器ld)进行链接。 编译型语言都会出现上述的步骤。 #####解释型语言: 在应用程序在运行的时候才被“翻译”成机械语言。但是在执行的时候才被翻译,所以相对已经“翻译”好的编译型语言相比,其执行效率会比较低。负责解释性语言的解析工作的工具叫做解释器,还是负责 下面以PHP7为例讲述解释型语言的运行过程 ######第一步.词法分析:源码通过词法分析器分析得到Token。 ######第二步.语法分析: 基于语法分析器生成抽象语法树(AST:Abstract Syntax Tree) ######第三步.转换成opcodes:将AST转换成opcodes(opcode指令集合),PHP解释执行opcode 其执行流程:[源代码]->词法分析器->[Token]->语法分析器->[AST]->抽象语法树->[(生成可执行文件:编译器执行)|(生成opcodes可以被解释器执行)]详情可参考下一章关于PHP代码在执行时候的一些详细的讲解. #######汇编语言:编译结果最终指向了针对当前CPU体系的指令; #######解释型语言:编译成中间代码,在经过该语言指定的特定虚拟机,经过虚拟机再被翻译成CPU体系的指令被执行。 两种语言的慢就慢在“**虚拟机**”的这一步骤上。