前言
阿里云函数计算 Function Compute(FC),旨在帮助用户采用弹性伸缩、动态分配资源的方式,来执行业务函数。让用户无需购买部署服务器,无需考虑业务负载,就能快速搭建可处理高并发的后台服务。
本文介绍HTTP触发器快速迁移Thinkphp应用到函数计算。函数计算运行 PHP 框架原理可以参考一下《十分钟上线-函数计算玩转 WordPress》。
案例开发配置步骤
- 打开tp5的入口文件(/public/index.php)在namespace think; 这句的下面,加如下代码:
if(!$_SERVER['PATH_INFO']) $_SERVER['PATH_INFO'] = preg_replace("/^(\?s\=\/)/","",$_SERVER['REQUEST_URI']);
2.准备tp5源码,将 thinkphp 工程包移动到的/code/2016-08-15/proxy/demo.LATEST/thinkphp 目录,在根目录创建index.php文件(作为函数的入口文件),代码包目录结构如图!
代码如下:
<?php
#自定义的域名,绑定了自定义域名的,可以换成自己自定义的。
$MY_HOST = "1986114430573743.cn-hangzhou.fc.aliyuncs.com";
#web目录绝对路径,如:/code
$WWW_DIR = '/code';
function handler($request, $context){
#如果不使用函数计算后台提供的那个厂厂的域名,这句可以注释掉。
if(strpos($request->getAttribute("requestURI"),"/2016-08-15/proxy") !== false) $request = clearFcHost($request,$context);#兼容 fc后台的url地址
$uri = $request->getAttribute("requestURI");
$file = explode("?", $uri)[0];
if($file=='/') $uri='/';#
$file = $GLOBALS['WWW_DIR'].$file;
if(file_exists($file) and $uri!='/'){
if(strpos($uri,".php")) return php_run(basename($file), $request, $context);#php_run
return static_run($uri);#static_run
}
$request = $request->withAttribute("requestURI", "?s=".$uri);
return php_run('index.php', $request, $context);# php_run
}
function php_run($name,$request, $context)
{
return $GLOBALS['fcPhpCgiProxy']->requestPhpCgi($request, $GLOBALS['WWW_DIR'], $name,['SERVER_NAME' => $GLOBALS['MY_HOST'], 'SERVER_PORT' => '80', 'HTTP_HOST' => $GLOBALS['MY_HOST']],['debug_show_cgi_params' => false, 'readWriteTimeout' => 15000]);
}
use RingCentral\Psr7\Response;
function static_run($uri): Response{
$file_dir = $GLOBALS['WWW_DIR'].$uri; #完整文件路径
$file_dir = explode("?", $file_dir)[0]; #去掉动态路径
if(is_dir($file_dir)) $file_dir .= '/index.html';# 可以这里定义目录的默认索引页
$handle = fopen($file_dir, "r");
$contents = fread($handle, filesize($file_dir));
fclose($handle);
return new Response(200, ['Content-Type' => $GLOBALS['fcPhpCgiProxy']->getMimeType($file_dir),'Cache-Control' => "max-age=8640000",'Accept-Ranges' => 'bytes'], $contents);
}
function clearFcHost($request,$context){
$uri = $request->getAttribute("requestURI");
$uri = str_replace("/2016-08-15/proxy/".$context['service']['name']."/".$context['function']['name'],"",$uri);
$request = $request->withAttribute("requestURI", $uri);
return $request;
}
#错误处理
function error($code) {
#if($resp->getStatusCode() !=200) return error($resp->getStatusCode());
return 'thinkphp框架测试~~';
}
Q1: 为什么创建 /2016-08-15/proxy/share/wp-func 这么奇怪的目录?
A:因为http trigger, 函数访问的格式为下面的url: http://${account_id}.${region}.fc.aliyuncs.com/2016-08-15/proxy/$(seevice_name.LATEST}/{function_name}/,为了保证从一个页面跳转到另外一个页面的时候,能自动带上/2016-08-15/proxy/$(seevice_name.LATEST}/{function_name}/,我们需要建立这样目录和设置 cgi 相关参数达到 PHP 框架内部自动跳转正确的目的。
3.由于函数计算只有/tmp 目录可写,所以要改一下tp5的配置文件
编辑/config/log.php
'path' => '/tmp/log',
编辑/config/cache.php
'path' => '/tmp/cache',
4.使用fun工具部署函数,在项目根目录下创建template.yml名称文件,内容如下:
ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Resources:
demo:
Type: 'Aliyun::Serverless::Service'
Properties:
Description: 'thinkphp测试'
thinkphp:
Type: 'Aliyun::Serverless::Function'
Properties:
Handler: index.handler
Runtime: php7.2
CodeUri: './'
Events:
http-test:
Type: HTTP
Properties:
AuthType: ANONYMOUS
Methods: ['GET', 'POST', 'PUT']
执行fun deploy部署函数,部署成功如图!
5.您可以到FC控制台执行函数了,如图!
但是如果在浏览器中执行 HTTP 触发器的请求地址,web 页面将会已文件的形式下载。这是因为函数计算为了安全强制设置了请求返回的 header 为 Content-Disposition: attachment,所以返回结果会以附件形式下载。为了解决这个问题,需要用户申请自定义域名,并绑定域名解析到函数计算中,请参考函数计算绑定自定义域名。
总结
函数计算有如下优势:
- 无需采购和管理服务器等基础设施
- 专注业务逻辑的开发
- 提供日志查询、性能监控、报警等功能快速排查故障
- 以事件驱动的方式触发应用响应用户请求
- 毫秒级别弹性伸缩,快速实现底层扩容以应对峰值压力
- 按需付费。只需为实际使用的计算资源付费,适合有明显波峰波谷的用户访问场景
- 除了上面所列的优势,FC 可以做为 Web Backend,只需要编写一个函数实现传统 Web 服务器中的 conf 中的逻辑,就可以将一个完整的 Web 工程迁移到 FC ,从而从传统的 Web 网站运维,监控等繁琐的事务中解放出来。
最后欢迎大家通过扫码加入我们用户群中,搭建过程中有问题或者有其他问题可以在群里提出来。
函数计算官网客户群(11721331)。