通常情况下,我们会在自己的独立分支中完成需求开发,此时就会有需求将自己的分支和其他分支进行对比。这个功能可以通过
git diff branch1 branch |
命令来实现。
如果希望对比暂存区和当前的HEAD,那么使用
git diff --cached |
命令会非常方便。普通的git diff
命令默认对比的是没有加到索引中的文件。
恢复暂存区
如果已经将一些文件添加到暂存区后又后悔了,Git提供了多个命令来实现这个功能,具体需要根据当时情况而定。
git rm path/to/file --cached |
命令将文件从暂存区索引中删除,但是仍然会将文件保留在工作目录。这比直接使用
git rm file -f |
命令完全删除文件会安全一点。
如果希望恢复一些已经提交的改动,我们可以使用
git reset |
命令。该命令有许多不同的行为,因此需要按照实际场景进行使用。
如果希望的是去除所有修改,包括索引中的内容和工作目录中的修改,那么可以使用
git reset --hard |
如果仅仅是希望重置索引,那么可以使用
git reset --mixed |
命令,这也是git reset命令的默认行为。混合的重置会保留当前工作目录中的改动。最后,如果仅仅希望修改分支的HEAD,可以通过
git reset --soft |
实现。
当运行git reset命令的时候,我们可以指定多个目标文件作为参数传入。当然可以通过
git reset --hard COMMIT_ID |
恢复到指定的提交版本。
大家应该对git stash命令并不陌生,它可以通过git stash pop命令方便的将之前的改动恢复回来。然而,如果工作目录中有未追踪的文件,默认情况下是不会将其存入临时储藏区的。为了能够临时保存未追踪的文件,可以使用
git stash --include-untracked |
命令。另外一个非常有用的命令是
git stash list |
它能列出临时储藏区中的内容。
Git自带了非常强大的工具来查看项目以及特定文件的变更情况。我个人非常喜欢用其中的一个命令:
git log --graph --decorate --oneline |
用以展示经过修饰的提交历史。这个命令非常冗长,因此我建议可以为它创建一个别名(这可能是所有技巧中最有用的,因为许多命令都比较难记)。git log命令可以显示HEAD、所有提交的ID以及分支信息。有了这些信息之后,我们可以使用
git show COMMIT_ID/HEAD/BRANCH |
命令来显示更详细的信息。
有的时候我们需要了解谁对一个文件做了哪些改动,这正是
git blame path/to/file |
命令所提供的功能。
之前提到过git diff命令,它也是一个查看历史的工具。例如,如果需要对比当前HEAD和前两个提交,可以使用
git diff HEAD HEAD~2 |
为了能够展示每个提交中的更详细的更新信息,可以使用
git log --patch |
命令。如果只想要看包含关键字“apple”的提交,使用
git log --grep apples --oneline |
命令。
需要查看历史提交记录中两个点之间的提交历史,我们可以用
git log HEAD~5..HEAD^ --oneline |
命令,对于分支可以使用
git log branch_name..master --oneline |
修复错误提交
注意:以下一些命令会修改提交历史,使用前请确保了解后再执行。
当提交出错时,我们可能会希望能够修改提交历史。我不建议修改已经推送到远程仓库的提交历史(即使git允许这样做),但是对于本地仓库的提交历史,我个人认为还是可以修改的。通过
git commit --amend |
命令可以删除前一次提交,并创建一个新的提交记录以替代之前的提交。
另一个我最喜欢的git使用技巧是交互式变基(rebase)。它可以用来编辑提交信息,或者将多个提交压缩成一个提交,这也是我最喜欢的一个功能。为了在远程仓库origin的master分支之后的所有提交上执行交互式变基,可以使用
git rebase -i origin/master |
该命令会显示提交列表和可执行操作的详细描述。例如以下操作将会把多个提交压缩成一个:
1 pick 80f2a48 Add feature X |
2 squash 2c74ea2 Add junit tests for feature X |
3 squash 4k81nm5 Bugfix for feature X |
最终的结果会是生成一个提交消息为“Add feature X”的提交。
如果需要恢复一个有问题的提交,我们可以使用
git revert COMMIT_ID |
该命令会创建一个新的提交,让当前项目状态恢复到指定提交之前。
如果我们在修复问题时出现了误操作,例如不小心删除了不应该删除的文件。我们还是可以从版本库中恢复回来,因为git保存了所有修改的版本,包括被移除的提交。git reflog命令就是用来实现这个功能的。
假设我们和同事在各自单独的分支上进行开发,同事有一个重要的提交我们也想应用到自己的分支上来,但是不需要对方分支的其他提交。这时我们可以使用
git cherry-pick COMMIT_ID |
以上都是我最喜欢的git实用技巧。希望你也能从中学到一些新知识。这些都是我在日常使用中发现非常有用的命令,它们对我的日常工作非常有用。如果你也有类似常用的git实用技巧或者常用命令,可以分享出来大家一起交流。
查看英文原文:Useful Git Tips and Commands
中文原文: Git实用技巧和命令
]]>这篇文章是Serverless系列的第三篇文章,这一系列文章是为了探索Serverless的本质。
Serverless技术承诺说可以消除IT运维相关的大部分繁重工作,第三方服务商会承担起更多服务器维护相关的管理工作,而不像企业组织为容器编排和微服务平台所做的那样。使用Serverless平台可以节省资源,其中部分原因是因为Serverless允许组织通过 “按使用量付费” 的模式来使用服务器。
迁移到Serverless资源有许多方法,有对的也有错的。在迁移之前,请记住以下几点。
DevOps的团队成员可能已经听说过Serverless,并希望知道迁移后这个平台可能为他们的组织提供哪些功能,但他们可能一开始就会对Serverless这个词产生疑惑,Serverless意思是无服务器的。但实际上,”Serverless” 应用程序仍在服务器上运行。
“Serverless” 这个词的使用可以追溯到至少2012年,当时Ken Fromm在一篇ReadWrite论文 “为什么软件和应用程序的未来是无服务器” 中使用了这个术语。一个更精确,合适的定义出现在2016年一篇开创性的博客文章中,由Symphonia的合作伙伴兼联合创始人Mike Roberts在Martin Fowler的网站上提出。他写到Serverless架构是 “将第三方 后端即服务
(BaaS,Backend as a Service)服务,和包含自定义的服务代码的容器整合在一起的应用,并将应用运行在 ‘功能即服务(Function as a Service,FaaS)’平台上。”
Roberts写道:“通过整合实践这些想法以及相关的类似于单页面应用程序(SPA)的想法,这种架构消除了传统的对永远在线服务器组件的大部分需求。Serverless架构帮助企业降低运营成本,复杂性和工程准备时间,但代价是增加了对供应商的依赖和相对不成熟的支持服务的依赖。”
以上定义概括了许多供应商提供的Serverless产品,包括亚马逊网络服务(AWS)的Lambda,它被广泛使用并提供BaaS(Backend as a Service)和FaaS(Function as a Service)服务。其他Serverless产品包括 Cloud Functions(Google),IronWorker(Iron.io),Manta Functions(Joyent),OpenWhisk(IBM),PubNub BLOCKS(PubNub)以及Serverless Docker(Docker)。
Serverless的优点在于它能够通过将服务器和相关的基础架构管理任务外包给第三方来帮助公司节省资源。例如,开发人员团队只需要开发应用程序,而Serverless提供商则在异地服务器上完成所有数据维护工作。
Cloud Academy的产品营销经理Albert Qian表示: “Serverless的易用性可以提高开发人员的效率,Serverless计算使开发人员不用接触基础设施,他们可以完全只专注开发单一功能”。
Serverless供应商允许组织根据他们的需求进行扩展或缩小,不再担心冗余的服务器容量。
“Serverless架构让云服务供应商管理服务器以及服务器的扩展以满足需求。将Serverless视为平台即服务(PaaS)的抽象,您需要做的就是上传代码,当您需要向上或向下扩展某个功能时,您只需扩展这个单一功能,”Qian说。 “因此,您无需扩展整个系统,容器或应用程序。另一个好处是无服务器具有内置的容错能力和设计的的高可用性。”
因此,企业可以通过依赖第三方执行操作和数据管理任务来节省资金。 “Serverless的最大优势之一是它可以降低成本。使用FaaS作为您的计算层,您只需为正在运行的功能付费,”Qian说。 “尤其是对于利用率较低的工作负载,您会节省很多支出。因为您只需支付处理请求所需的计算资源,而不是为等待请求进入的空闲服务器付费。”
但是,通过将服务器管理移交给第三方,您的组织也失去了对服务器的大部分控制权, 这一点在您确定是否以及何时迁移到Serverless时是需要慎重考虑的。
“由于Serverless解决了资源管理问题,它正在迅速发展。对于不想维护服务器的小公司来说,这是完美的解决方案,”Raygun的高级开发人员Jeremy Scott说。 “您可以在几乎完全不用关心运维问题的前提下将工作完成,并且比使用自己搭建的服务器架构更便宜。但是Serverless也有其局限性,当你交出责任时,你同时也交出控制权和访问权,这样一来,对你的服务的监控和分析会变得非常困难。”
通过这种方式,对在Serverless平台上运行的微服务和容器进行分析可能成为一个问题。 “你必须了解你的软件,否则就有可能在没有数据支持的情况下做出商业决策,”Scott说。 “因此,如果您使用Serverless,那么在某些情况下您可能需要在客户端(例如App或者浏览器)添加监控,或者您可以尝试为Serverless Function添加异常处理。”
虽然具有挑战性,但将分析软件应用于Serverless部署仍然是可行的。如果为Serverless Function添加了异常处理,可以将Function包装在try-catch中然后发送https API请求,那么错误信息就会被记录在错误报告客户端(例如:Raygun[2])。然而,如果是基于API的服务,将无法被监控,另一种解决办法就是观察API的行为方式”,Scott说。
在决定哪些功能可以移植到Serverless架构时,需要考虑到Serverless部署的缺点——不太强大的计算性能。 “Serverless Function有很多限制。任何需要超过3GB内存的功能都必须重新设计否则无法运行,”Cloud Academy的Qian说。 “要确保团队了解这些限制,并确保他们有足够的知识,经验和培训,来决定适合特定工作负载的最佳技术,这一点非常重要。Serverless或任何新技术的‘酷’因素在架构方面有时会笼罩批判性思维,结果可能导致的松散的Function的组合,而不是整体一致的应用程序。”
就像监控和分析一样,在Serverless架构上保护你的数据也十分困难。毕竟服务器的管理和控制都被转移给了第三方。
“例如,Serverless运行时环境不是标准化的,并且被运行的云服务隐藏起来,这使得我们更难以保护云上的数据”,Aqua Security营销副总裁Rani Osnat表示。“对于无服务器,我觉得有几个关键的安全问题,”Osnat说。在进行迁移时,某些安全检查尤其重要。 例如,如果在Serverless Functions中使用了潜在的易被攻击的代码,那么需要在使用之前解决这个问题”,同时对于那些违反政策的FaaS Functions, 我们必须使用强制控制来阻止这些功能的部署。
Osnat说道:“尽管Serverless架构如此具有挑战性,企业组织们仍需要确保他们的Serverless平台在运行时会被监控,以便监测异常。”
Cloud Academy的Qian表示,当迁移到无服务器时,同时也会面对多用户的挑战。 “即使客户的工作负载在虚拟机或容器中是被隔离的,也可能存在安全问题,特别是如果应用程序使用敏感数据。 一个客户代码中的潜在的bug可能会影响另一个应用程序的性能,从而影响客户服务和应用程序的质量。”
]]>译者:Grace Linktime Cloud公司全栈工程师
原文链接:https://thenewstack.io/serverless-migration-strategies-what-to-know-before-making-the-leap/
这篇文章是Serverless系列的第二篇文章,这一系列文章是为了探索Serverless的本质。
越来越多的企业与创业公司选择Serverless技术,并且Serverless技术发展速度远远快于之前的Container技术,而Container技术则是最近一次被行业广泛采用的新技术。
不论从何种维度分析,都可以看到Serverless这项技术正引起人们的兴趣。
目前只有一些创业公司会在全面使用Serverless,大部分的企业只会在一些特定的项目中采用Serverless技术来测试基础架构的方案,以及测试团队文化是否适合实施Serverless。
尽管Serverless技术只被用于一些独立的项目上进行测试,它们仍引起了多米诺骨牌效应,以一种意想不到的方式影响了公司业务。Serverless缩短了生产时间,引入了cost-for-usage(根据使用量付费)模型并鼓励团队成员更加自主。这些改变影响了企业的运作方式,包括如何选择需要在Serverless上运行的功能,企业研发新产品新功能的意愿,以及如何管理预算,程序员与产品经理如何履行职责等等。
O’Reilly系列的Microservices Architecture(微服务架构)书中提到 “微服务架构使Serverless更加快速,微服务使一个单体应用代码被拆分成小型的自治服务。因此,企业可以大规模的快速安全的构建解决方案”。
今年年初的一篇博客中,机器学习平台Algorithmia的Mike Anderson演示了一个典型的高科技公司通过微服务将标准发布周期从65天缩短至16天。他写道“微服务帮助他们解耦了开发流程中的阻塞部分,缕清以及隔离了问题,使他们只关注组件级别的变化。”
当一个组织的代码是以微服务而不是单体应用的形式组织的时候,才可能使用Serverless技术。现在,企业可以识别出适合在Serverless架构运行的任务,这些任务是一些特定的,无状态的任务。云平台会通过分配计算资源来解决问题,运行服务器来做计算,在数据转换完成后将这些操作任务关闭。
Red Hat产品管理部门的高级主管Rich Sharples 说道,该公司在过去两三年一直关注Serverless技术并且正在开发一个开源的,企业级别的Serverless产品,这个产品可以与Kubernetes一起使用。Red Hat希望今年能够发布整个产品。
Sharples说道 “通过客户,我们发现技术的技术成熟度曲线( The Hyper Curve)飙升的十分迅速,例如微服务,而Serverless攀升的速度更快”
因为微服务的增量交付,灵活,快速交付的特点,微服务受到越来越多企业的欢迎,Sharples说道“但是在我看来,这些使用者在疲于应对分布式系统管理和监控的运维复杂性,这也是为什么Serverless会引起他们的兴趣,通过Serverless,你可以获得微服务的好处,从开发人员角度来看,这也非常简单——仅仅只用修改一些代码。在运维人员看来,Serverless是一种非常适合建立自动化运维系统的模型,例如将回复一个日志事件实现成Serverless方法调用将会非常方便“。Sharples说道从他与企业级用户的日常对话中,可以感受到他们对Serverless的兴趣。
Sharples说道 “任何短时间运行的,无状态的,可以独立运行的任务都适用于Serverless”。
开源软件API Gateway Kong的高级解决方案工程师Aaron Miler说道,大部分开始设计Serverless架构的客户基本都采用了自下而上,或者自上而下的方案。使用自下而上方案的客户已经将他们的传统架构转换成微服务架构,并且正在寻找一种方案可以让他们在整个企业以不同方式使用Kong。他们倾向于选择开源技术公司的企业级方案,并且希望通过发掘Serverless方向的工作机会来进入一个新的领域。
Miller说道:“在Kong,的确有一些优秀的Serverless项目引起了那些想要快速跟进新技术的CTO的关注。Expedia的Serverless项目就采用了Kong的技术,Expedia是Serverless的深度用户,这家公司在他们所有日常的API网关都使用了Kong,因为Kong提供了AWS Lamda插件,通过插件,Expedia可以很方便的使用AWS Lamda,例如,每当用户在Expedia上订了一间房或是一张机票时,Expedia都会为客户提供一个可以用于下次消费的折扣券。Serverless技术非常适用于这种场景。”
Miller谈到,虽然减少成本是Serverless的一大优势,但是它更大的优势在于加快了开发速度。“如果团队只用专注于写代码,只用关心函数功能的质量,不用担心这些代码是在Linux哪个版本上运行,这些问题将由别人解决,而团队只用关心如何用Node、Python或是其他Serverless语言写代码,这样一来,每个人都从中收益。它可以让人更加专注于自己的事情同时交付更多的功能。”
许多企业和创业公司都找一个简单的例子来测试Serverless的潜力。The New Stack会定期列举一些简单事件作为Serverless用例( a number of the low-hanging fruit use cases for serverless)。
Steve Faulkner曾经帮助媒体公司Bustle公司构建Serverless基础架构,该公司现在所有的运维都在Serverless的架构上运行,只有一个兼职的运维员工, Steve有一个简单的经验法则来帮助企业找到从哪可以开始他们的Serverless旅程。
他问到 “你的CI/CD流水线有哪些缺陷?一个测试你的CI/CD流水线的简单方法:一个非技术人员是否可以对您的网站或文档中的文本或副本进行更改?将更改部署到生产的速度有多快?大多数公司甚至不能这样做。”
Faulkner说道,他见过有个CEO看到网站上有个错别字,改正后通过Git中提交,一小时内更改就在生产中生效了。“这是一个很高的标准,但是这对于找到你的CI/CD的缺陷是一个很好的测试,并且这也是一个Serverless解决问题的案例”。
Kong公司的Miller提出了一种适合使用Serverless的场景,当某个处理任务所需的资源是不可预估的时候,这个任务就很适合使用Serverless。“在任何你不确定计算容量的地方:比如你不确定使用1还是100台服务器,如果没有方式可以预估,那么这个任务就很适合用Serverless处理”。另一种情况则是当你有很高很多的需求,但是预算又非常紧张的时候,Serverless可以帮助你很好的控制成本。
就像是Expedia的用例一样,他也建议技术领导与产品经理以及销售和营销团队一起讨论企业当前如何提高用户的粘性,在此之中或许可以发现一些合适的用例。
这通常是James Beswick的起点,该公司的Indevelo开发商店为用户创建网页和移动应用程序,他们的企业和B2B客户端都是Serverless架构。最初,Beswick在所有标准图像大小调整类型任务中使用Serverless,但在纽约最近一个ServerlessConf中,“我突然意识到我可以将所有的工作都放在无服务器上,”他说。
Beswick说,每次跟新客户讨论时,他通常不会从一开始就讨论Serverless,而是把低廉的使用成本作为他的主要卖点。
“我们必须解释整个事情,”Beswick说。 “首先我们谈论软件需求是什么,然后谈论架构。在架构方面,我们从财务方面入手。我们解释了为什么Serverless更便宜,更易用。”
Beswick说,因为Serverless价格“非常难以估计”,他倾向于给潜在客户一个估价范围。 “网络规模的应用程序非常昂贵,但是你得运行它们”Beswick说。我倾向于表明,如果某个应用程序正在进行10,000次交易,那么每月帐户看起来如何?如果一个事件每个月花费500美元,那么什么可能会导致它突然每月花费5000美元?”
从成本的角度出发,促使企业思考Serverless架构可能会对他们未来运行公司的方式产生巨大的影响。
例如,在美国,IT项目可能会根据人力资源和资本支出(capX)进行预算,而不是纯粹的成本分配和运营支出(opX)。许多企业将其IT视为capX,因此获得特定的税收折扣。但是对于云环境,对于Serverless的情况更是如此,其中定价是基于实际使用情况,它全部是opX。这让一些首席财务官感到担忧,他们害怕失去IT项目的税务减免。在进行项目预算时,其他的项目并没有设置成可以降低现有员工的工资成本。
“你可能会为一名数据库员工每年支付12万美元,”Beswick解释说。 “如果您正在运行AWS Aurora,那可能会花费500美元一个月,这要便宜得多,但人们并没有考虑到人员成本,因为它被分成了多个部分。“Beswick说,企业将不得不推出新的会计方法,这不是寻求CapX税务减免,而是一种纯粹的成本分配,人力资源预算将会采用新的方式,而将运维成本划分到项目成本之中。
Serverless的引入也带来了其他的影响。其中一些影响在云技术和SaaS技术中产生,但随着Sevrerless应用的发展,它影响的速度和范围也在增加。
Beswick指出,他的设计店经常被IT以外的业务部门雇用,例如企业的营销和销售团队。例如,SaaS工具只被一个部门使用,但随后数据集成和移动设备集成则意味着跨越多个业务线,应用程序开发必须找到解决方法来限制传统IT部门的参与。 “当你与IT部门合作时,有一系列因素在起作用:他们不在权威,他们对发生的事故感到不满,并且怀疑它是否应该在Serverless中运行。 IT团队在这方面如此落后,“Beswick警告说。
“IT部门正在变懒,他们掉入了不想改变任何事物的陷阱之中。但大多数企业都看到自身行业发生的巨大变化,所以他们不想再依赖IT部门,而是从外部寻求问题的解决方案,”Beswick认为,大多数企业都在处于一个中间过渡时期,新的组织架构会代替传统IT部门的组织结构和作用,而Serverless正在加速这个过程。
Faulkner说道:“我确实看到了Serverless带来的业务流程的变化。 我认为Serverless不仅仅提高了软件开发的速度,还帮助你模块化你的应用程序。 我们通过Serverless的方式重新构建了Bustle。 Serverless架构是模块化的,并且具有许多功能,因此更容易与其他的应用适配。 在去年,我们开始建立可以搭载事件的架构并提供新价值的业务系统。”
Beswick也同意这个观点。 “想想以前的世界,MVP(Minimum Viable products 最小可行性产品)是不可扩展的,它们并不可靠。 如果想法真正被采用并进入生产阶段,那么MVP的大部分工作将被丢弃。 但是现在有了Serverless之后,我们可以轻易的将MVP投入生产来构建高级应用程序,从而解决问题,它变得更灵活。 以前当一个功能或应用规模扩大时,你只能默默祈祷不要发生问题,而现在Serverless使规模缩放变得更稳定。”
Beswick说,通过微服务和Functions,构建MVP所需的很多代码块都已经实现。 通过Serverless(根据使用量付费),企业可以加快开发速度,快速向客户群体发布原型以获得反馈,从而降低风险。 如果他们成功了,他们可以更快地转向生产,而无需重建整个应用。
保险科技创业公司Fabric的联合创始人兼首席技术官Steven Surgnier表示,在他们的业务中使用Serverless架构的确为该公司带来了的业务流程的优势,正如Faulkner和Beswick之前所提到的一样。
“最终都归结于执行力,”Surgnier说。 “作为一家早期的创业公司,我们希望迅速执行并最大限度地降低整体技术的复杂性。 我们使用Serverless技术来减少从我们的想法到客户手中的最终产品的时间。”
Miller和Surgnier都赞同一种观点,即Serverless技术帮助企业留住关键开发人员。 Miller说,企业内部的开发团队通常对测试新技术感兴趣,他们会找到一个项目,分配一个小团队,并给他们几个星期来建立一个原型。 “这些企业通过为开发人员提供有趣的工作来吸引和留住优秀的人才,”Miller解释说。 Surgnier说Serverless对公司和工程师都有好处:“工程师喜欢创造。 因此,通过为他们提供Serverless基础架构和专注于产品的机会,可以让工程师在其职业生涯中创造出更多的产品。”
Steve Faulkner说Serverless改变了软件开发的基本流程,在这个过程中培养企业内部的开发人员自主性。
作为Bustle的Serverless的冠军,他花费大部分时间来维护第一批bash脚本,并在之后构建了一个十分成熟的框架。 “我希望人们了解它是如何工作的,但我也坚信任何人都可以随时用一个命令部署生产环境,”他说。
Serverless鼓励这种程序员自主开发的文化。 “如果有的话,一切都会更快,”福克纳说。 “一个完全部署的Lambda的更改可以在30秒内完成。 如果你知道部署到生产需要一些过程,那么它会成为一种精神障碍,并会引入惰性,就像是我现在应该做么?还是我应该等待别人去做这件事?Serverless帮助开发者解除了这种精神障碍。 现在任何人都可以随时部署到任何生产端点,这就会给赋予人们自主权和能力。”
Faulkner说,在Bustle,这已经是文化的一部分,而大公司可能有一种根深蒂固的文化和观念,即鼓励开发者们在签字(上级认可)后才开始做事。 “我想如果你在大企业中使用Serverless,如果文化已经很糟糕,Serverless也无法帮助到你。”
Faulkner表示,Serverless也加速改变了另一种文化,即对轻量级架构决策记录的需求。 “人们需要记录他们正在做的事情,”他急忙说道。 “如果我们的目标是任何时候任何人都可以部署到生产,我们必然会有很多短暂存在的feature branch(Git的功能分支)。那么你需要一个功能标记系统,这样生产中的东西就不会完全暴露给外界。“尽管Faulkner表示这还不是规范,并且是分布式软件应用有着更广泛的趋势,这种议程和需求是由影响无服务器的采用创造了速度和发布生产级变更的能力。
“我最近的观点是,随着应用规模不断扩大,功能标志(feature flag)可能是改善软件开发过程最有用的方法。”Faulkner建议道。
Indevelo的Beswick认为,在许多企业,IT主管和业务部门经理会对未来的发展存在分歧。 云技术已经引入了新的领域,但Serverless的出现则向前推进了更大的一步。
“我从未像现在这样对一项技术感到如此兴奋,”Beswick说道,Faulkner,Surgnier,Miller和Sharples都表达了同样的观点。 “Serverless使所有事物汇集于一处,”Beswick继续说道。 “Serverless能交付的远超想象, 以后可以将它添加到机器学习,也可以被应用于移动方向。 你需要以一种全新的思维方式去思考,而不是继续维持老旧的思想,这才是Serverless令人兴奋的地方。 我们可以更好地去询问客户的问题,以及如何让每个人更容易解决这些问题。”
]]>译者:Grace Linktime Cloud公司全栈工程师
原文链接:https://thenewstack.io/serverless-impacts-on-business-process-and-culture/
最开始,一台单用户的物理服务器便能满足我们的日常所需,它快速,可靠并且安全,只对管理员负责。但是在实际中配置和扩展都很麻烦。虚拟机的出现满足了灵活性和可扩展性的需求,之后云服务提供商为我们带来了基础架构即服务(IaaS),云平台自助服务也由此诞生。在这片肥沃的土壤中出现AWS(Amazon Web Services),编排,以及基础设施即代码(IaC),之后开始了集装箱化,带来了平台即服务(PaaS)的架构,一切看起来都很顺利……但程序员仍想要更多的功能,如独立于编程语言(language agnostic)的端点,服务器的水平伸缩能力,以及可以实时支付服务使用量的能力。
为了满足这些需求,Serverless计算应运而生,Serverless计算也被称为功能即服务(FaaS)。运行时只会执行程序但不会存储数据。这意味着像AWS(Amazon Web Service),谷歌云以及微软Azure云这样的云服务提供商会动态的管理资源的分配和分布。
Serverless是付完即走,基于实际的消费而不是基于预测的预付款进行收费的。这本是基础设施应该有的样子,在2018年终于出现在我们面前。
首先,这个名字非常有误导性。 Serveless(无服务器)计算仍然需要服务器,它并不是什么神秘魔法。
这个术语的出现是因为服务器的管理以及容量规划都被隐藏起来了。Serverless被称作是无服务的是因为用户/程序员无需关心甚至意识到基础架构的存在——服务器被完全抽象出去了。Serveless代码可以和传统方式部署的代码一起使用,例如微服务,甚至一个应用程序可以完全不需要配置服务器,只需要以无服务器的方式编写即可。
Serveless 真正的价值不在于节省了成本,而在于节省了时间。
Bitnami的现任云技术高级总监Sebastien Goasguen说到 “我会把Serverles 想像成一个具有微型PaaS的像胶水一样的软件,它最大的优点就是可以从云中发生的事件中调用函数(即胶水)“,Goasguen描述了一个场景,例如,将图像放在AWS(Amazon Web Service)的storage bucket中存储,然后调用函数来调整该图像的大小。Serverless系统会获取这段代码并且自动注入到运行时环境(服务器或者容器),之后将这个函数暴露出来以便调用。
传统云计算和Serverless云计算最主要的区别在于客户是否需要为未被使用或者未被充分使用的资源支付费用。以前,无论是内部数据中心还是云上,我们都需要提前预测容量和资源需求,并且提前准备好。在之前的例子中,这意味着我们提前启动AWS服务器以便随时执行这项调整镜像大小的服务。而在Serverless配置中,你只需要调整代码执行的时机,即只在函数被调用时候执行。
Serverless计算服务将您的函数作为输入,执行逻辑,返回输出,之后关闭。你只需要为函数实际执行所消耗的资源付费。
即用即付(Pay-as-you-play),并且只用为你实际使用的资源付费,这显然是件好事,但是Goasguen以及其他Cloud Native的专家强调Serverless真正的价值在于时间效率,而不是成本效率。
Serverless就像一扇通往未来的门,它和其他即服务(other as-a-service)的技术一样,为公司提供了很多工具,可以让公司专注于构建使用如AI,机器学习等尖端技术的应用程序。而不是浪费时间精力在不停的构建,重建必需的基础设施。
Serverless其他的时间机器功能在于缩短了从代码开发到投入生产的时间。它真正实现了“这是我的代码,现在立刻运行它”。不会因为基础设施产生延迟。
Oracle公司负责Serverless业务的副总裁Chad Arimura说到“Serverless的基本思想是程序员只需要写代码然后推送到Serverless的服务就足够了,其余的事情都由这个服务来处理”。他还补充道,像数据库和数据存储这类的依赖关系也被当作服务无缝集成到Serverless底下。
Arimura说到“在Serverless背后,专业的团队和自动化工作相结合,大规模的操作这些系统,以便开发人员无需考虑这些问题,这项技术看起来就像是魔法一样,这也是为什么这项技术被炒作的如此厉害,正因为它带给了我们如此美妙的体验”。
虽然Docker技术简化了分布式应用打包和依赖管理的问题。Kubernetes帮助企业在生产中运行这些应用。但是使用它们并不简单易用。Dcokerfile、基础设施细节、Kubernets manifests文件,这些即便对于程序员听众来说,也异常复杂。
Serverless计算的核心就是作为一个功能即服务平台。从本质上讲亚马逊的AWS Lambda以及Google Cloud Function就是Serverless的实现。它们处理了资源管理,负载均衡以及多线程,开发人员就可以只关注他们的代码,而企业只用关心他们的目标。
iguaz.io的创始人兼CTO Yaron Haviv提到,一个持续的数据平台是为提升云上的性能而设计的,将一个新的技术栈按照FaaS(功能即服务)的工作流运行一遍,步骤如下:
除了以上列出的优点之外,FaaS(功能即服务)也存在一些潜在的缺点。专家提到,云服务提供商通常会降低那些不经常的运行环境的资源,他们也会限制你的可用资源的总量,由此带来延迟以及低性能问题。并且由于任何云计算工作流事实上都会运行在一个公有云环境,而你无法控制或者进入这些云环境,导致监控,调试,以及安全性都无法保障。
亚马逊Lambda已成称为Serverless计算的代名词,这也是大多数人可以完全理解一种Servless的模式。尽管Lambda已经开辟了Serverlss的前路,它也涵盖了所有Serverless的缺点:缓慢的冷启动(cold start),低性能,短时间存在的功能,以及一组封闭的触发器。目前普遍认为,所有的Severless平台都具有这些限制性,但事实上这些限制性可以在平台的实施中避免。值得注意的是有一些更新的Serverless平台比如 Nuclio,它演变出了很多更广泛的用例,这些更新的平台具有更少的限制,更高的性能,并且可以运行在多个云服务上甚至是内部环境。
Haviv说道“极客们喜欢Serverless,但是企业们仍在试水——他们甚至还没有熟悉Docker/Kubernetes,Serverless就开始出现了”,就如任何新技术一样,一开始总是由一些聪敏,愿意冒险的早期受众开始试用,之后慢慢面向大众。而大众往往需要在看到这项技术是值得信赖,并且有可靠证据证明它能解决性能问题,安全问题等等问题之后才会采用这项技术。
鉴于Serverlss这项技术几乎每天都在发展壮大,所以并非所有的方面都可以令人满意。虽然称不上是个缺点,但是这一点的确令整个董事会坐立不安。Haviv 指出“由于数字化转型”正影响着当代企业,创新者们以及Serverless一类的某某即服务(Other As A Service)技术正在威胁着现任者,让企业变的更加敏捷以及更加愿意承担风险。最有趣的是尽管Serverless比Docker/Kubernetes技术更新,但如果将Docker/Kubernetes的复杂性抽象出来,Serverless会更快更容易的被采用。
这里不是讨论你的公司到底适不适合Serverless,这里只是讨论一下那些最先采用Serverless技术的公司。
Oracle的Arimura说道“表面上来说,任何编写软件的公司和组织都非常适合采用Serverless”,不过,就当前的文化以及离达成全面“原生云”目标的距离而言,采用Serverless将会使这个过程变得更加艰难。换句话说,如果一个公司没有使用过任何的公有云,没有任何Docker/Kubernetes的实施经历。那么他们就不该从Serverless开始。
“这是一种全新的架构,需要完全不同的思维方式,最简单的例子就是如果要把一个单体应用拆分成10个微服务,100个函数,并且每个都具有独立的部署周期以及复杂的依赖图,配合成熟健壮的CI/CD以及自动化的系统。把这些和Serverlss一起使用的时候,将会大幅提升敏捷性和创新性,但是如果仅仅只有其中一个,那么带来的损失远大于收益。”
Arimura继续说道 “这就是为什么Devops(运维人员)不会变成noOps(无运维人员),因为这是一条完全错误的方向。“事实上,Serverless的出现使得DevOps比以往更重要。
事实上,Bitnami的Goasguen指出,他观察到的大部分使用Serverless的公司都是以程序员为中心的组织,尤其是使用AWS Lamba服务的,这些公司原本就使用AWS并且用AWS将服务连接在一起。 Goasguen说道“所以很有可能,如果你不使用AWS,那么你便不需要Serverless,但是你始终需要保持警惕,开始评估,辨别企业中哪些事件源可以被用来建立完整的应用程序管道。
Arimura建议道“如果一个企业仍处在适应DevOps的阶段,那么它不需要一开始就将一个大型的单体应用完全拆分转换成微服务或者功能,或是为了学习一个新架构就在一个重要的新项目中使用这项技术。最好是从小处着手,例如创建一些自动化的任务,或是事件驱动的用例。”
本系列Serverless的文章可以帮助您的公司开始使用这项技术。
]]>译者:Grace Linktime Cloud公司全栈工程师
原文:https://thenewstack.io/serverless-101-how-to-get-serverless-started-in-the-enterprise/
其实你根本就没有必要将自己的单体应用改写为现代的版本,使用云原生技术可以将之优雅的转变为微服务架构。
在互联网的早期,如果你来运行应用程序的话,需要购买或租用硬件。无论它是机架式的还是塔式的服务器,这不重要,重要的是每一个应用都需要一台服务器来运行,所以是非常昂贵的。在2001年,VMware推出了虚拟化软件,允许用户在同一硬件上运行多个应用程序。这也就意味着将一台服务器分割为多个,而且分割后的服务器是完全可以独立运行应用程序的。这对于用户的成本来说,是极大的节约。
时间过得很快,转眼就是2006年,亚马逊普及了基础设施即服务(IaaS),因为推出了颠覆性服务——AWS的弹性计算云(EC2),你不再需要购买你自己的硬件。你甚至都不需要去担心管理那些运行你的应用程序的虚拟机。而你实际上正在租用运行你的服务所需的计算环境和底层基础架构。你按小时来付费,像租用开会用的会议室一样。这样就可以让使用它们的公司,能够充分的优化自己的资源以节约成本,只需购买自己所需要的计算资源即可。要知道,IaaS 的出现是具有革命性的变革的,它的直接结果就是让计算的成本下降很多。
三年之后,Heroku提出了平台即服务(PaaS)的想法。PaaS 通过屏蔽了需要管理虚拟机操作系统重新抽象了一层。Heroku神奇地简化了部署应用程序的新版本;让应用变成了只需要输入 git push heroku 这样简单的命令即可。在Heroku当时诞生了很多现在知名的互联网公司。
这些进步使得以任何规模(大或小)部署应用程序变得更加容易和成本低廉。这就直接导致了许多的创新出现,并极大的推动了企业在处理基础设施上的实质转变,从而将其从资本支出转移到可变的运营支出。
以上所有看起来一切都很美好,不知道读者看到这里是否意识到?这其中有一个非常大的问题。那就是所有的这些技术提供商都是闭源的、专有的公司。这就存在一个现象:单独厂家锁定!在各个环境之间移植应用程序是非常困难的事情。混合和匹配内部部署和基于云的应用程序几乎是不可能的。
而这个大问题就需要开源来解决!不过也是时机正好。这次依旧是基于Linux之上,即 Docker 和 Kubernetes,而后者更是被人们称之为云时代的Linux。
Docker在2013年出现,将容器的概念迅速扩散。正如当年集装箱点燃了全球的货运革命一样,当时的船运公司使用这种大型的金属集装箱替代了过去纷杂的货运装置,以适应在卡车、船舶、铁路三者之间匹配。装什么无所谓,重要的是装载本身有了标准。
和现实世界的集装箱运输一样,Docker 容器创建了对于应用最为基本的封装,使之可以运行在任何的基础设施平台上。一时之间,Linux容器风靡世界。到今天为止,几乎所有的企业都有意愿将他们的应用跑在容器之上,即使是他们自己的内部的服务器,也同样在考虑。尽管容器仅仅是管理现代的应用程序的一种更好的方式,因为它们通常被分割成无数的组件(微服务),但仍然需要能够在服务器之间进行容易的移植和访问。
技术的本质,通常是解决了一个问题,而又引入新的问题,如此反复。Linux容器也不例外,它虽然封装的很好,但是它给DevOps团队带来前所未有的挑战,它在应用程序的移植、部署的活动中增加的了更多动态的东西。于是Kubernetes应时而生。
2015年,Google 以开源的方式发布了Kubernetes项目,它是Google内部系统Borg的实现。Google 联合Linux基金会成立了云原生计算基金会(CNCF),Kubernetes是此基金会下的第一个种子项目,Kubernetes迅速成为历史上发展最快的开源项目之一,目前拥有数十家公司和组织中成千上万的贡献者。
是什么让Kubernetes如此不可思议的快速增长?恐怕最主要的原因莫过于Kubernetes是Google内部集群系统Borg的再现。这个世界上还很少有哪家的数据中心有Google的规模,Borg 系统平均每周会推出大约20亿个容器,这也就是说每秒钟都会新启动3300个容器。大家可以想象一下高峰期的时候,会比这个数字大得多。是的,没错,Kubernetes就是诞生在这样一个强大的系统之上的,经历过严峻考验的、以应对比这个规模更大的负载!
在确定了 Docker 和 Kubernetes 作为核心之后,CNCF扩展了更多的云原生项目,到目前为止,CNCF拥有大大小小的项目数量达到了369,其中较为重要和成熟的项目有:Kubernetes, Prometheus, OpenTracing, Fluentd, Linkerd, gRPC, CoreDNS, rkt, containerd, Container Networking Interface, CoreDNS, Envoy, Jaeger, Notary, The Update Framework, Rook, 和 Vitess.
然而,作为后起之秀的CNCF,从以往过去的开源项目汲取了很多的经验,CNCF一直非常谨慎,以确保只选择那些能够很好地协同工作并能满足企业和创业公司需求的技术。而且这些技术正在大量采用。
企业拥抱开源技术最大的原因之一就是避免供应商锁定,并实现在多个云平台之间,以及云平台和私有的基础设施之间的容器的平滑移植。基于开源,最终用户可以很容器的切换供应商,也可以使用混合的云平台。如果用户拥有足够的技术能力,甚至都可以自己来进行管理。
Kubernetes和Docker 不仅增强了用户管理大规模负载的能力,而且还能够将大型的、单体应用更加容易的分割为更加易于管理的微服务。分割之后的服务,具备自我管理的功能,可以随时根据需要进行伸缩。微服务还支持更快的部署和更快的迭代,以符合现代持续集成实践。基于Kubernetes的业务流程可以通过动态管理和调度这些微服务来提高效率和资源利用率。它还增加了非凡的弹性水平。用户根本不必担心容器故障,且可以继续按需求进行伸缩。
Kubernetes 迅速成为云原生编排系统的首选,它也成为了开源历史上速度最快的开发项目之一。并得到包括AWS,微软,红帽,SUSE等在内的主要厂商的支持。
所有这些都对企业有直接的影响。具Puppet公司举行的2016年度DevOps形势报告称,高性能的云原生架构可以有更频繁的开发,更短的交付周期,更低的故障率以及更快的故障恢复。这意味着功能可以更快地推向市场,项目可以更快地发挥作用,而工程和开发团队的等待时间则少得多。在今天,如果您要从头开始构建新的应用程序,那么云原生应用程序体系结构就是实现它的最佳途径。同样重要的是,云原生会思考如何利用现有(棕地)应用程序提供了一个路线图,并将它们慢慢转化为运行在容器和Kubernetes上的更为高效和更具弹性的基于微服务的架构。棕地、单体应用其实是构成当今所有软件产品的大部分内容。
单体应用是站在云原生应用的对立面的,它们意味着的陈旧、代价昂贵、臃肿、紧耦合、且不够稳定。问题在于:如何将这些单体应用拆分为微服务架构? 用户或许考虑过重写所有的那些大型的旧版应用,而现实的情况告诉你:大多数重写都以失败告终。你试图重写的第一个系统,即使在你试图替换它时也是存在的,而且一直都在进化。有时候,第一个系统发展得太快,你永远无法赶上。
当然,用户也可以采用更加有效的方法来解决此问题。首先,停止向现有的单体应用程序添加重要的新功能。这里有一个“提升和转移”的概念,也就意味着用户可以将一个需要几GB内存的应用使用容器来封装。是不是很简单!
Ticketmaster 就是实现单体应用转换为容器典型的实例。它的代码运行在非常古老的PDP-11中,首先将创建了一个PDP-11的模拟器,然后使其在Docker中运行,这样就间接的将应用也容器化了。我们知道Kubernetes有一项功能叫做Stateful set(也就是过去的PetSets),此功能可以将某些容器固定的运行在特定的机器中,以确保它能够保持正常运行。
另外,Ticketmaster 还有一个特殊的问题:每当开始售票的时候,当所有人都来访问的时候,这无异于就是发动了分布式拒绝服务(DDoS)攻击。该公司需要一套前端服务器,可以扩展和处理这种需求,而不是试图将其写入他们的旧版应用程序中。最终的解决办法是,在旧版应用程序的前面部署了一套新的基于容器的微服务,进而最大限度地减少了传统体系结构中的持续蔓延。
当你试图将工作负载从旧版程序迁移到容器的时候,可能还想将某些功能从应用程序转移到微服务中,又或者是使用微服务来添加新的功能,而不是添加到旧的代码库中。举个例子,如果您想添加OAuth这项功能,可能只需一个简单的Node.js应用程序可以放在你的旧版应用程序前面即可。如果你有一个高性能敏感的任务,你可以在Golang中编写它,并将其设置为一个驻留的单体应用前,使得API驱动的服务能够生效。仍然可以将API调用返回到你现有的单体应用。
这些新功能可以由不同的团队用更现代的语言编写,这些团队可以使用自己的一套库和依赖关系,并开始拆分原有的单体应用。
来自北卡罗来纳的KeyBanc无疑是这方面最为生动的案例,它在传统的Java应用程序之前部署Node.js应用程序服务器来处理移动客户端。这比为旧版单体应用添加代码,显得更为简单,也更高效,而且有助于确保其基础架构在未来也能良性发展。
如果作为用户的你正在打算拥抱云原生技术的话,那么就应该考虑一下项目互补来交付核心的功能。举个例子,在云原生的环境中,最重要的莫过于监视、追踪和日志。此时就可以考虑诸如Prometheus、OpenTracing 和 Fluentd,Linkerd 是一个service mesh,其可以支持更复杂的路由。gRPC是一个非常高性能的API系统,完全可以替代原有的JSON,且获得更高性能。CoreDNS是一个服务发现平台。所有这些项目均是CNCF的一分子,在未来CNCF会增加更多的项目,为拥抱云原生技术的用户拥有更多选择。
作为开发者的你,或许此时会考虑迁移旧有的单体应道到云原生的微服务,那么恭喜你,你根本毋须完全另起炉灶新写一个,或者重新改写。诸如 Kubernetes 这样的CNCF技术非常拥抱旧有的应用程序,这对于所有的公司和企业来说,都是应该走的进化之路。用户既可以使用Kubernetes来构建一套全新的应用,也可以逐步的将原有的单体应用转化为微服务应用,以在不久的未来担当重要业务的支撑。
注解: 关于绿地(greenfeild)棕地(brownfeild)的解释: 绿地是指软件完全是不受任何原有系统干扰的新的项目,而棕地则表示,在开发新的系统时,要处处引进和考虑旧的系统。
关于原作者
]]>Swapnil Bhartiya 是一名专业的记者和编辑,有超过报道企业开源12年的职业经历。
本文由作者Swapnil Bhartiya 发表在Opensource.com上:How Kubernetes became the solution for migrating legacy applications。由开源之道精心翻译共享。本文在Creative Commons BY-SA 4.0许可证下发布。
Dell服务器的 OMSA (OpenManage Server Administrator )是安装在操作系统中的一套软件,提供硬件监控、驱动程序的升级等操作。
curl -s http://linux.dell.com/repo/hardware/dsu/bootstrap.cgi | bash |
DSU 是为操作更新驱动与软件的服务。
yum install dell-system-update |
yum install srvadmin-all -y |
安装完OMSA后,可以通过访问 https://<本机IP>:000 通过浏览器的方式查看硬件信息,如果机器成百上千台,这种方式的工作效率是非常低的,因此本文介绍通过nagios
插件 check_openmanage 的方式通过命令行检查,当然这个插件可以结合nagios和zabbix使用,有兴趣的同学可以深入学习一下。 下文只简单介绍使用方法
wget http://folk.uio.no/trondham/software/files/check_openmanage-3.7.12.tar.gz |
./check_openmanage -h |
A secure socks5 proxy,designed to protect your Internet traffic.—— 来自 shadowsocks.org
这里只介绍Ubuntu/Debian系统安装 Server 端程序
先添加 GPG public key :$ wget -O- http://shadowsocks.org/debian/1D27208A.gpg | sudo apt-key add -
配置包仓库地址
Debian Wheezy, Ubuntu 12.04 系统 libssl > 1.0.0 执行如下命令:
$ echo "deb http://shadowsocks.org/debian wheezy main" >> /etc/apt/sources.list |
如果操作系统是 Debian Squeeze, Ubuntu 11.04, libssl > 0.9.8, but < 1.0.0 执行下面命令:
$ echo "deb http://shadowsocks.org/debian squeeze main" >> /etc/apt/sources.list |
然后安装
$ apt-get update |
安装GUI 客户端
下载地址:https://github.com/shadowsocks/ShadowsocksX-NG/releases
通过命令行安装
brew install shadowsocks-libev |
编辑站点目录下的themes/layout/index.swig
文件,将下面的代码{% block title %} {{ config.title }} {% endlock %}
改成
{% block title %} {{ config.title }} - {{ theme.description }} {% endlock %} |
这时将网站的描述及关键词加入了网站的title中,更有利于详细地描述网站。
robots.txt是一种存放于网站根目录下的ASCII编码的文本文件,它的作用是告诉搜索引擎此网站中哪些内容是可以被爬取的,哪些是禁止爬取的。robots.txt应该放在站点目录下的source文件中,网站生成后在网站的根目录(站点目录/public/
)下。
我的robots.txt文件内容如下User-agent: *
Allow: /
Allow: /archives/
Allow: /categories/
Allow: /about/
Disallow: /vendors/
Disallow: /js/
Disallow: /css/
Disallow: /fonts/
Disallow: /vendors/
Disallow: /fancybox/
Sitemap即网站地图,它的作用在于便于搜索引擎更加智能地抓取网站。最简单和常见的sitemap形式,是XML文件,在其中列出网站中的网址以及关于每个网址的其他元数据(上次更新时间、更新的频率及相对其他网址重要程度等)。
npm install hexo-generator-sitemap --save |
# hexo sitemap网站地图 |
Sitemap: http://www.jeyzhang.com/sitemap.xml |
]]>
gh-ost
号称是不需要触发器(Triggerless)支持的在线更改表结构的工具。
原文地址:gh-ost: GitHub’s online schema migration tool for MySQL
本文先介绍一下当前业界已经存在的这些工具的使用场景和原理,然后再详细介绍
gh-ost
的工作原理和特性。
今天我们开源了GitHub内部使用的一款 不需要触发器支持的 MySQL 在线更改表结构的工具 gh-ost
开发 gh-ost
是为了应付GitHub在生产环境中面临的持续的、不断变化的在线修改表结构的需求。gh-ost
通过提供低影响、可控、可审计和操作友好的解决方案改变了现有的在线迁移表工具的工作模式。
MySQL表迁移及结构更改操作是业界众所周知的问题,2009年以来已经可以通过在线(不停服务)变更的工具来解决。迅速增长,快速迭代的产品往往需要频繁的需改数据库的结构。增加/更改/删除/ 字段和索引等等,这些操作在MySQL中默认都会锁表,影响线上的服务。 向这种数据库结构层面的变更我们每天都会面临多次,当然这种操作不应该影响用户的正常服务。
在开始介绍 gh-ost
工具之前,咱们先来看一下当前现有的这些工具的解决方案。
如今,在线修改表结构可以通过下面的三种方式来完成:
其他的还包括 Galera 集群的Schema滚动更新,以及一些其他的非InnoDB的存储引擎等待,在 GitHub 我们使用通用的 主-从 架构 和 InnoDB 存储引擎。
为什么我们决定开始一个新的解决方案,而不是使用上面的提到的这些呢?现有的每种解决方案都有其局限性,下文会对这些方式的普遍问题简单的说明一下,但会对基于触发器的在线变更工具的问题进行详细说明。
基于主从复制的迁移方式需要很多的前置工作,如:大量的主机,较长的传输时间,复杂的管理等等。变更操作需要在一个指定的从库上或者基于sub-tree的主从结构中执行。需要的情况也比较多,如:主机宕机、主机从早先的备份中恢复数据、新主机加入到集群等等,所有这些情况都有可能对我们的操作造成影响。最要命的是可能这些操作一天要进行很多次,如果使用这种方法我们操作人员每天的效率是非常高的(译者注:现如今很少有人用这种方式了吧)
MySQL针对Innodb存储引擎的在线DDL操作在开始之前都需要一个短时间排它锁(exclusive)来准备环境,所以alter命令发出后,会首先等待该表上的其它操作完成,在alter命令之后的请求会出现等待waiting meta data lock。同样在ddl结束之前,也要等待alter期间所有的事务完成,也会堵塞一小段时间,这对于繁忙的数据库服务来说危险系数是非常高的。另外DDL操作不能中断,如果中途kill掉,会造成长时间的事务回滚,还有可能造成元数据的损坏。它操作起来并不那么的Nice,不能限流和暂停,在大负载的环境中甚至会影响正常的业务。
我们用了很多年的 pt-online-schema-change
工具。然而随着我们不断增长的业务和流量,我们遇到了很多的问题,我们必须考虑在操作中的哪些 危险操作
(译者注:pt工具集的文档中经常会有一些危险提示)。某些操作必须避开高峰时段来进行,否则MySQL可能就挂了。所有现存的在线表结构修改的工具都是利用了MySQL的触发器来执行的,这种方式有一些潜藏的问题。
所有在线表结构修改工具的操作方式都类似:创建与原表结构一致的临时表,该临时表已经是按要求修改后的表结构了,缓慢增量的从原表中复制数据,同时记录原表的更改(所有的 INSERT, DELETE, UPDATE 操作) 并应用到临时表。当工具确认表数据已经同步完成,它会进行替换工作,将临时表更名为原表。
pt-online-schema-change
, LHM
和 oak-online-alter-table
这些工具都使用同步的方式,当原表有变更操作时利用一些事务的间隙时间将这些变化同步到临时表。Facebook 的工具使用异步的方式将变更写入到changelog表中,然后重复的将changelog表的变更应用到临时表。所有的这些工具都使用触发器来识别原表的变更操作。
当表中的每一行数据有 INSERT, DELETE, UPDATE 操作时都会调用存储的触发器。一个触发器可能在一个事务空间中包含一系列查询操作。这样就会造成一个原子操作不单会在原表执行,还会调用相应的触发器执行多个操作。
在基于触发器迁移实践中,遇到了如下的问题:
触发器是以解释型代码的方式保存的。MySQL 不会预编译这些代码。 会在每次的事务空间中被调用,它们被添加到被操作的表的每个查询行为之前的分析和解释器中。
锁表: 触发器在原始表查询中共享相同的事务空间,而这些查询在这张表中会有竞争锁,触发器在另外一张表会独占竞争锁。在这种极端情况下,同步方式的锁争夺直接关系到主库的并发写性能。以我们的经验来说,在生产环境中当竞争锁接近或者结束时,数据库可能会由于竞争锁而被阻塞住。触发锁的另一个方面是创建或销毁时所需要的元数据锁。我们曾经遇到过在繁忙的表中当表结构修改完成后,删除触发器可能需要数秒到分钟的时间。
不可信:当主库的负载上升时,我们希望降速或者暂停操作,但基于触发器的操作并不能这么做。虽然它可以暂停行复制操作,但却不能暂停出触发器,如果删除触发器可能会造成数据丢失,因此触发器需要在整个操作过程中都要存在。在我们比较繁忙的服务器中就遇到过由于触发器占用CPU资源而将主库拖死的例子。
并发迁移: 我们或者其他的人可能比较关注多个同时修改表结构(不同的表)的场景。鉴于上述触发器的开销,我们没有兴趣同时对多个表进行在线修改操作,我们也不确定是否有人在生产环境中这样做过。
测试:我们修改表结构可能只是为了测试,或者评估其负载开销。基于触发器的表结构修改操作只能通过基于语句复制的方式来进行模拟实验,离真实的主库操作还有一定的距离,不能真实的反映实际情况。
gh-ost
GitHub 的在线 Schema 修改工具,下面工作原理图:
gh-ost
具有如下特性:
gh-ost
没有使用触发器。它通过分析binlog日志的形式来监听表中的数据变更。因此它的工作模式是异步的,只有当原始表的更改被提交后才会将变更同步到临时表(ghost table)
gh-ost
要求binlog是RBR格式 ( 基于行的复制);然而也不是说你就不能在基于SBR(基于语句的复制)日志格式的主库上执行在线变更操作。实际上是可以的。gh-ost 可以将从库的 SBR日志转换为RBR日志,只需要重新配置就可以了。
由于没有使用触发器,因此在操作的过程中对主库的影响是最小的。当然在操作的过程中也不用担心并发和锁的问题。 变更操作都是以流的形式顺序的写到binlog文件中,gh-ost只是读取他们并应用到gh-ost表中。实际上,gh-ost 通过读取binlog的写事件来进行顺序的行复制操作。因此,主库只会有一个单独连接顺序的将数据写入到临时表(ghost table)。这和ETL操作有很大的不同。
所有的写操作都是由gh-ost控制的,并且以异步的方式读取binlog,当限速的时候,gh-ost可以暂停向主库写入数据,限速意味着不会在主库进行复制,也不会有行更新。当限速时gh-ost会创建一个内部的跟踪(tracking)表,以最小的系统开销向这个表中写入心跳事件
gh-ost 支持多种方式的限速:
pt-online-schema-change
工具的用户提供了类似的功能,可以设置MySQL中的状态阈值,如 Threads_running=30gh-ost
内置了心跳机制,可以指定不同的从库,从而对主从的复制延迟时间进行监控,如果达到了设定的延迟阈值程序会自动进入限速模式。SELECT HOUR(NOW()) BETWEEN 8 and 17
这样就可以动态的设置限流时间。gh-ost
(下文会提到) 通过网络连接的方式实现限速。现在的工具,当执行操作的过程中发现负载上升了,DBA不得不终止操作,重新配置参数,如 chunk-size,然后重新执行操作命令,我们发现这种方式效率非常低。
gh-ost
可以通过 unix socket 文件或者TCP端口(可配置)的方式来监听请求,操作者可以在命令运行后更改相应的参数,参考下面的例子:
echo throttle | socat - /tmp/gh-ost.sock
打开限速,同样的,可以使用 no-throttle
来关闭限流。chunk-size=1500
, max-lag-millis=2000
, max-load=Thread_running=30
这些参数都可以在运行时变更。同样的,使用上文提到的程序接口可以获取 gh-ost
的状态。gh-ost
可以报告当前的进度,主要参数的配置以及当前服务器的标示等等。这些信息都可以通过网络接口取到,相对于传统的tail日志的方式要灵活很多。
因为日志文件和主库负载关系不大,因此在从库上执行修改表结构的操作可以更真实的体现出这些操作锁产生的实际影响。(虽然不是十分理想,后续我们会做优化工作)。
gh-ost
內建支持测试功能,通过使用 --test-on-replica
的参数来指定: 它可以在从库上进行变更操作,在操作结束时gh-ost
将会停止复制,交换表,反向交换表,保留2个表并保持同步,停止复制。可以在空闲时候测试和比较两个表的数据情况。
这是我们在GitHub的生产环境中的测试:我们生产环境中有多个从库;部分从库并不是为用户提供服务的,而是用来对所有表运行的连续覆盖迁移测试。我们生产环境中的表,小的可能没有数据,大的会达到数百GB,我们只是做个标记,并不会正在的修改表结构(engine=innodb)。当每一个迁移结束后会停止复制,我们会对原表和临时表的数据进行完整的checksum确保他们的数据一致性。然后我们会恢复复制,再去操作下一张表。我们的生产环境的从库中已经通过 gh-ost 成功的操作了很多表。
上文提到说了这么多,都是为了提高大家对 gh-ost
的信任程度。毕竟在业界它还是一个新手,类似的工具已经存在了很多年了。
在第一次试手之前我们建议用户先在从库上测试,校验数据的一致性。我们已经在从库上成功的进行了数以千计的迁移操作。
如果在主库上使用 gh-ost
用户可以实时观察主库的负载情况,如果发现负载变化很大,可以通过上文提到的多种形式进行限速,直到负载恢复正常,然后再通过命令微调参数,这样可以动态的控制操作风险。
如果迁移操作开始后预完成计时间(ETA)显示要到夜里2点才能完成,结束时候需要切换表,你是不是要留下来盯着?你可以通过标记文件让gh-ost推迟切换操作。gh-ost 会完成行复制,但并不会切换表,它会持续的将原表的数据更新操作同步到临时表中。你第二天来到办公室,删除标记文件或者通过接口 echo unpostpone
告诉gh-ost开始切换表。我们不想让我们的软件把使用者绑住,它应该是为我们拜托束缚。
说到 ETA, --exact-rowcount
参数你可能会喜欢。相对于一条漫长的 SELECT COUNT(*)
语句,gh-ost 会预估出迁移操作所需要花费的时间,还会根据当前迁移的工作状况更新预估时间。虽然ETA的时间随时更改,但进度百分比的显示是准确的。
gh-ost 可以同时连接多个服务器,为了获取二进制的数据流,它会作为一个从库,将数据从一个库复制到另外一个。它有各种不同的操作模式,这取决于你的设置,配置,和要运行迁移环境。
这是 gh-ost 默认的工作方式。gh-ost 将会检查从库状态,找到集群结构中的主库并连接,接下来进行迁移操作:
如果你的主库的日志格式是 SBR,工具也可以正常工作。但从库必须启用二级制日志(log_bin, log_slave_updates) 并且设置 binlog_format=ROW
( gh-ost 是读取从库的二级制文件)。
如果直接在主库上操作,当然也需要二进制日志格式是RBR。
如果你没有从库,或者不想使用从库,你可以直接在主库上操作。gh-ost
将会直接在主库上进行所有操作。你需要持续关注复制延迟问题。
--allow-on-master
参数该模式会在从库执行迁移操作。gh-ost 会简单的连接到主库,此后所有的操作都在从库执行,不会对主库进行任何的改动。整个操作过程中,gh-ost 将控制速度保证从库可以及时的进行数据同步
--migrate-on-replica
表示 gh-ost 会直接在从库上进行迁移操作。即使在复制运行阶段也可以进行表的切换操作。--test-on-replica
表示 迁移操作只是为了测试在切换之前复制会停止,然后会进行切换操作,然后在切换回来,你的原始表最终还是原始表。两个表都会保存下来,复制操作是停止的。你可以对这两个表进行一致性检查等测试操作。我们已经在所有线上所有的数据库在线操作中使用了gh-ost ,我们每天都需要使用它,根据数据库修改需求,可能每天要运行多次。凭借其审计和控制功能我们已经将它集成到了ChatOps流程中。我们的工程师可以清醒的了解到迁移操作的进度,而且可以灵活的控制其行为。
虽然gh-ost在使用中很稳定,我们还在不断的完善和改进。我们将其开源也欢迎社会各界的朋友能够参与和贡献。随后我们会发布 贡献和建议的页面。
我们会积极的维护 gh-ost 项目,同时希望广大的用户可以尝试和测试这个工具,我们做了很大努力使之更值得信赖。
gh-ost 是MySQL业界在线修改表结构工具中的一名新秀,通常我们都是通过Percona的pt-online-schema-change工具来做这项工作,gh-ost的出现给我们带来了一种全新的方式。本文是翻译了一篇gh-ost的介绍文章,还没有尝试过这个工具。欢迎喜欢尝鲜网友谈谈使用感受。
]]>客户端配置比较简单,只需要配置一下server的地址就可以了,复杂的配置等到以后遇到的适合在进行介绍
# 配置salt服务端地址 |
# 查看有哪些client发起了验证请求 |
salt aws-bj* cmd.run uptime |
最新的salt包会发布在 Ubuntu saltstack PPA。如果你的系统中有add-apt-repository
工具,可以通过一条命令添加仓库并导入PPA key:
add-apt-repository ppa:saltstack/salt |
如果没有找到add-apt-repository命令可以执行下面的命令进行安装
apt-get install python-software-properties可能也需要安装下面的包
apt-get install software-properties-common
echo deb http://ppa.launchpad.net/saltstack/salt/ubuntu `lsb_release -sc` main | sudo tee /etc/apt/sources.list.d/saltstack.list |
apt-get update |
apt-get install salt-master salt-minion salt-syndic |
apt-get install salt-minion |
ZeroMQ 4 在 Ubuntu 14.04 以上版本已经与系统集成。因此Ubuntu 12.04 LTS 之前的版本需要升级到ZEROMQ 4
]]>利用iptables-save命令可以将iptable规则保存到一个持久化存储的目录中,不同的系统保存的目录也有所不同(IPv4):
Debian/Ubuntu: iptables-save
> /etc/iptables/rules.v4
RHEL/CentOS: iptables-save
> /etc/sysconfig/iptables
保存之后,可以通过iptables-restore命令载入(IPv4):
Debian/Ubuntu: iptables-restore
< /etc/iptables/rules.v4
RHEL/CentOS: iptables-restore
< /etc/sysconfig/iptables
上面是针对IPv5的规则,如果你有使用IPv6的规则,通常需要执行下面对应的IPv6保存和恢复的命令(IPv4:
Debian/Ubuntu: ip6tables-save
> /etc/iptables/rules.v6
RHEL/CentOS: ip6tables-save
> /etc/sysconfig/ip6tables
注意: 这种方式只是保存规则和恢复的一种方式,并不是说保存规则后下次启动就会自动加载。一定要记住这点,如果要想系统启动后自动加载请看下面的方式。
从 Ubuntu 10.04 LTS (Lucid) 和 Debian 6.0 (Squeeze) 版本开始,可以通过安装一个名为 “iptables-persistent” 的包,安装后它以守护进程的方式来运行,系统重启后可以自动将保存的内容加载到iptables中。当然前提也是需要先保存规则。
apt-get install iptables-persistent |
service iptables-persistent save |
RHEL/CentOS 提供了简单的方式来持久化存储iptables规则,可以直接通过iptables服务的命令来完成:
chkconfig --list | grep iptables |
IPv4规则信息会保存到 /etc/sysconfig/iptables 文件中,IPv6 规则保存到 /etc/sysconfig/ip6tables 文件中。 必须执行service iptables save
命令才会保存,保存后系统重启后会自动加载。
db01 (主)
db02 (从)
时间 | 备份类型 |
---|---|
00:01 | 全量备份 |
01:01 | 增量备份(当天首次) |
02:01~23:01 | 增量备份 |
随着数据量的增加,全量备份可以做成每周一次,每2~8小时一次增量备份
db{01,02}:/data/backup/{full,incremental}/
backup/ |
# Info : 数据库备份 |
/root/bin/bakdb.sh
|
innobackupex --user=root --defaults-file=/usr/local/mysql/my.cnf --apply-log /data/backup/full/2015-08-16 |
innobackupex --defaults-file=/usr/local/mysql/my.cnf --user=root --apply-log --redo-only /data/backup/full/2015-08-16 |
这里是我过去几年中编写的大量 Go 代码的经验总结而来的自己的最佳实践。我相信它们具有弹性的。这里的弹性是指:
某个应用需要适配一个灵活的环境。你不希望每过 3 到 4 个月就不得不将它们全部重构一遍。添加新的特性应当很容易。许多人参与开发该应用,它应当可以被理解,且维护简单。许多人使用该应用,bug 应该容易被发现并且可以快速的修复。我用了很长的时间学到了这些事情。其中的一些很微小,但对于许多事情都会有影响。所有这些都仅仅是建议,具体情况具体对待,并且如果有帮助的话务必告诉我。随时留言:)
多个 GOPATH 的情况并不具有弹性。GOPATH 本身就是高度自我完备的(通过导入路径)。有多个 GOPATH 会导致某些副作用,例如可能使用了给定的库的不同的版本。你可能在某个地方升级了它,但是其他地方却没有升级。而且,我还没遇到过任何一个需要使用多个 GOPATH 的情况。所以只使用单一的 GOPATH,这会提升你 Go 的开发进度。
许多人不同意这一观点,接下来我会做一些澄清。像 etcd 或 camlistore 这样的大项目使用了像 godep 这样的工具,将所有依赖保存到某个目录中。也就是说,这些项目自身有一个单一的 GOPATH。它们只能在这个目录里找到对应的版本。除非你的项目很大并且极为重要,否则不要为每个项目使用不同的 GOPATH。如果你认为项目需要一个自己的 GOPATH 目录,那么就创建它,否则不要尝试使用多个 GOPATH。它只会拖慢你的进度。
如果在某个条件下,你需要从 for-select 中退出,就需要使用标签。例如:
func main() { |
如你所见,需要联合break使用标签。这有其用途,不过我不喜欢。这个例子中的 for 循环看起来很小,但是通常它们会更大,而判断break的条件也更为冗长。
如果需要退出循环,我会将 for-select 封装到函数中:
func main() { |
你还可以返回一个错误(或任何其他值),也是同样漂亮的,只需要:
// 阻塞 |
这是一个无标签语法的例子:
type T struct { |
那么如果你添加一个新的字段到T结构体,代码会编译失败:
type T struct { |
如果使用了标签语法,Go 的兼容性规则(http://golang.org/doc/go1compat)会处理代码。例如在向net包的类型添加叫做Zone的字段,参见:http://golang.org/doc/go1.1#library。回到我们的例子,使用标签语法:
type T struct { |
这个编译起来没问题,而且弹性也好。不论你如何添加其他字段到T结构体。你的代码总是能编译,并且在以后的 Go 的版本也可以保证这一点。只要在代码集中执行go vet,就可以发现所有的无标签的语法。
如果有两个以上的字段,那么就用多行。它会让你的代码更加容易阅读,也就是说不要:
T{Foo: "example", Bar:someLongVariable, Qux:anotherLongVariable, B: forgetToAddThisToo} |
而是:
T{ |
这有许多好处,首先它容易阅读,其次它使得允许或屏蔽字段初始化变得容易(只要注释或删除它们),最后添加其他字段也更容易(只要添加一行)。
如果你利用 iota 来使用自定义的整数枚举类型,务必要为其添加 String() 方法。例如,像这样:
type State int |
如果你创建了这个类型的一个变量,然后输出,会得到一个整数(http://play.golang.org/p/V5VVFB05HB):
func main() { |
除非你回顾常量定义,否则这里的0看起来毫无意义。只需要为State类型添加String()方法就可以修复这个问题(http://play.golang.org/p/ewMKl6K302):
func (s State) String() string { |
新的输出是:state: Running。显然现在看起来可读性好了很多。在你调试程序的时候,这会带来更多的便利。同时还可以在实现 MarshalJSON()、UnmarshalJSON() 这类方法的时候使用同样的手段。
在前面的例子中同时也产生了一个我已经遇到过许多次的 bug。假设你有一个新的结构体,有一个State字段:
type T struct { |
现在如果基于 T 创建一个新的变量,然后输出,你会得到奇怪的结果(http://play.golang.org/p/LPG2RF3y39):
func main() { |
看到 bug 了吗?State字段没有初始化,Go 默认使用对应类型的零值进行填充。由于State是一个整数,零值也就是0,但在我们的例子中它表示Running。
那么如何知道 State 被初始化了?还是它真得是在Running模式?没有办法区分它们,那么这就会产生未知的、不可预测的 bug。不过,修复这个很容易,只要让 iota 从 +1 开始(http://play.golang.org/p/VyAq-3OItv):
const ( |
现在t变量将默认输出Unknown,不是吗? :)
func main() { |
不过让 iota 从零值开始也是一种解决办法。例如,你可以引入一个新的状态叫做Unknown,将其修改为:
const ( |
我已经看过很多代码例如(http://play.golang.org/p/8Rz1EJwFTZ):
func bar() (string, error) { |
然而,你只需要:
func bar() (string, error) { |
更简单也更容易阅读(当然,除非你要对某些内部的值做一些记录)。
将 slice 或 map 定义成自定义类型可以让代码维护起来更加容易。假设有一个Server类型和一个返回服务器列表的函数:
type Server struct { |
现在假设需要获取某些特定名字的服务器。需要对 ListServers() 做一些改动,增加筛选条件:
// ListServers 返回服务器列表。只会返回包含 name 的服务器。空的 name 将会返回所有服务器。 |
现在可以用这个来筛选有字符串Foo的服务器:
func main() { |
显然这个函数能够正常工作。不过它的弹性并不好。如果你想对服务器集合引入其他逻辑的话会如何呢?例如检查所有服务器的状态,为每个服务器创建一个数据库记录,用其他字段进行筛选等等……
现在引入一个叫做Servers的新类型,并且修改原始版本的 ListServers() 返回这个新类型:
type Servers []Server |
现在需要做的是只要为Servers类型添加一个新的Filter()方法:
// Filter 返回包含 name 的服务器。空的 name 将会返回所有服务器。 |
现在可以针对字符串Foo筛选服务器:
func main() { |
哈!看到你的代码是多么的简单了吗?还想对服务器的状态进行检查?或者为每个服务器添加一条数据库记录?没问题,添加以下新方法即可:
func (s Servers) Check() |
有时对于函数会有一些重复劳动,例如锁/解锁,初始化一个新的局部上下文,准备初始化变量等等……这里有一个例子:
func foo() { |
如果你想要修改某个内容,你需要对所有的都进行修改。如果它是一个常见的任务,那么最好创建一个叫做withContext的函数。这个函数的输入参数是另一个函数,并用调用者提供的上下文来调用它:
func withLockContext(fn func()) { |
只需要将之前的函数用这个进行封装:
func foo() { |
不要光想着加锁的情形。对此来说最好的用例是数据库链接。现在对 withContext 函数作一些小小的改动:
func withDBContext(fn func(db DB) error) error { |
如你所见,它获取一个连接,然后传递给提供的参数,并且在调用函数的时候返回错误。你需要做的只是:
|
你在考虑一个不同的场景,例如作一些预初始化?没问题,只需要将它们加到withDBContext就可以了。这对于测试也同样有效。
这个方法有个缺陷,它增加了缩进并且更难阅读。再次提示,永远寻找最简单的解决方案。
如果你重度使用 map 读写数据,那么就为其添加 getter 和 setter 吧。通过 getter 和 setter 你可以将逻辑封分别装到函数里。这里最常见的错误就是并发访问。如果你在某个 goroutein 里有这样的代码:
m["foo"] = bar |
还有这个:
delete(m, "foo") |
会发生什么?你们中的大多数应当已经非常熟悉这样的竞态了。简单来说这个竞态是由于 map 默认并非线程安全。不过你可以用互斥量来保护它们:
mu.Lock() |
以及:
mu.Lock() |
假设你在其他地方也使用这个 map。你必须把互斥量放得到处都是!然而通过 getter 和 setter 函数就可以很容易的避免这个问题:
func Put(key, value string) { |
使用接口可以对这一过程做进一步的改进。你可以将实现完全隐藏起来。只使用一个简单的、设计良好的接口,然后让包的用户使用它们:
type Storage interface { |
这只是个例子,不过你应该能体会到。对于底层的实现使用什么都没关系。不光是使用接口本身很简单,而且还解决了暴露内部数据结构带来的大量的问题。
但是得承认,有时只是为了同时对若干个变量加锁就使用接口会有些过分。理解你的程序,并且在你需要的时候使用这些改进。
抽象永远都不是容易的事情。有时,最简单的就是你已经实现的方法。要知道,不要让你的代码看起来很聪明。Go 天生就是个简单的语言,在大多数情况下只会有一种方法来作某事。简单是力量的源泉,也是为什么在人的层面它表现的如此有弹性。
如果必要的话,使用这些基数。例如将[]Server转化为Servers是另一种抽象,仅在你有一个合理的理由的情况下这么做。不过有一些技术,如 iota 从 1 开始计数总是有用的。再次提醒,永远保持简单。
特别感谢 Cihangir Savas、Andrew Gerrand、Ben Johnson 和 Damian Gryski 提供的极具价值的反馈和建议。
]]>阿里云的VPC与其他基于OpenStack的IaaS不同,他的路由只是作为多网段的路由交换,不提供内到外的路由,因此在VPC内的主机除非绑定EIP,否则是无法连接公网的。通过工单询问客服,得到的结论是通过在路由器上添加一个路由,通过一个绑定EIP的主机做NAT上网,通过设置iptables的方式来实现。
为了让内网服务器借助EIP访问公网,所以设置所有目标地址0.0.0.0/0下一跳都转发到绑定了公网IP的ECS实例上。这里的下一跳ECS不支持搜索,需要提前记号名称:
iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -o eth0 -j MASQUERADE |
注意: ubuntu 14.04 系统保存iptables设置需要安装iptables-persistent包,然后通过
service iptables-persistent save
的方式保存配置,安装完iptables-persistent后该服务随系统一起启动并会把保存的配置应用
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf && sysctl -p |
# 定义一个空数组 |
说明:
默认数组中的元素是以空格分隔的,如果元素是包含空格的字符串,最好用双引号括起来
shell中的默认分隔符可以通过修改 $IFS变量来设置
# 初始化并赋值数组 |
# 切片 |
- 切片(分片): 直接通过 ${数组名[@或*]:起始位置:长度} 切片原先数组,返回是字符串,中间用“空格”分开,因此如果加上”()”,将得到切片数组,上面例子:c 就是一个新数据。
- 替换: ${数组名[@或*]/查找字符/替换字符} 该操作不会改变原先数组内容,如果需要修改,请重新定义变量并赋值。
在一个多域名的web server环境中,通过分析访问日志,统计最近8小时有用户访问的域名(去重),并显示。
日志格式:X-Forworld-IP User-IP YYYY-MM-DD HH:mm:ss method “URL” HTTP响应码 服务器处理时间 返回大小 “Refer” “浏览器信息” “虚拟主机域名” 真实处理请求的主机
|
最近5年由于工作原因也没有顾得上更新blog,近期会有一系列文档更新,都是这五年来的一些工作经验。
由于大家共识的原因,本blog于2015-08-02正式迁移到GitHub
]]>