云原生之敏捷基础设施

226 阅读8分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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

  1. UUID

UUID由以下几部分组成:

  • 当前日期和时间
  • 时钟序列
  • 全局唯一的IEEE机器识别号,如果有网卡,则从网卡MAC地址获得。
  1. SnowFlake

核心算法是毫秒级时间41位+10位机器ID+毫秒级内序列12位。 3. Ticket Server

利用Mysql自增长ID实现。可以利用多台Mysql实现高扩展性和高可用性。

首先要保证ID是全局唯一的,另外,由于无法统一分布式环境的每台服务器的时钟,无法做到全局递增,因此A服务可能取ID早,但是入库晚。因此分布式ID无法保证全局顺序性。