在生产中配置和使用AWS EKS

到现在,我们已经完成了向Amazon EKS ( 工作地点)的迁移,并且集群已经投入生产。 过去,我已经写了一些要点的简短摘要,您可以在这里找到。 当系统正在为实际流量提供服务时,我有了一些额外的信心,因此我决定返回此过程,以获取更具体和透彻的步骤清单和一系列注意事项。 显然,那里有多家公司一直在使用Amazon的Kubernetes服务,因此,本文旨在作为EKS迁移和采用案例的另一个参考点。

平台–网络平台

整个平台是一个为网站(电子商店)提供动力的平台,EKS集群以主动-主动模式运行,这意味着它们共享负载并根据加权负载平衡进行相应利用。 集群负载均衡-如果我们可以调用它的方法是在`进行边缘 ',所以暂时没有kubernetes联盟的概念。 就CPU而言,累计计算总量约为400-600个内核(取决于负载)。 支持该平台的微服务的总量在20到30之间,主要是Java有效负载和混合的节点(基于Js Node)。 该平台处于扩展状态,通过向难题添加更多片段以覆盖更多功能或弃用旧版/旧版系统,系统的熵在不断增加。

该网站每天提供独特的页面浏览量,该页面的浏览量范围为每天50万(欧洲,英国和亚太地区的15个市场),由于业务性质的原因,流量变化很大。 与不忙碌的一天相比,在艺术家待售或宣布新活动的日子里,访问量的激增导致独特页面渲染多出50-70%。 该平台也是不可预见的(恶意的)流量的目标和目标,它会刮擦整个公共API或攻击某些区域。

支持上述站点的基础架构应提供:

  • 弹性–根据需求收缩和增长–还提供了基于手动干预的能力,可以在我们事先知道何时会有激增的情况下进行。
  • 稳定性–始终可用,始终为页面和API响应提供服务
  • 容忍故障,通常要考虑到不同AWS AZ或整个区域的潜在故障。
  • 成本效益,随着时间的推移降低运营成本(AWS使用成本)
  • 安全
  • 对开发团队公平开放。 对于一个单独的团队来说,部署和理解kubernetes是开发团队关注的问题,而不是一个奇特的操作。

Kubernetes

Kubernetes已经成为我们目标部署平台超过2年了。 唯一随时间变化的是用于旋转新集群的不同工具。 我们已经拥有运营经验,并且一直以来,使用不同版本和功能的kubernetes都面临着一些挑战。 尽管存在挑战,但采用kubernetes被认为是成功的。 我们从未遇到过完全的中断,集群和所实施​​的概念也从未偏离手册中的内容(我们确实获得了弹性,稳定性,对部署过程的控制,最后但并非最不重要的一点–采用kubernetes加快了生产和交付NET的道路。商业价值。

就我们而言,开发人员从未与基础架构建立如此紧密的关系。 这种关系随着时间的推移而发展,并有助于提高人们对两个分离的关注点(编写软件的一方和在生产环境中操作和运行代码的一方)之间的认识。 最大的胜利主要是使开发人员更加了解基础架构的过程–缓慢地导致软件开发方式的潜在改进。 显然,相同的概念适用于任何团队和以云为中心的计划。 对基础结构的抽象化担忧降低了将传统开发人员转变为与运营完全脱节的障碍。 在那之后,就更深入地挖掘细节并明显地更多地了解基础架构而言,天空是极限。 这个过程需要时间和愿意改变观念的人们。

EKS为​​什么呢?

第一个明显的答案是因为AWS。 如果AWS是您的主要云,那么您将不断尝试尽可能多地利用云的功能,除非您采用不同的方式(例如,您希望通过混合使用不同的解决方案来进行云自治对冲,或者您认为可以在如果您负担得起,则可以拥有)。 EKS与AWS世界的集成已经足够成熟,您可以在其中运行相当原始的Kubernetes设置(而不是愚蠢的),而在幕后则可以利用AWS / ESK提供的与其他AWS生态系统集成的功能。

第二个答案是集群升级和安全补丁。 在发布EKS之前,我们不得不与不同工具(安装程序)的细节打交道。 在许多情况下,尤其是如果您的云设置具有自定义配置,试图使具有自定义网络或特殊VPC语义的环境中的群集变得越来越具有挑战性。 尽管过去进行集群更新,但涉及的风险越来越大,我们很快面临许多人和公司所面临的通常的困境(许多人不愿承认)–如果要升级现有集群,那就抛弃它并创建一个新的。 在作为解决方案的同时,这还涉及我们许多额外的工作,需要在新集群之上重新建立我们的平台。 显然,对于我们来说,许多平台迁移更加自动化需要做更多的工作。

第三个答案是EKS的更新策略。 如果您想按照EKS的规则玩游戏,则可以在较小的修订版本上自动升级主服务器,然后轻轻地推动您将集群升级到主要版本。 尽管仍然可以选择不做任何事情,但是该模型鼓励并加速了针对群集更新的自动化开发。 同样,这也是信心问题–升级和控制升级过程的频率越高,您就越有信心。

团队

2个人。 此设置上最重要的不是团队规模(2),而是技能的组合。 由于我们希望尽可能地接近开发人员的实际需求,从而最终为企业服务,因此我们意识到,这样的变化不可能在技能真空中发生。 您不能仅以开发人员身份配置和旋转基础架构思维,而同时不能构建仅由开发人员考虑操作方面的基础架构,开发人员将在其中演化和创建平台。 当开发人员对基础架构安全性或性能等方面的知识不够充分或对开发人员进行全面监控时,您需要同时具备这两项功能,而Ops的技能和专业知识将提供上述所有内容并同时进行教育,以便下次获得改进。

另一方面,当开发人员不容易使用基础结构,无法访问或存在看不见的障碍时,会使软件制造商与生产系统脱离连接–在这里,开发人员的观点可以帮助找到中间立场。 与其他功能相比,迭代和渐进式更改是软件开发人员通常做得更好的一个领域。

这是当前市场上双方都争夺控制权和影响力的最忌讳的事物之一。 我不确定DevOps的正确定义是什么,但是在我看来,这次旅程是DevOps旅程,我希望我在整个职业生涯中都能在其他地方体验到它。 在团队中结合技能并鼓励知识流动,而不是引入组织障碍或隔壁。

侧面关注– EKS工人网络

由于这是我们第一次采用EKS,因此我们决定最安全,更灵活的方法是完全采用AWS CNI网络模型。 与我们以前专注于覆盖网络的集群相比,这是一个巨大的变化。 由于Pod具有可路由的IP,因此现在更容易进行故障排除和发现网络问题。 看这里 。 遵循原始方法会引起对VPC CDIR大小的担忧,我们选择了一种干净的解决方案,将群集与共享的VPC隔离开来,并启动范围相当广的全新,干净的新VPC。

如果次要热点IP开始用尽,或者您的工作人员能力有限(ENI数量),请参见此处 。 也很好看
在这里 。

工具类

我们的主要目标不是破坏现有开发团队的工作流程和语义,而是使我们的EKS集群看起来与现有集群相同。 这并不意味着我们现有的设置是完美的,或者我们不想进行现代化。 同样,第一要务是集群应满足在其上部署服务的团队的需求,而不是我们一直尝试新技术的冲动。 显然,有很多东西是新的和不同的,但是应该迭代地介绍配置更改和工具更改。 基本流程如下:

  1. 创建集群并建立集群
  2. 引入或多或少相同的语义和配置-使团队可以轻松移动其有效载荷(应用程序)
  3. 稳定
  4. 逐步教育并开始在群集之上进行更多更改,这些更改如新策略,新部署方式或实施新规则。 首要任务是开发人员的生产率,同时还要兼顾良好实践和明显保持简单

为了设置/升级和配置集群,我们提出了使用以下工具的解决方案

  • 地形 (大师和工人/ asg)
  • 基于EKS参考支持新AMI的打包程序
  • 在terraform生命周期中进行bash(通常作为运行后步骤调用)
  • 头盔/ kubectl

工作流程如下:

  • 如果要烘焙新的辅助AMI,请使用Packer(如果需要,否则请跳过)
  • 计划并应用用于控制母版和工作人员自动缩放组,IAM和其他详细信息状态的Terraform堆栈,从而形成集群。 即使现在在这里找到的参考EKS模型非常可靠,我们也有自己的terraform模块。
  • 集群形成后开始调用kubectl或helm,以安装一些基本服务。

在集群顶部安装服务

一旦在AWS上建立了集群,这意味着主服务器可以与各种工作程序节点进行对话,我们将在顶部部署并配置以下组件。

  1. 安装头盔(翻土机)
  2. 根据我们的RBAC / AWS角色配置aws-auth以启用对用户的访问– kubectl补丁
  3. 安装指标服务器(修改后的头盔图)
  4. 安装aws cluster-autoscaler (头盔图)
  5. 安装kubernetes-dashboard(舵图)
  6. 安装Prometheus / Kube-State-Metrics(Helm Chart)
  7. 安装流利的通配符集(已预先配置为将日志发送到ES)(头盔图)
  8. 安装或修改适用于kube-proxy的正确版本,请参见此处
  9. 为aws-cni安装或修改正确的版本,请参见此处
  10. 为CoreDNS安装修改正确的版本+扩大coreDNS
  11. 扩大核心DNS
  12. 创建或更新名称空间
  13. 在某些情况下安装–大使-proxy –混合Ingress。
  14. 使用机密填充群集和特定的名称空间-已存储在Vault中

总体而言,整个业务流程由Terraform控制。 集群的结构更改(例如,工作节点的大小,缩放语义等)在terraform级别上更新。 在供应期间,上面指示的某些Helm图表由terraform动态地模板化-因此所应用的Helm图表已经同步并且具有正确的值。 这个想法是,terraform vars可以作为变量传递给单独的kubectl或helm调用-local_exec和bash提供者的强大功能和简单性
在这里 。

自动扩展组和工作人员细分

支持实际的群集设置,并且非常重要的一点是自动扩展组,使群集的工作人员旋转。 有几种模式和技术,通过在Internet上搜索相关材料,您会发现不同的方法或建议。

我们选择了一个简单的设置,将我们的工作人员分为两个不同的组(自动缩放组/启动模板)。

  • 系统–工人 :我们将在这些工人上安装kube系统材料,这些材料将始终为生命周期类型: OnDemandReserve实例。 有效载荷如prometheus,集群自动缩放器, coredns pod或有时是Ambassador Proxy(如果我们也选择的话)。
  • 普通–工作者 :将在各种名称空间上托管我们的应用程序容器。 就数量而言,这是预计将增长更快的asg。

以上在terraform上的设置-必须反映并映射到我们上面定义的一个kubernetes-aws
集群自动缩放器

 - --namespace=kube-system - --skip-nodes-with-local-storage= false - --skip-nodes-with-system-pods= true - --expander=most-pods - --nodes={{.Values.kubesystemMinSize}}:{{.Values.kubesystemMaxSize}}:{{.Values.kubesystemAsgName}} - --nodes={{.Values.defaultMinSize}}:{{.Values.defaultMaxSize}}:{{.Values.defaultAsgName}} 

上面的设置–要求最小化我们的应用程序头盔图。 介绍2个节点相似性或节点选择器规则。 当前,更简单的方法是通过nodeSelector,即使它们将被弃用。

竞价型实例(降低成本!)


通过能够将Kubernetes方面(通过集群自动缩放器配置)与AWS方面分离,尤其是由于我们使用的是terraform,我们现在可以灵活地试验Spot实例。 我们的主要目标是使竞价型实例的使用对在集群上部署应用程序的人员尽可能透明,并使它成为集群运营商的关注点。 显然,所有相关各方仍应意识到广泛的担忧/变化。 集群工作人员的波动性不断增加,这意味着要在可能会在2分钟内通知的工作人员上运行有效负载,从而带来了挑战,这些挑战是在这些集群上编写服务的人们应该意识到的。

假设使用正确的启动模板和混合实例策略,可以使用2个自动扩展组的设置将竞价型实例添加到混合中。 许多人决定将他们的工人分为两个以上的ASG,例如,您可能有5个或10个,而不是2个,在那里您可以更精确地控制所使用的EC2 /类及其生命周期。 此外,您还可以根据他们的能力或生命周期将Pod /应用程序的某些部分定位到特定的工作组。

通常,您需要越精细的控制,并且您越想对冲终止现货的风险,您就越会倾向于以下策略或选择。

  • 将您的工作人员划分为不同的功能组 (现场/按需/保留的单个或多个类/混合实例策略
  • 增加每个副本集上的Pod的平均数量 -这样您就可以对付同一副本集(部署)上的Pod落在同一类型的工人上的风险,这些工人可能同时被杀死。
  • 多无状态少有状态 。 这样一来,您的平台就可以恢复持续遭受的计算/内存的微小或轻微故障。 对单例服务或集中式资源的依赖越多,对冲随机中断的可能性就越大。

现货实例意味着价格降低,但也意味着终止通知。 考虑终止当前模式时,您需要考虑3个因素

  1. AWS区域(eu-west-1)
  2. AWS可用性(eu-west-1a,eu-west-1b。)
  3. 类(m4.xlarge)

上述三重态通常是通常会影响该类现货价格的主要因素。 当前的策略是您的有效载荷(容器/容器)需要明显地尽可能有效地散布

  • 区域 :因此不止一个集群
  • AZ :您的ASG应该在区域提供的所有可用区域上旋转工作人员。
  • 类别 :如果您的ASG是单一类别,则该类别成为随机点终止并影响您的集群的机会要比使用更大的类别列表高。

总体思路是通过运行工作负载(多区域/多asg /多类)来规避现货实例终止的风险。 仍然存在一些风险–例如,AWS同时大量退休–现货资源–或价格快速变化。

这是一个非常棘手的区域,ASG上的设置可以帮助您对此进行更多套期保值–例如,如果您对价格限制有严格的规定,则ASG可以遵守,例如“不要出价超出此价格”之类的规则单一现货资源”。 使ASG /启动模板严格控制成本估算的次数越多,由于此硬限制和价格突然变化,遭受停机的风险就越大。

最灵活的方法是让ASG为您选择“最低价格”,因此您可以确保它会尽力找到下一个可用的价格组合,以为您的群集提供计算和内存。

关于将豆荚散布给不同的工人,我认为最简单的建议不是将所有鸡蛋都放在一个篮子里。
在这种情况下, Pod Affinity / AntiAffinity规则是您的第一工具+节点上的标签。 您可以在这里找到一篇非常不错的文章。

最后但并非最不重要的。 当发生竞价型实例终止时,能够在集群级别做出反应至关重要,这样这些工作程序终止不会使集群变得疯狂。 发生的并发终止越多,您将看到工人和az之间的吊舱移动大浪的风险越大。 Kubernetes将尝试平衡Pod并将其填充到剩余资源中,并明显地旋转新资源,但这确实取决于在很大程度上可以容忍这些运动,并控制Pod的重新调度方式。 在该区域,另一个可供您使用的有用工具是kubernetes pod中断预算 ,它可以作为kubernetes掌握的另一套规则-将在其资源可用性不断变化时考虑(意味着工作人员进出)。

最重要的是,为了优雅地处理这些终止,实际上需要2分钟的通知, 这种守护进程(现场终止处理程序)将减轻痛苦,并提供更多可见性。 守护程序一旦竞价型实例收到终止事件,就会正常耗尽您的节点,这又将工作进程标记为尚未准备好接收和调度工作负载,这又将启动一个调度回合,而kubernetes会尝试将pod放置在其他节点上如果有足够的空间或杀死新工人。 最终,系统将尝试平衡并满足您的设置配置和要求-但它实际上取决于您将拥有的并发终止数量以及Pod如何在这些工作人员周围分布。

点差越大,影响越小。 此外,您还可以考虑采用混合策略,其中某些工人始终处于需求状态,其余工人处于现货状态,以便您可以对冲更多,更激烈的现货实例终止事件。

集群升级的担忧与困扰

集群更新需要协调+建立流程方面的一些工作。 有3种情况:

  • 没有EKS或kubernetes版本更新–仅对安装在群集顶部的组件进行了修改,例如,您想将fluentd-bit更新为较新的版本。
  • 需要EKS AMI更新的次要EKS更新(自动模式),使您的工作人员处于相同版本状态。
  • 主要EKS更新(例如,kubernetes从1.12升级到1.13)–需要AMI更新+一些aws EKS组件更新。

第三种情况是最具挑战性的一种情况,因为不仅需要基于AWS的引用提供程序来烘焙新的AMI,而且还需要遵循此处定义的组件的约定和版本:

  • 核心域名系统
  • 库贝代理
  • AWS CNI插件更新。

这意味着在进行更新之前,您需要更新配置脚本(在我们的情况下为terraform变量),以便在新AMI投入生产并且我们拥有集群设置的核心时,能够进行更新或重新配置。 -安装某些组件。 始终遵循本指南 .AWS的文档非常可靠。

AWS API节流和EKS

作为您的最终用户,AWS主服务器是一个黑匣子,但强烈建议您默认情况下启用其CloudWatch日志。 与我们之前的集群相比,这对我们而言是巨大的进步。 主日志是隔离的且易于搜索,因此我们避免了过滤或搜索大量日志的麻烦。 另外,请检查这个非常好的工具,在许多支持情况下, EKS日志收集器通常都会引用该工具。

EKS的其他所有组件的主人都利用AWS API来使事情成真。 这适用于在AWS上运行的所有内容。 您需要知道的是,如果您在繁忙的集中式AWS账户上进行操作,则从不同组件(EC2 / etc)发出的API调用上总会有配额。 您的EKS管理员也很健谈,他们发出的API调用将计入您帐户的其余调用中,并记入帐单中(它们不是免费的,它们会增加配额)。 这意味着您的帐户何时以及是否发生AWS API节制–您的EKS集群也会受到影响,因此请确保您具有适当的监视权以检查何时发生这种情况。 如果节流时间很多(EKS的内部组件无法同步或相互通信的风险更大),这意味着整个群集可能开始报告有时无法关联的随机错误。 这是一个棘手的问题,我真的希望AWS更改EKS主机对此的政策,并保护他们免受帐户可能发生的API限制。 另一种解决方案是将您的群集“ 装箱 ”到特定帐户中,而不是将所有内容放到具有单个API配额的单个帐户中。

在生产中迁移和使用EKS可以说是非常成功的。 显然,我们的平台仍在不断变化,并且随着时间的流逝会发生变化。 这同样适用于EKS产品,随着时间的推移,您会看到来自AWS的更改和更新,这是一个非常积极的信号,因为您可以看到AWS对该产品进行了投资,并且随着每一次主要的kubernetes更新,EKS也都在发展。 另一个积极的事情是来自AWS的支持质量,在很多情况下,我们不得不重复检查AWS支持内容,我不得不承认解决方案和提供的答案非常彻底。

正如我在过去所说的那样,我认为AWS会决定在某个时候为其用户完成集成之旅,并提供一个交钥匙解决方案,在该解决方案中,集群的配置将以端到端的方式自动进行端对端(主机,工作人员,插件和设置) )。 让我们来看看。

翻译自: https://www.javacodegeeks.com/2019/06/configuring-using-aws-eks-production.html

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

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

相关文章

java 监听 变量_[Java学习小记]使用PropertyChangeSupport来监听变量的变化

今天要处理的问题是:监听一个变量,当该变量的值出现变化时能够获知,并进行相应处理。使用java.bean.PropertyChangeSupport类。看如下的构造方法,其实就是将你要控制的对象绑定到该工具中。PropertyChangeSupport changes new Pr…

处理异常功能样式

Java从一开始就支持检查异常。 在Java 8中,语言元素lambda和支持流操作的RT库修改将功能编程风格引入了该语言。 函数样式和异常并不是真正的好朋友。 在本文中,我将描述一个简单的库,该库在某种程度上类似于使用Optional处理null方式处理异常…

C语言项目:灰度处理技术

Hello,今天给大家带来的是一个比较简单的图形处理技术-灰度处理技术。那么到底什么是灰度处理技术呢?简单来说,所谓的灰度处理技术就是把一张彩色的图片变成一张灰色的图片。如下图所示,左边是原图,右边则是已经被处理…

java 设置文本颜色_在Java中更改文本的颜色

添加到我的评论:1)您不应该通过调用paintComponent(..)方法的super.XXX实现来尊重paint链,它应该是覆盖方法中的第一个调用,否则可能发生异常:Overrideprotected void paintComponent(Graphics g) {super.paintComponent(g);Font font new Font("S…

C语言项目:推箱子大战

还记得大家小时候玩过的游戏吗?曾经的坦克大战、推箱子、贪吃蛇都是我们以前玩过的小游戏,然而现在随着大型单机、网络游戏的光芒照耀下,那些曾经的小游戏都渐渐消失了,也或许是我们都已经长大了吧。那么今天,我给大家…

在Spring@Component vs @Repository vs @Service

介绍: 借助Spring的自动扫描功能,它可以自动检测我们的应用程序中定义的各种bean。 我们通常使用可用的Spring注释之一来注释我们的bean- Component, Repository, Service, Controller 。 在检测到bean时,…

java项目加减乘除验证码_课堂Java小程序(加减乘除与验证码)

一、编写一个程序,用户输入两个数,求出其加减乘除,并用消息框显示计算结果。1.设计思想:从键盘输入两个数字和运算符,然后计算。将输入的数字及运算符由字符型转换为整型,再用if判断输入的运算符&#xff0…

C语言绘图:可爱叮当猫

大家对于叮当猫可以说是很熟悉了吧,他还有另外一个名字,也就是哆啦a梦。即便你没有看过他的电影动画,也总会听说过的。叮当猫神奇的口袋总是能够掏出我们幻想功能的任何道具,任意门能够带我们去到任何地方,以及插在头上…

jgit git pull_使用JGit API探索Git内部

jgit git pull您是否想过提交及​​其内容如何存储在Git中? 好吧,我有,在上一个下雨的周末我有一些空闲时间,所以我做了一些研究。 因为我对Java的感觉比对Bash的感觉要多,所以我使用JGit和一些学习测试来探究提交的G…

MFC实现Windows锁屏

编辑Windows锁屏锁屏软件相信大家都见过,以前我去网吧上网的时候也用过这个功能,当你有事情需要立即离开,而又不想让别人碰你的电脑,就需要用扫锁屏软件啦,锁住屏幕之后等回来的时候再输入密码解锁。同样的&#xff0c…

pdf 截图 java_java实现pdf文件截图的方法【附PDFRenderer.jar下载】

本文实例讲述了java实现pdf文件截图的方法。分享给大家供大家参考,具体如下:最近做的一个网站中,有个需求是上传pdf文件,显示pdf的封页,点击封页之后进行在线阅读,这里使用的是PDFRender对pdf进行截图。pub…

检查Java测试中发生了什么

有人想到了在Java单元测试中使用try和catch块的想法: Test public void test() { try { callSomeCode(); } catch (Exception e) { assertEquals( "foo" , e.getMessage()); } } 上面的内容很诱人,但不起作用 。 如果被测代码没有抛出&…

学习红客技术必备

互联网时代已悄悄来临,作为新时代的人们,我们日常生活、工作、学习方面都需要借助互联网来完成,这样,又产生一种新的问题,那就是网络安全的问题,有时我们拼命加班好不容易完成的东西,在一夜之间…

md5withrsa java_浏览器运行java插件报错:Algorithm constraints check failed: MD5withRSA

今天使用kvm管理机房机器的时候发现一只连不上,报以下错误:sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: Algorithm constraints check failed: MD5withRSA我确认我已经把…

jpa 实体映射视图_JPA教程:实体映射-第3部分

jpa 实体映射视图在上一篇文章中,我展示了两种读取/写入持久实体状态的不同方法-字段和属性。 使用字段访问模式时,JPA使用反射直接从实体的字段读取状态值。 如果我们没有明确指定列名,它将直接将字段名转换为数据库列名。 在属性访问模式下…

今晚课题:2019-3-20

今晚课题C/C万年历技术实现原理上课时间:20:30--22:30上课老师:杰越教育-Larry老师上课地址:https://ke.qq.com/course/353889 课程内容:1、C/Cfor逻辑原理2、重要点数据结构分析3、万年历效果实现展示赢在别人休息时,…

python在材料模拟中的应用_材料模拟python_模拟-python模拟-在不妨碍实现的情况下修补方法...

此答案解决了Quuxplusone用户提供的赏金中提到的其他要求:对于我的用例而言,重要的是它可以与MagicMock一起使用,即,它不需要我在构造Potato(在此示例中为spud)实例与调用spud.foo(在本例中)之间插入任何代码。我需要293984865472…

新版本的Selenium 4 Alpha会有什么期望?

我们所有人都属于测试领域,他们熟悉Selenium,Selenium是业界最流行的开源自动化工具之一。 Selenium的创始成员Simon Stewart在2018年8月正式宣布Selenium 4的发布日期以及它将为用户带来哪些新功能时,我们感到非常兴奋。 与Selenium 3一样&…

今晚课题:2019-3-22

今晚课题数据结构必会重点集合上课时间:20:30--22:30上课老师:杰越教育-Larry老师上课地址:https://ke.qq.com/course/353889 课程内容:1、C/C技术工作运用2、数据结构重点数组定义特点3、工作项目数组合理使用赢在别人休息时&…

java 单例 实现_java 实现单例的各种方式

概述上一篇日志中,我们介绍了单例模式的概念和基础的应用本节中,我们就来介绍一下 java 语言中如何编写单例模式类只适合单线程环境的单例模式public class Singleton {private static Singleton instance null;private Singleton() { }public static S…