说说分布式系统容器化

news2024/11/28 8:36:40

继上一篇浅谈高并发分布式架构演进路径,单体服务完成分布式架构改造,转型为微服务。随着微服务数量的急剧增加,跨应用、跨系统的调用越来越多,调用关系和依赖关系日益复杂,这种复杂性增加了系统的设计、实施和维护的难度。下图是由某系统生成的全局调用关系图:

带来的一些问题:

  1. 运维成本增加:分布式系统如何适应快速迭代上线,分布式系统如何处理节点故障;

  2. 资源成本增加:构建和维护分布式系统通常需要更多的资源、硬件、网络和人力投入,从而带来更高的成本;

  3. 系统集成: 将不同的分布式组件和服务集成到一个完整的系统中可能会导致兼容性和集成问题;

  4. 一致性难度增大:不同的一致性模型(如强一致性、弱一致性、最终一致性等)在不同的场景下可能会引发数据一致性问题,开发人员需要权衡不同的一致性要求;

  5. 数据分区与复制需要考虑: 数据在分布式系统中通常会被分区和复制到不同的节点上,以提高性能和可用性。然而,数据分区和复制会引发数据一致性、更新冲突等问题;

    死锁与并发控制需要精通:在分布式系统中,由于资源分布在不同节点上,死锁和并发控制问题可能变得更加复杂,需要特殊的算法和机制来解决。

本篇将聊聊1~3方面的问题和解决方案,4~6会在下一篇数据一致性进行专题说明。对应运维成本和资源成本的增加,业界一般是通过云原生的能力来提升运维效率和资源使用率。

在说云相关技术前,先说一下什么是云计算。 “云”这个名字其实能困扰技术小白好长时间,什么是云?

云就是资源(如网络、服务器、存储、应用及服务等),云计算是一种资源的服务模式,该模式可以随时随地、便捷按需地从可配置计算资源共享池中获取所需的资源,资源能够快速供应并释放,大大减少了资源管理工作开销。

降低系统上云难度 - 容器

但随着云的发展,由于没有一个统一的标准,造成各家都有自己的云解决方案,如IaaS发展主要以虚拟机为最小粒度的资源单位,出现了资源利用率低、调度分发慢、软件栈环境不统一等问题。Docker技术的出现解决了虚机的一些问题,Docker容器以资源分割和调度为基本单位,封装整个软件运行时环境,是一个跨平台、可移植并简单易用的容器解决方案。Docker可在容器内部快速自动化的部署应用,并通过操作系统内核技术(namespaces、cgroups等)为容器提供资源隔离和安全保障。

Docker镜像

Docker镜像(Docker Image)就是一个只读的模板。比如,一个镜像可以包含一个完整的Ubuntu操作系统环境。其中只读层被称为镜像,镜像是永远不会变的。

仿真环境测试搭建场景

可别小看这个设计,有了这个设计可以使容器消除线上线下的环境差异,保证应用生命周期环境的一致性和标准化。比如阿里每年都会为双11做成千上万套预案和各种测试场景,如何将线上环境快速部署到测试环境,通过手动配置?这是不可能实现的。有了镜像技术,开发人员使用线上系统的Docker容器镜像,实现测试环境的构建,完全保证线上线下系统和环境完全一致,使测试更加准确真实。

基础组件更新替换场景

Docker这种一层一层的镜像技术,为基础插件更新和添加提供了极大的便利。举个栗子,公司有100台装有Java1.6环境的机器,现在需要将Java1.6统一升级到1.8,传统的运维解决方案就是一台一台的安装,如果使用Docker的话,只需要加一层JDK1.8的容器镜像,系统重新编译后重启一下就OK了,运维效率可以得到很大的提升。

容器编排及管理 - Kubernetes

Docker解决了节点级(单机)服务的一些问题,随着微服务系统拆分的越来越多,彼此之间解耦,具备了独立开发、部署、升级和伸缩能力,迭代频率变得越来越高。这就需要一整套业界标准的解决方案,Kubernetes基于上述需求提供了一套自动化运维解决措施,并形成了统一的业界标准,从而解决成千上万系统的管理问题,帮助企业获得更高的基础设施利用率。

比如一些常见的运维问题,如:

  1. 线上服务宕机问题,如何自动拉去、如何将重要的服务分不到不同的物理机中;

  2. 某核心服务线上几十个节点,如何保证线上自动化部署、如何保证上线时业务依然稳定运行。

Kubernetes提供了自动化容灾、无损上线和自动扩缩容等解决方案。

自动化容灾

在日常系统运维期间,对于一些影响到业务的核心系统是需要重点保障的,各个公司都有自己的各自解决方案,除了应急预案和日常应急演练外,常规的自动恢复功能也是要有的。在虚机时代常用的解决方案:

  • 服务挂掉重启,可以通过监听系统进程,判断系统是否挂掉,通过Agent触发重启脚本,将应用拉起;

  • 通过VM厂商自带产品功能,将同一个服务的应用程序,防止在不同的物理机器中。如果没有VM厂商,只能自己手动选择物理节点放置。

不过这些能力都需要自研或借助厂商产品的能力,对于CPU、内存、连接池100%等服务假死场景,虚拟机时代的功能也是力不从心的。Kubernetes提供的探针和区域亲和性技术,可以很好的解决上述运维问题。

系统挂掉场景

使用Liveness探针,可以定义容器的运行状况。如果容器处于不健康状态(例如,应用程序崩溃),Kubernetes 将自动重启容器,实现系统自愈的能力。

系统启动或假死场景

通过Readiness探针,可以告诉 Kubernetes 何时应该将流量引导到容器。当容器准备好接收流量时,Readiness探针返回成功,否则返回失败。这有助于防止流量发送到尚未完全启动或故障的容器上。

https://storage.googleapis.com/gweb-cloudblog-publish/original_images/google-kubernetes-probe-readiness6ktf.GIF

Spring Boot 2.3版本以后对Kubernetes的readiness和liveness探针做了支持,如果没有特殊自定义要求,直接使用即可。

YAML示例

apiVersion: v1
kind: Pod
metadata:
  name: my-app
spec:
  containers:
  - name: my-app-container
    image: my-app-image
    readinessProbe:
      httpGet:
        path: /actuator/health/readiness
        port: 8080
    livenessProbe:
      httpGet:
        path: /actuator/health/liveness
        port: 8080

亲和性和非亲和性场景

Kubernetes 可以通过 Node 亲和性规则来控制 Pod 在哪些节点上运行,可以使用这些规则确保相关的 Pod 在不同的可用区或区域中运行,以提高容灾性。

亲和性

Node affinity diagram

有两个Node节点A、B,希望将app-worker-node镜像部署到Node B上,就可以使用亲和性能力,在Node B添加name:app-worker-node标签,通过affinity将app-worker-node的pod调度到name:app-worker-node的Node B节点上。

  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: name
            operator: In
            values:
            - app-worker-node

非亲和性

有两个app:green的Pod,为了提升容灾能力,希望分布在不同的Node服务节点上,就可以通过如下YAML实现。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: green
  labels:
    app: green
spec:
  replicas: 2
  selector:
    matchLabels:
      app: green
  template:
      labels:
        app: green
    spec:
      containers:
      - name: green
        image: green:latest
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchLabels:
                  app: green
              topologyKey: "kubernetes.io/hostname"

非亲和性与亲和性相反,可以让调度器将同一组Pod分配到不同的Node节点或不同的可用性区域,这样当某个节点或区域出现故障时,不会使整个服务不可用,可以有效提升业务连续性。

业务流量无损版本发布

滚动发布

滚动发布就是将旧版本逐步替换为新版本的过程,滚动进行旧版本下线新版本上线,最后所有版本都发布为新版本。配合无损下线,可以起到发布新版本时业务无感,依然保持连续性。

通过maxSurge和maxUnavailable来控制滚动速率,特别适用于服务节点较多或较少的发布场景。当服务节点较多时,可以一次部署多个节点,保持部分节点可用,这样提升能上线效率;对于只有少量节点,为保持业务连续性,可以一个节点一个节点的部署,如下图所示。

详细的可参考《Kubernetes in Action》第9章内容。

灰度发布

灰度发布有别与滚动发布,主要是灰度发布可以发布少量新版本,通过导入少量流量,小范围测试,如果出现问题,只会影响小范围流量,减轻新版本发布代码等问题对业务造成的影响。但如果想做金丝雀发布等AB测试,Kubernetes目前是不具备这个能力,需要借助Istio的Flagger来完成。

flagger-abtest-steps.png

自动扩散容

Kubernetes可以通过控制Pod副本数量实现自动伸缩的能力,一般通过HorizontalpodAutoscaler(HPA)资源,周期性检查pod的度量(如CPU、内存使用情况)实现自动扩缩容。

常用应用场景

  1. 应用程序的负载通常会随时间变化。有些应用程序可能在白天负载高,而在夜间负载较低,而另一些应用程序可能会在特定事件或促销期间负载高。HPA可以根据这些负载变化来动态调整资源,以适应不同的负载模式,从而提高资源的利用率;

  2. HPA会根据应用程序的实际负载情况动态调整Pod的副本数量。当负载增加时,HPA会自动增加Pod的副本数量,以满足应用程序的需求。当负载减少时,HPA会自动减少Pod的副本数量。这种动态性质使得资源的使用更加高效,因为它可以根据需求提供足够的容器实例,而无需手动干预;

资源利用率提升

对应虚拟机场景下的运维,一般都是固定节点资源,这可能导致过多或过少的资源。过多的资源配置势必会造成资源浪费;配置过少的资源,应用程序可能无法满足负载,会出现性能问题。

总结

微服务实现了系统的解耦,使系统节点横向扩展变为了可能。但随之而来的是系统复杂度的提升,微服务+云可以有效降低运维和资源成本,已Docker和Kubernetes等云技术,进一步降低上云系统门槛,统一业界云技术标准,形成了多场景的云化应用和中间件,使云原生相关的技术得到了蓬勃发展。

参考:

  • 京东微服务平台架构解密-微服务 (uml.org.cn)

  • 《Docker容器与容器云》

  • 《Kubernetes in Action》

  • Kubernetes best practices: Setting up health checks with readiness and liveness probes

  • Kubernetes node affinity: examples & instructions - (kubecost.com)

  • K8s Pod Anti-affinity. How to ensure high availability when… | by Daniel Weiskopf | Medium

  • Kubernetes Deployment Strategies (weave.works)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/992455.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java并发基石——CAS是如何实现的?

目录 1. 什么是CAS? 2. Java中关于 CAS 的 API 在哪里? 3. CAS API方法和参数解析 4. CAS的底层实现 5. CAS是如何保证多核线程安全的? 6. CAS的缺点? 7. 如何避免ABA问题? 1. 什么是CAS? CAS的全程是…

动态库静态库对比

程序编译成可执行程序的过程 静态在连接阶段会把代码复制到可执行文件中 动态则不,而是打包一些信息进去,在执行的时候根据信息找到动态库执行 制作过程 静态库 动态库 优缺点 库比较小且更新慢的时候一般使用静态,反之则动态 静态库 …

七种 BeanDefinition,各显其能!

聚沙成塔!不知不觉 Spring 源码已经连续更了两个月啦,视频也录制了不少了,对 Spring 源码分析感兴趣的小伙伴戳这里哦Spring源码应该怎么学?~ 今天我们继续来看 Spring 源码中一个非常重要的概念:BeanDefi…

万物皆可连的腾讯轻联

文章目录 前言关于腾讯轻联小试牛刀新建流程配置逻辑组件配置连接器流程上线 其它功能核心能力总结 前言 工作中有这样一个需求,每周五下午三点定时给小组内成员发送邮件,邮件内容固定,主要作用是提醒大家记得发周报;其实这个需求…

iOS:解决Could not find a storyboard named ‘LaunchScreen.storyboard‘ in bundle NSBundle

打开项目的:HBuilder-uniPlugin-Info.plist 删除Launch screen interface file base name 然后看图,清空掉之前的LaunchScreen.storyboard东西 再运行就可以了,我也是改自定基座出的问题略

西门子LAD编程扫描周期带来的步序跳转问题

一、程序目的 按一下启动,程序进入第一步。延时五秒之后进入第二步进行自加1,然后回到第一步继续延时5秒循环,依次类推。 二、出现的问题 第一次程序进入第一步时,定时器正常定时,计数正常加1,但从第二轮开…

使用WinDbg进行动态调试

前言 本文章主要介绍如何使用WinDbg进行动态调试。如果程序崩溃后,没有记录dump文件,或者程序启动时发生异常,比如常见的 应用程序无法正常启动(0xc000007b) 报错,都可以使用WinDbg动态调试功能来定位问题。文章最后,…

用go实现一个循环队列

目录 队列数组队列的“假溢出”现象循环队列三种判断队列空和满的方法无下标(链式)有下标(顺序)长度标记 go用顺序表实现一个循环队列队列的链式存储结构 队列 队列(queue)是只允许在一端进行插入操作&…

物联网世界的无线电报之MQTT详解

文章目录 1. 前言1.1. 物联网与MQTT的关系1.2. MQTT的重要性及应用场景 2. MQTT基础2.1. MQTT的定义与起源2.2. MQTT的工作原理2.3. MQTT的协议格式2.4. 用java造个轮子 3. 深入理解MQTT3.1. MQTT的主要组件3.1.1. Publisher(发布者)3.1.2. Subscriber&a…

RTSP流媒体服务器EasyNVR视频平台以服务方式启动异常却无报错,该如何解决?

EasyNVR是基于RTSP/Onvif协议的安防视频云服务平台,可实现设备接入、实时直播、录像、检索与回放、云存储、视频分发、级联等视频能力服务,可覆盖全终端平台(电脑、手机、平板等终端),在智慧工厂、智慧工地、智慧社区、…

【2023微博评论爬虫】用python爬上千条微博评论,突破15页限制!

文章目录 一、爬取目标二、展示爬取结果三、爬虫代码四、同步视频五、获取完整源码 您好,我是 马哥python说,一枚10年程序猿。 一、爬取目标 前些天我分享过一篇微博的爬虫: 马哥python说:【python爬虫案例】爬取微博任意搜索关…

【网络编程】IO多路复用

IO多路复用是一种高效的I/O处理方式,它允许单个进程能够同时监视多个文件描述符(sockets、文件等),并在其中任何一个文件描述符准备好进行I/O操作时进行处理。它的核心在于使用少量的线程或进程来管理多个I/O操作,以提…

【JavaSpring】spring接口-beanfactory和applicationcontext与事件解耦

beanfactory 1.applicationcontext的父接口 2.是Spring的核心容器 功能 表面只有getBean,但实现类默默发挥了巨大作用 1.管理所有bean 2.控制反转 3.基本的依赖注入 applicationcontext 功能 1.继承了MessageSource,有了处理国际化资源的能力 …

【C++】继承基础知识一遍过

目录 一,概念 二,继承定义 1. 继承格式 2. 访问限定符与继承方式的关系 3. 继承父类成员访问方式的变化 小结: 三. 父类与子类对象赋值转化 四,继承作用域 1.特点 2. 测试题 五,派生类不一样的默认成员函…

【nacos】2.1.1持续输出事件警告日志

nacos-server 2.1.1 持续输出事件警告日志,修复NamingTraceEvent连续打印日志。这是 2.1.1 beta 功能跟踪事件。如果没有订阅者处理TraceEvent,将打印此日志。2.1.1版本中忽略它,我们将在2.1.2版本中对其进行增强。 WARN There are no [com.alibaba.nac…

Linux系统中驱动之设备树的platform驱动实现

每日一个简单的驱动,日久方长,对Linux驱动就越来越熟悉,也越来容易学会写驱动程序。今日进行设备树下的platform设备驱动。 前面一篇我们讲解了传统的、未采用设备树的 platform 设备和驱动编写方法。最新的 Linux 内核已经支持了设备树&…

c语言练习45:模拟实现内存函数memcpy

模拟实现内存函数memcpy 针对内存块&#xff0c;不在乎内存中的数据。 拷贝内容有重叠的话应用memmove 模拟实现&#xff1a; 代码&#xff1a; 模拟实现memcpy #include<stdio.h> #include<assert.h> void* my_memcpy(void* dest, const void* src, size_t num…

【计算机基础知识3】IP 地址和子网掩码、DNS、HTTP

目录 前言 一、IP地址和子网掩码 1. IP地址的概念 2. IP地址的分类 3. 子网掩码的概念 4. 子网掩码的用途 二、域名系统&#xff08;DNS&#xff09; 1. DNS的作用 2. 域名解析过程 3. 如何配置和管理域名解析 三、HTTP&#xff08;超文本传输协议&#xff09; 1. H…

Pytest系列-测试用例前后置固件setup和teardown的介绍和使用(2)

简介 在unittest框架中&#xff0c;有两个前置方法&#xff0c;两个后置方法&#xff0c;还有两个模块方法&#xff0c;分别是 setup()&#xff1a;每个用例执行之前都会自动调用setupClass()&#xff1a;在类中所有的测试方法执行前会自动执行的代码&#xff0c;只执行一次t…

华为云中对象存储服务软件开发工具包(OBS SDK) C语言介绍

华为云的OBS介绍&#xff1a;摘自华为云官网&#xff1a;https://support.huaweicloud.com/obs/index.html 华为云的对象存储服务(Object Storage Service&#xff0c;OBS)是一个基于对象的海量存储服务&#xff0c;为客户提供海量、安全、高可靠、低成本的数据存储能力。 …