头条夏令营作业1,微服务相关调研
微服务
概念
微服务是一种架构风格,大型的复杂软件通常由一个或多个微服务组成。系统中各个微服务可以被独立部署,各个微服务之间也是松耦合的。每个微服务有各自需要专注的任务,因此各自代表着一个小的业务能力
特点
- 组件化:将整体拆分为多个可独立部署和升级的单元
- 围绕业务能力组织:每个微服务团队应该是夸功能的,且开发运维一体化的。但是每个团队并不会有太多成员
- 视为产品而非项目:谁开发,谁运营
- 通讯松耦合:将通信的相关业务放在组件端点侧。RESTful协议和仅提供消息路由功能的轻量级异步机制是微服务架构中最常用的通讯机制
- 去中心化:每个微服务可以采用最适合自己的工具/技术,而不会让整体都应用同一个技术。通常倾向于对于每个微服务,使用有现成或类似解决方案的方式进行实现。
- 基础设施自动化:云+自动化部署等方式,降低微服务构建、部署和运维的难度
- 故障处理设计:注重实时监控和日志机制,考虑服务失败的容错机制
- 演进式设计:更注重快速更新迭代
常见误区
- 微服务不能等同于API,微服务指的是将原有的整体式架构进行拆解,组件化后产生的微服务应用。是更细粒度的组件,而非更细粒度的API。
- 微服务架构和微组件架构是有差异的。微服务架构更强调独立部署和快速迭代。
- 微服务架构不等同于SOA(面向服务架构)。虽然都是以服务为核心的架构,但是微服务更倾向于应用范畴,而SOA更倾向于企业规模范畴
应用领域
- 记录型系统:可将大型应用按照相对独立的业务功能分解成若干个微服务实现
- 交互型系统
- 分析型系统
优点
- 每个服务简单,更关注于一个业务功能
- 松耦合,灵活性很好
- 可在应用中使用最适合的语言/工具
- 每个微服务之间独立开发,互不影响,加快市场推进
- 在频繁发布某个微服务同时可保持其他微服务的可用和稳定
缺点
- 需要同时维护多个独立服务,运维开销和成本增加
- 对于开发人员的运维能力也更有考验
- 对于一个新产品发布导致大量服务协同发布的情况,会产生更多的隐式接口和其中的匹配问题,服务服务架构有更高的发布风险
- 为了防止“同步耦合”,不同服务之间会产生一定的代码重复
- 分布式系统的复杂,也会带来一定的问题
- 异步的机制会导致实现的复杂化
- 在动态环境中,服务间的交互会产生一些不可测的现象
框架
- Spring Cloud
- 基于java语言
- 应用广泛,社区支持好
- 架构整体覆盖比较全,有较为完善的架构体系
- 自由开发,但是较难约束接口规范
- Dubbo
- 基于java语言
- 年轻的框架,目前也有一定的社区用户
- dubbo的jar依赖会是一个较难解决的问题
- gRPC
- 基于Go语言
- 很弱的负载均衡
- 只有服务调用,没有服务治理
- Go-micro
- 基于Go语言
- 服务治理rpc框架
- 性能较为一般
- Tars
- 支持C++、Java、PHP、NodeJS 、Go
- 自带服务治理
- 目前对Go的社区支持TarsGo框架较为弱
服务发现
简介
- 通过在服务中介节点的注册和查找,完成新加入服务的发现和调用。
- 当服务提供者挂掉时,取消注册,通知服务调用方更换地址
- 当新服务加入时,服务注册,服务中介通知服务调用方
问题
- 对于意外退出的服务如何通知服务中介服务地址时效?=> 使用存活汇报机制
- 服务器列表变化中介如何通知服务调用者
- 服务调用者轮询
- 发布订阅模式对服务调用者广播
- 单点redis挂掉如何处理?=> 使用分布式数据库zookeeper/ etcd/ consul作为中介
形式
- 客户端服务发现
- 客户端通过访问服务注册表使用均衡算法访问服务
- 可对不同的客户端实现不同的均衡机制,灵活但是麻烦
- 服务端服务发现
- 服务请求通过一个负载均衡器进行转发,均衡器从主服务注册表查询可用服务实例
- 客户端对服务发现逻辑并不知道,只需要像负载均衡器发送请求
服务注册表
服务发现实现中关键部分,需要高可用和实时更新
实现
-
- Java语言,sdk接口
- 功能强大,不仅作为服务发现框架
- 需要客户端对服务保活,增加了开发难度
-
- Go 语言,http/dns接口
- 简单易用,不需要集成sdk
- 不能实时获取服务信息变化通知
- Etcd
- Go 语言,http接口
- 简单易用,不需要集成sdk,可配置性强
- 需要第三方工具一起完成服务发现,不支持多数据中心
- 高可用、分布式、一致性、k - v 方式存储
self-registration 模式
- 服务实例自己通过注册表进行服务注册和注销
- 通过发送心跳请求防止注册过期
- 和服务强耦合,必须在所有编写的服务中实现一遍服务注册逻辑
- 在服务运行中但是没有能力提供服务的情况下,缺乏解注册的能力
third-party registration模式
- 通过service registrar轮询或者订阅事件来检测运行实例的变化,当检测到可用实例就加入注册表
- 可以从服务端解耦注册逻辑,将服务注册集中管理
- 如果没有内置在部署环境中,需要是一个高可用系统组件
Service Mesh
简介
- 解决服务间通信的基础设施层,保证请求在复杂服务拓扑中可靠传输
- 可以理解为微服务之间的TCP/IP,用于微服务间的网络调用、限流、熔断和监控,对应用透明
- 用于服务间通信而单独分理出的组件(Sidecar)
发展过程
- 服务间通信使得服务业务逻辑中夹杂网络传输问题处理逻辑
- TCP协议出现,解决了网络传输中流量控制的问题,将流量控制从服务实现中抽离,成为操作系统中网络层的一部分
- 分布式系统特有的如熔断策略、负载均衡、服务发现、认证授权、trace、监控等又需要根据业务需求实现
- 某些框架实现了分布式系统通信需要的各种通用语义功能,以依赖的方式引入,屏蔽一些通信细节,使得使用较少代码开发健壮分布式系统
- 通过部署在服务环境中的代理服务实现服务间通信,减去了框架学习成本,更解决了通信库版本兼容的问题,防止了由于升级通信库而带来的服务被迫升级
- 统一上层运维入口,集中对每个服务中的代理组建进行管理,通过和控制面板交互进行网络拓扑策略的更新和单机数据的汇报。
优点
- 屏蔽了分布式系统通信的复杂性
- 真正的语言无关,服务可以使用任何语言,只需要和Service Mesh通信即可
- 对应用透明,Service Mesh组件可以单独升级
劣势
- Service Mesh组件以代理模式计算并转发,一定程度上会影响效率
- 服务的整体稳定性依赖于Service Mesh,同时额外引入了对Service Mesh的管理成本
框架
- Istio
- Go语言和C++实现
- 性能相对较低一些
- Linkerd
- Scala语言
- 总体开销较低,在高qps下性能会有所下降
- 仅用于Kubernetes
- Conduit(Linkerd 2.x)
- 基于Rust和Go语言
- 专为Kubernetes定制的轻量级服务网格
头条夏令营作业2,cgroups相关概念
Cgroups
介绍
- 进行分组化管理的Linux内核功能
- 通过子系统来完成,每个子系统就是一个资源分配器
- 例如,
cpu子系统就是控制CPU资源的分配器 - 如果进程加入了某一个控制组,该控制组对Linux的系统资源都有严格限制,进程在使用这些资源时不能超过最大限制
一些概念
- 任务(task):在cgroup中任务就是系统的一个进程
- 控制族群(control group):一组按照某种资源限制划分的进程组
- 层级(hierachy): 控制族群组成的控制族群树,子控制进程组继承父控制进程组
- 子系统(subsystem):任务组中的一个模块,是一个控制器,提供多种资源限制的控制器
子系统
- 可以使用
lssubsys -a查看所有子系统 - 要为cgroup分配限制的资源首先要挂在子系统,然后才有控制组
blkio限制块设备的输入输出控制cpu使用调度程序为cgroup任务提供cpu访问cpuacct产生cgroup任务的cpu资源报告cpuset在多核心cpu中为cgroup任务分配单独cpu和内存devices允许或拒绝cgroup任务对设备的访问freezer暂停和恢复cgroup任务memory设置每个cgroup的内存限制及产生内存资源报告perf_event增加了对每个group的监测和跟踪能力,可监测某个特定group的所有进程以及运行在特定cpu上的线程hugetlbHugeTLB页的资源控制功能
安装
- ubuntu:
apt-get install cgroup-bin - Centos:
yum install libcgroup
CPU子系统
一些参数
cpu.cfs_period_us每个CPU时间片的微秒数,限制从1毫秒到1秒之间cpu.cfs_quota_us在当前的每个CPU时间片中可以使用的CPU时间数