管道最佳实践

本指南为管道提供了一小部分最佳实践,并指出了最常见的错误。

目标是将管道作者和维持者指向导致更好的管道执行,并远离陷阱的模式,否则他们可能不知道。本指南并不意味着是所有可能的管道最佳实践的详尽列表,而是提供许多有用的特定示例,可用于跟踪常见实践。用它作为“做到这一点”,而不是一个令人难以置信的详细的“how-to”。

本指南由区域,指南,然后列出特定示例排列。

一般的

确保在流水线中使用Groovy代码作为胶水

使用Groovy代码连接一组操作,而不是将其作为管道的主要功能。换句话说,不要依赖管道功能(Groovy或管道步骤)来推动构建过程,而是使用单个步骤(例如上海)来完成构建的多个部分。管道,随着其复杂性的增加(Groovy代码的数量、使用的步骤的数量等),需要更多的控制器资源(CPU、内存、存储)。可以将Pipeline看作是完成构建的工具,而不是构建的核心。

示例:使用单个Maven构建步骤通过其构建/测试/部署进程来驱动构建。

在管道中避免复杂的Groovy代码

对于管道,Groovy代码总是在控制器上执行意味着使用控制器资源(内存和CPU)。因此,减少管道执行的Groovy代码(包括在管道中导入的类上调用的任何方法)是非常重要的。下面是最常见的避免使用的Groovy方法示例:

  1. JSonslurper:该函数(以及其他类似的函数,如XmlSlurper或readFile)可用于从磁盘上的文件中读取数据,将该文件中的数据解析为JSON对象,并使用命令(如JsonSlurper(). parsetext (readFile("$LOCAL_FILE"))将该对象注入到管道中。该命令将本地文件加载到控制器的内存中两次,如果文件非常大或命令经常执行,将需要大量内存。

    1. 解决方案:而不是使用JSonslurper,使用shell步骤并返回标准。这个shell看起来像这样:def JsonReturn = sh label: ", returnStdout: true, script: 'echo "$LOCAL_FILE"| jq "$PARSING_QUERY"'.这将使用代理资源来读取该文件,$ parsing_query将帮助将文件解析为较小的尺寸。

  2. httprequest:通常该命令用于从外部源获取数据并将其存储在变量中。这种做法并不理想,因为不仅该请求直接来自控制器(如果控制器没有加载证书,那么对于HTTPS请求可能会给出不正确的结果),而且对该请求的响应会存储两次。

    1. 解决方案:使用shell步骤执行来自代理的HTTP请求,例如使用如下工具旋度或者w, 作为适当的。如果结果必须在管道中稍后,请尝试尽可能多地过滤代理侧的结果,以便仅将最小所需信息传输回Jenkins控制器。必威国际有限公司

减少类似管道步骤的重复

尽可能经常地将管道步骤合并为单个步骤,以减少管道执行引擎本身造成的开销。例如,如果连续运行三个shell步骤,则必须启动和停止每一个步骤,这就需要创建和清理代理和控制器上的连接和资源。但是,如果将所有命令放入单个shell步骤中,则只需要启动和停止单个步骤。

例:与其创建一系列回声或者上海步骤,将它们组合成单个步骤或脚本。

避免呼叫必威国际有限公司jenkins.getInstance.

使用Jenk必威国际有限公司ins.Instance或其访问者方法在管道或共享库中,指示该管道/共享库中的代码误用。使用jenk必威国际有限公司ins apis从一个不适合的共享库意味着共享库是共享库和某种jenkins插件。与Jenkins API从管道交互时,您需要非常小心,以避免严重的安全性和性能问题。必威国际有限公司如果您必须在构建中使用Jenki必威国际有限公司ns API,则建议的方法是在Java中创建一个最小的插件,该插件在jenkins API周围实现安全包装器,您要使用管道的步骤API访问。使用Jenk必威国际有限公司ins Apis从沙盒的Jenkinsfile直接意味着您可能不得不多白名单方法,允许任何可以修改管道的人绕过沙箱保护,这是一个重要的安全风险。白名单方法作为系统用户运行,具有整体管理员权限,这可能导致具有比预期的更高权限的开发人员。

解决方案:最佳解决方案是在所做的呼叫周围工作,但如果必须完成,那么更好地实现能够收集所需数据的Jenkins插件。必威国际有限公司

使用共享库

不要覆盖内置管道步骤

尽可能远离定制/覆盖管道步骤。覆盖内置管道步骤是使用共享库来覆盖标准管道API的过程上海或者暂停.此过程是危险的,因为管道API可以随时改变,导致自定义代码破坏或给出不同的结果而不是预期的。当自定义代码因管道API而发生变化时,难以解决,因为即使自定义代码没有改变,也可能在API更新后可能无法运行。因此,即使自定义代码没有改变,也不意味着在API更新之后它将继续工作。最后,由于在整个管道中使用这些步骤,如果某些东西被编码错误/效率低下,结果可能对Jenkins造成灾难性。必威国际有限公司

避免大型全局变量声明文件

拥有较大的变量声明文件可能需要大量内存,但收效甚微,因为无论是否需要变量,都会为每个Pipeline加载文件。建议创建只包含与当前执行相关的变量的小变量文件。

避免非常大的共享库

在流水线中使用大型共享库需要在流水线启动和加载当前正在执行的每个作业的相同共享库之前检查一个非常大的文件,这可能导致内存开销和较慢的执行时间。

回答额外的常见问题解答

处理管道中的并发性

尽量不要在多个管道执行或多个不同的管道上共享工作空间。这种做法可能导致每个管道或工作区重命名内意外的文件修改。

理想情况下,共享卷/磁盘安装在单独的位置,并且文件将从该位置复制到当前工作区。然后,当构建完成时,如果完成更新,可以复制文件。

构建不同的容器,从零开始创建所需的资源(云类型代理在这方面工作得很好)。构建这些容器将确保构建过程在每次开始时就开始,并且易于重复。如果构建容器不能工作,在管道上禁用并发,或者使用Lockable Resources Plugin在工作空间运行时锁定它,这样当它被锁定时其他构建就不能使用它了。警告:禁用并发或锁定工作区运行时会导致管道当这些资源被任意锁定时等待资源时被阻止。

此外,请注意,这两种方法都具有比每个作业的独特资源的构建结果较慢

避免notserializableException.

管道代码是CPS转换,使得管道能够在Jenkins重新启动后恢复。必威国际有限公司也就是说,当管道运行脚本时,可以关闭Jenkins或丢失与代理的连接。必威国际有限公司当它恢复后,jenkins记得它在做什么必威国际有限公司,你的管道脚本恢复执行,就好像它永远不会中断一样。一种称为“连续的传递方式(CPS)“执行在恢复管道中发挥着关键作用。但是,由于CPS转换,某些Groovy表达式无法正常工作。

在引擎盖下,CPS依赖于能够将管道的当前状态序列以及剩余的管道序列。这意味着在不序列化的管道中使用对象将触发anotserializableException.当管道试图持久化其状态时抛出。

看到管道CPS方法不匹配有关更多细节和可能存在问题的一些示例。

下面将涵盖确保管道可以按预期运行的技术。

确保持久化变量是可序列化的

在序列化期间捕获局部变量作为管道状态的一部分。这意味着在管道执行期间存储在变量中的非序列化对象将导致notserializableException.被抛出。

不将非序列化对象赋值给变量

一种利用非序列化对象的一个​​策略始终推断它们的值“即时”,而不是计算它们的值并将该值存储在变量中。

使用@noncps.

如有必要,您可以使用@noncps.注释为禁用CPS转换的特定方法,如果它是CPS转换的那样,其身体不会正确执行。只要意识到这也意味着Groovy函数必须完全重新启动,因为它没有转换。

异步管道步骤(例如上海睡眠)总是经过cps转换的,并且不能在带注释的方法中使用@noncps..通常,您应该避免使用管道步骤注释的方法内@noncps.

管道耐用性

值得注意的是,改变管道的耐用性可能导致notserializableException.而不是被扔到本该在的地方。这是因为通过PERFORMANCE_OPTIMIZED降低管道的持久性意味着管道的当前状态被持久保存的频率大大降低了。因此,管道永远不会尝试序列化非序列化的值,因此不会引发异常。

此注释的存在是为了告知用户导致此行为的根本原因。不建议将Pipeline的持久性设置设置为性能优化,以避免序列化问题。



此页面有用吗?

请通过此提交您关于此页面的反馈快速形式

或者,如果您不希望填写快速表格,您可以简单地指示您是否找到此页面有用吗?


查看现有的反馈这里