第五届字节跳动青训营讲师十分用心给咱们整理了课前、中、后的学习内容,同学们自我评价,挑选性查漏补缺,便于咱们更好的跟上讲师们的节奏,祝咱们学习愉快,多多提问交流~
课程一:【实践课】规矩引擎规划与完结
一、概述
1.1 前语
规矩引擎是一种嵌入在运用服务中的组件,能够将灵敏多变的业务决议计划从服务代码中分离出来。经过运用预界说的语义模块来编写业务逻辑规矩。在履行时接受数据输入、解说业务规矩,并做出决议计划。规矩引擎能大大进步体系的灵敏性和扩展性。
在字节跳动,规矩引擎现已在风控识别、活动运营、装备下发等场景得到了广泛的运用。开发人员能够将业务逻辑与服务代码解耦,完结灵敏、高效的业务战略发布。现在公司内部依据规矩引擎的动态决议计划体系现已承接了千万等级QPS的决议计划恳求。
规矩引擎的完结需求在满意大容量、高恳求、低延迟的根底上尽或许做到简略易上手。本次课程将会带领咱们完结一个简略版的规矩引擎。
1.2 课程方针
- 了解规矩引擎的组成部分和运用场景。
- 学习并掌握规矩引擎的规划与完结原理。
- 清晰一个规矩引擎的规划方针,并完结各部分的规划与完结进程拆解。
- 着手完结规矩引擎项目,完结预定方针。
- [课外扩展] 结合其他课程,完结一个在线 规矩引擎 服务。
1.3 课程重难点
要点
- 规矩引擎的规划 。清晰规划方针、完结进程拆解、完结各部分状况机的具体规划
- 规矩引擎的完结。依据项目工程完结词法剖析、语法剖析、笼统语法树的履行功用
难点
- 规矩引擎的核心原理(理论)。词法剖析、语法剖析、类型查看、语法树履行
首要触及到编译原理的部分
二、课前预习
课前必看!!!
本部分是需求咱们在上课之前了解的内容,首要是一些底子的概念和原理。
在这门课程之前你或许底子没有听说过规矩引擎这个东西,当然也或许是浅浅的大约知道这是个什么东西,或许是个规矩引擎方面的资深专家(还没毕业,五年工作经验那种,假如是这样请赶紧找我内推)。都没有联络,这门课包教包会!!!(学不会的下课后能够找咱们运营人员联络我一对一教育)
当然,这门课程仍是有必定的门槛的,这也便是我为什么要说这么多必定要让你仔细看看这部分的原因。经过试验,课程的内容假如只依赖于课上教师的讲解,只能做到:能听懂,能跟上,来不及考虑。要想能够了解掌握这部分内容,能跟他人battle下,再向自己的知识山峰上加那么一块小石头,得好好预习。
开端之前先百度或许Google一下 “规矩引擎”简略阅览下哈,另外app上面也有许多不错的文章。能够先阅览看看。
2.1 数据结构根底
数据结构得学过吧,考多少分?
这块的预习方针呢,包括以下几个部分
- 精一般用数据结构:数组、结构体、指针、行列、二叉树 等等等,课本上有的都得看看
- 熟练掌握二叉树的各种遍历方法:前中后序遍历,层序遍历,打印二叉树,有时刻能够自己写几个小demo,当然最根底的是需求知道各种遍历方法的差异
2.2 Go言语根底
- 掌握Go言语的根底语法,能读懂项目代码
是的,就这一个要求,其实学完青训营的前几节课就能够到达了
2.3 编译原理根底
编译原理被誉为”程序员的三大浪漫”之一,足以可见这块知识的深度与广度,咱们这次课程也是简略的介绍一下与规矩引擎相关的概念。
那么或许会有疑问了,不是讲规矩引擎么?为啥还得学编译原理?
规矩引擎的实质呢便是咱们自己界说一套语法,然后去解析用这套语法写的表达式,然后依据解析的内容履行表达式。这个进程其实便是编译和履行的进程。
因而呢需求自行了解以下的内容
-
编译的概念:
- 编译的进程发生了什么?
- 一般分为哪几个进程,每个进程的中心成果是什么?
-
词法剖析:
- 词法怎样表明?| 正则文法
- 词法剖析阶段的输出是什么
- 词法剖析阶段是怎样做的?
- 词法剖析或许会发生什么问题?
- 怎样处理词法剖析进程中发生的问题?| 左递归问题怎样处理
-
语法剖析
- 语法怎样表明?上下文无关语法、巴克斯范式怎样了解
- 语法剖析阶段的输出是什么? 一般怎样表明
- 语法剖析有哪些方法?什么是递归下降算法?
-
笼统语法树
- 笼统语法树是什么?
- 笼统语法树怎样履行?
-
类型查看
- 类型查看怎样做?有哪些方法?
- 类型查看什么时分做?有什么差异?
2.4 环境建立
课程之前,咱们需求依据项目工程,来完结环境的建立和Demo的运行
项目地址:
github.com/qimengxingy…
信任咱们现已完结了Go环境的建立,项目工程依赖了hertz结构,假如在之前的课程中完结了项目环境建立能够直接复用。
项目环境:
- go言语环境建立
www.runoob.com/go/go-envir…
- 需求装置docker环境
www.runoob.com/docker/wind…
- 装置docker-compose东西
www.runoob.com/docker/dock…
项目clone到本地后,能够履行测验脚本来测验环境的可用性。假如有过错欢迎百度和Google处理
git clone https://github.com/qimengxingyuan/young_engine.git
chmod a+x ./setup.sh
./setup.sh
脚本履行成功,则环境能够支撑项目的履行
项目阐明:
本项目是一个简略的规矩引擎的完结,具体目录能够参考README.md
项目完结时刻有限,没有做比较齐备的测验,假如在demo履行的进程中呈现某些bug或许履行异常能够直接在github提交issue或许修复后提起PR
/post/711798…
三、课中知识点弥补
3.1 什么是编译
编译的进程便是 把某种言语的源程序,在不改变语义的条件下,转化成另一种言语程序(方针言语程序)

- 假如源代码编译后要在操作体系上运行,那方针代码便是汇编/机器代码。
- 假如编译后是在虚拟机里履行,那方针代码就能够不是汇编代码,而是一种解说器能够了解的中心方法的代码即可。
解说型言语和编译型言语
-
有的言语提早把代码一次性转化结束,这种便是编译型言语,用的转化东西就叫编译器,比方C、C++、Go。一次编译可重复履行
- 编译后产品不能跨渠道,不同体系对可履行文件的要求不同。.exe
- 特殊的,c、c++、汇编、源代码也不能跨渠道
-
有的言语则能够一边履行一边转化,用到哪里了就转哪里,这种便是解说性言语,用的转化东西叫虚拟机或许解说器,比方java python、javascript

关于 Java 和 Python .
- Java既有编译又有解说。可是编译并没有直接编译成机器码,而是编译成字节码,然后再放到虚拟机中履行。
- Python履行进程也是经过两个阶段,先编译成字节码 .pyc 再放到虚拟机中去履行
JVM 和 Python解说器 | 为什么一个叫虚拟机一个叫解说器
- “虚拟机”对二进制字节码进行解说,而“解说器”是对程序文本进行解说。
- 从历史上看,Java 是为解说二进制字节码而规划和完结的,而 Python 最初是为解说程序文本而规划和完结的。因而,“Java 虚拟机”这个术语在 Java 社区中具有历史含义而且十分老练,“Python 解说器”这个术语在 Python 社区中具有历史含义而且十分老练。人们倾向于延伸传统并运用很久以前运用的相同术语。
- 关于 Java,二进制字节码解说是程序履行的首要方法,而 JIT 编译仅仅一种可选的和通明的优化。而关于 Python,现在,程序文本解说是 Python 程序履行的首要方法,而编译成 Python VM 字节码仅仅一种可选的通明优化。
3.2 词法剖析
把源代码字符串转化为词法单元(Token)的这个进程。
确认的有限自动机 DFA | Deterministic Finite Automaton

确认的有限自动机便是一个状况机,它的状况数量是有限的。该状况机在任何一个状况,依据输入的字符,都能做一个确认的状况转化。
3.3 语法剖析
词法剖析是识别一个个的单词,而语法剖析便是在词法剖析的根底上识别出程序的语法结构。这个结构是一个树状结构。这棵树叫做笼统语法树(Abstract Syntax Tree,AST)。树的每个节点(子树)是一个语法单元,这个单元的构成规矩就叫“语法”。每个节点还能够有下级节点。
Token -> AST
上下文无关语法 Context-Free Grammar
言句子子无需考虑上下文,就能够判别正确性
...
a = 0;
...
这是一个赋值句子,不管此句子的前后是什么代码,此句子所代表的操作是确认的。即给变量a赋值等于0
编程言语为什么不用人类的言语(自然言语),而是用上下文无关的文法呢? 由于
- 便于规划编译器。 客观上技能现在无法完结,假如运用了上下文相关文法,那便是真实完结了人工智能,NLP领域将会有重大突破。
- 便于代码开发保护。 假如开发出来的代码像高考的语文阅览了解相同,每个人都有不同的了解,那么,到底哪个才是作者真实想要表达的?假如人类都确认不了含义,那核算机同样也确认不了,终究成果便是过错履行或无法履行。
- 汇编言语/机器言语是上下文无关的。CPU履行指令时,读到哪条履行哪条。假如CPU需求考虑上下文,来决议一个句子到底要做什么,那么CPU履行一条句子会比现在慢千倍万倍。考虑上下文的工作,完全能够用户在编程的时分用算法完结。既然机器言语是上下文无关的,那高档言语也底子上是上下文无关的,或许有某些个别语法为了方便运用,规划成了上下文相关的,比方脚本言语的弱类型。在便于运用的一起,增加了解析器的杂乱度。
上下文无关语法G:终结符调集T + 非终结符调集N + 发生式调集P + 开端符号S
G由T、N、S和P组成,由语法G推导出来的一切句子的调集称为G言语!
终结符: 组成串的底子符号。能够了解为词法剖析器发生的token调集。比方 +
Id
(
)
等
非终结符: 表明token的的调集的语法变量。比方 stmt
varDecl
等等
start:blockStmts ; //开端
block : '{' blockStmts '}' ; //句子块
blockStmts : stmt* ; //句子块中的句子
stmt = varDecl | expStmt | returnStmt | block; //句子
varDecl : type Id varInitializer? ';' ; //变量声明
type : Int | Long ; //类型
varInitializer : '=' exp ; //变量初始化
expStmt : exp ';' ; //表达式句子
returnStmt : Return exp ';' ; //return句子
exp : add ; //表达式
add : add '+' mul | mul; //加法表达式
mul : mul '*' pri | pri; //乘法表达式
pri : IntLiteral | Id | '(' exp ')' ; //根底表达式
发生式:表明方法,S : AB ,便是说S的含义能够用语法AB进行表达
S : AB
A : aA |
B : b | bB
打开
(expand):将P(A->u )运用到符号串vAw中,得到新串vu **w
折叠
(reduce):将P(A->uu )运用到符号串vuu w中,得到新串vAw
推导
(derivate):符号串u 运用一系列发生式,变成符号串v ,则u =>v:S => ab | b | bb
巴科斯范式
BNF是描绘上下文无关理论的一种具体方法,经过BNF能够完结上下文无关文法的具体化、公式化、科学化,是完结代码解析的必要条件。
<expr> ::= <expr> + <term>
| <expr> - <term>
| <term>
<term> ::= <term> * <factor>
| <term> / <factor>
| <factor>
<factor> ::= ( <expr> )
| Num
BNF实质上便是树形分解,分解成一棵笼统语法树
- 每个发生式便是一个子树,在写编译器时,每个子树对应一个解析函数。
- 叶子节点叫做 终结符,非叶子节点叫做 非终结符。
递归下降算法 Recursive Descent Parsing
底子思路便是依照语法规矩去匹配 Token 串。比方说,变量声明句子的规矩如下:
varDecl : types Id varInitializer? ';' ; //变量声明
varInitializer : '=' exp ; //变量初始化
exp : add ; //表达式
add : add '+' mul | mul; //加法表达式
mul : mul '*' pri | pri; //乘法表达式
pri : IntLiteral | Id | '(' exp ')' ; //根底表达式
假如写成发生式格局,是下面这样:
varDecl -> types Id varInitializer ';'
varInitializer -> '=' exp
varInitializer ->
exp -> add
add -> add + mul
add -> mul
mul -> mul * pri
mul -> pri
pri -> IntLiteral
pri -> Id
pri -> ( exp )
而依据这个规矩做解析的算法如下:
匹配一个数据类型(types)
匹配一个标识符(Id),作为变量名称
匹配初始化部分(varInitializer),而这会导致下降一层,运用一个新的语法规矩:
匹配一个等号
匹配一个表达式(在这个进程会导致多层下降:exp->add->mul->pri->IntLiteral)
创立一个varInitializer对应的AST节点并回来
假如没有成功地匹配初始化部分,则回溯,匹配,也便是没有初始化部分。
匹配一个分号
创立一个varDecl对应的AST节点并回来

int a = 2
-
关于一个非终结符,要从左到右依次匹配其发生式中的每个项,包括非终结符和终结符。
-
在匹配发生式右边的非终结符时,要下降一层,持续匹配该非终结符的发生式。
-
假如一个语法规矩有多个可选的发生式,那么只要有一个发生式匹配成功就行。假如一个发生式匹配不成功,那就回退回来,测验另一个发生式。这种回退进程,叫做回溯(Backtracking)。
四、课后作业
4.1 完结一个在线规矩引擎
课上咱们要点讲了规矩引擎的规划和完结,结合前面课程的内容课后完结一个在线版别的规矩引擎
4.1.1 项目要求
运用Hertz结构开发一个HTTP服务,服务运用mysql,支撑表达式的增删查改和编译履行。
并完结以下接口
直接表达式履行:
恳求参数为待履行的表达式和表达式中参数的值,并输出编译成果
实时编译并履行成果,不需求写入DB中
POST api/engine/run
- Request
{
"exp": "uid == 12345 && did > 0",
"params": {
"uid": 123456,
"did": 0
}
}
- Response
{
"code": 0,
"message": "success",
"data": { // 履行成果
"result": true
}
}
新增表达式:
新增一条表达式到DB中,并回来表达式在DB中的ID
需求检测表达式是否现已存在,假如现已存在,直接回来表达式的ID
需求检测表达式是否合法(编译是否经过) ,假如编译失利,回来过错码 20001
和编译过错
POST api/engine/exp/new
- Request
{
"exp": "uid == 12345 && did > 0",
}
- Response
{
"code": 0,
"message": "success",
"data": { // 表达式ID
"id": 1
}
}
// 编译失利时
{
"code": -1,
"message": "compile error: xxxxx", // 编译失利的信息
"data": { // 表达式ID
"id": 0
}
}
查询表达式:
查询数据库中一切的表达式
GET api/engine/exp/list
- Response
{
"code": 0,
"message": "success",
"data": [
{
"id": 1,
"exp": "uid > 0"
}
]
}
删去表达式:
依据ID删去表达式,表达式不存在时回来过错码20002
, 和过错信息
删去成功回来被删去的表达式信息
DELETE api/engine/exp/:id
- Response
// 删去成功时
{
"code": 0,
"message": "success",
"data": { // 表达式ID
"id": 1,
"exp": "uid > 0"
}
}
// 删去失利时
{
"code": -1,
"message": "exp id 1 not exist", //查询失利的信息
"data": {}
}
履行表达式
依据表达式的ID,查询出表达式内容,并编译履行。表达式不存在时回来过错码20002
, 和过错信息
POST api/engine/exp/run
- Request
{
"exp_id": 1,
"parmas": {
"uid": 123456,
"did": 0
}
}
- Response
{
"code": 0,
"message": "success",
"data": { // 履行成果
"result": true
}
}
// 表达式不存在时
{
"code": -1,
"message": "exp id 1 not exist", //查询失利的信息
"data": {}
}
课程二:架构初探 – 谁动了我的蛋糕
运用指南
为了协助同学们更好地了解本课程,我为咱们预备了本学员手册。它包括以下几大模块内容:
- 课程方针,本课程首要结构的简略介绍,便于同学们抓住课程的结构结构,掌握听课节奏;
- 课前,本课程的重要前置知识点,便于同学们在听课进程中快速了解、跟紧思路;
- 课中,本课程各章节触及的要害概念和知识点,协助同学们加深核心内容的了解和认识;
- 课后,本课程的内容提炼,便于同学们总结课程关键,争取到达举一反三的作用。
课程方针
本课程的包括以下四个方面:
-
什么是架构
- 围绕架构的界说和演进两部分内容打开
-
企业级后端架构剖析
- 具体介绍企业级后端架构的形状
-
企业级后端架构的应战
- 企业级架构都面临着哪些应战,怎样处理
-
后端架构实战
- 结合前三部分的知识点,以第三部分中的一个应战为例,讲解怎样做架构规划
课前
什么是架构
常见软件架构:
- 单机
- 单体
- 笔直运用
- SOA (Service Oriented Architecture)
- 微服务 (Microservice)
一些小问题:
- 怎样给架构下界说?
- 架构的重要性?
- 架构演进的初衷?
- 架构演进的思路?
企业级后端架构剖析
-
云核算
-
根底
- 虚拟化
- 编排
-
架构
- IaaS
- SaaS
- PaaS
- FaaS
-
-
云原生
-
弹性资源
- 核算资源
- 存储资源
-
微服务架构
- 通讯协议
- 中心件
-
DevOps
- 软件生命周期
-
服务网格
-
企业级后端架构的应战
- 离线使命
- 在线使命
- IO 密集型
- CPU 密集型
- 服务办理
- IPC (Inter-Process Communication)
- RPC (Remote Procedure Call)
后端架构实战
- 负载均衡 Load Balancing
- 服务发现 Service Discovery
- 服务注册 Service Registry
- 宿主机 Host
- 容器 Container
- 时序数据 Time Series
- 共同性哈希 Consistent Hash
课前考虑题
-
软件架构演进至今都有哪些形状?它们别离处理了什么问题?依然存在什么问题?
-
云核算有哪些根底技能?云核算服务的形状又有哪些?
-
云原生是什么?它跟云核算的联络是?
-
云原生的代表技能有哪些?
-
企业级后端架构面临的应战有哪些?
课中
什么是架构
架构界说
Q:怎样给架构下界说?
A:架构,又称软件架构:
-
是有关软件全体结构与组件的笼统描绘
-
用于指导软件体系各个方面的规划
Q:架构的重要性?
A:那盖房子来做举比如。
咱们都知道,地基关于一栋高楼的首要性,架构关于一个软件的重要性也是相似的:
- 架构没规划好,软件简略崩,用户体会上不去。终究要么重构,要么抛弃
- 架构规划好了,软件的稳定性上去了,用户体会高了,口碑一点点就打造出来了
- 良好的架构根底,也为软件的未来开展供给了更多的或许。为用户赋能,完结自身价值
单机架构
All in one,一切的东西都在一个进程里,布置在一个机器上。
长处:
- 简略
缺陷:
- 运维需求停服,用户体会较差
- 承载才能有限。了解下 c10k 问题
单体架构
在单机架构的根底上,将进程布置到多个机器上。
长处:
- 具有水平扩容才能
- 运维不需求停服
缺陷:
- 后端进程职责太多,越来越臃肿
- 爆破半径较大,进程中一个很小的模块呈现问题,都或许导致整个进程崩溃
笔直运用架构
在单机架构根底上,将进程依照某种依据切分开。比方,A 软件和 B 软件的后端原先选用单机架构布置,那便是一个进程布置在多个机器上;假如用笔直运用架构,能够将 A 和 B 的后端拆分为 A、B 两个进程,然后再依照单体模式的思路,布置在多个机器上。
长处:
- 必定程度上减少了后端进程职责
- 必定程度上缩小爆破半径
缺陷:
- 没有底子处理单体架构的问题
SOA (面向服务架构)
SOA 架构中,服务为一等公民,将进程依照不同的功用单元进行笼统,拆分为『服务』。有了服务之后,SOA 还为服务之间的通讯界说了规范,确保各个服务之间通讯体会的共同性。
长处:
- 各服务的职责更清晰
- 运维粒度减小到服务,爆破半径可控
缺陷:
- ESB (企业服务总线) 往往需求一整套处理计划
微服务
在 SOA 架构中,ESB 起到了至关重要的作用。但从架构拓扑来看,它更像是一个集中式的模块。有一个 SOA 分布式演进的分支,终究的形状便是微服务。
长处:
- 兼具 SOA 处理的问题
- 服务间的通讯更灵敏、灵敏
缺陷:
- 运维本钱
小结
- 架构演进的初衷:满意软件迭代诉求,进步迭代效率
- 架构演进的思路:笔直切分——分布式,水平切分——分层/模块化
企业级后端架构剖析
云核算
云核算根底:
-
虚拟化技能
- 硬件层面(VM 虚拟机)- KVM/Xen/VMware
- 操作体系层面(Container 容器)- LCX/Docker/Kata Container
- 网络层面 – Linux Bridge/Open v Switch
-
编排计划
- VM – OpenStack/VMWare Workstation
- Container – Kubernetes/Docker Swarm
云核算架构:
-
云服务
- IaaS – 云根底设施,对底层硬件资源池的笼统
- PaaS – 依据资源池笼统,对上层供给的弹性资源渠道
- SaaS – 依据弹性资源渠道构建的云服务
- FaaS – 更轻量级的函数服务。好比 LeetCode 等 OJ,刷题时只需求完结函数,不需求重视输入输出流
-
云布置模式(拓宽)
- 私有云 – 企业自用
- 公有云 – AWS/Azure/Google Cloud/Huawei
- 混合云
云原生
云原生,实践是云原生(核算)的简称,它是云核算开展到现在的一种形状。
云原生技能为组织(公司)在公有云、自在云、混合云等新型的动态环境中,构建和运行可弹性拓宽的运用供给了或许。 它的代表技能:
- 弹性资源
- 微服务架构
- DevOps
- 服务网格
弹性资源
依据虚拟化技能,供给的能够快速扩缩容的才能。能够分为弹性核算资源和弹性存储资源两个方面。
弹性核算资源:
-
核算资源调度
- 在线核算 – 互联网后端服务
- 离线核算 – 大数据剖析。Map-Reduce/Spark/Flinnk
-
音讯行列
-
在线行列 – 削峰、解耦
-
离线行列 – 结合数据剖析的一整套计划,如 ELK
-
弹性存储资源:
-
经典存储
- 对象存储 – 视频、图片等。结合 CDN 等技能,能够为运用供给丰富的多媒体才能
- 大数据存储 – 运用日志、用户数据等。结合数据发掘、机器学习等技能,进步运用的体会
-
联络型数据库
-
元数据
- 服务发现
-
NoSQL
-
KV 存储 – Redis
-
文档存储 – Mongo
-
在云原生的大布景下,不论是核算资源仍是存储资源,他们都像是服务相同供用户运用。
微服务架构
微服务架构下,服务之间的通讯规范是依据协议而不是 ESB 的。
-
HTTP – H1/H2
-
RPC – Apache Thrift/gRPC
怎样在 HTTP 和 RPC 之间挑选?
- 功能 – RPC 协议往往具有较好的压缩率,功能较高。如 Thrift, Protocol Buffers
- 服务办理 – RPC 中心件往往集成了丰富的服务办理才能。如 熔断、降级、超时等
- 可解说性 – HTTP 通讯的协议往往首选 JSON,可解说性、可调试性更好
服务网格
什么是服务网格?
-
微服务之间通讯的中心层
-
一个高功能的 4 层网络署理
-
将流量层面的逻辑与业务进程解耦
没有什么是加一层代了处理不了的问题,服务网格相比较于 RPC/HTTP 结构:
- 完结了异构体系办理体会的统一化
- 服务网格的数据平面署理与业务进程采取进程间通讯的模式,使得流量相关的逻辑(包括办理)与业务进程解耦,生命周期也更简略办理
企业级后端架构的应战
应战
根底设施层面:
Q:咱们总说,云是弹性的,也便是说,在用户的角度,云供给的资源是无限的。然而,云背面的物理资源是有限的。在企业级后端架构里,云怎样处理近乎无限的弹性资源和有限的物理资源之间的对立?
Q:闲事的资源就这么空着呢?怎样进步资源利用率,进步物理资源的价值转化率?
用户层面:
Q:上了云原生微服务后,服务之间的通讯开支较大,应该怎样做本钱优化?
Q:微服务看起来没有那么美好,抖动导致的运维本钱较高,怎样处理?
Q:异构的物理环境应该对用户是通明的,怎样屏蔽这些细节?
离在线资源并池
考虑到在线业务的潮汐性,物理资源的用量不是原封不动的。离在线资源并池,能够:
- 进步物理资源利用率
- 供给更多的弹性资源

微服务亲合性布置
微服务之间的通讯本钱较高,是否能够:
-
形状上是微服务架构
-
通讯上是单体架构
亲合性布置,经过将微服务调用形状与资源调度体系结合,将一些调用联络紧密、通讯量大的服务布置在同一个机器上,而且运用 IPC 替代 RPC 的方法,下降网络通讯带来的开支
流量办理
Q:微服务之间的通讯流量为什么需求办理?
Q:都有哪些常用的办理手段?
Q:微服务中心件和服务网格在其间扮演着怎样的人物?
屏蔽异构环境的算力差异
Q:根底设施层往往是个杂乱的异构环境,比方,有些机器的 CPU 是英特尔的,而有些是 AMD 的。就算是同一个品牌,也或许是不同代际。怎样将这些差异屏蔽掉,运用户尽或许不感知呢?
Q:什么状况下,咱们觉得,服务需求扩容了?异构环境会对这个评判规范发生怎样的影响?
后端架构实战
问题
怎样规划一个依据主机层面的资源信息,实时进行流量调度的体系,打平不同宿主机异构环境的算力差异。
要害点:
- 紧迫回滚才能
- 大规模
- 极点场景

课后
课后作业-兰师傅蛋糕房要支撑线上售卖了!请协助做整套体系的架构规划
规划需求:
-
多端支撑
- 微信/支付宝小程序
- App
- 网页
-
运用云原生根底设施
-
用户画像很重要
-
积极参加妇女节/光棍节等活动
⚠️留意: 不需求考虑与做蛋糕相关服务的交互
结尾
-
没有最好的架构,只要最合适的架构
-
做架构规划
- 先从需求出发。要满意什么样的需求?预期规模有多大?
- 做足够的业界调研。业界关于相似的需求是怎样做的?有无老练的计划能够学习?直接拿来用有什么问题?
- 技能选型。触及的技能组件是自研,仍是运用开源的?
- 异常状况。任何时分,都不能做『输入合法』的假定。容灾才能必定要有
-
学好架构,是工程师成长的一个重要标志
参考文献
- C10K 问题
- CNCF
- CNCF landscape
课程三:分布式理论 – 现代架构柱石
概述
本节课程首要分为6个方面:
- 概述
- 体系模型
- 理论根底
- 分布式业务
- 共同协议
- 分布式实践
课前部分首要罗列课程中触及到的概念。关于不熟悉的概念,同学们能够提早查询预习;课中部分首要罗列每一部分的要害思路,协助同学们跟上课程的进度;课后部分是一些问题,协助同学们在课后整理本课程的要点。
课前 (有必要)
概述
- 什么是分布式?
- Why-How-What
- 常见的分布式体系
体系模型
- 毛病模型
- 拜占庭将军问题
- 共同和共同性
- 时刻和事情顺序
理论根底
- CAP理论
- ACID理论
- BASE理论
分布式业务
- 两阶段提交
- 三阶段提交
- MVCC
共同协议
- Quorum NWR模型
- RAFT协议
- Paxos协议
分布式实践
- MapReduce
- 分布式KV
课中
概述
-
什么是分布式?
- 分布式体系界说:跨多个节点的核算机程序的调集
- 运用分布式体系的五大优势:去中心化、低本钱、弹性、资源共享、可靠性高
- 分布式体系的应战:毛病、网络、环境、安全
-
Why-How-What
- 运用者视角:大规模核算存储的述求
- 学习者视角:后端开发必备技能
-
常见的分布式体系
- 分布式存储:GFS、Ceph、HDFS、Zookeeper
- 分布式数据库:Spanner、TiDB、HBase、MangoDB
- 分布式核算:Hadoop、YARN、Spark
体系模型
毛病模型
-
六种毛病模型,从处理的难易程度分类
- Byzantine failure:节点能够任意篡改发送给其他节点的数据,是最难处理的毛病
- Authentication detectable byzantine failure (ADB):节点能够篡改数据,但不能伪造其他节点的数据
- Performance failure:节点未在特定时刻段内收到数据,即时刻太早或太晚
- Omission failure:节点收到数据的时刻无限晚,即收不到数据
- Crash failure:节点停止响应,持续性的毛病
- Fail-stop failure:过错可检测,是最简略处理的毛病
-
毛病模型举例,依照模型分类
- 磁盘、主板、交换机、网络分区、cpu、内存、线缆、电源等毛病具体阐明
拜占庭将军问题
-
两将军问题
-
界说:
- 两支戎行的将军只能派信使穿越敌方疆域互相通讯,以此约定进攻时刻。该问题希望求解怎样在两名将军派出的任何信使都或许被俘虏的状况下,就进攻时刻到达共同
-
定论:
- 两将军问题是被证实无解的电脑通讯问题,两支戎行理论上永远无法到达共同
-
TCP是两将军问题的一个工程解
-
-
三将军问题:
- 两个“忠将”A和B,一个“叛徒”C,互相传递音讯,音讯或许丢失,也或许被篡改,当有一个将军是“叛徒”(即呈现拜占庭毛病)时,整个体系无法到达共同。
- 由于“叛徒”C的存在,将军A和将军B获得不同的信息。这样将军A获得2票进攻1票撤退的信息,将军B获得1票进攻2票撤退的信息,发生了不共同
-
四将军问题:
-
将军D作为音讯分发中枢,约定假如没收到音讯则履行撤退
-
进程:
- 假如D为“叛徒”,ABC不管收到任何音讯,总能到达共同
- D为“忠将”,ABC有2人将D的音讯进行正确的传递,同样能确保终究决议计划契合大多数。
-
从而能够证明,当有3m+1个将军,m个“叛徒”时,能够进行m轮洽谈,终究到达共同
-
共同和共同性
- 不同客户端A和B看到客户端C写入,由于机遇的不同,发生数据读取的偏差。引导出终究共同性的具体阐明
- 要确保一切客户端看到相同的值,需求多节点进行“洽谈”,到达共同,来确保线性共同性
- 共同性和可用性是对对立
时刻和事情顺序
-
1978年Leslie Lamport发表《Time, Clocks, and the Ordering of Events in a Distributed System》
- 界说了核算机体系中的时刻和事情顺序,引进happened before和并发的界说,能够以此对分布式体系中的事情进行推导
- 依据上述推导,发明了Lamport逻辑时钟的概念,这个概念在分布式理论中具有革命性的含义,协助咱们在一系列分布式事情傍边整理出逻辑的先后联络。利用逻辑时钟,咱们能够对整个体系中的事情进行全序排序
理论根底
CAP理论
-
CAP的界说,别离代表共同性、可用性、分区容错性。三者无法一起到达
-
CAP诞生了三类体系:
- CA体系:传统数据库的代表
- AP体系:抛弃强共同性,确保高可用,不少nosql存储体系选用
- CP体系:抛弃可用性,确保数据共同性
-
举例阐明两个分布式进程之间同步数据,当呈现毛病的时分,怎样挑选不同的CAP体系,以及带来的影响
- CP体系:毛病发生时,为了避免读到不共同的数据,或许回绝访问
- AP体系:毛病发生时,为了确保可用性,答应不同进程读到不同的数据
-
针对毛病场景,能够经过毛病搬运的方法,做一个相对较优的处理方法:
- 答应一个进程作为Master,其他进程作为Backup,当毛病时将恳求搬运给Backup进行处理
ACID理论
- ACID理论是针对CA体系而言的,一般在数据库中具有广泛含义
- 业务是数据库体系中十分重要的概念,它是数据库办理体系履行进程中的一个逻辑单元,它能够确保一个业务中的一切操作要么悉数履行,要么全都不履行
- 数据库业务拥有四个特性ACID:原子性(Atomicity)、共同性(Consistency)、隔离性(Isolation)和耐久性(Durability)

BASE理论
-
BASE理论是针对AP体系而言的,其来源于对大型互联网分布式实践的总结
- Basically Available(底子可用):假定体系,呈现了不行预知的毛病,但仍是能用
- Soft state(软状况):答应体系中的数据存在中心状况,并以为该状况不影响体系的全体可用性
- Eventually consistent(终究共同性):数据终究必定能够到达共同的状况
分布式业务
二阶段提交
-
界说:
- 二阶段提交(Two-phase Commit):为了使依据分布式体系架构下的一切节点在进行业务提交时坚持共同性而规划的一种演算法。
-
三个假定:
- 和谐者和参与者进行通讯
- 预写式日志被坚持在可靠的存储设备上
- 一切节点不会永久性损坏,即便损坏后依然能够康复
-
正常流程:Prepare阶段和Commit阶段
-
异常流程:Prepare阶段失利 -> 回滚;和谐者宕机 -> 从头启用新的和谐者;双毛病重启 -> 数据库办理员介入
-
两阶段提交需处理的问题:
- 功能问题:需求屡次网络通讯,资源需求等待并锁定
- 新和谐者:怎样确认状况选出新和谐者
- Commit阶段网络分区带来的数据不共同:非一切节点都收到Commit恳求
-
两个考虑:
- 日志被保存在「可靠」的存储设备上。怎样确保这一点?
- 参与者Commit了,但Ack信息和谐者没收到。怎样办?
三阶段提交
- 针对两阶段提交的弥补,将两阶段提交中的Prepare阶段,拆成两部分:CanCommit和PreCommit机制
- CanCommit阶段:询问是否能够履行;PreCommit阶段:从头确认是否能够履行
- DoCommit阶段:向一切人提交业务
MVCC
-
MVCC:多版别并发操控的方法。保持一个数据的多个版别使读写操作没有抵触。所以既不会阻塞写,也不阻塞读。进步并发功能的一起也处理了脏读的问题。
-
失望锁和达观锁
- 失望锁:操作数据时直接把数据锁住,直到操作完结后才会开释锁;上锁期间其他人不能修正数据
- 达观锁:不会上锁,仅仅在履行更新时判别他人是否修正数据,只要抵触时才抛弃操作
-
版别的选取:运用物理时钟或逻辑时钟
- 物理时钟:供给TrueTime API,有Master节点保持一个肯定时刻,确保各个服务器之间时钟误差操控在内,一般<7ms。
- 逻辑时钟:中心化授时的方法–时刻戳预言机(TSO),优点是无需硬件的支撑
共同协议
Quorum NWR模型
-
三要素:
- N:在分布式存储体系中,有多少份备份数据
- W:代表一次成功的更新操作要求至少有w份数据写入成功
- R: 代表一次成功的读数据操作要求至少有R份数据成功读取
- 为了确保强共同性,需求确保 W+R>N
-
Quorum NWR模型将CAP的挑选交给用户,是一种简化版的共同性模型
-
引起的并发更新问题
- 假如答应数据被掩盖,则并发更新简略引起共同性问题
RAFT协议
-
概述
- Raft协议是一种分布式共同性算法(共同算法),即便呈现部分节点毛病,网络延时等状况,也不影响各节点,从而进步体系的全体可用性。Raft是运用较为广泛的分布式协议。
-
三种人物
- Leader – 领导者:Leader 负责处理一切的客户端恳求,并向Follower同步恳求日志,当日志同步到大多数节点上后,通知Follower提交日志
- Follower – 跟随者:接受并耐久化Leader同步的日志,在Leader告知日志能够提交后,提交日志
- Candidate – 备选者:Leader推举进程中的暂时人物。向其他节点发送恳求投票信息
-
四种界说:
- Log(日志):节点之间同步的信息,以只追加写的方法进行同步,处理了数据被掩盖的问题
- Term(任期号):单调递加,每个Term内最多只要一个Leader
- Committed:日志被复制到多数派节点,即能够为现已被提交
- Applied:日志被运用到本地状况机:履行了log中指令,修正了内存状况
-
状况搬运:
-
Leader推举进程:
-
初始悉数为Follower
-
Current Term + 1
-
推举自己
-
向其它参与者建议RequestVote恳求,retry直到
- 收到多数派恳求,成为Leader,并发送心跳
- 收到其它Leader的恳求,转为Follower,更新自己的Term
- 收到部分,但未到达多数派,推举超时,随机timeout开端下一轮
-
-
Log Replication进程:
- 新Leader发生,Leader和Follower不同步,Leader强制掩盖Followers的不同步的日志
-
切主:当Leader呈现问题时,就需求进行从头推举
- Leader发现失掉Follower的响应,失掉Leader身份
- 两个Follower之间一段时刻未收到心跳,从头进行推举,选出新的Leader,此时发生了切主
- Leader自杀重启,以Follower的身份参加进来
-
Stale读:
- 发生Leader切换,old leader收到了读恳求。假如直接响应,或许会有Stale Read
Paxos协议
-
Paxos算法与RAFT算法差异:
- Multi-Paxos 能够并发修正日志,而Raft写日志操作有必要是接连的
- Multi-Paxos 能够随机选主,不必最新最全的节点中选Leader
-
优下风
- 优势:写入并发功能高,一切节点都能写
- 下风:没有一个节点有完好的最新的数据,康复流程杂乱,需求同步历史记载
分布式实践
MapReduce
- 规划一个简易的MapReduce体系,考虑怎样应对毛病?
分布式KV
- 规划一个简易的分布式键值体系,要求具有弹性的才能和到达线性共同
课后
- 分布式体系有哪些优势和应战?
- 两将军问题为什么理论上永远达不成共同?
- 为什么TCP选用三次握手?而不是两次和四次?
- 为什么在4将军问题中,增加1轮洽谈就能够对抗拜占庭毛病?
- 什么是终究共同性?什么是线性共同性?
- CAP理论中,请举例阐明可用性和共同性的对立?
- 数据库里的共同性和分布式体系中的共同性有什么差异?
- 两阶段提交中,什么场景需求数据库办理员介入?
- 三阶段提交平缓两阶段提交的哪两个问题?
- 什么场景合适达观锁?什么场景合适失望锁?
- 在共同协议中,为什么说答应数据被掩盖会带来数据共同性问题?
- RAFT协议中,Leader写成功日志Log20但未同步给Followers后宕机,Follower从头推举后发生一条新日志Log20,这时Leader重启,整个体系发现两种不相同的Log20的记载,请问怎样区分并拒掉前面的Log20?
- RAFT协议中,Stale读是怎样发生的?该怎样处理Stale读的问题?