草庐IT

无需修改代码,用 fcapp.run 运行你的 REST 应用

Serverless社区 2023-03-28 原文

作者 | 阿里云 Serverless 技术研发 落语

背景

阿里云函数计算产品在较早的时候支持了HTTP触发器能力,支持用户使用 HTTP 协议进行函数调用。函数计算后端通过一个共享的 APIServer 组件对所有客户提供响应 HTTP 触发器调用的服务,需要依赖 URL 中的 Path 将客户流量路由到客户的函数容器内部。容器内收到的 HTTP 请求 Path 会带有函数计算的路由标识,如果客户在函数计算部署 REST 风格的应用,那么就会遇见 404 问题。

在一开始,函数计算并不是为客户运行中小型规模应用而设计的。函数计算提供了原生的 REST 架构,将每个函数视为一个独立的资源,通常一个函数只负责一小块功能,也就是一个 API。如果一个函数只对应一个 API,那么在函数代码中也不必去实现一套路由逻辑去响应不同 URL Path 路径的请求了。

函数计算在近两年引入了Custom Runtime/Custom Container Runtime类型的函数,客户可以直接在函数计算上运行自己存量的应用,而不必按照函数计算推荐的架构去拆分自己的应用。客户以及社区内比较成熟的项目的开发习惯是采用MVC等架构,在一个程序中开发大量的REST API,在进程内按照报文中的HTTP Path进行路由,将不同路径的请求“转发”至不同的方法或函数进行处理。

在这样的背景下,客户可以在函数计算运行存量的 REST 应用,但应用无法正常对外提供服务。客户花费大量的精力对存量的应用进行改造,而且这个改造仅仅在函数计算是必须的,是一种典型的平台携裹用户的产品设计。

使用 fcapp.run调用函数

为了解决上述的问题,并兼容存量的函数以及客户习惯,函数计算为每个新创建的 HTTP 触发器分配了一个独立的域名,例如{random-string}.cn-shanghai.fcapp.run。使用该域名访问函数计算,函数计算会按照域名进行路由,将流量转发至函数容器内,避免对客户代码造成侵入性。

使用 fcapp-test.run 进行本地网页测试

由于中国大陆政策的影响,函数计算主域名无法在互联网为客户提供网站类型的业务,所有的函数请求结果将被转为下载行为。对于纯 API 类型的函数,我们认为将请求结果转为下载是没有影响的。但对于网站属性的函数,返回的 HTML 文本以及 JavaScript 代码强依赖浏览器的解释器才能正常展示。我们判断让开发者能够实时看到函数返回的页面是一个强诉求。

在生产场景,我们推荐客户为函数绑定已备案的域名来解决这个问题,而在测试环境有更加简洁的方案。在测试阶段可以临时通过测试域名fcapp-test.run以及添加本地的host解析绕过这个问题,请求结果将不会被转为下载行为,可以正常进行网页调试。

# 1. 从页面获取fcapp.run的域名
FC_DOMAIN='wordpress-xxxxx-serverlordpress-ydziwvakfn.cn-shenzhen.fcapp.run'
FC_TEST_DOMAIN=`echo ${FC_DOMAIN} | sed 's/fcapp.run/fcapp-test.run/g'`
echo "FC域名: ${FC_DOMAIN}"
echo "FC测试域名: ${FC_TEST_DOMAIN}"

# 2. 查询域名解析的IP
FC_IP=`ping ${FC_DOMAIN} -c 1 | HEAD -1 | awk '{print $3}' | sed 's/[():]//g'`
echo "FC IP: ${FC_IP}"

# 3. 修改host文件,将测试域名的本地解析指向fcapp.run的解析
#    如果没有权限需要手动加
sudo -- sh -c  "printf '\n${FC_IP} ${FC_TEST_DOMAIN}\n' >> /etc/hosts"
cat /etc/hosts

# 4. 使用测试域名在浏览器访问函数
curl -v "${FC_TEST_DOMAIN}"


了解 TCP 协议以及HTTP协议的同学可以很容易地理解背后的技术细节。客户端在发起HTTP请求时,首先会通过域名解析查询到域名对应的IP地址,并发起TCP连接。接下来会通过建立的TCP连接,将HTTP Request报文发送至Server端。如果客户端直接向函数计算的Server发起TCP连接,并将可以与函数关联的域名发送至函数计算,那么函数计算就可以返回客户期望的内容。

函数计算在后端进行了处理,兼容了fcapp-test.run域名的访问,但并不提供权威DNS解析。客户只需要在本地进行Host配置或者使用自建的DNS服务器,将fcapp-test.run的域名解析至函数计算Server,就能够正常测试函数。该方案既满足了中国大陆法律法规的要求,又以极低的成本满足了客户调试页面的需求,极大地优化了客户在函数计算的研发体验。

使用函数计算运行 wordpress 官方镜像

通过以上的方案,函数计算支持客户在不修改任何业务代码的前提下迁移自己的REST应用。下面使用wordpress官方镜像进行说明。

前置条件

  1. 开通函数计算账号。
  2. 将 wordpress 镜像转存到阿里云容器镜像服务中。
  3. 创建或使用已有的 mysql 实例,并为wordpress服务初始化相应的账号以及数据库。如果使用阿里云RDS实例,请确保函数服务的VPC配置与RDS实例的VPC配置一致,且白名单配置正确。

创建相应的函数以及服务

使用wordpress官方镜像创建函数,并设置容器内监听端口为80。

注入数据库配置

修改函数配置,将mysql的数据库配置以环境变量的方式注入函数容器内。

无需备案,测试wordpress函数功能

查看创建的触发器分配的域名,按照上述文档配置,使用fcapp-test.run域名进行测试。

上线你的函数

对外提供网站类型服务只能通过已备案域名来实现。函数计算用户可以通过配置自定义域名的功能,将域名与函数进行绑定,使用自己的域名对外提供服务。同时也可以使用任意标准的网关类型的云产品或者开源产品,使用fcapp.run的内网域名上线你的函数。

小结

作为 Serverless 技术的标志性产品之一,函数计算长久以来专注于提升产品适用的场景。fcapp.run域名以及相关产品特性的引入,标志着函数计算在 REST 场景以及 Web 场景的很大一步。客户从此可以将 REST 应用零改造地部署在函数计算上,研发测试的体验以及正式上线的方案都做到了优秀。非常欢迎同学们使用函数计算,并提出宝贵的意见。

更多内容关注 Serverless 微信公众号(ID:serverlessdevs),汇集 Serverless 技术最全内容,定期举办 Serverless 活动、直播,用户最佳实践。

有关无需修改代码,用 fcapp.run 运行你的 REST 应用的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  3. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  4. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  5. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

  6. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  7. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  8. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  9. ruby-on-rails - Rails 应用程序中的 Rails : How are you using application_controller. rb 是新手吗? - 2

    刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr

  10. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

随机推荐