LaravelConf Taiwan

1
from {{$idea}} to {{$production}}

LaravelConf 2019

1 Laravel 在高併發下的系統架構與效能優化 - 陳光賢 (Albert)

高并发分为两种场景,依据不同场景有不同的解决方案:

缓存使用注意事项

当 DB 中的数据更新时,缓存同样需要更新,在 Laravel 中,通过观察者模式来实现同步更新,这是一个很好的应用场景。

根据“二八定律”,DB 在 20% 的时间写入,80% 的时间读取。(DB 主从)

通过 SQL Proxy,可以自动识别 SQL 的读写,也可以隔离具体的 DB,但同时也可能限制一些 SQL 函数的使用。

抢购的特点:

  • 持续时间短
  • 瞬时高并发
  • 响应缓慢造成用户发起更多的请求,形成恶性循环

抢购的一些解决方案:

  • 对抢购的商品热点数据提前预热至 Redis 中
  • 通过 Redis 的set setnx限制用户的重复提交
  • 采用消息队列处理 DB 写入
  • 当请求接近最大负载时,拒绝服务响应,触发熔断自我保护机制
  • 过滤请求

高并发的核心问题就是,如何将当前服务无法承载的请求降低到可以承受的范围内?

架构设计时需要注意保留有弹性,再随着业务的发展堆叠。

LaravelConf 2018

1 站点国际化

我们可通过用户的 Session、IP、设定偏好等方式来确定用户的位置,并呈现出本地化信息,如语言、时间、币种等。
geoip2/geoip2 可以通过 IP 获取到相关的地区、时区、语言等信息

1.1 语言

在 Laravel 5.x 中,可设定/config/app.php中的

1
2
$local = App::getLocale();
App::setLocale($locale);

Locale 的名称需要与 lang 目录的名称相同
en => /resources/lang/en

可以一种语言对应一个 view 目录,也可以多种语言对应一个 view(如 en-us 与 en-uk 对应 en)

php可以使用mcamara/laravel-localization来处理本地化问题:

  1. 如果语言在网址中没有携带,则可以依据此包中的设定,决定使用app.php中的默认语言,还是浏览器请求头中的Accept-Language
  2. 将没有请求语言的网址自动 301 到设定的默认语言

1.2 网址

1.2.1 以国家做区分

http://example.com/cn
相关ISO标准:ISO-3166-1
示例:Apple、Google

1.2.2 以语言做区分

http://example.com/zh
相关ISO标准:ISO-639-1
示例:LINE

1.3 时间

大多跨境网站的时区设定为 UTC
时区设定为 UTC,存储时间信息时可以通过以下两种方式

  1. 前端请求的时间转换为 UTC 后发送给后端
  2. 前端请求中携带时区信息,由后端转换为 UTC

注意夏令时对同一时区的时间影响。

php中可以使用nesbot/carbon来处理时间问题

1.4 币种

问题一:该平台允许交易的币种有哪些?
问题二:如果支持多种币种,是否可以设定基础币种
问题三:使用固定汇率还是浮动汇率?

可使用moneyphp/moneywebpatser/laravel-countriestorann/currency

1.5 数据格式

手机号、地址
giggsey/libphonenumber-for-php可处理手机号信息、如格式化、获取国家、运营商等
commerceguys/addressing 可用于处理地址信息

2 小项目的制作与推广

  1. 很多功能可能并不确定是否会有好的反响,此时应该先快速做一个基础功能推出,根据用户使用情况再决定方向。
  2. 网站可通过捐赠或者出售,或者为客户定制化来盈利(定制化可将基础功能开源,然后对搭建与维护系统进行收费)
  3. Laravel module 与 Git tree 可以管理多个相似定制化的项目

3 工程师的职业规划

3.1 Junior(毕业5年内)

  • 寻找方向,融入行业(加入大型稳定公司,学习高效行事能力、行业规范及职业价值观)

3.2 Senior(毕业5~10年)

  • 挑好的产品、好的团队文化加入(加入有潜力、正在快速成长的公司,积累很多经验。最好是面向普通用户型产品的精英团队。在下份工作时,要找自己感兴趣的 C 端产品,询问公司的加班文化及自由度,比如:我们通常的上下班时间?贵公司对经常加班怎么看?是否会允许远程工作?是否会有经常会有凌晨上线?

3.3 接案者

  • 自由,但极需自律与严谨

无法转换为产品的技术没有价值。
一个优秀的工程师不会只会一种语言,不会只能写业务代码。

3.4 职业生涯怎么走

钱?前途?自己喜欢的事?

钱很重要,但什么时候变现更重要

在职业后期,更需要将技术转换为产品,一个了解技术和用户的产品会有绝对优势。
在开发一些不认同的功能时,可以询问产品与运营,看看他们的思维角度与方式。

架构师与了解产品的技术是市面很缺乏的人才。

简历可以写的更富有创意,比如 json 格式,面试语言代码等。至少在简历筛选关能获得较高的通过率

4 Laravel 與 Swoole 的整合之路

首先,我们来看下一个 PHP 请求的生命周期

PHP's Lifecycle

如图所示,在一个 PHP 请求中,需要加载相关的依赖文件,并进行语法验证与解析、编译等过程,而我们都知道,I/O 是最大的性能瓶颈,这就是为什么php性能较低的原因了。

接下来,我们通过get_included_requires()看下 Laravel 的一个请求需要载入多少文件。经实验得知,纯净 Laravel 加载文件数量在 218 个,如果加载了其他 vendor,数量会更多。

加载了这么多的文件,那 Laravel 的生命周期是怎样的呢?

Laravel's Lifecycle

现在,我们找到了拖慢 Laravel 的原因:

What Makes Laravel Slow?

我既想要 Laravel 的优雅,又想要高性能,该怎么做呢?还好,已经有前人做了 swoole 这样的工具,为 php 插上翅膀,我们要做的工作就是把 Laravel 和 swoole 结合起来。我们先来了解下 Swoole 的模型:

Swoole's Model

在 Linux 中,使用 Epoll 方式处理异步,在 BSD 中,则使用 Kqueue。

了解了 swoole 后,我们自然会想到如下的几种集成方案:

集成方案

但是,我们在集成中会遇到以下的问题:

集成所存在的问题

我们先来了解下 Laravel 的容器服务机制:

Laravel's Service Container

Laravel's Facades

如果我们将那些重复的工作只在第一次启动 Laravel 完成,在之后的请求不就可以直接跳过那些不必要的流程了吗?但这样会带来一个问题:如果上次请求的结果未能及时清除,可能会污染到后续的请求(尤其是那些静态变量、全局变量等),那我们将每次请求隔离在沙箱中不就解决了吗?

Sandbox App Container

但并非所有的实例都需要在每次请求时加载,完全可以读取共享文件,如 db, session, config, cache …

Instances Outside of Sanbox

在沙箱模型中,我们的请求流程就变成了这样:

Sandbox App Container

到目前为止,似乎我们的已经完成了所有的工作,但 Laravel 中复杂的容器机制让我们还有新的挑战需要去克服:

Redirection of App Container

现在,Laravel 的生命周期就变为了这样:
Laravel's New Lifecycle

接下来,让我们看下 Laravel Swoole 的优势有哪些:

Laravel Swoole Advantage

以前,我们在 Laravel 中这样使用 Websocket
Websocket in Laravel

现在,我们在 Laravel 中这样使用 Websocket
Websocket in Laravel Swoole

在 Swoole 4.0+ 中,异步方式被协程所取代,我们可以通过协程来加速应用



MySQL Coroutine

关于 Laravel 集成 Swoole 的相关文章:
Part 1 https://blog.albert-chen.com/the-integration-of-laravel-with-swoole-part-1/
Part 2 https://blog.albert-chen.com/the-integration-of-laravel-with-swoole-part-2/
Part 3 https://blog.albert-chen.com/the-integration-of-laravel-with-swoole-part-3/
Part 4 https://blog.albert-chen.com/the-integration-of-laravel-with-swoole-part-4/

Swoft 框架中相关信息说明
Nginx + php-fpm 模式
Linux 中 I/O 多路复用的说明
Swoole 中的协程

关于协程的概念讲解:漫画:什么是协程?

协程,英文Coroutines,是一种比线程更加轻量级的存在。正如一个进程可以拥有多个线程一样,一个线程也可以拥有多个协程。最重要的是,协程不是被操作系统内核所管理,而完全是由程序所控制(也就是在用户态执行)。

扩展阅读
什么是CPU密集型、IO密集型?
CPU 和 GPU 的区别是什么?
总的来说,由于动态解释型语言的执行效率不高,但开发效率较高,CPU大部分时间都在等待 I/O,因此适合做 I/O 密集型业务,而不适合做 CPU 密集型业务。相反,静态语言的执行效率高,因此适合做 CPU 密集型,如 C 语言。 GPU 相比 CPU 而言,运算能力更强,但逻辑处理能力较低,因此 GPU 适合做简单的密集型计算,比如图形渲染,密码暴力破解等。

5 打造自己的粉专客服机器人

PHP版本的机器学习库php-ml
一个较为成熟的机器人接口图灵机器人

6 快速打造定制化管理后台

使用 Voyager 可以快速搭建管理后台,该工具实现了

  1. 媒体管理
  2. 菜单管理
  3. 数据库管理
  4. 站点设置

7 网站信息安全

  1. 不要相信任何外部信息来源
  2. 管理平台不要泄露在任何一个前端节点
  3. 不要让用户上传的文件成为可执行文件
  4. 务必遵循最小权限原则
  5. 写代码的时间远小于被黑客攻击的损失

8 如何正确部署 Laravel

  • php >= 7.1
  • Extension
    • OpenSSL
    • PDO
    • mbstring
    • Tokenizer
    • XML
    • Ctype
    • JSON
    • opcache
    • gd
    • bcmath
    • pcntl
    • zip

使用 Crontab 时,尽量避免使用时区的功能,最好设定 cache 使用。
phpredis 性能更好,predis 开发更便捷。

9 代码质量

代码风格工具:PHP-CS-Fixer, PHP_CodeSniffer
php 静态分析:phpstan, psalm
CI 工具:Travis CI, StyleCI

LaravelConf 2017


未完待续……

因为热爱,所以执着。