正確佈署 Laravel 應用程式

Laravel Conf 2018

大家好,我是 芥龍

現任 希幔數位 後端工程師

Muzik Online

Modern PHP

Laravel

WebSecurity

Lumen

C/C++

Rust

Linux

Shell Script

Golang

Javascript

GCP

Docker

rkt

Kubernetes

GitLab CI

Bitbucket Pipeline

Python

Travis CI

Libevent

FFMpeg

OpenGL

投稿緣起

2017 年 Laravel Conf

Can Laravel Be Hacked?

開始之前

  • 初學者定位

  • 官方文件導讀

  • 沒有 Live Demo

歡迎提問

基礎環境開始,對吧

Web Server

PHP Runtime

Database

AOL Server

Apache HTTP Server

Apache Tomcat

Bao

Caddy

Caudium

Cherokee HTTP Server

GlassFish

Hiawatha

HFS

IBM HTTP Server

Internet Information Service

Jetty

Jexus

lighthttpd

LiteSpeed Web Server

Mongoose

Monkey HTTP Server

NaviServer

NCSA HTTPd

Nginx

OpenLink Virtuoso

OpenLite Speed

Oracle HTTP Server

Oracle iPlanet Web Server

Oracle WebLogic Source

Resin OpenSource

Resin Professional

thttpd

TUX Web Server

Wakanda Server

WEBrick

Windows Webserver

Xitami

Yaws

Zeus Web Server

Zope

  • Internet Informatcion Service
  • LiteSpeed Web Server
  • Apache HTTP Server
  • OpenLiteSpeed
  • Caddy
  • Nginx

PHP Runtime

  • 版本 >= 7.1
  • Extension
    • OpenSSL
    • PDO
    • Mbstring
    • Tokenizer
    • XML
    • Ctype
    • JSON

नमस्ते

官方文件沒寫的事

  • Extension
    • memcached
    • opcache
    • gd
    • bcmath
    • pcntl
    • zip

predis vs. php-redis

Database

  • 官方聲明
    • MySQL
    • Postgresql
    • SQL Lite
    • MS SQL
  • 理論上
    • PDO 有支援的都可以使用

天地萬物,朕賜給你,才是你的

朕不給你,你不能搶

來看看一些特別的 Feature

Queue

Cron Job

Queue - 任務佇列

使用時的注意事項

  • 務必建立 failed_jobs 資料表
  • 務必注意 retry 及 sleep
  • 利用 supervisor/systemd 保證執行
[program:laravel-worker]
process_name=%(program_name)s_%(processnum)02d
command=/usr/bin/php /path/to/laravel/artisan --sleep=3 --tries=3
autostart=true
autorestart=true
user=www
numprocs=8
redirect_stderr=true
stdout_logfile=/var/www/html/storage/logs/worker.log

Supervisor

[Unit]
Description=Laravel queue worker

[Service]
User=www-data
Group=www-data
Restart=on-failure
ExecStart=/usr/bin/php /path/to/laravel/artisan queue:work --sleep=3 --tries=3

[Install]
WantedBy=multi-user.target

Systemd

Queue 的另一種思路

Cron Job - 定時任務

使用時的注意事項

  • 盡量避免使用時區的功能
  • 最好設定 Cache 使用

佈署時的注意事項

應用程式進入點

public/index.php

Client

Server

request: index.php

response: index.php

request: notfound.php

404 Not Found

Found

index.php

Not Found

notfound.php

Client

Server

request: index.php

response: index.php

request: notfound.php

response:

index.php/notfound.php

Found

index.php

bypass to index.php

Not Found notfound.php

Why?

  • 避免 client 存取無關檔案
    • .env
    • .git/
    • composer.json
    • node_modeuls/
  • 統一應用程式進入點
    • 只引入一次 autoload.php

Front Controller Pattern

如何設定資料夾權限

權限重點提要

  • 需讓 php-fpm 有可讀可執行權限
    • 整個 laravel app 範圍
  • 需讓 php-fpm 再加可寫權限
    • bootstrap/cache
    • storage/

 權限都 777

還是 Permission Denied?

  • 八成是 SELinux 搞得鬼
    • chcon -Rt httpd_sys_content_t {dir}
    • chcon -Rt httpd_sys_rw_content_t {dir}
  • 當然你也可以嫌麻煩直接關掉 SELinux
    • 許多 VPS 廠商都會這麼做
    • 許多 Linux 發行版都會這麼做

加速應用程式

Composer

  • composer install -o
  • composer install -a
    • 與 --apcu-autoloader 不可混用

PHP 端

  • config:cache
  • route:cache
  • view:cache

Laravel Connection

ProxySQL (MySQL)

  • 優點
    • 可完全適應 PDO 特性
  • 缺點
    • 需要修改程式
  • 優點
    • 可設定較複雜的規則
  • 缺點
    • 不支援 Prepare Statement

分離快取其它服務

除了 Queue Worker 與 Cron Job

Global Cache

vs.

Local Cache

分離核心應用

Application

將會產生的問題

  • Cron Job 重複執行
  • Queue Worker 資源閒置
  • 無法正確取得 Client IP

Cron Job 重複執行

  • 只在一個核心應用執行 Cron Job
    • 如何保證服務可用?
  • 利用 onOneServer() 的內建特性

Queue Worker 資源閒置

  • 分配 Queue/non-Queue 策略
  • 不使用 Laravel Queue Worker

無法正確取得 Client IP

Client

1.1.1.1

Server

<?php

var_dump($_SERVER['REMOTE_ADDR']);
string(7) "1.1.1.1"

Client

1.1.1.1

HA Proxy

1.2.3.4

App

<?php

var_dump($_SERVER['REMOTE_ADDR']);
string(7) "1.2.3.4"
<?php

var_dump($_SERVER['HTTP_X_FORWARDED_FOR']);
string(7) "1.1.1.1"

Client

1.1.1.1

HA Proxy

1.2.3.4

App

<?php

var_dump($_SERVER['REMOTE_ADDR']);
string(7) "1.2.3.4"
<?php

var_dump($_SERVER['HTTP_X_FORWARDED_FOR']);
string(7) "103.21.244.0,1.1.1.1"

CloudFlare

103.21.244.0

Client

1.1.1.1

HA Proxy

1.2.3.4

App

<?php

var_dump($_SERVER['REMOTE_ADDR']);
string(7) "1.2.3.4"
<?php

var_dump($_SERVER['HTTP_X_FORWARDED_FOR']);
string(7) "2.2.2.2,1.1.1.1"

Unkown Proxy

2.2.2.2

Trusted Proxies

邁向現代化 DevOps

容器化的迷思

  • PHP 天生不適合容器化?
    • FastCGI 必須綁定 Web Server
    • 檔案結構複雜許多,不利容器運作
  • 在 MicroService 的時代,PHP 終將被淘汰?

走向現實:容器化

  • PHP-FPM 與 WebServer
  • 原始碼應該 copy 或 mount

沒有最好的程式語言,只有最佳的應用場景

沒有最好的架構模式,只有最適的使用時機

ーー芥龍 2018 Laravel Conf TW

Thank you

Q&A 就留到交流趴吧

正確佈署 Laravel 應用程式

By chivincent

正確佈署 Laravel 應用程式

  • 1,805