最近把一个小系统迁移到阿里云『函数计算』,
本以为很顺利的,然而遇到麻烦,折腾了两天;
项目是PHP写的,所以『函数计算』使用的是PHP环境。
首先是gd和sqlite库的问题,默认这两个库都没有安装,
按照阿里云的文档,创建 extension目录放so和ini文件,
如图:
实际测试就是不成功,后来向阿里云求助,
阿里云工程师发来两个文件才成功,所以难得的是这两个so文件;
所得文件gd.so和pdo_sqlite.so,下面提供下载链接 :
链接: https://pan.baidu.com/s/1_RcaAqYuopDaNCCt76GJFw 提取码: s6h9
或者:https://download.csdn.net/download/envon123/12742887
另外,
对于迁移PHP项目,我开始的时候,进入了一个误区,
以为要改很多东西,如session、cookie、header/echo/print、GET/POST。。。
我花了不少时间在看原项目,在规划着怎样调整;
后来才发现,原来阿里云提供了 fcPhpCgiProxy 这么个东西。。。
问题是这么重要的东西,文档上只在案例那里有点介绍,估计很容易被人忽略。
有了 fcPhpCgiProxy ,原来的项目几乎不用改动,就可以迁移到函数计算。。。
fcPhpCgiProxy 我个人看,就类似一个 http代理,
你只要把你原项目放到某个目录下,然后在函数入口使用它调用,
就这样,你也可以把它当作是nginx,具体的自行去了解一下。
下面是我为这项目参考一些资料写的函数入口文件,如下:
<?php
use RingCentral\Psr7\Response;
function handler($request, $context): Response {
$host = "xxxx.xxxx.com";//使用的域名
$root_dir = '/mnt/nfs/webroot';//你原项目放在的目录
$requestURI = $request->getAttribute('requestURI');
$filename = rawurldecode($root_dir . explode("?", $requestURI)[0]);
// 取后缀名
$ext = false;
$pathinfo = pathinfo($filename);
if(!isset($pathinfo['extension'])){
}else{
$ext = strtolower($pathinfo['extension']);
}
// 判断文件是否存在
$isFileExist = false;
$isStaticFile = false;
if (is_file($filename)) {
$isFileExist = true;
if (!empty($ext) && strtolower($ext)=='php') {
// 动态
$isStaticFile = false;
} else {
// 静态
$isStaticFile = true;
}
} else {
if (empty($ext)) {
$phpIndex = '/'.trim($filename, '/').'/index.php';
$htmlIndex = '/'.trim($filename, '/').'/index.html';
if (is_file($phpIndex)) {
// 动态
$isFileExist = true;
$isStaticFile = false;
$filename = $phpIndex;
} else if (is_file($htmlIndex)) {
// 静态
$isFileExist = true;
$isStaticFile = true;
$filename = $htmlIndex;
}
} else {
// 动态
$isStaticFile = false;
}
}
// 调用动态或者静态文件
if (!$isStaticFile) {
$script_name = empty($ext) ? '/index.php' : ('/'. $pathinfo['basename']);
$script_filename = $filename;
if (!$isFileExist) {
$script_filename = $root_dir . $script_name;
}
$GLOBALS['fcPhpCgiProxy'] = new \ServerlessFC\PhpCgiProxy();
$resp = $GLOBALS['fcPhpCgiProxy']->requestPhpCgi(
$request,
$root_dir,
trim($script_name, '/'),
[
'SERVER_NAME' => $host,
'SERVER_PORT' => '80',
'HTTP_HOST' => $host,
'SCRIPT_FILENAME' => $script_filename,
'SCRIPT_NAME' => $script_name
],
['debug_show_cgi_params' => true, 'readWriteTimeout' => 15000]
);
return $resp;
} else {
$GLOBALS['fcPhpCgiProxy'] = new \ServerlessFC\PhpCgiProxy();
$handle = fopen($filename, "r");
$len = filesize($filename);
$contents = $len > 0 ? fread($handle, $len) : '';
fclose($handle);
$ctype = '';
if ($ext=='woff') { // 我项目需要的特别处理
$ctype = 'application/font-woff';
} else {
try {
$ctype = $GLOBALS['fcPhpCgiProxy']->getMimeType($filename);
} catch (Exception $e) {
$ctype = 'application/octet-stream';
}
}
$headers = [
'Content-Type' => $ctype,
'Cache-Control' => "max-age=8640000",
'Accept-Ranges' => 'bytes',
];
return new Response(200, $headers, $contents);
}
}
上面代码,主要是使用 fcPhpCgiProxy 来调用原来项目,原项目几乎不用改动就可以成功部署。
你可以直接使用这代码(函数计算的入口文件),注意修改 $host 和 $root_dir 变量。
(完)