1.1
电商行业特点
1.
分布式
垂直拆分
:
根据功能模块进行拆分
水平拆分
:
根据业务层级进行拆分
2.
高并发
用户单位时间内访问服务器数量
,
是电商行业中面临的主要问题
3.
集群
抗击高兵发的有效手段
,
同时集群内部实现高可用
4.
海量数据处理
随着公司数据的不断积累
.
自身的数据量很庞大
.
如果高效的处理数据
/
分析
1.2
框架调用流程
1.3 EasyUI
后台调用流程
1.4
分布式项目的设计思想
为了实现架构之间的松耦合
,
将项目根据分布式的思想进行拆分
.
1.
项目的垂直拆分
根据功能模块的不同将项目进行拆分
.
2.
项目的水平拆分
在大型项目中
,
由于开发的人数众多
,
项目复杂度高
.
为了保证项目开发的耦合性低
.
实现项目的水平拆分
.
将一个大型项目根据层级模块进行拆分
.Controller
项目
/Service
项目
Mapper
项目
项目创建时采用
聚合项目
的方式进行管理
1.5
分布式项目的
jar
包如何管理
将项目中用到公共的
jar
包使用服务支撑项目
jt-parent
进行添加
,
其他的项目只需要继
承
jt-parent
后获取对应的
jar
包全部依赖
.
从而实现了
jar
包的统一管理
1.6
介绍一下通用
Mapper
1.
早期使用
JDBC
操作数据库
.
该操作特别的繁琐
,
并且所有的数据需要自己手动的封
装
.
2. JPA:
是
java
持久化的
API(
用面向对象的方式操作数据库
)
思想
User user = new User(); setXXXX
User.setId(1);
User.setName(tom);
工具
API.insert(user); JPA
内部将对象自动转化为
sql
语句
Insert into …….
3. Haibernate
框架
.
号称是自动化的
(ORM)
程序员只需要操作对象
,
从而完成了对数据库的操作
.
缺点
:
1.
做新增
/
删除
/
修改会产生一些冗余的
sql(
出于安全性性考虑
)
2.
如果做多表关联操作
(CRUD) ,
需要装备配置文件
,
通过配置文件进行数据关
联设定
.
同时需要学习
Hql(
语句
)
3.
早期数据库容量是有限
,
超过
500
万后查询效率开始变低
.
4.Mybatis
优点
:
继承
ORM,
摈弃了冗余的
sql(
自己手写
),
5.
通用
Mapper
插件基于
mybaits
的
效果
:
可以实现单表
CRUD
使用对象操作
.(
反射机制
)
1.7 Nginx
是什么
,
有什么作用
Nginx
(engine x)
是一个轻量级的是一个高性能的
HTTP
和反向代理服务器
,
其特点是占
有内存少,
并发
能力强
主要是用来反向代理和实现负载均衡
.
1.8
谈一下反向代理和负载均衡
说明
:
1. Nginx
首先需要监听特定的域名
.
2.
当用户根据域名进行资源访问时
.
首先会访问
nginx
3.
之后
nginx
代替请求者根据内部的配置文件
,
实现反向代理
.
将请求转化为特定的请
求路径进行资源访问
.
4.
当
Nginx
获取资源后将数据返回给用户
.
完成请求的正确的响应
.
负载均衡
:
访问量高时
,
可以让服务器尽量分摊压力
,
实现策略
:
轮询
,
权重
,IP_HASH(
一般不用
)
1.9 Nginx
的健康监测机制
当后台的服务器出现宕机的现象
,
当时
nginx
中的配置文件并没有改变时
,
请求依然会
发往故障的机器
.
需要人为的维护配置文件
,
这样的操作不智能
.
那么
采用健康检测机制
.
可以
实现故障的自动的迁移
.
属性介绍
:
1.max_fails=1
当检测服务器是否正常时
,
如果检测失败的次数达到规定的次数时
,
则断定该服务器故障
,
在规定的时间周期内
,
不会将请求发往该机器
.
2.fail_timeout=60s
定义时钟周期
1.10 Nginx
如何保证请求参数不丢
在
nginx
中添加请求头的参数
,
表示每次请求时
,
携带请求者的请求头信息
,
访问服务器
.
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
1.11
数据库数据如何备份
(
数据备份策略
)
1.
冷备份
:
定期将数据库中的文件进行转储
,
定期进行数据备份
.
2.
热备份
:
搭建数据库主从结构
,
当主库数据发生改变时
,
从库根据主库的二进制日志
文件进行备份
.
3.
双机热备
:
数据库互为主从
,
数据库代理服务器对主库进行心跳检测
,
实现数据的高
可用
,
为了防止主库宕机后发生雪崩现象
1.12
数据库压力大时
,
怎么实现高可用
1.
用数据库代理服务器搭建数据库的读写分离进行分流
.
读取从库数据
,
写数据在主库
可用的数据库代理服务器有
Amoeba
和
Mycat
由于大量的用户的数据库操作都需要通过数据库来完成
.
造成数据库负载过高
.
因为数
据库操作中查询的操作占很大的比重
.
2.
数据库实现双机热备
.
1.13
数据库的优化策略
1.
优化
sql
语句
(
多表操作
) where
左连接 右连接 内连接
原则
:
尽可能根据主键查询
,
尽可能少用关联查询
.
2.
创建索引
(
对经常查询的数据创建索引
)
3.
添加缓存
(Redis/MemCache)
4.
定期进行数据转储
(
将一些查询较少的数据保存到历史表
,
让当前表维护可控的数
据量
)
5.
分库分表
(
需要大量的数据库服务器
)
1.14
什么是
Mycat
是一个数据库中间件
,
实现读写分离
,
分库分表和数据库故障迁移
.
1.15
什么是
Redis,
运行在哪里
开源的内存中的数据结构存储系统
,
可以用做数据库
,
缓存和消息中间件
基于
C
语言开发
,
运行时在内存中
,
运行速度很快
https://mp.weixin.qq.com/s/0Fqp2aGq7c_x_bEK9pOeeg
1.16 Redis
中的数据持久化策略
如果使用时允许丢失部分数据
(
少量的
)
则使用
RDB
模式
,
它的效率高
,
也是
redis
默认的
策略
,
如果不允许丢失数据则采用
AOF
模式
,
它的安全性高
,
但是效率较低
.
1.17 Redis
中的内存维护策略
问题
:
如果数据都存储到
redis
中
,
如果内存占满了
,redis
如何维护
?
解决方案
:
1.
动态的扩容
redis
节点
(
不科学
)
2.
为数据设定超时时间
3.
动态的将不用的数据删除
.(LRU
算法
)
算法介绍
:
内存管理
的一种页面置换算法,对于在内存中但又不用的
数据块
(内存块)叫做
LRU
,操作系统会根据哪些数据属于
LRU
而将其移出内存而腾出空间来加载另外的数据。
1.18 redis
为什么要分片
特点
:
实现动态内存扩容
数据存储机制
:
1.19 Hash
一致性
1.
均衡性
尽可能均匀分片节点中的数据
2.
单调性
实现数据的动态迁移
3.
分散性
由于分布式原因
,
导致不能获取全部节点信息
,
使得一个
key
有多个位置
4.
负载
是分散性另一种表现形式
.
表现为一个位置有多个
key
1.20
知道哨兵机制吗
,
怎么实现的
,
实现了什么功能
功能
:
实现
redis
高可用
机制
:
心跳检测
1.21
哨兵和分片的优缺点
优点
:
1.
分片可以使
redis
动态内存扩容
.
2.
分片可以将数据均匀的分配到不同的节点中
,
使数据分散保存
.
3.
哨兵可以实现
redis
高可用
.
缺点
:
1.
分片如果有一个节点出现宕机则整个分片都不能正常使用
.
2.
哨兵如果发生宕机现象
,
则影响整个
redis
服务
.
升级
:
1.
使用多台
redis
实现内存空间的动态扩容
.
2.
实现在
redis
内存实现高可用
(
不再使用哨兵机制
)
使用组件
(
ruby
)
搭建集群
,
实现分片和高可用的全部功能
.
1.22 Redis
集群
使用
ruby
工具创建集群
.
集群中全部的节点相互之间互相通讯
.
在
redis
内部实现高可
用
.redis
集群是分片和哨兵的集合体
.
1.23
伪静态技术
动态页面不能被搜索引擎收录
.
为了保证搜索引擎的友好性
.
则以
.html
的静态页面形式
展现动态页面数据
1.24
跨域问题
说明
:
在
www.jt.com
中调用
manage.jt.com
时访问不成功
.
原因该操作是一个跨域请求
.
浏览器不允许进行跨域请求
.
会将成功返回的数据进行拦截
.
不予显示
.
一切出于安全性
的考虑
.
1.25
同源策略
规则
:
请求
协议
/
域名
/
端口号
是否相同
,
如果三者都一致
,
那么是同域访问
.(
即同源策略
)
浏
览器可以正常执行
.
除此之外的全部的请求都是跨域请求
.
1.26
怎么解决跨域问题
?
利用
javascript
中
src
属性实现跨域
.
客户端定义回调函数
callback=hello
服务端程序封装特定的
JSON
格式
callback(JSON)
执行回调函数
JSONP
就是基于这个原理实现的
.
JSONP(JSON with Padding)
是
JSON
的一种
“
使用模式
”
,可用于解决主流
浏 览 器 的 跨 域 数 据 访 问 的 问 题 。 由 于 同 源 策 略 , 一 般 来 说 位 于
server1.example.com
的网页无法与不是
server1.example.com
的服务
器沟通,而
HTML
的
<script>
元素是一个例外。利用
<script>
元素的这
个开放策略,网页可以得到从其他来源动态产生的
JSON
资料,而这种使用
模式就是所谓的
JSONP
。用
JSONP
抓到的资料并不是
JSON
,而是任意的
JavaScript
,用
JavaScript
直译器执行而不是用
JSON
解析器解析
1.27 JQuery
中怎么使用
JSONP
跨域的缺点
:
回调的函数需要提前定义
.
程序员自己定义
.
解决方案
:
采用
jQuery
中的
JSONP
实现跨域的请求
.
语法
:
$.ajax({
url:
"http://manage.jt.com/web/testJSONP"
,
type:
"get"
,
dataType:
"jsonp"
,
//
返回值的类型
JSONP
必须添加否则不能回调 函数
jsonp:
"callback"
,
//
指定参数名称
jsonpCallback:
"hello"
,
//
指定回调函数名称
success:
function
(data){
alert(data.id);
alert(data.name);
//
转化为字符串使用
//var obj = eval("("+data+")");
//alert(obj.name);
}
});
1.28 HttpClient
HTTP
协议可能是现在
Internet
上使用得最多、最重要的协议了,越来越多的
Java
应
用程序需要直接通过
HTTP
协议来访问网络资源。虽然在
JDK
的
java net
包中已经提供了
访问
HTTP
协议的基本功能,但是对于大部分应用程序来说,
JDK
库本身提供的功能还不
够丰富和灵活。
HttpClient
是
Apache Jakarta Common
下的子项目,用来提供高效的、最新
的、功能丰富的支持
HTTP
协议的客户端编程工具包,并且它支持
HTTP
协议最新的版本
和建议。
HttpClient
已经应用在很多的项目中,比如
Apache Jakarta
上很著名的另外两个开
源项目
Cactus
和
HTMLUnit
都使用了
HttpClient
。现在
HttpClient
最新版本为
HttpClient 4.5
(GA)
(
2015-09-11
)
总结
:
HttpClient
是
java
为了远程请求开发的
http
请求工具包
.
1.29 HttpClient
和
JSONP
的区别
1. JSONP
是基于浏览器的
,
解决跨域问题的
.
而
httpClient
是基于代码
.
模拟
http
请求
.
获
取服务端的参数的
,
功能上类似
,
但是经过的环节不同
.
2.
安全性不同
JSONP
的全部信息都可以通过浏览器进行监控
.
但是
HttpClient
浏览器不能监控
.
3.
代码调用层级不同
Jsonp
需要调用服务端业务逻辑
,
最多
3
层
HttpClient
需要调用
5
层
适用场景
:
如果从服务端获取数据
,js
可以直接解析
.
使用
JSONP,
如果服务端的程序的返回
值
,
需要进一步处理
.
这时使用
HttpClient
1.30
你的单点登录是怎么调用的
流程图
:
原理
:
实现步骤
:
当用户登陆时
,
通过
nginx
访问
jt-web
中任意的服务器之后输入用户名和密码访问
JT-SSO
单点登录服务器
.
获取用户的登陆信息查询数据库
,
校验用户名和密码是否正确
.
如果用户名和密码是正
确的
,
将用户信息转化为
JSON
串
.
之后生成加密的秘钥
TOKEN(MD5(
盐值
+
随机数
)).
将
token:userJSON
保存
redis
中
.
并且将
token
信息返回给客户端
(jt-web).
Jt-web
接收到服务端数据时首先校验数据是否有效
.
如果数据准确无误
,
将
token
信息写
入到浏览器的
Cookie(4K)
中
当用户再次访问
jt-web
时
,
首先应该获取用户的
Token
信息
,
之后查询
redis
缓存服务器
获取
userJSON
数据
,
之后将
userJSON
转化为
User
对象进行使用
.
实现免密登录
.
如果
token
数
据为
null,
那么则让用户访问登陆页面
.
1.31
同一线程内的数据怎么实现共享
(ThreadLocal)
名称
:
本地线程变量
作用
:
在同一线程内实现数据共享
.
原理
:
说明
:ThreadLocal
是线程安全的
,
在同一个线程内实现数据的共享
.
注意
:
使用完成后
,
切记销毁
threadLocal
对象
,
否则
gc
不能回收
.
导致
JVM
内存泄漏
.
public class
UserThreadLocal {
//
如果保存数据有多个
,
则使用
Map
集合
private static
ThreadLocal<User>
userThread
=
new
ThreadLocal<User>();
public static void
set(User
user
){
userThread
.set(
user
);
}
public static
User get(){
return
userThread
.get();
}
//
线程销毁方法
public static void
remove(){
userThread
.remove();
}
}
1.32
如何实现的单点登录
SSO
问题
:
因为后台的服务器采用的是集群的部署方式
,
肯定有多台服务器
.
如果将用户的登
陆信息保存到服务器端
,
因为多个服务器之间不能共享
session.
所以相互之间不同实现
Session
共享
.
导致用户频繁登陆
.
初级
:
使用
Nginx
提供的
IP_Hash
高级
:
1.
当用户登陆操作时
,
首选访问时单点登录服务器
.
进行登录操作
.
2.
如果登录正确
.
则生成用户的秘钥
token.
将用户信息转化为
JSON
串和
token
一起保
存到
redis
缓存中
.
3.
将
token
信息返回给客户端
.
将数据保存到客户端浏览器中的
cookie
中
.
4.
当用户进行其他操作需要用到用户信息时
,
首先检测
Cookie
中是否有
token,
第二步检
测
redis
中的数据是否为
null.
如果一切正确
,
则允许跳转到指定页面中
.
如果其中有一项
有误
,
则表示用户登陆异常
.
让用户重新登陆
.
1.33
当
zk
如果宕机后
,
消费者能否正确消费
?????
说明
:
答案
:
可以
因为
zk
会动态的向客户端更新服务列表信息
.
当
zk
宕机后
,
由于之前已经同步了
zk
的服务列表信息
,
所以客户端可以按照自己已经缓存的清单进行访问
.
如果在这个期间服务端
程序发现宕机现象
,
那么则访问故障机时由于不能通信
,
则等待超时时间
,
则访问下一台服务
器
.
如果这时
,
所有的服务端程序都宕机
,
则整个服务陷入瘫痪
.
1.34
微服务治理方案
(ZooKeeper)
说明
:
增加服务器或者减少服务器都是自动完成
客户端
zookeeper
注册中心
Jt-web
的购物车按钮
JT-CARTA
连接
zk
查询服务端地址
服务端启动将
IP:
端口写入到
zk
中
根据查询到地址访问服务器
JT-CARTB
将
IP
和端口写入
zk
中
分布式架构设计
微服务的架构
Zk
可以通过心跳机制和负载均衡算
法
,
返回正常工作的服务给客户点
Nginx
业务逻辑说明
:
1.
当服务的提供者启动时
,
会将服务的名称
:IP:
端口会写入注册中心
.
2.
注册中心内部会维护服务列表
3.
当消费者需要访问服务时
,
需要先访问注册中心获取服务列表信息
.
之后将服务
列表保存到本地缓存中
.
方便后续的访问
.
在客户端内部有负载均衡的算法
,
筛选
出一台服务器
,
之后进行访问
.
4.
如果后台服务器出现宕机现象
.
这时注册中心通过心跳检测的方式判断服务器
是否宕机
.
如果服务器宕机则会将该服务器信息从服务列表中删除
.
之后将新的
服务列表发送消费者
(
客户端
)
进行更新
.
1.35
你怎么理解
SOA(
面向服务
)
面向服务的架构
(
SOA
)是一个组件模型,它将应用程序的不同功能单元(称为服务)
通过这些服务之间
定义良好的接口
和契约联系起来。
接口是采用中立的方式进行定义的
,它
应该独立于实现服务的硬件平台、操作系统和编程语言。这使得构建在各种各样的系统中的
服务可以以一种统一和通用的方式进行交互。
1.36
知道
RPC
协议吗
总结
:RPC
调用的规则可以传输
java
对象
.
底层实现时将数据转化流
,
并且该流经过加密
处理
.
并且
rpc
内部使用
UTF-8
编码格式
要求
:
传输的
java
对象必须序列化
1.37
什么是
Dubbo
框架
Dubbo
是
[1]
阿里巴巴公司开源的一个高性能优秀的服务框架
(
SOA
)
,使得应用可通过
高性能的
RPC
实现服务的输出和输入功能可以和
Spring
框架无缝集成
。
1.38 Nginx
和
ZK
的区别
Nginx:
1.
Nginx
主要是为了反向代理
(Http)
2.
负载均衡
3. Nginx
主要搭建在公司网关服务器上
Zk:
通过
RPC
进行远程方法调用
,
是服务端程序
主要作用是实现服务端的高可用
.
搭建在内网中
.
1.39
知道什么是消息队列吗
,
并说出几种常用的
消息队列可以
缓解服务器的访问压力
,
请求在在访问服务器时
,
先写入消息队列中
,
可以
实现请求的
异步操作
,
起到
平峰削骨
的作用
但是缺点是消耗了用户的实际等待时间
.
常见的消息队列产品有
activeMQ(apache
的
),RabbitMQ(
爱立信的
)
1.40
消息队列有几种工作模式
1.
简单模式
2.
工作模式
3.
发布订阅模式
4.
路由模式
5.
主题模式
6.RPC
模式
1.41
倒排索引
倒排索引源于实际应用中需要根据属性的
值
来查找记录。这种索引表中的每一项都包
括一个属性值和具有该属性值的各记录的地址。由于不是由记录来确定属性值,而是由
属性
值来确定记录的位置
,因而称为倒排索引
(inverted index)
。带有倒排索引的文件我们称为倒
排
索引文件
,简称
倒排文件
(inverted file)
。
1.42 Solr
介绍
/ES
Solr
是一个独立的
企业级搜索应用服务器
,它对外提供类似于
Web-service
的
API
接口。用户可以通过
http
请求,向搜索引擎服务器提交一定格式的
XML
文件,生成索引;
也可以通过
Http Get
操作提出查找请求,并得到
XML
格式的返回结果
.
基于
Lucene
的全文搜索服务器。同时对其进行了扩展,提供了比
Lucene
更为丰富
的查询语言,同时实现了可配置、可扩展并对查询性能进行了优化,并且提供了一个完善的
功能管理界面,是一款非常优秀的
全文搜索引擎
。
特点
:
1. solr
可以根据数据库表自动生成索引文件
.
2. Solr
可以动态的定期自动更新索引
(
对更新的数据进行索引的修改
)
1.43 Docker
介绍
Docker
是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个
可移植的容器中,然后发布到任何流行的
Linux
机器上,也可以实现虚拟化,容器是完全
使用沙箱机制,相互之间不会有任何接口。
一个完整的
Docker
有以下几个部分组成:
DockerClient
客户端
Docker Daemon
守护进程
客户端和
Docker
容器交互的媒介
Docker Image
镜像
应用程序的模板
DockerContainer
容器
启动后的应用程序
1.44 Docker
调用原理
模块描述
:
1.docker
Docker
客户端程序
2.daemon
一般在宿主主机的后台运行
,
作为服务端接收客户端的请求
,
并且处理这些请求
(
创建
/
运行
/
分发容器
).
客户端和服务器既可以运行在一个主机中
,
也可以通过
socket/RESTful
来实现通信
3.image:
Docker
中的镜像文件
,
为应用程序的模板
,
一般都是只读的不允许修改
Docker
的镜像文件来源有两种
:
1.Docker
官网中的镜像文件
2.
本地的镜像文件
4.Container:
Docker
容器
,
通过
image
镜像创建容器后
,
在容器中运行应用程序
(
类似于
new
一个对象
)
5.Repository:
管理镜像的仓库
,
类似于
Maven
仓库管理
jar
包文件
调用原理
:
1.Docker
客户端通过
Daemon
请求创建
Docker
容器
2.Daemon
接收请求后
,
从
Repository
中查找需要的
Image
镜像文件
3.
找到对应的镜像文件后
,
创建
Docker
容器
4.
调用容器完成具体任务
(redis/nginx/tomcat/mysql
等
)
1.45 Docker
镜像拉取过程
1.
当客户端获取镜像文件时
,
会向服务器发起请求
.
2.Docker
引擎首先会检查本地是否含有镜像文件
,
如果没有则会联网下载镜像文件
3.
从共有云中获取
Image
镜像文件后
,
保存到本地
4.
当用户需要使用该应用是
,
通过
镜像
文件创建
容器
,
为用户提供服务
Dockerfile
难
1.46
京淘项目人员分配
开发周期
:
开发
4
个月但是不停的更新迭代
购物车商品展现页面 商品规格
评价系统
订单物流系统 京东物流
/
调用菜鸟裹裹 调用第三方接口获取数据进行展现
(http)
支付系统
:
银行接口
/
第三方支付
http
推荐系统
:….
产品经理:
3
人,确定需求以及给出产品原型图
项目经理:
1
人,项目管理。
前端团队:
5
人,根据产品经理给出的原型制作静态页面。
后端团队:
20
人,实现产品功能。
测试团队:
5
人,测试所有的功能。
2
人
3
人 脚本
shell
运维团队:
3
人,项目的发布以及维护。
1.47
日活量
/
并发量
日活量
:200
万
并发量
:1500-2300
左右
单点并发压力
18
台
tomcat
服务器
服务器划分
Mysql
2
Mycat
服务器
1
Solr
3
Redis
3
图片服务器
2
Nginx
2
注册中心
3
RabbitMQ
2
18
台服务器
Jt-manage
5
Jt-web
10
Jt-sso
3
Jt-cart
5
Jt-order
5
Jt-search
5
33
台
tomcat
1.48 SpringBoot
全新开发方式特点
⚫
创建独立的
Spring
应用程序
⚫
嵌入的
Tomcat
,无需部署
WAR
文件
⚫
简化
Maven
配置
⚫
自动配置
Spring
⚫
提供生产就绪型功能,如指标,健康检查和外部配置
1.49
什么是微服务架构?
“微服务”源于
Martin Fowler
的博文
Microservices
。
Martin
说:微服务是系统架构上的一种设计风格,它的主旨是将一个原本独立的系统拆成多
个小型服务,这些小型服务都在各自独立的进程中运行,服务之间通过基于
HTTP
的
RESTful
API
进行通信协作。被拆分成的每一个小型服务都围绕着系统中的某一项或者某些耦合度较
高的业务功能进行构建,并且每个服务都维护着自身的数据存储、业务开发、自动化测试案
例以及独立部署机制。由于有了轻量级的通信协作基础,所以这些微服务可以使用不同的语
言来编写。
1.50
核心功能
⚫
configuration management
配置中心
⚫
service discovery
服务发现
⚫
circuit breakers
断路器
⚫
intelligent routing
智能路由
⚫
micro-proxy
微代理
⚫
control bus
控制总线
⚫
one-time tokens
一次性令牌
⚫
global locks
全局锁
⚫
leadership election
选举算法
⚫
distributed sessions
分布式会话
⚫
cluster state
集群状态
1.51
核心组件架构图
1.52
拓展:
CAP
定理
CAP
原则又称
CAP
定理,指的是在一个分布式系统中,
Consistency
(一致性)、
Availability
(可用性)、
Partition tolerance
(分区容错性),三者不可得兼。它是分布式系统中最核心最
重要的理论。
分布式系统的
CAP
理论:理论首先把分布式系统中的三个特性进行了如下归纳:
⚫
一致性(
C
):在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同
于所有节点访问同一份最新的数据副本)
⚫
可用性(
A
):在集群中一部分节点故障后,集群整体是否还能响应客户端的读写
请求。(对数据更新具备高可用性)
⚫
分区容错性(
P
):以实际效果而言,分区相当于对通信的时限要求。系统如果不能
在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在
C
和
A
之间做出选择。
CAP
理论就是说在分布式系统中,最多只能实现上面的两点。而由于当前的网络硬件肯定会
出现延迟丢包等问题,所以分区容忍性是我们必须需要实现的。所以我们只能在一致性和可
用性之间进行权衡,要么选择
CP
要么选择
AP
,没有分布式系统能同时保证这三点。
1.53 ZooKeeper
和
Eureka
对比
Eureka
本身是
Netflix
开源的一款提供服务注册和发现的产品,并且提供了相应的
Java
封装。
在它的实现中,节点之间相互平等,部分注册中心的节点挂掉也不会对集群造成影响,即使
集群只剩一个节点存活,也可以正常提供发现服务。哪怕是所有的服务注册节点都挂了,
Eureka Clients
(客户端)上也会缓存服务调用的信息。这就保证了我们微服务之间的互相调
用足够健壮。
Zookeeper
主要为大型分布式计算提供开源的分布式配置服务、同步服务和命名注册。曾经
是
Hadoop
项目中的一个子项目,用来控制集群中的数据,目前已升级为独立的顶级项目。
很多场景下也用它作为
Service
发现服务解决方案。
对比
根据著名的
CAP
定理(
C-
数据一致性;
A-
服务可用性;
P-
服务对网络分区故障的容错性
CAP
这三个特性在任何分布式系统中不能同时满足,最多同时满足两个
CP
或者
AP
)。
ZooKeeper
Zookeeper
是基于
CP
来设计的,即任何时刻对
Zookeeper
的访问请求能得到一致的数据结果,
同时系统对网络分割具备容错性,但是它不能保证每次服务请求的可用性。从实际情况来分
析,在使用
Zookeeper
获取服务列表时,如果
zookeeper
正在选主,或者
Zookeeper
集群中
半数以上机器不可用,那么将无法获得数据。所以说,
Zookeeper
不能保证服务可用性。
诚然,在大多数分布式环境中,尤其是涉及到数据存储的场景,数据一致性应该是首先被保
证的,这也是
zookeeper
设计成
CP
的原因。但是对于服务发现场景来说,情况就不太一样
了:针对同一个服务,即使注册中心的不同节点保存的服务提供者信息不尽相同,也并不会
造成灾难性的后果。因为对于服务消费者来说,能消费才是最重要的——拿到可能不正确的
服务实例信息后尝试消费一下,也好过因为无法获取实例信息而不去消费。(尝试一下可以
快速失败,之后可以更新配置并重试)所以,对于服务发现而言,可用性比数据一致性更加
重要——
AP
胜过
CP
。
Eureka
而
Spring Cloud Netflix
在设计
Eureka
时遵守的就是
AP
原则。
Eureka Server
也可以运行多个
实例来构建集群,解决单点问题,但不同于
ZooKeeper
的选举
leader
的过程,
Eureka Server
采用的是
Peer to Peer
对等通信。这是一种去中心化的架构,无
master/slave
区分,每一个
Peer
都是对等的。在这种架构中,节点通过彼此互相注册来提高可用性,每个节点需要添
加一个或多个有效的
serviceUrl
指向其他节点。每个节点都可被视为其他节点的副本。
如果某台
Eureka Server
宕机,
Eureka Client
的请求会自动切换到新的
Eureka Server
节点,当
宕机的服务器重新恢复后,
Eureka
会再次将其纳入到服务器集群管理之中。当节点开始接受
客户端请求时,所有的操作都会进行
replicateToPeer
(节点间复制)操作,将请求复制到其
他
Eureka Server
当前所知的所有节点中。
一个新的
Eureka Server
节点启动后,会首先尝试从邻近节点获取所有实例注册表信息,完
成初始化。
Eureka Server
通过
getEurekaServiceUrls()
方法获取所有的节点,并且会通过心跳
续约的方式定期更新。默认配置下,如果
Eureka Server
在一定时间内没有接收到某个服务
实 例 的 心 跳 ,
Eureka Server
将 会 注 销 该 实 例 ( 默 认 为
90
秒 , 通 过
eureka.instance.lease-expiration-duration-in-seconds
配置)。当
Eureka Server
节点在短时间内
丢失过多的心跳时(比如发生了网络分区故障),那么这个节点就会进入自我保护模式。
总结
ZooKeeper
基于
CP
,不保证高可用,如果
zookeeper
正在选主,或者
Zookeeper
集群中半数
以上机器不可用,那么将无法获得数据。
Eureka
基于
AP
,能保证高可用,即使所有机器都
挂了,也能拿到本地缓存的数据。作为注册中心,其实配置是不经常变动的,只有发版(发
布新的版本)和机器出故障时会变。对于不经常变动的配置来说,
CP
是不合适的,而
AP
在
遇到问题时可以用牺牲一致性来保证可用性,既返回旧数据,缓存数据。
所以理论上
Eureka
是更适合作注册中心。而现实环境中大部分项目可能会使用
ZooKeeper
,
那是因为集群不够大,并且基本不会遇到用做注册中心的机器一半以上都挂了的情况。所以
实际上也没什么大问题。
1.54
拓展:分布式对关系型数据库的冲击
对于
web
网站来说,关系数据库的很多主要特性却往往无用武之地
⚫
数据库事务一致性需求
很多
web
实时系统并不要求严格的数据库事务,对读一致性的要求很低,有些场合对写一
致性要求并不高。允许实现最终一致性。
⚫
数据库的写实时性和读实时性需求
对关系数据库来说,插入一条数据之后立刻查询,是肯定可以读出来这条数据的,但是对于
很多
web
应用来说,并不要求这么高的实时性,比方说发一条消息之后,过几秒乃至十几
秒之后,我的订阅者才看到这条动态是完全可以接受的。如:
MQ
消息队列机制,意义,可
以解决瞬时的高并发,消峰填谷作用。
⚫
对复杂的
SQL
查询,特别是多表关联查询的需求
任何大数据量的
web
系统,都非常忌讳多个大表的关联查询,以及复杂的数据分析类型的
报表查询,特别是
SNS
类型的网站,从需求以及产品设计角度,就避免了这种情况的产生。
往往更多的只是单表的主键查询,以及单表的简单条件分页查询,
SQL
的功能被极大的弱化
了。
SNS
:全称
Social Networking Services
,专指社交网络服务,包括了社交软件和社交网站。例
如:脸谱
facebook
、腾讯
QQ
、微信等。
1.55
自我保护模式
什么是自我保护模式?默认配置下,如果
Eureka Server
每分钟收到心跳续约的数量低于一
个阈值(
instance
的数量
(60/
每个
instance
的心跳间隔秒数
)
自我保护系数),并且持续
15
分
钟,就会触发自我保护。在自我保护模式中,
Eureka Server
会保护服务注册表中的信息,不
再注销任何服务实例。当它收到的心跳数重新恢复到阈值以上时,该
Eureka Server
节点就
会自动退出自我保护模式。它的设计哲学前面提到过,那就是宁可保留错误的服务注册信息,
也不盲目注销任何可能健康的服务实例。该模式可以通过
eureka.server.enable-self-preservation = false
来禁用,同时
eureka.instance.lease-renewal-interval-in-seconds
可以用来更改心跳间隔。
1.56 Ribbon
Feign
是
netflix
开发的声明式、模板化的
http
客户端,在使用时就像调用本地
(
服务消费者自
己
)
的方法一般,帮助我们更加优雅的调用服务提供者的
API
。
Feign
自身支持
springMVC
,还
整合了
Eureka
、
Ribbon
,极大的简化了
Feign
的使用。就整合
Euraka
而言,只需和普通的服
务配置
Eureka server
的信息即可。整合
Ribbon
,就意味着不再需要通过标注
@LoadBalanced
的实例化后的
RestTemplate
去调用服务提供者方法了。
Feign
只需通过简单的定义一个接口
即可实现负载均衡。
和
nginx
不同,它是客户端侧负载均衡。
1.57
负载均衡策略
常见提供的负载均衡算法有三种:
⚫
第一种也是默认为轮询
⚫
第二种为
random
随机
⚫
第三种为
WeightedResponseTimeRule
,响应时间
1.58 Feigh
概念
Feigh
是一个声明式
web
服务客户端。它能让开发
web
服务变得容易。使用
Feign
需要创
建一个接口并注解它。它拥有包括
Feign
注解和
JAX-RS
注解的可插拔支持。它还支持可
插拔的编码器和解码器。
Spring Cloud
拥有
Spring MVC
支持,并使用
Spring Web
中默认
同样的
HttpMessageConverters
。在使用
Feign
时,
Spring Cloud
集成了
Ribbon
和
Eureka
来提供负载均衡的
HTTP
客户端。
总结:
Feign
简化
HttpClient
开发,封装了
JAX-RS
和
SprinMVC
的注解,学习成本很低。
1.59
微服务设计引发新的问题
微服务的设计,服务分散在多个服务器上,服务之间互相调用,要调用的服务由于跨网络跨
服务器调用,响应速度明显比传统项目单机调用慢很多,甚至由于网络涌动的不稳定的现象
发生导致调用超时;还有类似级联失败、雪崩效应(依赖的基础服务宕机,关联的服务导致
失败甚至宕机,就像滚雪球一样层层失败。)
如何解决这类新的问题呢?传统的机制就是超时机制。
1.60
熔断机制
家里电表都有个断路器(俗称电闸),当使用的电器很多,用电巨大(例如功率过大、短路
等),当电流过载时,电路就会升温,甚至烧断电路,引起火灾。有了这个断路器,我们及
时拉闸,就不会造成严重后果了。
断路器可以实现快速失败,如果它在一段时间内检测到许多失败,如超时,就会强迫其以后
的多个调用快速失败,不再请求所依赖的服务,从而防止应用程序不断地尝试执行可能会失
败的操作,这样应用程序可以继续执行而不用等待修正错误,或者浪费
CPU
时间去等待长
时间的超时。断路器也可以使应用程序能够诊断错误是否已经修正,如果已经修正,应用程
序会再次尝试调用操作。
断路器模式像是那些容易导致错误的操作的一种代理。这种代理能够记录最近调用发生错误
的次数,然后决定使用允许操作继续,或者立即返回错误。