当访问域名后 解析nginx 配置文件
/home/service/nginx/conf/vhost]# cat happy.xxxxx.com.conf
首先 include common/header.conf; 文件中会定义变量
关键代码
反向代理到项目所在服务器
# 接口
location / {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
add_header Access-Control-Allow-Headers accept,content-type,x-requested-with;
if ($request_method = 'OPTIONS') {
return 204;
}
proxy_store off;
proxy_pass http://upstream_happy${var_virtual_host};
proxy_set_header Scheme $var_scheme;
proxy_set_header Host happy.xxx.com;
proxy_set_header virtualhost $var_virtual_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Referer $http_referer;
proxy_set_header X-Real_IP $remote_addr;
client_max_body_size 35m;
#####ADAPT#######
proxy_set_header protocolflag $var_scheme;
proxy_set_header rootflag $var_virtual_host;
proxy_connect_timeout 5s;
proxy_read_timeout 5s;
proxy_send_timeout 5s;
}
实际访问的目录为
/home/service/swoole/bin/swoole.sh
文件
#!/bin/sh
script="/home/service/swoole/lib/Server.php"
pidfile="/home/work/$2/var/swoole.pid"
pid=""
if [ -f "$pidfile" ]; then
pid=$(cat $pidfile)
fi
start () {
if [ -z "$pid" ]; then
echo "Starting : begin"
/home/service/php7/bin/php $script start $1
echo "Starting : finish"
else
echo "Starting : running"
fi
}
stop () {
if [ -z "$pid" ]; then
echo "Stopping : no master"
else
echo "Stopping : begin"
/home/service/php7/bin/php $script stop $1
pids=$(ps aux | grep Swoole | grep $1 | awk '$0 = $2')
for pid in $pids ; do
kill -9 $pid
done
echo "Stopping : finish"
fi
}
case "$1" in
start)
start $2
;;
stop)
stop $2
;;
*)
echo $"Usage: $0 {start|stop} project"
;;
esac
而 sh 访问的主要文件为 两个
1./home/service/swoole/lib/Server.php
#!/home/service/php7/bin/php
<?php
require_once('RequestWorker.php');
require_once('JobTasker.php');
class Server {
private $project = '.';
//环境
private $base = 'web';
private $pidfile = 'var/swoole.pid';
private $logPath = '/data/logs/prod_logs';
private $pid = -1;
protected $name = '';
protected $server = null;
protected $worker = null;
protected $tasker = null;
protected $config = [
'host' => '0.0.0.0',
'port' => 8080,
'reactor_num' => 2,
'worker_num' => 1,
'task_worker_num' => 0,
'max_conn' => 256,
'max_request' => 5000,
'dispatch_mode' => 2,
'open_tcp_keepalive' => 1,
'enable_static_handler' => true,
'http_parse_post' => true,
'document_root' => __DIR__,
];
protected $appConfig = [];
public static function createInstance($name, $path) {
$instance = new self($name, $path);
return $instance->init();
}
public static function attachInstance($name, $path) {
$instance = new self($name, $path);
return $instance->attach();
}
public function __construct($name, $path) {
$this->name = $name;
$this->project = $path;
$this->base = $this->project . '/web';
$this->pidfile = $this->project . '/var/swoole.pid';
$this->logPath = '/data/logs/prod_logs';
}
public function attach() {
$pid = $this->readPid();
if($pid <= 0) {
echo "服务实例未找到\n";
return;
}
$this->pid = $pid;
return $this;
}
public function start() {
//配置服务
$this->configServer();
//启动服务
$this->server->start();
}
public function stop() {
\Swoole\Process::kill($this->pid, SIGTERM);
file_put_contents($this->pidfile, '', LOCK_EX);
unlink($this->pidfile);
echo "Finish\n";
}
public function writePid() {
file_put_contents($this->pidfile, $this->pid, LOCK_EX);
}
public function readPid() {
if(!file_exists($this->pidfile)) {
return 0;
}
$data = file_get_contents($this->pidfile);
$pid = intval(trim($data));
return $pid;
}
protected function init() {
$pid = $this->readPid();
if($pid > 0) {
echo "服务正在运行中,无法启动多实例\n";
return;
}
$this->config['log_file'] = $this->logPath . '/server.log';
$this->config['document_root'] = $this->base;
//读取容器配置
$this->loadContainerConfig();
return $this;
}
protected function configServer() {
//读取项目配置
$this->loadAppConfig();
//服务对象
$this->server = new \swoole_http_server($this->config['host'], $this->config['port']);
$this->server->set($this->config);
//master
$this->configMaster();
//manager
$this->configManager();
//worker
$this->configWorker();
//tasker
$this->configTasker();
}
protected function configMaster() {
$that = $this;
$this->server->on('Start', function(Swoole\Server $server) use ($that){
$ret = cli_set_process_title('Swoole Master ['. $that->name .']');
$that->pid = $server->master_pid;
$that->writePid();
echo "Swoole Master -> [$ret]\n";
});
}
protected function configManager() {
$that = $this;
$this->server->on('ManagerStart', function(Swoole\Server $server) use ($that) {
cli_set_process_title('Swoole Manager ['. $that->name .']');
});
}
protected function configWorker() {
$that = $this;
$this->server->on('WorkerStart', function(Swoole\Server $server, $workerId) use ($that){
if($server->taskworker && $that->tasker) {
cli_set_process_title('Swoole Tasker ['.$that->name.']');
$that->tasker->start();
return;
}
//worker
cli_set_process_title('Swoole Worker ['.$that->name.']');
$that->worker = $that->createWorker();
});
$this->server->on('WorkerStop', function(Swoole\Server $server, $workerId) use ($that){
if($server->taskworker && $that->tasker) {
$that->tasker->shutdown();
return;
}
});
//HTTP请求
$this->server->on('Request', function(Swoole\Http\Request $request, Swoole\Http\Response $response) use ($that) {
$that->worker->doRequest($request, $response);
});
}
protected function configTasker() {
if(!$this->config['task_worker_num']) {
return;
}
$this->server->on('Task', function($server, $taskId, $fromId, $data){});
$this->server->on('Finish', function($server, $taskId, $data) {});
//tasker
$tasker = new JobTasker($this->base, $this->name, $this->appConfig['Task']);
$this->tasker = $tasker;
}
private function loadContainerConfig($configFile = 'swoole.ini') {
if(strpos($configFile, '/') !== 0) {
$configFile = $this->project . '/' . $configFile;
}
if(!file_exists($configFile)) {
return;
}
$config = parse_ini_file($configFile, true);
if(array_key_exists('swoole', $config)) {
$server = $config['swoole']['server'];
if(!array_key_exists($server, $config)) {
return;
}
$config = $config[$server];
}
foreach($config as $k => $v) {
$this->config[$k] = $v;
}
}
private function createWorker() {
$path = $this->base . '/gateways';
$fd = opendir($path);
if(!$fd) {
return null;
}
$apps = [];
while(($item = readdir($fd)) !== false) {
if(strpos($item, '.') === 0) {
continue;
}
$name = "$path/$item";
if(!is_dir($name)) {
continue;
}
$file = "$name/bootstrap/app.php";
if(!file_exists($file)) {
continue;
}
$app = require($file);
$apps[$item] = $app;
echo "Regist Application [$item] Success\n";
}
return new RequestWorker($this->base, $apps);
}
/**
* 读取服务配置
**/
private function loadAppConfig($configFile = 'server.ini') {
if(strpos($configFile, '/') !== 0) {
$configFile = $this->base . '/' . $configFile;
}
if(!file_exists($configFile)) {
return;
}
$config = parse_ini_file($configFile, true);
$this->appConfig = $config;
if(array_key_exists('Task', $config) && $config['Task']) {
$this->config['task_worker_num'] = 1;
}
}
}
$argsCount = count($argv);
$script = $argv[0];
if($argsCount < 3 || !in_array($argv[1], ['start', 'stop', ])) {
echo "Usage: $script {start|stop} project\n";
exit(1);
}
$command = $argv[1];
$project = $argv[2];
$path = "/home/work/$project";
if(!file_exists($path)) {
echo "项目[$project]不存在\n";
exit(1);
}
if($command === 'start') {
$instance = Server::createInstance($project, $path);
if(!$instance) {
exit(1);
}
$instance->start();
} else if($command === 'stop') {
$instance = Server::attachInstance($project, $path);
if(!$instance) {
exit(1);
}
$instance->stop();
} else {
echo "Usage: $script {start|stop} project\n";
exit(1);
}
2.swoole.ini
[swoole]
server=happy
[happy]
host=0.0.0.0
port=23100
worker_num=24
max_conn=5000
max_request=5000
dispatch_mode=3
daemonize=1
backlog=2048
open_tcp_keepalive=1
tcp_defer_accept=5
open_tcp_nodelay=1
log_file=/data/logs/prod_logs/swoole.log
request_file=/data/logs/prod_logs/request.log
request_slowlog_timeout=3
request_slowlog_file=/data/logs/prod_logs/swoole_happy_php_slow.log
trace_event_worker=true
package_max_length=50000000
用swoole 启动了 http 服务 代替 PHP-FPM
原因有以下几点
1.fpm仅仅只是对节省了进程层级的开销,PHP的所有对象请求时创建,请求结束时全部销毁。对于普通PHP程序来说避免了内存泄漏。对于大型网站来说,这是严重的资源浪费
2.PHP-Server中每次请求仅销毁与请求相关的对象。与请求有关的全局对象都不需要销毁。直接在下次请求中复用。
3.APC/OpCache只能节省编译OpCode的时间,但OpCode还是要执行的。PHP-Server可以保留OpCode执行后的内存,节省资源。
4.PHPer可以操控的范围更⼤了,局部缓存,Once操作,写文件合并,统计数据合并,数据库连接,对象持久化,数据库连接池等都可以做。