精华内容
下载资源
问答
  • 2020-12-05 16:10:50

    一、前言

    分布式大行其下的时代,让大家彻底的抛弃了传统陈旧的技术框架。几乎每一个技术人都知道和掌握了微服务架构,微服务自然有它的美,但是所以技术框架都必须服务于业务,结合自身业务选取甚至自研适合自身的技术框架也是技术人必须首先考虑的事情。分布式作业调度框架,是一个开发迅速、学习简单、轻量级、易扩展、高可用分布式任务调度框架。

    二、分布式任务调度框架

    2.1 任务调度框架的简介

    任务调度是指基于给定的时间点,给定的时间间隔或者给定执行次数自动的执行任务。任务调度涉及到多线程并发、运行时间规则定制及解析、线程池的维护等诸多方面的工作。

    • 同一服务多个实例的任务存在互斥时,需要统一协调
    • 定时任务的执行需要支持高可用、监控运维、故障告警
    • 需要统一管理和追踪各个服务节点定时任务的运行情况,以及任务属性信息,例如任务所属服务、所属责任人

    2.2 常见分布式任务调度框架

    目前主流的分布式作业调度平台,主要有:当当网开源项目Elastic-job、大众点评开源项目xxl-job、唯品会开源项目Saturn、阿里巴巴早期开源项目TBSchedule等。

    2.3 实现原理

    Java有个标准定时任务Quartz,它的关注点在于定时任务而非数据,并无一套根据数据处理而定制化的流程。虽然Quartz可以基于数据库实现作业的高可用,但缺少分布式并行调度的功能。

    分布式任务调度框架,就是基于Quartz的理念,支持任务动态分片、集群部署、轻量级易上手的分布式定时作业调度架构。

    详细查看另一篇文章,专门介绍Saturn:唯品会开源分布式作业调度平台Saturn

    三、分布式微服务框架

    3.1 微服务框架的简介

    官方对于微服务并没有一个详细的定义,最初是有从传统的单体式应用架构,可以做垂直于水平拆分而衍生出的一种架构理念。于是,分布式微服务技术就因运而生了。一个去中心化的多业务独立部署和运维的SOA(面向服务的架构)集群。

    3.2 主流的微服务框架

    目前主流的微服务框架有:国外开源项目SpringCloud、阿里巴巴开源项目Dubbo和SpringCloudAlibaba(基于SpringCloud)、新浪微博Motan、腾讯开源项目Tars等。

    国内用的最多的框架是SpringCloud和Dubbo,详细查看另一篇文章:SpringCloud与Dubbo的比较

    3.3 原理简介

    简单来说,微服务就是一种将一个单一应用程序拆分为一组小型服务的方法,拆分完成后,每一个服务都运行在独立的进程中,服务于服务之间采用轻量级的通信机制来进行沟通(Spring Cloud 中采用基于HTTP 的 RESTful API)。

    微服务可以理解为是 SOA (面向服务的体系结构) 的一个传承,一个本质的区别是微服务是一个真正分布式、去中心化的,微服务的拆分比 SOA 更加彻底。

    微服务的优势

    1. 复杂度可控

    2. 独立部署

    3. 技术选型灵活

    4. 较好的容错性

    5. 较强的可扩展性

    四、任务调度和微服务的区别

    4.1 对比

    任务调度:可用于精确至时分秒定时执行的作业,可重复执行,可动态设置分片参数来设置任务的并发大小数。

    1、轻量级,支持通过Web页面对任务进行动态CRUD操作,操作简单,一分钟上手,这点应该都差不多
    2、只依赖数据库作为集群注册中心,接入开发简单,不需要ZK
    3、高可用、解耦、高性能、监控报警、分片、重试、故障转移
    4、团队持续开发
    5、支持后台直接查看每个任务执行实时日志

    微服务:去中心化,基于业务拆分的某个独立部署和运行的模块,高可用高扩展。

    ●单一职责原则

    指的是每一个微服务模块,只关心自己的业务规则。例如订单模块只关心订单的相关业务,不牵扯其他业务的逻辑。

    ●服务自治原则

    每一个微服务模块的开发,需要有自己的开发、测试、运维、部署这一条独立的栈,并且有自己的数据库等一切,完全把其当成一个单独的项目来做,不牵扯到其它无关业务。

    ●轻量级通信原则

    微服务的通信协议需要跨平台、跨语言的通信协议,因为微服务是不绑定技术栈的,不论使用Java、PHP还是.net去开发Web系统,它们之间的通信一定是去语言特色的。

    ●接口明确原则

    前面提到了微服务的“接口调整成本高”,那么怎么去避免它呢?我们一开始就应该规划好微服务的模块是一种什么样的模型,尽量去避免A接口的改动会导致B接口的改动这种情况。

    五、总结

    技术框架没有好坏之分,只有适合于不适合的概念。基于各自业务和场景,选择适合的技术框架是每一个技术人必须要首先考虑的事情。业务驱动技术,技术为业务服务,每一个伟大的技术架构的诞生都是从业务本身抽象和发展而来。随着时代的发展,先进的技术架构必然淘汰陈旧的技术框架。保持持续学习的热情和心态才能让我们跟随科技发展的脚步。


    既然都看完了整篇文章,相信对你一定有所帮助。原创不易,勿做伸手党。

    点击下方【打赏】小编,或者关注公众号给予支持,你们的每一份鼓励都将是小编伟大的动力。


    同名原创公众号:  程序大视界

     

    更多相关内容
  • 从头开始构建,并牢记 DevOps 至上的原则。 那么它有什么作用,为什么要使用它? 可靠且可重复:自动将 Git 存储库部署到服务器(通过 SSH)。 易于使用:与应用程序的所有交互都是通过 Web 界面进行的(设置需要...
  • 本来想使用自建的K8S集群来演示混合部署的,无奈作者的电脑配置实在是跟不上,一开虚拟机就卡得不行。于是果断选择氪金使用阿里云的容器服务K8S版,既省去了自己各种操作的压力,也权当是体验一把国内顶级的...

    本来想使用自建的K8S集群来演示混合部署的,无奈作者的电脑配置实在是跟不上,一开虚拟机就卡得不行。于是果断选择氪金使用阿里云的容器服务K8S版,既省去了自己各种操作的压力,也权当是体验一把国内顶级的Kubernetes容器服务。
    在这里插入图片描述

    一、混合部署的概念

    在开始介绍混合部署的概念之前,我们需要先考虑K8S在实际业务中可能存在的问题。

    假设你是一个中小企业的运维,并且公司业务都部署在K8S的集群上。那么毫无疑问,我们要尽可能地发挥K8S集群的机器利用率,也就是尽可能地不浪费K8S集群的计算能力。因为如果你不充分利用,一看CPU使用率连5%都不到,那一堆设备就相当于放那吃灰,这对于企业来说显然是不能接受的。

    我们假设业务分为在线和离线两种模式:在线任务需要资源相对较少,但要求响应时间短;离线任务则不需要对任务进行迅速响应,但是计算量相对较大、占用资源多。那么我们应该怎么在K8S集群上完成这两种业务的部署、并且使得CPU利用率始终维持在一个比较高的水平上呢?

    答案显而易见,就是“混合部署”,即在一台计算机上同时部署咱们的在线任务和离线任务。(当然,混合部署更常见的说法是混合云部署)

    那么这么搞,问题也随之而来了。比方说我们的在线服务是给客户端提供Web资源,但是某天离线任务(比如TF)突然来了好几十个TB的数据要训练,一下就把所有node资源给占用了。那这下可好了,用户点我们的网站进不去,一天损失好几亿,一下就把我们之前辛辛苦苦省下来的买服务器的钱给霍霍干净了,这不完犊子了吗?

    不要慌,这个问题早就得到了解决。接下来,咱们就来学习一下Kubernetes中的QoS管理。

    二、QoS相关知识

    QoS(Quality of Service),大部分译为 “服务质量等级”,又译作 “服务质量保证”,是作用在 Pod 上的一个配置,当 Kubernetes 创建一个 Pod 时,它就会给这个 Pod 分配一个 QoS 等级。

    我们使用的QoS等级主要有以下三个,他们所决定Pod的重要程度从上到下依次递减。

    • Guaranteed:Pod 里的每个容器都必须有内存/CPU 限制和请求,而且值必须相等。如果一个容器只指明limit而未设定request,则request的值等于limit值,是最严格的要求。
    • Burstable:Pod 里至少有一个容器有内存或者 CPU 请求且不满足 Guarantee 等级的要求,即内存/CPU 的值设置的不同。或者可以这么表达:在不满足Guaranteed的情况下,至少设置一个CPU或者内存的请求。
    • BestEffort:容器必须没有任何内存或者 CPU 的限制或请求,就很佛系。

    在这里插入图片描述
    那么QoS的作用体现在哪呢?我们举个例子,比方说计算机中的内存和磁盘资源是不可以被压缩的,而当资源紧俏时,kubelet会根据资源对象的QoS进行驱逐:

    • Guaranteed,最高优先级,最后kill。除非超过limit或者没有其他低优先级的Pod。
    • Burstable,第二个被kill。
    • BestEffort,最低优先级,第一个被kill。

    这也就意味着如果一个Node中的内存和磁盘资源被多个Pod给抢占了,那么QoS为BestEffort的Pod显然是第一个被kill的。那么说到这里,想必各位读者对于上一节中存在的问题应该如何解决想必已经有了答案。我们在实际部署的时候,可以把在线服务所使用的Pod的QoS设置为Guaranteed,这样就避免了负载过大的离线任务占用过多资源把我们的在线Pod给挤掉的情况。

    哔哔了这么多,咱们还是看几个Pod的yaml文件来学习一下QoS。我们创建一个QoS为Guaranteed的Pod。

    # kubectl create namespace example-qos
    

    QoS为Guaranteed的pod中每个容器都必须包含内存和CPU的请求和限制,并且值相等。那么我们就遵循这一原则,编写如下的yaml文件。

    apiVersion: v1
    kind: Pod
    metadata:
      name: qos-demo
      namespace: example-qos
    spec:
      containers:
      - name: qos-demo-ctr
        image: nginx
        resources:
          limits:
            memory: "300Mi"
            cpu: "500m"
          requests:
            memory: "300Mi"
            cpu: "500m"
    

    接下来我们启动该pod,并查看该pod的详细信息。

    # kubectl apply -f https://k8s.io/examples/pods/qos/qos-pod.yaml --namespace=example-qos
    # kubectl get pod qos-demo --namespace=example-qos --output=yaml
    

    在这里插入图片描述
    如果正常的话,最后会多出一行qosClass: Guaranteed,这代表我们创建的Pod的QoS为Guaranteed。如果Pod仅声明了内存限制,而没声明内存请求,那么kubernetes会自动赋予它与限制相同的内存请求。CPU也是如此。

    三、操作过程

    因为作者是第一次体验阿里云K8S容器服务,除了跟着阿里手册和K8S中文社区,还借鉴了不少技术文档,因此在步骤上可能稍有出入。以下步骤仅供参考,具体请以官方文档为准。

    我们先登录阿里云的容器服务K8S的控制台

    1. 创建Kubernetes集群

    想要创建一个Kubernetes集群,需要开通容器服务、弹性伸缩(ESS)服务和访问控制(RAM)服务。因此我们先登录容器服务管理控制台 、RAM 管理控制台和弹性伸缩控制台开通相应的服务。

    控制台界面如下所示。
    在这里插入图片描述
    我们点击创建集群,进入以下界面。
    在这里插入图片描述由于阿里的官方文档已经很详细地解释了每一步的各个选项的内容,这里本人就不狗尾续貂了,仅简单介绍阿里云K8S对应的三种服务模式。

    容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的云原生应用管理能力,并提供了以下三种 Kubernetes 集群形态,

    • 专有版 Kubernetes: 需要创建 3 个 Master(高可用)节点及若干 Worker 节点,可对集群基础设施进行更细粒度的控制,需要自行规划、维护、升级服务器集群。
    • 托管版 Kubernetes:只需创建 Worker 节点,Master 节点由容器服务创建并托管。具备简单、低成本、高可用、无需运维管理 Kubernetes 集群 Master 节点的特点,您可以更多关注业务本身。
    • Serverless Kubernetes:无需创建和管理 Master 节点及 Worker 节点,即可通过控制台或者命令配置容器实例的资源、指明应用容器镜像以及对外服务的方式,直接启动应用程序。

    那么为了体验原生Kubernetes的操作,我们这里选择的是专有版Kubernetes。读者可根据个人情况自行选择。
    在这里插入图片描述之后,我们一路点点点,选择适合自己的配置和插件,即可完成K8S集群的创建,创建完成结果如下。
    在这里插入图片描述
    接下来要做的就是安装配置kubectl客户端,并连接到我们的K8S集群上了。之前作者在本地虚拟机部署K8S集群时,在master节点上安装过kubectl并用它对K8S集群输入命令。其实,Kubectl客户端可以在任意一台主机中部署,并连接K8S集群。

    首先我们需要从 Kubernetes 版本页面下载最新的kubectl客户端。
    在这里插入图片描述
    因为在创建集群的时候,我们设置使用公网访问,所以我们选择KubeConfig(公网访问)页签,并单击复制,将内容复制到本地计算机的 $HOME/.kube/config之中。

    配置完成后,咱们就可以使用kubectl从计算机访问Kubernetes集群了。当然,作者比较懒,直接通过自带的CloudShell使用kubectl控制的K8S。具体方法如下。
    在这里插入图片描述在这里插入图片描述点击进入即可。我们查看nodes的状态,发现我们的集群已经正常启动了。
    在这里插入图片描述(相信大家也发现了作者的K8S集群里就一个node。无奈作者家境贫寒,这也是没办法的办法。)

    至此,咱们的K8S集群的创建就算完成了。接下来,咱们就正式部署一下咱们的在线服务和离线任务。

    2. 部署在线服务

    因为阿里云已经封装好了大部分内容,这也就使得我们无需通过kubectl apply等命令去自己手动执行yaml文件了。我们只需要点击“控制台”,在新的页面点“创建”。
    在这里插入图片描述接下来,咱们只需要输入yaml文件,K8S集群将自动部署好咱们的项目。具体界面如下,这里我们选择部署一个简单的mysql作为我们的在线服务模块。如下所示,我们先后上传mysql-deployment.yaml和mysql-svc.yaml两个文件。
    在这里插入图片描述
    该两个yaml文件的完整代码可参考我之前的博客

    上传成功之后,我们可以清楚地看到CPU、内存的利用率,以及在当前命名空间中各Pod、副本集、deployment等信息。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    我们在外部能够轻松访问该Mysql,代表在线服务部署完成。

    3. 部署离线任务

    本例中,作者选择部署tf-operator、并在上边跑tensorflow程序来代表离线任务。所谓 tf-operator,就是让用户在 K8S 集群上部署训练任务更加方便和简单,大家可以参考官网和 Github 进行学习。

    在部署 tf-operator 之前,我们首先要在集群中部署Kubeflow,它是基于Kubernetes和TensorFlow的机器学习流程工具,使用Ksonnet进行应用包的管理。当然,我们必须提前部署好ksonnet。

    具体过程我就不写了,大家有兴趣可以参考这篇博客。(本例只示范用tf-operator跑一些简单的测试程序,因此Kubeflow不装也可以,但是尽量还是部署)

    我们部署好了ks和kubeflow之后,就可以正式安装tf-operator了。我们简单写个脚本并执行一下。

    # 指定工作目录
    APP_NAME=my-kubeflow
    ks init ${APP_NAME}
    cd ${APP_NAME}
    
    # 指定 ks registry,方便安装 pkg
    ks registry add kubeflow github.com/kubeflow/kubeflow/tree/master/kubeflow
    
    # 安装需要的 pkg
    ks pkg install kubeflow/common
    ks pkg install kubeflow/tf-training
    
    # all 已经可以替代所安装的 pkg 了
    ks generate all
    ks apply all
    

    理论上我们已经部署好了tf-operator,我们可以执行以下命令查看tf-operator的运行状态是否正常。

    # kubectl get pods
    

    而部署好了tf-operator之后,我们就可以跑一些tf程序了。这里我们采用官方的测试程序,一个分布式的 mnist 训练任务,原yaml文件如下。

    apiVersion: "kubeflow.org/v1"
    kind: "TFJob"
    metadata:
      name: "dist-mnist-for-e2e-test"
    spec:
      tfReplicaSpecs:
        PS:
          replicas: 2
          restartPolicy: Never
          template:
            spec:
              containers:
                - name: tensorflow
                  image: kubeflow/tf-dist-mnist-test:1.0
        Worker:
          replicas: 4
          restartPolicy: Never
          template:
            spec:
              containers:
                - name: tensorflow
                  image: kubeflow/tf-dist-mnist-test:1.0
    

    通过这个yaml文件,我们不难看出这个TFJob,作为离线计算任务,它的QoS为BestEffort。这也意味着当它和我们的在线服务之间因为资源占用问题而冲突时,它是不会影响我们的在线服务的(因为在线任务的QoS为Guaranteed)。

    我们依然可以采用直接递yaml文件的方式创建TFJob。
    在这里插入图片描述

    实际上,我们也可以通过下载源文件并执行kubectl命令行来建立该TFJob。

    # cd ./examples/v1/dist-mnist
    # docker build -f Dockerfile -t kubeflow/tf-dist-mnist-test:1.0 .
    # kubectl create -f ./tf_job_mnist.yaml
    

    可以通过以下命令来查看该Pod的状态。

    # kubectl get tfjobs.kubeflow.org dist-mnist-for-e2e-test -o yaml
    
    apiVersion: kubeflow.org/v1
    kind: TFJob
    metadata:
      creationTimestamp: "2020-03-20T10:13:14Z"
      generation: 1
      name: dist-mnist-for-e2e-test
      namespace: default
      resourceVersion: "11825"
      selfLink: /apis/kubeflow.org/v1/namespaces/default/tfjobs/dist-mnist-for-e2e-test
      uid: f3c0a2c6-b1cb-11e9-9279-0800274cd279
    spec:
      tfReplicaSpecs:
        PS:
          replicas: 1
          restartPolicy: Never
          template:
            spec:
              containers:
              - image: kubeflow/tf-dist-mnist-test:1.0
                name: tensorflow
        Worker:
          replicas: 1
          restartPolicy: Never
          template:
            spec:
              containers:
              - image: kubeflow/tf-dist-mnist-test:1.0
                name: tensorflow
    status:
      completionTime: "2020-03-20T11:21:47Z"
      conditions:
      - lastTransitionTime: "2020-03-20T11:21:47Z"
        lastUpdateTime: "2020-03-20T11:21:47Z"
        message: TFJob dist-mnist-for-e2e-test is created.
        reason: TFJobCreated
        status: "True"
        type: Created
      - lastTransitionTime: "2020-03-20T11:13:30Z"
        lastUpdateTime: "2020-03-20T11:21:47Z"
        message: TFJob dist-mnist-for-e2e-test is running.
        reason: TFJobRunning
        status: "False"
        type: Running
      - lastTransitionTime: "2020-03-20T11:21:47Z"
        lastUpdateTime: "2020-03-20T11:21:47Z"
        message: TFJob dist-mnist-for-e2e-test successfully completed.
        reason: TFJobSucceeded
        status: "True"
        type: Succeeded
      replicaStatuses:
        PS:
          succeeded: 1
        Worker:
          succeeded: 1
      startTime: "2020-03-20T11:21:47Z"
    

    四、监控模块

    在本例中,我们采用的容器监控服务依托于阿里云云监控服务,能够提供默认监控、报警规则配置等服务。只需要在创建Kubernetes集群的时候选择“云监控”插件,就可以一键解决K8S集群的监控问题。

    我们打开云监控的控制台,可以清楚地看到每一个节点的工作状态和资源利用率等指标。

    在这里插入图片描述
    点进去,可以看到单独节点的具体信息和各项指标的数据可视化。
    在这里插入图片描述阿里云监控服务的报警模块也做得十分完善。比如在某些关键服务中,我们可以根据自己业务的实际情况添加报警规则,容器监控服务会在监控指标达到告警阈值后短信通知云账号联系人。
    在这里插入图片描述阿里云的监控模块十分容易上手,在此就不赘述了。

    当我们自己使用虚拟机创建K8S集群时,为了实现对集群 的监控,我们只能自己部署监控插件,比如Prometheus。有兴趣的朋友可以移步https://www.cnblogs.com/fatyao/p/11007357.html学习Prometheus的安装和操作,作者开学之后也会尝试在自己搭建的K8S集群中采用Prometheus,在此先占个坑。

    五、小结

    作为国内云技术最优秀的互联网技术公司,阿里巴巴的云计算服务,无论从用户体验、稳定性能还是容灾管理、版本更新,都无疑是国内顶尖的。今天我们尝试了在阿里云容器服务Kubernetes版中构建一个K8S集群,并把我们的在线服务和离线任务同时部署在了K8S集群上,实现了“混合部署”的概念,并通过阿里云监控组件对系统的运行状态进行监控和预警,从而对企业生产中所应用的K8S业务部署有了实际的体验。

    展开全文
  • 本章将重点介绍产品团队设计和使用部署流水线的基本原则,以及企业开发部署流水线平台工具链时,需要构建的平台能力要求,以及相关子系统的服务逻辑架构。 让我们先从一个简单的部署流水线案例开始吧! 7..

    部署流水线(deployment pipeline)是持续交付1.0的核心模式。它是对软件交付过程的一种可视化呈现方式,展现了从代码提交、构建、部署、测试到发布的整个过程,为团队提供状态可视化和即时反馈。部署流水线的设计受到软件架构、分支策略、团队结构以及产品形态的影响,因此每个产品的部署流水线均有所不同。

    本章将重点介绍产品团队设计和使用部署流水线的基本原则,以及企业开发部署流水线平台工具链时,需要构建的平台能力要求,以及相关子系统的服务逻辑架构。

    让我们先从一个简单的部署流水线案例开始吧!

    7.1 简单的部署流水线(示例)

    我们以2008年商业套装软件产品Cruise为例,来解释持续交付部署流水线的概念。该产品思想最早来源于开源软件CruiseControl的企业版本。Cruise自2008年第一个版本发布以后,每3个月发布一个商业化版本,供全球企业用户试用和购买。截至2010年,代码行数约为50000行,自动化单元测试和集成测试用例约为2350个,端到端功能测试用例约为140个。后来更名为「GoCD」,并将社区版开源后,放到了网站上。以下均以“GoCD”之名进行描述。

    7.1.1 简单的产品研发流程

    GoCD系统是典型的Server/Agent架构,服务器和客户端各自可独立启行。服务器本身曾是一个典型的巨石应用,包含关系型数据库和Java应用服务器。用户可以通过浏览器访问其Web服务,同时它也提供RESTful API接口,方便用户进行程序扩展,架构示意图如图所示:
    pasted_image.png

    服务器和代理的代码(包括自动化测试代码)全部保存于同一个代码仓库,版本控制软件使用的Mercural是(与Git类似的分布式版本管理工具),团队成员均有权修改代码库中的任何代码。产品研发团队的总人数保持在12人左右。在产品版本交付期中,迭代周期为一周。团队自身也使用该产品进行持续集成与持续交付实践。在每个迭代结束后,用最新版本替换团队自己正在使用的旧版本。每两个迭代将试用版本部署到公司内部的公用服务器上,供公司其他团队使用。若公司内部试用版本运行质量达标,一周后再将该版本交付给该产品的试用企业,进行外部企业用户早期体验,如图所示:
    pasted_image001.png

    由于团队使用「测试驱动开发」方法,因此开发人员编写所有的自动化单元测试用例与功能自动化测试用例,并负责维护它们。单元测试的行覆盖率在75%~80%波动。

    7.1.2 初始部署流水线

    GoCD团队遵守「持续集成六步提交法」(参见第9章),任何人提交代码后,立即自动触发一次部署流水线实例化,该部署流水线如图所示:
    pasted_image003.png

    第一个阶段是“提交构建”(自动触发,自动执行):包括7个并行自动化任务,分别是编译打包、代码规范静态扫描、5个不同的自动化单元/集成测试用例集合,使用自动触发机制。产品的自动化集成测试也使用单元测试框架编写,并在提交构建阶段与单元测试一起执行。由于GoCD支持多种操作系统,因此在这一阶段会同时构建生成对应不同操作系统的软件包,如deb文件、.exe文件、.zip文件等。这些安装文件生成以后,可供后续所有阶段使用。后续所有阶段不再重新编译打包。

    第二个阶段是“次级构建”(自动触发,自动执行):包括两个并行自动化功能测试集任务,分别运行于两类环境,即Windows/IE和Linux/Firefox浏览器,并且两个环境中所用的测试用例集相同,使用自动触发机制。

    第三个阶段开始,每个阶段都只有一个任务。

    第三个阶段是“UAT部署”(手工触发):将软件包部署到手工UAT环境(用户验收环境,User Acceptance Environment)

    第四个阶段是“UAT结果”(手工触发):测试人员“手工验证”完成后,将其标记为“验收通过”

    第五个阶段是“性能测试”(手工触发):就是做自动化性能测试。

    第六个阶段是“内部体验”:就是将Alpha版本部署到企业内部服务器,给内部其他团队试用。

    第七个阶段是“外部体验”:就是将Beta版本发给外部的企业用户体验。

    第八个阶段是“上传发布”:就是上传版本。将确定的商业发布版本上传到指定服务器,供用户登录产品网站自行下载。

    每次提交代码后,部署流水线的「提交构建」都会被自动触发。「提交构建」成功后会自动触发「次级构建」。提交构建阶段的7个任务中,执行时间最长的是单元测试,其中JavaScriptFu和Java单元测试用例与集成测试用例共有2350个,被分成5个测试集,最长的一个测试集持续时间约为15分钟。「次级构建」的两个并行任务,端到端功能验收测试140多个,执行时间最长需要约30分钟。

    第三个阶段(UAT部署)由测试工程师手工触发。测试工程师根据具体需求完成情况,在已经通过次级构建阶段的那些构建中,选择一个被测版本,向UAT环境部署软件包,用于手工验收测试。如果该版本通过了手工验收测试,则测试人员会手工触发第四个阶段,系统自动标记该版本为已测试通过版本。

    第五个阶段的「性能测试」也是手工触发。

    7.1.3 流水线执行状态解析

    开发人员每次提交代码都会触发一次部署流水线。测试人员只从通过「次级构建」的那些版本中选择包含新功能的版本进行UAT部署,并进行手工测试。验收结束后,触发“UAT结果”。团队会定期触发性能测试。这个部署流水线的运行实例示意图:
    pasted_image004.png

    团队开发工程师每人每天都会提交一次。因此,这个部署流水线每天都会启动多次。当然并不是每次提交的变更都会走到最后的「上传发布」。也不是每次提交都会走到「UAT部署」,因为开发人员并不是完成一个功能需求后才提交代码,而是只要做完一个开发任务,就可以提交。每个功能可能由多个开发任务组成,开发工程师需要确保即便提交了功能尚未开发完成的代码,也不会影响已开发完成的那些功能。

    7.2 部署流水线的设计与使用

    上面介绍的GoCD团队的部署流水线虽然是一个简单的部署流水线,但其设计及运作方式体现了团队使用部署流水线的设计原则与协作纪律。

    7.2.1 流水线的设计原则

    流水线的设计遵循以下原则:

     

    # 1. 一次构建,多次使用 #
    当某个部署流水线的一次运行实例构建出制品(如二进制软件包),如果需要,它就应该直接被用于该流水线后续阶段的构建过程,而不是在后续阶段中被再次重复构建。如果该部署流水线实例触发了下游流水线,并且下游流水线也使用该制品,那么,部署流水线工具应该确保它来自上游部署流水线的同一个实例。只有这样,我们对该制品的质量信心才能随着部署流水线的前进而增加。例如,在图7-4中,构建号为521的部署流水线实例中,其内部发布阶段所用的软件包就是同一构建号521的提交构建阶段生产出来的二进制产物。

     

     

    2008年GoCD的所有代码和构建安装脚本及配置信息都保存在同一个代码库中。每次触发部署流水线后,如果该实例后续各阶段需要前面阶段的构建产物,则均从构建产物仓库中取出,而非再次重新构建。

     

     

    即使有同一个部署流水线的多个实例正在同时运行,每个实例中后续各阶段所用的制品和源代码也应与同一部署流水线实例前面阶段的版本和出处保持一致。

     

     

    # 2. 与业务逻辑松耦合 #
    部署流水线工具应该与具体的部署构建业务相分离。我们不应该为了方便实现自动化,而将软件代码的构建和部署过程与所选择的部署流水线工具紧耦合。例如将一些软件部署时所用的脚本或所需信息由部署流水线平台保存。相反,我们应该提供单独的脚本,并将其放入该产品的代码仓库中。这样就可以轻松对这些脚本的修改进行跟踪和审核。也就是说,仅仅将部署流水线平台工具视为任务的调度者、执行者和记录者,它只需要知道部署流水线中各种任务触发与调度流程,而不必知道我们如何构建和部署软件。

     

     

    # 3. 并行化原则 #
    在部署流水线的设计中,我们也应该尽可能考虑并行化。在GoCD的部署流水线中,很多阶段都有并行任务。例如,提交构建阶段中有5个自动化测试任务,它们各自包含不同的测试用例,在不同的计算节点上运行。简而言之,应该尽早提供质量反馈信息,从而及时修正发现的问题。

     

     

    如果任何资源都是无限且免费使用的,那么我们希望每一次变更都会同时触发所有类型的测试,而且所有自动化测试用例都是并行执行。如此一来,整体的反馈时间就会大大缩短。

     

     

    # 4. 快速反馈优先 #
    在资源不足的情况下,部署流水线应该让那些提供快速反馈的任务尽早执行。例如GoCD的部署流水线中,单元测试放在了端到端功能自动化测试和性能自动化测试的前面。这是「反馈速度」与「反馈质量」之间的一种权衡。为了确保能够更快地得到反馈,我们可能会冒一些风险,优先执行那些运行速度快的自动化验证集合,而将那些运行较慢、消耗资源较多的自动化验证集合放在后面执行。

     

     

    # 5. 重要反馈优先 #
    对于反馈机制,不能只因其执行速度慢,就把它放在后面执行。这一条与前面看似矛盾,但在某些情况下却是必要的质量手段。

     

     

    例如,软件安装包的安装测试虽然运行速度比单元测试速度慢,但其反馈更加真实有价值,也应该放到流水线的前面阶段来执行,免所有的单元测试都通过以后才发现软件无法部署启动。

     

    7.2.2 团队的协作纪律

    团队协作有以下几条原则:

     

    # 1. 立即暂停原则 #
    「立即暂停原则」是指当部署流水线运行时,某个环节一旦出了问题导致执行失败,团队应该立即停下手中的任务,安排人员着手开始修复它,而不是放任不管。并且,在问题被修复之前,除因修复这个问题而提交代码以外,禁止其他人再向代码仓库提交新的代码变更。

     

     

    「立即暂停原则」是质量内建理念的具体体现,它借鉴丰田生产系统中的Stop the line原则。在丰田汽车生产线上,无论什么原因,只要操作者无法高质量地完成他的工作任务,他就可以拉下警示灯,让整个生产线停下来直到问题被解决(详见第4章的相关内容)。

     

     

    GoCD团队在实践部署流水线时,也采用了类似的做法。为了不妨碍团队其他成员提交代码,若提交构建阶段失败,提交者在10钟内无法修复问题的话,应该回滚代码。

     

     

    # 2. 安全审计原则 #
    角色协作时,如果要传递代码或软件包,那么它们应该来自「受控环境」。「受控环境」是指对该环境的一切操作均被审计,并且在该环境中的任何组件(如源代码、二进制代码包或者已安装的程序)均已通过审计。每个部署流水线实例(以唯一实例编号为标识)的任何环节均应使用部署流水线所提供的制品,其产生的任何产物也应该接受受控管理。

     

     

    例如,测试人员不应该私自拉取代码,自己手工构建软件包进行测试,也不应该接受开发人员通过各种方式(如即时通信工具)传递的软件包进行测试。每个角色对交付物进行验证时,都应该确保该交付物来自公共受信源,即统一的版本控制仓库或制品库。

     

     

    尽可能早地对部署流水线产物进行安全审计,包括在构建过程中所使用的第三方软件包以及企业内其他团队提供的类库或软件服务。

     

    7.3 部署流水线平台的构成

    企业或团队需要一个灵活且强大的工具平台,才能快速建立自己的部署流水线。那么,这个工具平台应该包含哪些部分,需要具备哪些能力,才能称为灵活且强大呢?接下来我们就讨论一下部署流水线平台工具链的主要组成部分,以及应当具备的基本能力。

    7.3.1 工具链总体架构

    部署流水线几乎贯穿于整个持续交付“8”字环中的验证环,涉及从代码提交到生产环境部署的整个流程。支撑部署流水线的平台通常由一系列工具组合而成。这个部署流水线工具体系主要分为3部分:

     

    第一部分是“唯一受信源”,它是部署流水线的基础,为部署流水线的运行提供原材料(即代码和第三方组件),也用于保存部署流水线运行过程中的产物。

     

     

    第二部分是“部署流水线工具”本身,负责各种任务的调度与结果统一展现,通过与其他专项工具或系统相互协作,完成整个交付流程。

     

     

    第三部分是“基础支撑服务层“,由多种专门工具组成,提供软件的构建、测试和部署等基础能力。

     

    pasted_image005.png

     

    # 1. 唯一受信源 #
    唯一受信源是团队日常工作过程中所需信息的权威仲裁者。在图中,底部的3个仓库(图中灰色方框)就是企业软件生产中的唯一受信源。当不同角色对某一信息产生质疑时,都应该能够追溯到唯一受信源,并以其为标准唯一受信源应该对信息之间的关联关系进行持久化。例如,制品库中的任意制品都可以在代码仓库源找到其对应的源代码。而代码仓库中的信息应该能在需求/缺陷管理平台中找到其对应的需求出处。

     

     

    对于任何环境中安装并运行的软件(甚至包括操作系统本身),我们都应能在制品库中找到与其对应的二进制安装包,以及它所依赖的其他二进制包。即使由于存储空间限制,也应该能够找到它的准确出处,如下载的URI。

     

     

    代码仓库中的代码也应该从需求/缺陷管理平台上找到相应的关联关系。也就是说,当不同角色对源代码是否满足需求验收条件产生分歧时,都应该可以在需求/缺陷管理平台上找到正确无二义性的答案

     

     

    # 2. 部署流水线平台 #
    根据产品团队在平台上对其自身产品流水线的定义,部署流水线平台通过一定的形式连接受信源与不同基础服务,并能够协调和调度不同任务,完成整个交付流程运作,并能够展示所有部署流水线进展与历史信息。

     

     

    # 3. 基础支撑服务层 #
    一个有历史的软件企业,很可能已经具备相应的基础服务(构建、测试、部署),并且根据原有职责的划分,这些基础服务已经分布于不同的职能部门,很可能还会有重复建设的问题。例如,测试部门管理着多套测试环境,运维部门则严格控制着生产环境。与此同时,每个职能部门都定义各自的验证体系与规范。例如,开发团队要求自测和代码规范;测试部门建立了自己使用的自动化测试体系,并建设自动化测试用例集,同时使用这种自动化测试体系来要求和验证开发团队的软件提测质量标准;运维部门也会建设运维内部的工具体系平台,达到提高运维效率、降低工作强度的目标。

     

     

    当我们的软件交付模式向持续交付模式改变时,要求这些服务管理能力必须与部署流水线形成连通,从而使持续交付模式的收益最大化。因此,我们需要对原有支撑平台进行一系列改造,以适应部署流水线模式。

     

    7.3.2 平台应当具备的基本能力

    部署流水线平台是团队多角色协作的中枢系统,其关注点是软件自身的价值流动效率,包含从代码提交到部署上线的全流程活动信息,能够谁确展现部署流水线各环节的状态,并在不增加团队负担的情况下自动收集各环节产生的衡量数据,并对价值流动的效率进行度量。例如,度量某一功能的开发周期时间(development cycle time),即从某一功能特性的第一行代码提交,到该功能特性发布到生产环境(或者交付到客户手中)的时间长度,如图所示:
    pasted_image006.png

    平台要具备可追溯能力:

     

    一、对事件的追溯能力,即部署流水线中发生的任何事件都应该能够追溯,包括:什么人?在什么时间执行了什么操作?为什么执行?以及操作过程与相应的脚本是什么?只有这样,才能支持良好的安全审计工作。另外,也有利于快速定位和缺陷分析,或者帮助诊断线上问题。

     

     

    二、对部署流水线产物的追溯能力。这些信息包括部署流水线的任意产物、其对应的源,构建时的脚本与环境,以及其所依赖的其他组件及相应的版本信息等。

     

    平台要具有对历史构建进行重建的能力。一个极端的场景就是当一个旧的软件版本出现了生产问题以后,即便在产品仓库中已经找不到对应的二进制安装包,只要「唯一受信源」的内容无损,部署流水线平台就可能马上找到当时的部署流水线配置,并再次重建这个旧版本。另外,我们经常会遇到需要重新执行部署流水线中个别环节的场景。例如,如果你怀疑某次的自动化测试失败是由于运行环境相关因素导致的,那么你可能就希望重新运行这个环节。

    7.3.3 工具链建设策略

    虽然「工具链总体架构」中以较高的抽象层次来描述持续交付部署流水线平台架构,但并不是说它是一个巨石架构。事实上,它由很多不同的工具与子系统整合而成。由于每个公司所使用的技术架构、开发语言、运维方式等都有所不同,因此所用的工具也会有所差异。

    对创业公司或「小型公司」来说,由于团队人员规模小,业务场景相对单一,软件架构不是特别复杂,因此通过相关领域的开源工具拼装就可以建立适合自己团队的部署流水线平台。

    对有一定历史的「中型公司」来说,遗留系统和代码增多,并有一定的工具基础,可能就需要自己开发一些工具实现一些定制化需求,从而解决某些领域的特定问题,以便提高管理效率。例如,当自动化测试用例数量较多时,就可能需要增加自动化测试用例的管理与分发系统。GoCD团队自动化测试用例较多后,就自行开发了一个自动化测试用例自动分组插件,由该插件自动将所有测试用例分配到不同任务里,并将这些任务分配到多个测试环境中并行执行。

    但对「大型公司」来说,其软件产品的运行环境更加复杂,各产品组件之间的关联关系更加复杂,数量规模也比较大,因此定制化需求会更高。为了发挥持续交付的威力,各类支撑服务的云化管理也成了必选项。例如,亚马逊、谷歌、Facebook Facebook、Netflix公司等都开发了自己的持续交付部署流水线平台工具链,甚至将其中的部分工具贡献给了开源社区。

    「部署流水线平台」本身只是用于软件部署流水线的定义与任务调度,以及当前状态的展现,具体任务的执行均应由基础支撑服务承担。而这些「基础支撑服务」之间也有相互的关联关系,一个系统的输入可能就是另一个系统的输出。下面让我们从部署流水线中流动的内容来理解这些系统之间的关联关系。

    7.4 基础支撑服务的云化

    业界领先互联网公司的服务端程序部署频率都非常快,如表所列。
    pasted_image007.png

    这些公司都建立了自己的云化基础支撑服务,以便支持公司内的大规模持续交付实践,并鼓励使用统一平台和工具,在提升交付效率的同时,也提高资源利用率,降低管理成本。

    有些公司认为,内部工具反正是给内部员工用的,只要能用就行,使用体验如何、是否需要统一都不重要。

    然而,在持续交付模式下,不好用的工具会对效率产生很大的影响。亚马逊早在2006年就认识到了这一点,在功能性和易用性方面,其公司内部的支撑工具平台在业界也可以算数一数二,让亚马逊电商这个超级庞大复杂的网站流畅运行。其所有工具在全公司范围内统一使用,更新及时且统一,有专门的团队负责开发和维护。

    7.4.1 基础支撑服务的协作过程解析

    为了能够更好地了解各类基础支撑服务系统的定位与职责,让我们先以一个简单部署流水线(如图所示)的运行示例来说明持续交付部署流水线平台工具链中各种基础支撑服务之间的协作过程:
    pasted_image008.png
    这个部署流水线只包含3个阶段,分别是“提交构建阶段”、“次级构建阶段”、“部署生产环境阶段”。其中,「提交构建阶段」包括构建打包、单元测试、代码规范检查;「次级构建阶段」包括端到端自动化测试;「部署生产环境阶段」就是直接将成功通过前两个阶段的代码部署到生产环境中。各阶段之间为自动触发关系,如图所示:
    pasted_image009.png
    平台中所有相关系统的协作信息都会经部署流水线平台展示出来。但是,为了让示意图更简洁,图中没有画出部署流水线平台的调度操作。粗线箭头的方向就是部署流水线的推进方向,带圈的序号表示部署流水线中不同的阶段活动,“0”表示各种基础环境的初始准备活动。所有配置与描述信息及代码都来自代码仓库,二进制包在第一次构建生成后就被放入二进制管理库,并被后续两个环节重复利用,不必再次构建生成。

     

    第0步:环境准备。运维部门提供的 「基础环境管理服务」从代码库中获取某产品基础环境要求后,自动为团队准备部署流水线运行所需要的基础环境。如,用于编译打包的构建环境、单元测试用的测试环境、手工验收测试的UAT环境,甚至生产环境。

     

     

    第1步:提交构建。提交构建阶段不但包括软件的编译打包,还包括基本的软件包验证,如单元测试、代码规范扫描、安装包验证测试等。因此, 「构建包管理服务」从代码库中取出源代码,在构建环境中构建打包后,放入制品库。然后,「部署包管理服务」根据流水线的定义将编译好的产物放到测试环境中。若测试过程需要一些特殊配置,则同时从源代码库中拉取测试部署配置。部署成功后,执行流水线指定的测试任务,最终返回测试是否成功的信号。

     

     

    第2步:次级构建。 「部署包管理服务」从制品库中取出第1步生成的二进制包,并从代码库中取出UAT部署配置信息,将二者结合后,部署到UAT环境,运行端到端自动化测试用例。结束后,返回是否成功的标记。

     

     

    第3步:部署生产环境。「部署包管理服务」从制品库中取出第1步生成的二进制包,并从代码库中取出生产部署配置信息,将二者结合后,部署到生产环境。

     

    # 最简流水线 — MVU每日50次部署 #
    IMVU是一个以3D人物为特性的陌生人社交与游戏应用创业公司,成立于2004年,截止到2009年,其开发工程师约为50人,但其每日生产部署次数达到50次。其部署流水线只有两个阶段,即“提交构建”和“生产环境部署”,并且都是自动触发。自动化测试套件在30~40台机器上并行执行,一共需要运行9分钟,生产环境部署需要6分钟。这两个步骤是连续进行的,这也意味着每9分钟就会向网站推送一次新的代码修订版本,即一个小时之内可以部署6次。平均每天部署50次之多。

    现在,我们已经了解了各基础支撑服务之间的协作过程,接下来我们分别讲解不同系统的逻辑结构。

    7.4.2 「构建管理服务」

    「构建管理服务」包括构建的「任务管理服务」、「调度服务」、「构建集群管理」、「构建执行器」,如图所示:
    pasted_image010.png

    「任务管理服务」包括两个子服务,一个是接收子服务,另一个是通知子服务:

     

    「接收服务」是指从开发者个人或者部署流水线(或持续集成服务器)向其发送构建任务请求,记录构建请求的相关信息(请求者、请求任务内容与类型),并将其加入待构建队列中。

     

     

    「通知服务」是指从已构建完成任务列表中取出相关信息,及时通知任务发起人有关构建任务的结果信息。

     

    「调度服务负责」从待构建任务列表中,根据一定的调度算法选择构建任务,并将其发送到相应的构建机上执行构建,例如C++代码的构建任务应该发送到有对应C++编译环境的机器上。

    「集群管理服务」负责对各类构建环境的管理,包括编译各类构建环境的建立与销毁、环境的状态管理(繁忙、空闲、失去连接)。

    「执行器」是执行构建任务的代理,在集群中有很多个执行器,甚至一个计算节点可以有多个执行器。每个执行器需要根据接收到的信息从对应的代码仓库URI检出代码,并根据要求进行编译构建。当构建任务完成之后,根据任务信息将指定的产物放到构建描述中指定的位置(通常为企业的制品库),并向调度服务汇报执行结果。「执行器」本身并不真正执行任务,而是调用专门的构建工具来执行,例如对应Java语言项目的构建工具有Ant Maven Gradle等。

    目前很多开源持续集成服务器(如nJenkins、GoCD)提供相应的调度管理功能,大部分情况下已能够满足中小企业需求。只有当企业比较大、构建任务比较多的情况下,才需要自己定制构建管理系统。您可能注意到,在上图中,构建请求既有来自部署流水线的请求,也有来自工程师的请求。这表示,该「构建管理服务」也支持工程师在未提交代码前,就利用它进行个人构建。这令工程师在本地编写代码期间,就可以利用这种强大的服务能力。在第16章的案例中,就使用了类似做法,用于提升持续集成六步提交法中个人构建的反馈速度。

    事实上,每种基础支撑服务都应该支持这种工作模式,从而最大化利用资源,提升质量反馈速度。

    7.4.3 「测试管理服务」

    「测试管理服务」包括「测试任务管理服务」、「测试用例调度服务」、「测试集群管理服务」。对于有大量自动化测试用例的公司,可能还要有「用例健康管理自动化服务」。

    「测试任务管理服务」与「构建任务管理服务」类似,也是用于接收任务和反馈任务执行结果,包括任务接收子服务和任务反馈子服务。

    「测试用例调度服务」负责根据一定的调度算法从「任务管理服务」中选择测试任务执行。这个调度服务有两种工作模式:一种是顺序执行测试用例,即将所有测试用例分配到符合测试条件的一台测试设备上执行;另一种是并行执行测试用例,即将测试用例分成数个子集,将其分发到多台测试设备上执行。

    「测试集群管理服务」与「构建管理服务」中的「集群管理服务」职责类似,包括测试环境的建立与销毁、测试环境的状态管理(繁忙、空闲、失去连接)。但是,其管理的集群类别会更多一些,如单元测试集群、功能测试集群、性能测试集群等。另外,由于每条产品线所需的测试环境可能存在差异,因此还需要按产品线再进行细分。

    对执行大量自动化测试用例来说,测试用例本身不稳定也会成为一个比较严重的问题。一些公司会建立「测试用例健康管理服务」。例如,按照一定的规则来自动判断某个用例是否为不稳定测试用例。若被判定为不稳定用例,就将其从健康测试用例集中移出,放入不稳定用例池。那么,当下次正常调用原测试用例集时,该不稳定测试用例会被自动排除在外。

    与此同时,「用例健康管理服务」还会对不稳定用例池中的用例以不同的策略进行检查(例如,将该用例在不同的网络节点、不同的节点资源的条件下,连续重复执行100次)如果仍旧有超过一定数量的失败次数,就认定该用例为非常不稳定用例,通知该测试用的归属团队进行处理,如图所示:
    pasted_image011.png

    7.4.4 「部署管理服务」

    我们常会遇到“软件在测试环境和预生产环境中的测试都没有问题,但是到了生产环境就会出错”的现象。其中一个主要原因就是:生产环境与测试环境的差异导致的。例如,十几年前,国内很多大型企业的生产环境中用的J2EE应用服务器都是商业软件。由于它们过于笨重,使得开发人员和测试人员在调试或测试期间都喜欢使用Tomcat作为服务器。而Tomcat对语法检查并不严格,但商业软件却常严格。因此,Web应用上线之后,总是有一些页面因Html标签不匹配而报错。这就是由于环境不一致导致的。

    另外,运维部门与产品研发团队之间的责任冲突由来已久。运维部门负责生产环境的稳定性,产品研发团队负责开发新功能。他们之间的接口是一个正式产品仓库。产品研发团队将验收合格的软件包放入这个正式产品仓库,即算完成了研发任务。接下来由运维部门从这个生产仓库中取出该软件包,并根据研发团队提供的上线部署清单,将其部署到生产环境中,如图所示:
    pasted_image012.png

    在持续交付工作模式下,所有人应该使用相同的工具集。任何人只要获得授权,他就可以一键发出部署指令,而「部署管理服务」接收到指令后,根据其中描述的不同环境部署配置信息,在指定的环境部署指定的软件包,这些环境包括开发测试环境、测试环境、预生产环境、生产环境。

    此时,「部署管理服务」负责接受来自不同方的部署请求,分别从制品库中获得指定软件包,从代码仓库中获取部署脚本与配置文件,并根据其中的部署描述,将该软件包分发到指定运行的节点上,将其正确安装后,启动服务。目前市场上已有很多部署管理工具,如Puppet/Ansible/SaltStack等,能够与部署流水线平台协同工作,完成环境部署任务。

    7.4.5 「基础环境管理服务」

    「基础环境管理服务」为上面3种管理服务(构建管理、测试管理、部署管理)提供环境准备、管理、监控服务。它会接受来自「构建管理服务」、「测试管理服务」、「部署管理服务」的请求,根据请求描述为其准备相应的基础环境,如图所示。「基础环境管理服务」接到3个前端服务的请求后,根据相关的信息,从代码仓库、镜像仓库、软件包仓库获取所需内容,经过加工后得到所需环境。将其放到对应的集群中,并发出通知即可。
    pasted_image013.png

    「基础环境管理服务」由技术运维团队负责,且不直接为研发团队提供服务。研发团队仅与构建服务、测试服务、部署服务打交道。

    随着 Docker技术的成熟,越来越多的公司开始使用这一技术,使得环境准备工作大为简化,可以直接将软件应用、配置、基础环境构建为一个Dockerf镜像,在部署时直接拉取并启动已经生成的Docker镜像即可。

    7.5 企业制品库的管理

    「企业制品库」是部署流水线工具链中的企业「唯一受信源」之一,也是企业信息安全管理中很重要的一个节点。只有通过安全审计的二进制软件包才能被纳入「企业制品库」,而且安全审计部门应当定期对其中存储的内容进行安全扫描,及时清理存在安全隐患的二进制软件包。

    7.5.1 制品库的分类

    制品库(artifact repository)的类型如表所示:
    pasted_image014.png

     

    # 1. 临时软件包库 A (企业内部) #
    企业内部的「临时软件包库」用于存储企业内部团队开发的通过部署流水线生成代码的所有软件包。例如,每次触发构建后产生的二进制包。该仓库中的二进制包不能被直接部署到生产环境。如果存在存储空间的限制问题,则临时软件包库的内容可以被清理。

     

     

    # 2. 正式软件包库 B (企业内部) #
    正式软件包库用于存储那些经过部署流水线验证,被确认能够且将要被发布到生产环境(或用户手中)的软件包。一旦经过确认,这些软件包就应该从临时软件产物库移动到正式产品库中。正式软件包库中所存储的软件包应该被一直保存, 直至退市

     

     

    # 3. 外部软件包库 #
    外部软件包库是指该软件包的源代码不是由企业自身团队管理和维护,但是企业在研发自己的软件产品过程中所用到的软件制品。这些软件制品由企业从互联网或第三方机构获得,并保存到外部软件包库中。

     

     

    外部软件包库中的存储形式可能包括3种:第一种是直接以二进制形式保存;第二种是以源代码副本的方式保存;第三种是以外部链接地址的形式保存,即仅记录该外部软件包的互联网下载地址,当有人需要时,通过该外部链接地址获取。

     

     

    在企业内部建立统一管理的外部软件包库,其目的有3个:一是方便快捷,在企业内部保存这些软件包后,内部人员可以比较方便从内网获取,而不需要连接外网;二是统一审计,内部团队仅从该库中获取外部软件包,容易管理控制,避免同一软件的多种版本却有很多种不同来源,也避免内部人员违规使用不安全的版本;三是保证安全,由于所需的外部软件包全部在这里,因此企业可以对其进行安全检查,以确保企业自己的软件产品不会因不安全的外部包而出现问题,即使市场上发现某个外部软件包存在安全隐患,也能够立即采取措施,通知内部团队打补丁或替换。

     

     

    # 4. 临时镜像库 C、正式镜像库 D、外部镜像库 Y #
    这3个镜像库与上面的软件包库的职责类似,只是保存的内容有所不同。我们可以将其中保存的镜像看作是一种特殊形态的软件包,使用相同方式进行管理即可。

     

    7.5.2 制品库的管理原则

    在企业制品库中,每一个制品都应该有唯一标识,并且连同其来源、组成部件以及用途等,一起保存为该制品的元信息。

    所有制品都可以追溯至源头,包括临时制品库中的制品。

    无论何时何地,通过制品的唯一标识,任何人从制品库获取的制品都是相同的。

    如果制品库中的制品本身被删除或丢失,那么企业可以根据其保留在制品库中的元信息描述,通过原有的部署流水线再次生成与原来相同的制品。

    7.6 多种多样的部署流水线

    由于软件产品所在行业不同,产品本身的形态不同,负责研发的团队人员组成不同,源代码的版本管理分支策略不同,使用的部署流水线形式也会各不相同。

    7.6.1 多组件的部署流水线

    如果一个软件产品由多个组件构建而成,每个组件均有独自的代码仓库,并且每个组件由一个单独的团队负责开发与维护,那么,整个产品的部署流水线的设计通常与图中相似。每个组件的部署流水线成功以后,都能触发下游的产品集成部署流水线。这个集成部署流水线的集成打包阶段将自动从企业软件包库中获取每个组件最近成功的软件包,对其进行产品集成打包,并触发集成部署流水线的后续阶段。
    pasted_image015.png

    7.6.2 个人部署流水线

    GoCD使用分布式版本管理工具Mecurial,每名工程师都创建了自己专属的部署流水线,用于个人在未推送代码到团队仓库之前的快速质量反馈。个人部署流水线并不会部署到团队共同拥有的环境中,而是仅覆盖个人开发环节,如图所示:
    pasted_image016.png

    每名工程师均通过部署流水线提供的模板功能克隆一份团队部署流水线,将其他阶段全部删除,仅保留前面两个阶段,即“提交构建”和“次级构建”的内容。令这个部署流水线监听工程师自己的代码仓库代码变化,并自动化触发。每当开发人员提交代码到个人仓库时,都会自动触发其个人专属的部署流水线。

    这样做的收益有以下3个:

     

    (1)该部署流水线与团队部署流水线共享构建和测试集群环境。由于这些环境是统一管理的,因此能够确保任何时刻,每个人的构建与自动化测试环境均与团队所属的环境一致。

     

     

    (2)保证每名工程师都能利用更强大的测试资源,加快个人验证的速度。

     

     

    (3)个人部署流水线运行的测试用例与团队部署流水线前两个阶段的验证集合相同,假如团队部署流水线出现构建失败,则容易定位问题,例如工程师遗漏文件未提交。

     

    7.6.3 部署流水线的不断演进

    如果你认为GoCD团队的部署流水线一直是本章开始介绍的那样,没有任何变化,你就错了。随时间的推移,部署流水线也应该随着产品的发展而演进。截止到2018年4月,GoCD的社区版本每个月发布一次正式版,其部署流水线设计也已经发生了很大的改变,如图所示:
    pasted_image017.png

    在图中“构建Linux包”这个部署流水线中,包含两个阶段:

     

    第一个阶段是“build-no_server”。在这个阶段,在这个阶段一共39个任务并行执行,既并行构建组成Server所需的多个Jar包,也并行执行Java测试用例和JavaScript单元测试用例。这体现了部署流水线“尽量并行化”原则。

     

     

    第二个阶段是“build-server”,使用经第一个阶段已初步验证通过的多个Jar包组装成Server包。

     

    在图中“Linux验收测试”这个部署流水线中,也包含两个阶段:

     

    第一个阶段是运行高优先级的功能测试;

     

     

    第二个阶段是对插件部分的自动化功能测试,这体现了部署流水线的“快速反馈优先”原则。

     

    而在后续的各类测试(如验收测试、回归测试或者功能测试)中,被测试的二进制包均来自前面各部署流水线的产出物,而且确保其使用同一源代码版本。

    在性能测试部署流水线中,共包含8个阶段它们分别是生成测试用脚本、准备测试环境、启动Server、启动Agent、配置用例、等待就绪、运行和停止。

    7.7 为开发者构建自助式工具

    在很多企业中,每个职能部门构建的工具都是为自己部门服务的。例如,测试团队开发的自动化测试集主要是为了减少测试人员的手工回归测试工作量,并且常常将其中一部分核心用例集作为提测的门槛,用于验收开发部门提交测试的软件包质量。

    另外,还有下面这类场景。在某大型互联网公司中,测试部门开发的测试平台只能在浏览器表单中编写测试用例,而且必须手动提交保存,一不小心就会丢失刚刚写到一半的测试用例。这样差的易用性怎么可能让习惯于本地集成开发环境的开发人员喜欢使用它呢?又怎么能让开发人员喜欢运行这些测试呢?运维部门更是为了生产环境的稳定性,建立起复杂的审批流程,一步步设卡。其负责开发的生产环境配置管理中心非常适合生产环境的管理,可能还非常强大。但是,如果为了践行持续交付中的环境一致性原则,让开发工程师和测试工程师也来使用这套系统,那么你一定会遇到很多困难,因为这样的系统并不是为日常调试和测试环境使用的。

    世界优秀的互联网公司却采用了另一种工具平台的设计理念,即“为开发工程师设计他们认为好用的工具”。在2006年,亚马逊公司的首席技术官 Werner VogelsXf对工程师提出“谁构建,谁运营”(you build it you run it)的工作指导原则。他说:

     

    无论从客户的角度还是从技术的角度来说,让开发工程师承担一部分技术运营的责任,都有利于大大提高服务质量。传统方式下,开发人员把软件隔“墙”(指部门墙)扔给运维工程师就完事儿不管了。在亚马逊,情况却不是这样的。谁构建,谁运营。这不但让开发人员每天都与他们自己的软件打交道,而且也让他们在日常工作中经常与客户联系。而客户反馈环对改进服务质量至关重要。

     

    这种方式要求创建强大的工具平台,能够很好地支持开发工程师做产品服务的技术运营工作。亚马逊也的确投入了大量的人力和物力,创建了一整套支撑系统。同时,也要求改变工具建设的思路,即所有DevOps的工具除审查性服务以外,都应该提供自助式服务。

    例如,在Facebook公司,开发人员可以通过他们内部平台看到自己的代码已经发布到哪个阶段,有多少用户在使用(如图7-16所示)。此时,开发工程师在不需要任何人帮助的情况下,就能够了解他的代码已经发布到哪个阶段了。
    pasted_image018.png

    在互联网电商公司Etsy,开发工程师可以查看到自上次生产部署以后,每次的代码变更数量,并且非常方便地查找代码差异,如图所示:
    pasted_image019.png

    综上所述,为了实现“谁构建,谁运营”,企业对于DevOpsI工具的建设,应该坚决从开发工程师的工作场景出发,为其构建强大的DevOps工具。不仅是生产环境的运维工具,而且是整个工作流程中的业务软件监控工程基础设施,它包括:

     

    基础的研发流程自助平台,如各类运行环境(构建、测试、生产)的自助平台

     

     

    数据自助平台(包括三层监测数据)

     

     

    用于业务快速试错的实验测量平台

     

     

    针对移动设备,建立用户触达平台

     

    当我们以这种思路来建设基础工具平台,我们的组织才能成为由多个真正自驱动、自服务的业务导向型全功能团队的学习型组织。

    7.8 小结

    我们在本章中介绍了团队设计和使用部署流水线的原则,以及企业定制开发私有部署流水线工具链的设计要点和工具平台的能力要求。

    同时,还对四大基础支撑服务(编译构建服务、自动化测试服务、部署管理服务及基础环境服务)的逻辑组件进行了简要介绍。

    同时,还介绍了三大受信源(需求管理仓库、源代码仓库和制品库)之间的关联关系,以及对它们的管理要求。

    本章中我们还列举了几个不同的产品场景,以及相应的部署流水线设计方案,供大家参考。要想让部署流水线发挥最大的作用,研发团队需要尽可能遵守以下5条原则:

     

    (1)任何软件包的取用皆须通过受控源,各角色之间禁止通过私有渠道(如电子邮件、即时通信工具等)获取。

     

     

    (2)尽可能将一切流程自动化,并持续优化执行时间。

     

     

    (3)每次提交都能够自动触发部署流水线。

     

     

    (4)尽可能地少用手动触发方式。

     

     

    (5)必须执行立即暂停原则(stop the line)

     

    展开全文
  • 文章目录Flink架构介绍基本架构安装部署文件准备及部署规划上传文件到服务器并解压修改配置文件分发安装文件到其他服务器启动集群访问webUI Flink架构介绍 Flink 的安装和部署主要分为本地(单机)模式和集群模式,...

    Flink架构介绍

    Flink 的安装和部署主要分为本地(单机)模式和集群模式,其中本地模式只需直接解压就可以使用,不以修改任何参数,一般在做一些简单测试的时候使用。本地模式在我们的课程里面不再赘述。集群模式包含:
    Standalone。
    Flink on Yarn。
    Mesos。
    Docker。
    Kubernetes。
    AWS。
    Goole Compute Engine。
    这里先部署Standalone 模式集群

    基本架构

    Flink 整个系统主要由两个组件组成,分别为 JobManager 和 TaskManager,Flink 架构也遵循 Master-Slave 架构设计原则,JobManager 为 Master 节点,TaskManager 为 Worker(Slave)节点。所有组件之间的通信都是借助于 Akka Framework,包括任务的状态以及Checkpoint 触发等信息,架构图如下:
    在这里插入图片描述
    客户端
    客户端负责将任务提交到集群,与 JobManager 构建 Akka 连接,然后将任务提交到JobManager,通过和 JobManager 之间进行交互获取任务执行状态。客户端提交任务可以采用 CLI 方式或者通过使用 Flink WebUI 提交,也可以在应用程序中指定 JobManager 的 RPC网络端口构建 ExecutionEnvironment 提交 Flink 应用
    JobManager
    JobManager 负责整个 Flink 集群任务的调度以及资源的管理,从客户端中获取提交的应用,然后根据集群中 TaskManager 上 TaskSlot 的使用情况,为提交的应用分配TaskSlots 资源并命令 TaskManger 启动应用。JobManager 相当于整个集群的 Master 节点,且整个集群中有且仅有一个活跃的 JobManager,负责整个集群的任务管理和资源管理。
    JobManager 和 TaskManager 之间通过 Actor System 进行通信,获取任务执行的情况并通过 Actor System 将执行情况发送给客户端。同时在任务执行过程中,Flink JobManager 会触发 Checkpoints 操作,每个 TaskManager 节点收到 Checkpoint触发指令后,完成 Checkpoint 操作,所有的 checkpoint 协调过程都是在 Flink JobManager中完成。当任务完成后,Flink 会将任务执行的信息反馈给客户端,并且释放掉 TaskManager中的资源以供下一次提交任务使用

    TaskManager
    TaskManager 相当于整个集群的 Slave 节点,负责具体的任务执行和对应任务在每个节点上的资源申请与管理。客户端通过将编写好的 Flink 应用编译打包,提交到 JobManager,然后 JobManager 会根据已注册 TaskManager 的资源情况,将任务分配给有资源的 TaskManager 节点,然后启动并运行任务。TaskManager 从 JobManager 接收需要部署的任务,然后使用 Slot 资源启动 Task,建立数据接入的网络连接,接收数据并开始数处理。同时 TaskManager 之间的数据交互都是通过数据流的方式进行的。
    Flink 的任务运行其实是采用多线程的方式,这和 MapReduce 多 JVM 进程的方式有很大的区别 Fink 能够极大提高 CPU 使用效率,在多个任务和 Task 之间通过 TaskSlot方式共享系统资源,每个 TaskManager 中通过管理多个 TaskSlot 资源池进行对资源进行有效管理

    安装部署

    文件准备及部署规划

    我们准备三台服务器 server01、server02、server03
    server01作为 jobManager(master) server01、server02、server03 作为TaskManager(slave) server01既作为master又作为一个slave
    下载安装文件 flink-1.9.1-bin-scala_2.12.tgz,下载地址:https://download.csdn.net/download/zhangxm_qz/12732760

    上传文件到服务器并解压

    将文件flink-1.9.1-bin-scala_2.12.tgz 上传到server01服务器 /opt/apps目录
    并解压如下:

    [root@server01 apps]# ll
    total 750912
    lrwxrwxrwx.  1 root  root         11 Jun 14 22:54 flink -> flink-1.9.1
    drwxr-xr-x. 10   502 games       156 Sep 30  2019 flink-1.9.1
    -rw-r--r--.  1 root  root  246364329 Aug 20  2020 flink-1.9.1-bin-scala_2.12.tgz
    

    修改配置文件

    进入flink 下 conf 目录 修改配置文件 flink-conf.yaml ,修改如下两项

    jobmanager.rpc.address: server01   # 修改master节点服务器 我这里是 server01 做master
    taskmanager.numberOfTaskSlots: 3 # taskmanager.numberOfTaskSlot 参数默认值为 1,修改成 3。表示数每一个TaskManager 上有 3 个 Slot
    

    修改 slaves 文件内容如下:

    "flink-conf.yaml" 259L, 10326C written
    [root@server01 conf]# vi slaves
    server01
    server02
    server03
    ~
    

    分发安装文件到其他服务器

    将修改后的flink目录复制到 server02 和 server03 两台服务器,命令如下:

    [root@server01 apps]# scp -r flink-1.9.1  root@server02:/opt/apps 
    [root@server01 apps]# scp -r flink-1.9.1  root@server03:/opt/apps 
    

    启动集群

    执行bin下的 start-cluster.sh 命令启动集群如下:

    [root@server01 flink]# bin/start-cluster.sh 
    Starting cluster.
    Starting standalonesession daemon on host server01.
    Starting taskexecutor daemon on host server01.
    Starting taskexecutor daemon on host server02.
    Starting taskexecutor daemon on host server03.
    

    访问webUI

    启动成功后访问 http://server01:8081 可以访问到flinkwebUI如下:
    在这里插入图片描述

    上传任务到集群

    开发实例程序WordCount

    代码如下

    package com.test.flink.wc
    
    import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment
    
    object StreamWordCount {
      def main(args: Array[String]): Unit = {
        val streamEnv: StreamExecutionEnvironment =
          StreamExecutionEnvironment.getExecutionEnvironment
        //导入隐式转换,建议写在这里,可以防止IDEA代码提示出错的问题
        import org.apache.flink.streaming.api.scala._
        //读取数据
        val stream: DataStream[String] = streamEnv.socketTextStream("server01",8888)
        //转换计算
        val result: DataStream[(String, Int)] = stream.flatMap(_.split(","))
          .map((_, 1))
          .keyBy(0)
          .sum(1)
        //打印结果到控制台
        result.print()
        //启动流式处理,如果没有该行代码上面的程序不会运行
        streamEnv.execute("wordcount")
      }
    }
    

    通过命令上传任务到Flink集群

    将程序jar包上传到server01位置如下:

    [root@server01 flink]# ll appjars
    total 24
    -rw-r--r--. 1 root root 22361 Aug 20  2020 test-1.0-SNAPSHOT.jar
    

    执行命令 上传任务

    由于程序中需要连接server01 的 8888端口,因此要先通过如下命令 开启数据发送程序,否则任务会由于连接失败而导致启动失败
    server01上执行如下命令(如果提示命令不存在 执行 yum install -y nc 进行安装):

    [root@server01 flink]# nc -lk 8888
    

    上传程序包到flink引擎

    [root@server01 flink]# bin/flink run -d -c com.test.flink.wc.StreamWordCount ./appjars/test-1.0-SNAPSHOT.jar 
    Starting execution of program
    Job has been submitted with JobID 75fd7304caa7d429b343b77dff4ce65d
    

    通过在终端中发送字符串给处理程序,可以在webUI中看到任务的执行情况

    [root@server01 flink]# nc -lk 8888
    a
    a
    a
    a
    a
    a
    a
    a
    

    在这里插入图片描述
    在这里插入图片描述

    通过webUI上传任务到Flink集群

    也可以通过webUI界面上传任务程序

    在这里插入图片描述

    展开全文
  • 允许进行适当的构建步骤,从而在开发和部署过程中自动执行构建任务 适当地管理插件和主题,使其受到版本控制并易于更新 管理发布的创建,包括回滚 自动生成诸如新应用程序和新主题之类的常用对象 Whippet可以管理...
  • 流水线的设计原则 一次构建,多次使用:当部署流水线的一次运行实例构建出制品,如果需要,它就应该直接被用于该流水线后续阶段的构建过程,而不是在后续阶段中被再次重复构建 与业务逻辑松耦合:部署流水线应该与...
  • 导读:本文是对GaussDB 200产品的整体描述,包含产品架构、数据流程、组网方案、服务部署原则、企业级增强特性等。 产品描述 GaussDB 200是企业级的大规模并行处理关系型数据库。GaussDB 200采用MPP(Massively ...
  • 它处理配置管理,应用程序部署,云配置,临时任务执行和多节点编排-包括琐碎的事情。Ansible Ansible是一款非常简单的IT自动化系统。 它处理配置管理,应用程序部署,云配置,临时任务执行,网络自动化和多节点编排...
  • XXL-Job分布式任务调度

    千次阅读 2020-12-23 20:41:05
    分布式情况下定时任务会出现哪些问题?分布式集群的情况下,怎么保证定时任务不被重复执行分布式定时任务解决方案①使用zookeeper实现分布式锁 缺点(需要创建临时节点、和事件通知不易于扩展)②使用配置文件做一个...
  • JAVA项目如何通过Docker实现持续部署

    千次阅读 2021-03-02 11:15:39
    本篇实操性的案例讲解——JAVA项目如何通过Docker实现持续部署(只需简单四步),即:开发通过git push上传代码,经Git和Jenkins配合,自动完成程序部署、发布,全程无需运维人员参与。这是一种真正的容器级的实现,这...
  • 要缩小规模,请指示实例在完成当前任务后终止。 修复:要“修复”组件的失败实例,只需尽可能优雅地终止它并启动替换。 回滚:如果部署不好,无状态组件更容易回滚,因为您可以终止它们并启动旧版本的实例。 跨负载...
  • 云效应用交付平台 AppStack是一款开发者友好的、以应用为核心的云原生应用交付平台,提供应用编排、环境管理、部署运维、资源管理、应用发布等一站式能力,帮助企业建立应用持续交付整体解决方案,加速企业云原生与 ...
  • 分布式定时任务

    千次阅读 2019-08-02 16:46:10
    分布式定时任务 1,什么是分布式定时任务;2,为什么要采用分布式定时任务;3,怎么样设计实现一个分布式定时任务;4,当前比较流行的分布式定时任务框架; 1,什么是分布式定时任务: 首先,我们要了解计划...
  • 自动化构建部署(CICD)

    千次阅读 2020-12-23 01:53:35
    项目管理之自动化构建部署(CICD) 理解敏捷项目管理 掌握ones使用 掌握GitLab使用 掌握Jenkins自动化项目构建与部署 1. 研发管理概述 1.1.概念 ​研发管理就是在研发体系结构设计的基础之上,借助信息平台对研发...
  • 云原生应用的十大设计原则

    万次阅读 2021-03-10 22:19:12
    云应用程序的十大设计原则 自我修复设计 实现全面冗余 尽量减少协调 横向扩展设计 通过分区解决限制 运营设计 使用托管服务 使用最佳的数据存储完成作业 演变设计 根据业务需求构建 越来越多的企业选择...
  • 一文看懂RPA的3种部署模式

    千次阅读 2019-09-02 14:27:44
    RPA产品的部署模式大致分为3种类型:开发型、本地部署型(On-premises型)、云型(SaaS型)。 开发型开发型RPA使用通用编程语言和API自动执行。API即应用程序编程接口,可以轻松完成最初需要复杂编程的进程。通过...
  • AD域详细介绍和部署

    千次阅读 2020-12-10 11:16:12
    文章目录网络基础域一、概述二、部署域模式1. 部署活动目录(AD)2. 客户机加入域 网络基础 域 一、概述 计算机内网模式 工作组 在工作组模式的网络中,各服务器都是独立的,而且各服务器中的帐户和资源也是各自...
  • kubesphere集群部署

    千次阅读 2020-07-28 19:59:38
    支持从已有的代码仓库中获取代码,或通过上传制品的方式,自动构建镜像和完成部署,并将镜像推送至目标仓库,每次构建镜像和服务的过程将以任务 (Job) 的方式去完成。 多维度监控 KubeSphere 全监控运维功能可通过...
  • 前端巨型项目拆分与整合原则方案

    千次阅读 2021-12-04 14:33:47
    前端项目组织原则 微服务下的前端项目 ​ 随着微服务与容器化技术的兴起,web项目变得不再像原来的单体应用项目那样庞大,通常以单一服务功能的实现为原则,服务端应用被拆分成了一个个的互不依赖的小型项目。被拆分...
  • Flink 的安装和部署 Flink 的安装和部署主要分为本地(单机)模式和集群模式,其中本地模式只需直接解压就可以使用,不以修改任何参数,一般在做一些简单测试的时候使用。本地模式在我们的课程里面不再赘述。集群...
  • 因此如果我们需要使用WAF完成安全合规的任务,或者做误杀排查工作,就必须要启用WAF日志功能。 WAF日志搜集和处理有多种选择。我们这里先介绍成本最低廉的S3日志存储方式。这种方法适用于仅把WAF日志作为访问记录...
  • Flink的安装与部署

    千次阅读 2020-06-20 17:32:23
      Flink 的安装和部署主要分为本地(单机)模式和集群模式,其中本地模式只需直接解压就可以使用,不以修改任何参数,一般在做一些简单测试的时候使用。本地模式在本文不再赘述。集群模式包含: Standalone。 ...
  • spring schedule 配置多任务动态 cron 【增删启停】

    千次阅读 多人点赞 2021-03-13 21:47:38
    开发原则是: 在满足项目需求的情况下,尽量少的依赖其它框架,避免项目过于臃肿和复杂。主要研究spring 自带的schedule。 常见的任务调度方式 单机部署模式 Timer: jdk中自带的一个定时调度类,可以简单的实现按...
  • jenkins 部署项目的一点建议

    千次阅读 2016-12-25 10:29:17
    1.部署 web 项目可以使用插件: Deploy to Container Plugin 存在的问题: 1.因为代码问题而导致内存溢出的情况。 2.因为代码问题导致 tomcat 进程无法被杀死,而原有的进程没有被删除,新的进程又产生,而导致...
  • 由于最近爬虫用的服务器到期,需要换到新服务器重新部署,所以干脆把整个模块封装入Docker,以便后续能够方便快速的进行爬虫的部署。同时,由于我的Scrapy整合了redis,能够支持分布式爬取,Docker化后也更方便进行...
  • ...这是我尝试用流程化的思路进行项目开发实现的记录。 至于为什么不适用市面上现有且...近期间歇性踌躇满志的对博客功能点进行升级、优化,该项目分为后台nestjs项目、前台nuxtjs、管理系统vue.js,目前部署方式采用D
  • 集群部署方案

    千次阅读 2018-07-10 13:35:00
    集群部署方案目录[显示]第一章 EZSonar高可用集群1.1 集群基本概念简单的说,集群(cluster)就是一组计算机,它们作为一个整体向用户提供一组网络资源。这些单个的计算机系统就是集群的节点(node)。一个理想的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 64,895
精华内容 25,958
关键字:

任务部署原则