持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第24天,点击查看活动详情
敏捷基础设施
2.1 传统基础设施面临的挑战
- 资源利用率低,服务器没有被完全利用
- 服务器数量呈爆炸性增长
- 没有标准化,因为一些事故,导致运维操作了某台服务器,那么这台与其他服务器有差异
- 脆弱的基础设施。传统运维方式花费大量时间
2.2 敏捷基础设施
第一阶段:运维“全人肉”操作
第二阶段:脚本阶段
第三阶段:工具阶段。通过私有云管理虚拟机,通过CI工具实现持续部署。运维人员通过虚拟机镜像来封装常用依赖环境。但是开发环境、测试环境、生产环境差距很大。可能开发环境可以的,上了测试环境不行
第四阶段:敏捷基础设施阶段,无须运维人员,全部自动化,通过容器封装环境,实现开发、测试、生产环境的一致。敏捷基础设施也可称为基础设施既代码,基础设施配置可以当作编写代码进行。整个过程只需要开发人员负责,无需运维人员参与。
2.3 基于容器的敏捷基础设施
敏捷基础设施的目标如下:
- 标准化
- 可替换。任意节点能够被轻易的创建,销毁,替换
- 自动化。
- 可视化。当前环境要做到可控,就需要对当前环境情况可视
- 可追溯。所有的配置统一作为代码进行版本化管理
- 快速。资源申请和释放要求秒级
目前比较常用的基础设施自动化工具有:Ansible、Chef、SaltStack、Terraform等。
2.3.1 容器 VS 虚拟机
容器和虚拟机的区别:虚拟机是在硬件的基础上进行虚拟化,隔离性更高,而容器是在操作系统上进行的虚拟化。严格意义上来说,容器并不是虚拟化,因为所有容器是共享内核的。区别如图所示:
- 资源利用率。容器更轻量级,比虚拟机资源利用率更高
- 创建速度。Docker的启动速度是秒级的,虚拟机启动是分钟级的
- 性能。虚拟机需要运行完整的Guest OS,不可避免的会出现性能损失。而容器相当于一个进程,性能相当于物理机
- 隔离性。虚拟机隔离性更高。
2.3.2 Docker
安装及使用
2.4 监控告警服务
传统的监控更强调以资源为中心,关注CPU、内存、宽带等。这种方式不够精确。现在更偏向于应用,如订单量下降一半是否存在问题,吞吐量到达阈值后先关注依赖的其他系统是否正常在弹性伸缩。
2.4.1 监控数据采集
(1)直接上报
(2)通过打印的日志上报
(3)通过agent上报
2.4.2 通过Prometheus和Grafana监控
2.5 分布式消息中间件
2.5.1 常见的消息中间件
ActiveMQ
优点:历史悠久,功能丰富,能够适配各种协议,文档多,有鉴权机制,多语言客户端
缺点:性能差、只支持主从,扩展性差
RabbitMQ
优点:可以看作ActiveMQ的改进版,用Erlang语言实现,性能比ActiveMQ高
缺点:虽然性能有所提高,但是对比Kafaka、RocketMQ还有差距。只支持主从,扩展性差
Kafka
优点:性能非常高,0.8版本后可靠性得到了保障,分布式能力强大。
缺点:支持的协议少,工具少
RocketMQ:
优点:基于Java语言开发,模仿了Kafka的设计理念,继承了高性能,分布式能力强的优点。同时有一些对企业比较好的功能,如:消息服务端过滤,定时消息等。
2.5.2 Kafka的设计原理
- Broker:Kafka的服务端,负责接收数据,并持久化数据,Broker可以有多个,每个Broker可以包含多个Topic,Broker并不保存Offset,由Consumer自己保存,默认保存在Zookeeper中
- Producer:生产者。生产数据发送到Broker,Producer直连Broker,不经过任何代理。Producer还有异步发送功能,也就是说多条消息缓冲到客户端,达到一定数量或时间后,批量发送给Broker。通常Producer是一个包含Kafka客户端的业务服务。
- Consumer:消费者。业务服务从Broker订阅Topic。每个消费组属于某个消费者组,一个组里的消费者订阅的是同一个Topic,同一个组的消费者分别订阅同一个Topic下面的不同的Partition的数据。每个Partition只能被一个消费者订阅,
- Topic:主题。Topic更像一个逻辑概念,每个Topic下包含了多个Partition,所有的元数据都存在Zookeeper中。
- Partition:分区。Kafka为了扩展性,提升性能,可以将一个Topic拆分为多个分区,每个分区可以独立放到一个Broker上。
2.5.3 为什么Kafka性能高
- 顺序访问磁盘,访问速度比随机访问磁盘快了非常多
- 零拷贝
2.5.4 Kafka的数据存储结构
Kafka的存储设计基于日志实现,非常简单。这里的日志是按时间序列排列的追加记录序列,只能在末尾添加,不能修改,以此来利用磁盘顺序写的能力。
一个Partition是一个文件夹,每个Partition下包含多个Segment。物理上每个Segment包含两种文件,一个是数据文件,以log结尾,一个是索引文件,以index结尾。
2.5.5 如何保证Kafka不丢消息
1.ACK
生产消息投递到Broker时,可以通过ACK保证消息投递
- 最多一次。消息可能会丢失
- 最少一次。消息绝对不丢,但是会重复
- 有且只有一次
2.复制机制
谈到复制机制,必须先从消息的持久化谈起。Linux写文件有如下三种方式。
- 直接持久化到磁盘
- 写到内核态Buffer,间隔一段时间刷新一次磁盘
- 数据直接持久化,元数据间隔一段时间持久化
RocketMQ可以在配置文件上设置前两种写文件的格式,Kafka当前版本还不支持。因此单机的可靠性上RocketMQ优于Kafka。Kafka保证可靠性的依赖是复制机制。
举例说明,假如Topic1复制因子设置为3,分区数为2。当生产者发送消息时,先计算属于哪个Partition,如果属于part1,则会发送至Broker0,写入Topic1-part1-leader,Broker1和Broker2下面的Topic1-part1-follower会去拉取消息并复制到本地,一旦副本数够了,leader就会提交。
3.消息删除机制 Broker默认7天才删除消息
4.发送消息 Kafka支持在生产者一侧进行本地buffer,也就是累积到一定条数才发送。生产端可以设置producer.type=async\sync,默认为sync。当然设置为async会提高性能,但是如果消息缓存到了本地,还没发出去就挂了,就会丢消息。
5.消费消息 消费消息的时候,如果更注重可靠性,可以显示提交Offset,也就是当业务都处理完了再提交Offset,当然这可能会导致重复消费,需要提供幂等性接口。
2.6 分布式缓存服务
2.6.1 分布式缓存的应用场景
按照缓存的位置分类,可以分为本地缓存和分布式缓存。相较于本地缓存,分布式缓存有具有如下优点:
- 不需要各个业务节点同步数据
- 能够做到业务服务无状态
- 不需要管理数据。例如Java,本地内存多了会导致FullGC
当然本地缓存也有优点,性能更高,不用维护额外的缓存服务。
那么什么样得数据可以放进缓存:
- 数据量比较小
- 不经常变化
- 计算代价比较高的
- 核心热点数据
相反,什么样的数据不应该被缓存呢?
- 变化比较快的数据
- 要求强一致性的数据
2.6.2 常用的分布式缓存Memcached
Memcached是一款开源、高性能的分布式内存对象缓存系统。
2.6.3 常用的分布式缓存Redis
可以基于Codis实现Redis分布式缓存集群
Codis是一个基于代理的分布式Redis解决方案,业务应用可以像使用单机Redis那样使用它。
2.7 分布式任务调度服务
一般对可用性和性能要求不高的任务,采用单点即可,例如Spring的Quarz。但是对可用性的要求更高的话,上面的方案就不适用了。
分布式调度至少满足两个要求:
- 不重复的执行任务
- 不遗漏的执行任务
2.7.1 通过Tbschedule实现分布式调度
Tbschedule是阿里开源的分布式任务调度系统,后期维护较少,但是代码简单,可塑性好。
2.7.2 通过Elastic-Job实现分布式调度
由当当开源的,国内应用十分广泛。原理是通过Zookeeper作为分布式协调服务实现任务调度的。
2.8 如何生成分布式ID
- UUID
UUID由以下几部分组成:
- 当前日期和时间
- 时钟序列
- 全局唯一的IEEE机器识别号,如果有网卡,则从网卡MAC地址获得。
- SnowFlake
核心算法是毫秒级时间41位+10位机器ID+毫秒级内序列12位。 3. Ticket Server
利用Mysql自增长ID实现。可以利用多台Mysql实现高扩展性和高可用性。
首先要保证ID是全局唯一的,另外,由于无法统一分布式环境的每台服务器的时钟,无法做到全局递增,因此A服务可能取ID早,但是入库晚。因此分布式ID无法保证全局顺序性。