编译丨千山
3月底,在云界有一件盛事发生。
亚马逊云科技于3月30日举办亚马逊云科技创新大会。据会议信息显示,这届大会的高主题是“全面拥抱Serverless时代”。
有心的朋友应该注意到了,从去年到今年,无论是此前的AWS re:Invent大会还是阿里云云栖大会,抑或是即将召开的这个会议,Serverless都是当仁不让的主角。
不管是AWS还是阿里云,都在坚定推进核心产品全面Serverless化。中美两大云巨头同时押Serverless,无疑是在向全行业传递出这样的信号:Serverless 是云计算的未来。
那么Serverless真有这么香吗?
“无服务器(Serverless)”这个概念最早出现在2012年,但真正为人熟知却始于——2014年Amazon Lambda服务推出时,时至今日,这一理念已经成为业内热词。
所谓“无服务器”,并不是指真的无需服务器,其指代的更多是一种云应用程序开发和执行模型。允许开发人员构建和运行代码,而无需管理服务器,也无需为闲置的云基础架构付费。
当选择无服务器和Lambda来搭建云架构时,你需要了解固有的限制,以便在应用程序和代码的规模以及复杂性开始增长时进行扩展。
在构建应用程序代码时,无服务器是快速升级的一个好选择,但有一个常见的误解,即无服务器意味着DevOpsLess或NoOps,而事实并非如此。
更重要的是,有时你必须提前在设计和架构上进行投资,以避免后来遇到瓶颈或招致大量技术债务。
当应用程序开始增长时,如果你不提前计划,很快就会遇到无服务器范式特有的挑战。很多人在开始尝试无服务器时很可能意识不到,为什么他们需要提前设计。
Lambda节流是可以同时运行的实例数量的结果。
AWS Lambda默认一个账户的区域并发限制为1000,也就是可以同时处理1000个请求。一旦到达上限,新的请求会被节流。当然你可以请求提高此阈值,不过要注意,这会产生成本影响。因此在检查架构设计并确保你确实需要它之前,不应自动提高阈值。
需要直面的现实是,你同时运行的事件或服务越多,你就会越快地遇到瓶颈。如果你计划安全在无服务器架构上运行,那么就有必要在编写第一行代码的时候就考虑到这一点。
即使今天你只需要满足小规模请求的设计,但必须尽早考虑,当你有数千个(甚至更多)租户或客户时,这是否会线性缩放。根据构建资源、Lambda和微服务的方式(以及每个服务的“微”程度),如果将服务分解为太小的块,则最终可能会由于过多并行事件的限制而中断整个服务链流。
这意味着需要充分了解当前正在处理的流量(以每分钟事件的形式),甚至是服务处理的峰值和异常流量。所有这些都需要考虑,此外还需要考虑每种调用所采用的通信调用方法——同步或异步(稍后会更深入地研究)——其中,使用同步调用,每个服务或系统调用都会叠加起来,并可能使系统过载。
重要的是要意识到节流的工作方式并不是完全可预测的。因此,即使你有适当的监视以确保你不会达到1000个并行事件,并且你认为你已经覆盖了,但这实际上可能在你的第一个峰值时发生,其中节流可能发生在更低的阈值,因为这本质上是意外行为(但在AWS文档中有记录)。因此,一个好的实践是,以一种能够在这种情况发生时恢复的方式构建你的系统(例如等幂性和重试)。
顾名思义,无服务器不运行在永远运行的服务器上,它们提供临时运行时,函数运行时最多只有15分钟的总窗口。这可能会影响服务可以处理的输入的大小。当你从头开始设计函数时,输入的大小随着处理时间的增加而不断增加,你可能会在运行时遇到超时。
因此,对于运行时随输入大小线性扩展的服务或函数,建议的设计模式是将输入拆分为块或批处理,并在不同的Lambda中处理它们。这样做时,使用队列也是一个很好的实践,从而避免节流。
事件驱动的设计模式在基于无服务器的系统中很常见,很多时候需要链中的各种服务来进行事件处理,包括API网关、SQS(Amazon Simple Queue Service)、事件桥接器、SNS(Amazon 的发布/订阅服务),其中每种服务都有不同的事件大小限制。你使用的每个资源可能都有需要注意的不同大小限制,在发送大型有效负载时,沿链传递数据可能会中断。
这意味着你不能在资源之间发送无限的有效负载,并且在构建函数和服务时需要注意这一点。链中的每一个资源都能够处理不同大小的有效负载,这意味着如果不提前考虑这一点,并确保可以在系统服务和资源中接收此有效负载,则会遇到失败事件。
一种解决方案,本质上是一种变通方法,可以通过利用支持有效负载大小的不同资源,在S3存储桶中传递大型有效负载。(提示:搜索“AWS 服务配额”以了解有关你使用的资源的更多信息,这是一个很好的入门参考)
所谓的幂等性,是分布式环境下的一个常见问题,一般是指我们在进行多次操作时,所得到的结果是一样的,即多次运算结果是一致的。也就是说,用户对于同一操作,无论是发起一次请求还是多次请求,最终的执行结果是一致的,不会因为多次点击而产生副作用。
由于前文中列出的所有挑战,故障总是会发生,因此会出现延迟。Lambdas和无服务器资源通常构建在重试机制上。这就是幂等性至关重要的地方。服务需要为给定的输入交付相同的结果,无论它们被重试或部分重试了多少次(这意味着即使只重试了流的一部分,结果仍然需要相同)。
你需要提前设计幂等性,以便重试和重放不会影响生产系统的状态。一个好的做法是确保在运行数据时为每个实例创建唯一的但不随机的确定性ID。这是正确执行此操作的良好指南。
若要了解内存泄漏是如何发生的,首先需要了解运行代码的机制是如何工作的,因为它也有其局限性。对于Lambda函数,相同的Lambda运行程序会被一次又一次地重用,直到它死去。也许它可以完美运行1000次,但它可能会在第1001次运行时开始崩溃,并可能导致你的服务出现问题。
例如,使用相同解释器的Python代码会被反复使用。如果这段代码在每个运行中都添加全局内存对象,这些对象可能会通过不同的运行实例传递,这可能会导致内存泄漏,即超出实例内存限制。然后你的Lambda就会崩溃。
在使用共享资源和多租户架构时,这一点尤其重要。你需要确保不会留下未使用的资源、敏感数据或其他垃圾。在租户隔离方面,如果使用共享内存,则需要非常小心,确保数据不会在实例之间泄漏,因为数据可能会在租户之间泄漏。
无服务器中的同步调用可能会导致许多问题(比如前文中提到的“节流”)。在可能且不需要立即响应的情况下,异步调用模式是无服务器的首选模式。
无服务器通常被设计成异步和无状态的,而不是同步和有状态的,因此发挥技术的优势总是最好的。当你确实需要同步调用时,请确保有适当的保护措施(如使用API网关),并通过适当的日志记录获得可见性。
对于那些希望快速运行、专注于交付和推出产品、不想在基础设施管理上耗费过多的人来说,无服务器是一个很好的选择。不过在选择运行无服务器时,你需要记住,这意味着使用许多不同的AWS资源,了解每种资源如何独立工作、如何协同工作以及它们的局限性和缺陷非常有必要。
要发挥无服务器的优势,需要建设适当的“护栏”,从而尽可能规避上述问题。
首先,与不可预测的动态云环境中的所有云原生应用程序一样,对于无服务器应用程序,通过监控、日志记录和追踪,确保对应用程序的工作方式具有适当的可见性尤为重要。
再者,谈到在无服务器上运行时,另一个常见且不容忽视的问题是成本。设计和构建应用程序的方式也会直接影响成本。你需要有适当的机制,以避免过度滥用资源,从计费警报和常规的具有成本意识的系统设计开始,这是无服务器的一个极其重要的实践。
另外,确保安全性和数据隐私也很重要,以免在使用共享资源和多租户时危及关键数据。有一些优秀的DevSecOps工具可以帮助你做到这一点。
当你了解了无服务器的工作原理后,你可以优化设计、架构和应用程序代码,进而实现显著的成本改进,同时获得更好的性能、安全性和容错能力。
Lambda的推出开启了云计算的新时代,随后,微软、谷歌、IBM等大厂也先后推出了自己的Serverless产品。云产品的全面Serverless化逐渐成为时之所趋。
一旦Serverless进入规模化使用阶段,一方面,资源的使用由平台统一调度,按需使用,整个云计算资源的使用成本有望实现大幅降低;另一方面,编程方式会随着Serverless的发展产生很大不同。我们有理由相信,Serverless将成为IT基础设施变革中不可轻忽的拐点。
参考链接:https://thenewstack.io/serverless-doesnt-mean-devopsless-or-noops/
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru
在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo
我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b
您如何在Rails中的实时服务器上进行有效调试,无论是在测试版/生产服务器上?我试过直接在服务器上修改文件,然后重启应用,但是修改好像没有生效,或者需要很长时间(缓存?)我也试过在本地做“脚本/服务器生产”,但是那很慢另一种选择是编码和部署,但效率很低。有人对他们如何有效地做到这一点有任何见解吗? 最佳答案 我会回答你的问题,即使我不同意这种热修补服务器代码的方式:)首先,你真的确定你已经重启了服务器吗?您可以通过跟踪日志文件来检查它。您更改的代码显示的View可能会被缓存。缓存页面位于tmp/cache文件夹下。您可以尝试手动删除
require"socket"server="irc.rizon.net"port="6667"nick="RubyIRCBot"channel="#0x40"s=TCPSocket.open(server,port)s.print("USERTesting",0)s.print("NICK#{nick}",0)s.print("JOIN#{channel}",0)这个IRC机器人没有连接到IRC服务器,我做错了什么? 最佳答案 失败并显示此消息::irc.shakeababy.net461*USER:Notenoughparame
我有一个使用PDFKit呈现网页的pdf版本的Rails应用程序。我使用Thin作为开发服务器。问题是当我处于开发模式时。当我使用“bundleexecrailss”启动我的服务器并尝试呈现任何PDF时,整个过程会陷入僵局,因为当您呈现PDF时,会向服务器请求一些额外的资源,如图像和css,看起来只有一个线程.如何配置Rails开发服务器以运行多个工作线程?非常感谢。 最佳答案 我找到的最简单的解决方案是unicorn.geminstallunicorn创建一个unicorn.conf:worker_processes3然后使用它:
关于如何使用git设置类似Dropbox的服务,您有什么建议吗?您认为git是解决此问题的合适工具吗?我在考虑使用git+rush解决方案,你觉得怎么样? 最佳答案 检查这个开源项目:https://github.com/hbons/SparkleShare来自项目的自述文件:Howdoesitwork?SparkleSharecreatesaspecialfolderonyourcomputer.Youcanaddremotelyhostedfolders(or"projects")tothisfolder.Theseprojec
我将以下代码放在一起用于一个简单的RubyTFTP服务器。它工作正常,因为它监听端口69并且我的TFTP客户端连接到它,我能够将数据包写入test.txt,但我不只是写入数据包,我希望能够从我的客户端通过TFTP传输文件到/temp目录。预先感谢您的帮助!require'socket.so'classTFTPServerdefinitialize(port)@port=portenddefstart@socket=UDPSocket.new@socket.bind('',@port)whiletruepacket=@socket.recvfrom(1024)putspacketFile