- rango: http://rango.swoole.com/ - 鸟哥: http://www.laruence.com/ --- - [swoole 编码实例](https://gitee.com/daydaygo/coding/tree/master/php/swoole) - [swoole wiki](https://wiki.swoole.com) - [swoole 基础知识——会敲代码的喵](http://www.catplanet.me/) - [swoole 视频教程](https://wiki.swoole.com/wiki/page/227.html) - [swoole 运行流程图](https://wiki.swoole.com/static/uploads/swoole.jpg) - [swoole 进程/线程 结构图](https://wiki.swoole.com/static/image/process.jpg) - [内核参数调整](https://wiki.swoole.com/wiki/page/p-server/sysctl.html) --- - [**swoft**](https://github.com/swoft-cloud/swoft): Modern High performance AOP and Coroutine PHP Framework base on Swoole2, 1000+ star - [swoole-jobs](https://github.com/kcloze/swoole-jobs): 使用 swoole_process 实现进程调度 - [swoole distributed](http://docs.youwoxing.net/) - [php-msf](https://www.gitbook.com/book/pinguo/php-msf-docs) ## 服务器开发 同步代码, 进程模型, 一个进程只能处理一个请求, 依赖进程多少来来处理并发, 进程越多, 进程间切换开销会越来越大 异步代码(事件驱动), 所有地方都要改为异步代码, 当某个请求进入等待后, work 进程并不会等在这里, 而是切换去处理其他请求 tcp/udp的选择: 一般实时下使用 udp(相较 tcp 4 倍的性能提升) tcp/ip 4 层网络协议: 数据链路层 网络层 传输层 应用层 tcp: 顺序 丢包重传 流式的,数据包没有边界,分包/合包,需要协议支持,EOF协议,固定包头协议 3 种网络类型: `127.0.0.1`(本地主机, 只有本地可以连接) / 内网 / 外网; `0.0.0.0`, 允许上面3种网络接入 cpu密集/io密集: 真正慢的是 php 写的代码, 如用户函数/类/对象操作 协程 coroutine: 异步太难写 / 时间静止游戏 / go erlang lua协程; 进程/线程由操作系统进行 eventloop, 协程由用户调度 AIO: gcc aio, `<aio.h>`, 阻塞IO + 线程池; libeio; linux native aio, `<linux/aio_abi.h>` 多线程: - 同一个进程内, 共享内存实现线程间通信, 更轻量级, 占用更少系统资源 - 需要加锁, 锁的粒度, 多个锁逻辑复杂, 某个线程发生致命错误会导致整个进程崩溃 - 线程带来的坑更多 c10k: kqueue(freeBSD) epoll(linux) IOCP(window) 系统默认 dns 查询是一次 udp 同步阻塞请求 IPC: - 共享内存, 也需要锁 - 消息队列, 多个子进程抢队列, 性能更好 - PIPE, unixsocket, tcp, udp, tcp/udp 子进程可以分布式并行 linux IPC 消息队列: - `./configure --enable-sysvmsg` - `msgget() / msgsnd() / msgrcv() / msgctl()` - `ipcs -q` ``` # tool pstree -a|grep server.php # 查看进程树 strace -pf # 查看线程 tcpdump # 网络抓包工具 nc # netcat 用来取代 telnet 来进行网络编程测试 kill -l # 查看信号 ``` ## php phar: 类似 jar, 方便打包代码集成部署 闭包函数 + use php session 数据同步的问题: 高并发下 `$_SESSION` 写 session, `file_put_contents` 写 cache php 相关扩展: - stream(2 层封装)/socket(系统 socket api 的封装) - libevent/event - pcntl/posix - pthread: 线程安全版本可用 - php 共享内存/信号量(semaphores)/消息队列 相关扩展 - ext-aop: 面向切片编程 - PECL php 面向对象: - 对象的传递全部采用引用 - private protected public extends final abstract interface implements static self parent $this const - Magic Methods PHP 并发IO编程: - 同步阻塞: 直接fork进程 进程池/线程池 - io复用: select(1024连接)/poll 循环检测是否有事件; epoll Reactor模型(add/set/del/callback) - 异步 io - 协程 单机环境下共享数据: - ext-apc: `apc_store() / apc_fetch() / apc_delete() / APCIterator / apc_bin_dumpfile() / apc_bin_loadfile()`, 锁 + 共享内存 - 读写内存文件 `/dev/shm/` + `swoole_lock` - memcache / redis / mysql php 程序员解决问题的能力: - php 错误信息: display_errors / display_startup_errors / error_reporting / `error_reporting(E_ALL)` - cli / fpm - var_dump() / die() - strace: `strace -p pid` / `strace php test.php` - tcpdump - xhporf/xdebug - gdb: `php/src/.gdbinit` zbacktrace / 有一个 gdb 调试时, 不能再使用 gdb/strace 调试 - 查看内核和扩展源码 php7 性能优化: - zval 使用栈内存 vs 堆内存 - zend_string 存储 hash 值 - hashtable bucket 内直接存数据 vs 每个元素都是一个 bucket - 新增 4 种 opcode: `call_user_function/is_int/string/array/strlen/defined` php7 新特性: - 参数 / 返回值 类型限定 - fatal error -> Exception - 匿名类 ## swoole > https://wiki.swoole.com swoole 源码: 2层目录, 面对对象风格写 c swoole 使用 c 写: php 无法直接调用 os api / php 内存管理粒度太粗 c 语言实现的客户端, 在性能上远超其他语言 RPC 支持 swoole 的异步 redis 也是使用魔术方法 异步安全重启(热更新): 给 worker 进程发送 SIGTERM 信号, manager 进程收到 worker 退出消息后, 创建新的 worker swoole 进程模型: - master 进程: 启动 manage 进程, reactor 线程, 接受 accept 后投递给 reactor(均衡负载和防止惊群) - reactor 线程: 管理 socket 的连接和收发, 收到数据后投递给 worker 进程; cpu 亲和; 组装数据 - manage 进程: 管理 worker 进程 / task 进程 / process 进程, 平滑重启/热加载 - worker 进程: 接收 reactor 线程投递的数据, 进行业务处理, 耗时任务投递给 task 进程, 返回数据给 reactor - task 进程: 处理耗时任务 - process 进程: 用来处理其他业务, 比如消息订阅 swoole 3 种运行模式: - base: Reactor 线程中直接回调 php 函数, 适合不会发生阻塞(读文件/数据库/网络请求)的场景, 简单高效 - 线程模式: 多线程 worker 模式, mutex/读写锁/文件锁/信号量/自旋锁 - 进程模式: 进程间通信/进程管理, 适合业务逻辑复杂的场景 swoole 同步: 类似 fpm swoole 异步: 异步 `Swoole\Server` 配合 `Swoole\Client` / `Swoole\Event::add()`, `Swoole\Task` 处理阻塞任务 ## rango blog - [关于PHP程序员技术职业生涯规划](http://rango.swoole.com/archives/570) web server push: websocket / XHR轮询 + KeepAlive 大型网站运营: 日志系统(日志中心) php错误日志收集 数据统计中心(数据上报) 硬件系统报警 容灾工具(雪崩) 开发效率: 单元测试 bug修复 提升用户体验 完善细节 提供配套工具 优化性能 增加关键日志 增加监控报警 增加容灾方案 腾讯: 产品驱动型管理 -> 技术失去积极性 Facebook: 产品给技术出谋划策 ## laruence blog - [授人渔而非鱼](http://www.laruence.com/2007/11/06/9.html): 就是刚刚被一个小孩子给烦的。。。。一下想了这么多,不知道归什么类了。。。 - [深入理解PHP原理之Opcodes](http://www.laruence.com/2008/06/18/221.html) - [关于PHP你可能不知道的-PHP的事件驱动化设计](http://www.laruence.com/2008/04/21/101.html) - [深入浅出PHP(Exploring PHP)](http://www.laruence.com/2008/08/11/147.html) - [深入理解PHP原理之变量(Variables inside PHP)](http://www.laruence.com/2008/08/22/412.html) - [扩展PHP[Extending PHP](一)](http://www.laruence.com/2008/08/16/301.html) - [PHP Life Cycle演讲幻灯片(PHP Life Cycle Slides)](http://www.laruence.com/2008/08/15/283.html) - [深入理解PHP原理之变量分离/引用(Variables Separation)](http://www.laruence.com/2008/09/19/520.html) js + vs array.join: gc perl 的思维方式: 符号代替文字 php header() -> http 协议 header 深入 mysql 字符集: http://www.laruence.com/2008/01/05/12.html 调用规范(Calling Conventions): 函数调用需要多少/什么样的参数; stdcall / cdecl / fastcall / thiscall / naked call `var_export()` 不能打印 resource 类型, 返回 null `php_globals.h`: php module 中获取 `$_GET` 等变量 将回调函数作为函数参数 「apache 源码分析」「深入 php 内核」「php power programing」 php异步调用方法: - html ajax / img 标签等 - `pclose(popen("/home/xinchen/backend.php &", 'r'));` - curl 设置超时 - fsockopen(): `ignore_user_abort(true) / set_time_limit(0)` `ob_end_flush()`: php 设置输出缓存 sysvsem 系列函数: `sem_xxx()`, 信号量 sysvshm 系列函数: `shm_xxx()`, 共享内存 `shmop_xxx()`: 也可以操作共享内存 sysvmsg 系列函数: `msg_xxx()`, 进程间通信 `ftok()`: 获取消息队列的 key 汉字和Unicode(utf-8)之间转换: `unpack('H6', '中') / pack('H6', 'e4b8ad')` zend 引擎执行 php 代码: - scanning(lexing): php 代码 -> tokens - parsing: tokens -> 有意义的表达式 - compilation: 表达式 -> opcodes - execution 深入理解 php: - zend engine - ext 扩展: http://www.laruence.com/2009/04/28/719.html; 扩展载入过程/关闭函数 - opcode: opcode list(高级指令集); 载入顺序(单配置文件/多配制文件/`zend_module_dep`) - zval: `struct _zval_struct / union _zval_value`; refcount / `debug_zval_dump()`; copy on write / change on write - global 变量: 全局 `symbol_table` 中查找 - scope in php: hashtable 存储变量名到 zval 的隐射; 全局符号表/函数符号表 - lambda 匿名函数 closure - Embed SAPI: 允许在 c/c++ 中使用 PHP/ZE 提供的函数 - Iterator 接口 - `$_GET` 等变量生成过程 - 变量: 名字 hashtable; 生命期; 作用域 - 函数 vs 语句 - 匿名函数 - 对象: 命名空间(字符串匹配) - 文件上传: rfc1867 - foreach 实现: 编译原理 lex and yacc - hash: 算法; 数组的遍历顺序 - php 内嵌 html; `@` 错误抑制 - 引擎分发方式: GOTO CALL SWITCH - 异常处理机制 - core 调试 - 内存管理: 应用层 -> 引用计数/写时复制; 自身 -> `zend_mm_heap` 混淆加密 -> 反编译 线程安全资源管理器(Thread Safe Resource Manager) TSRM存储器(TSRM Local Storage) Zend线程安全(Zend Thread Safety) 多线程场景下的 global 变量 `get_loaded_extensions() / get_extension_funcs()` `==` 进行字符串比较 PhpDocumentor ext-soap 数组非数字键名带引号 受 locale 影响的函数: 推荐使用 `mb_*` 系列函数; `getext()` 实现多语言 字符编码基础 html entities 与 `mb_*` 函数 `json_encode()/json_decode()` `include()/require()` `ob_*` 系列函数 字符串递增: perl / c php调试技术: `echo/die/var_dump()/debug_zval_dump()/memory_get_usage()` 错误控制/日志 浏览器调试 ide xdebug phpunit php其实是更高级的语言, 看似「简单」的背后, 需要知道原理可能多得多 JsonSerializable接口 `mysqlnd_ms` native dirver 实现读写分离 `json_encode()` 中文支持 binary number format `exit(-1)` 如何设置一个 30 分钟过期的 session? `ex-bcmath/ex-gmp` 数学运算 release resource manually 静态方法调用 直接使用 nginx/apache 发送文件 编译不做任何语义优化 错误码 vs 异常 try-catch-finally generator yield libcurl + `--enable-ares`: 异步 dns autoconfi/automake: http://www.laruence.com/2009/11/18/1154.html `pkg-config/ldconfig`: http://www.laruence.com/2010/01/27/1265.html apache prefork: 先 fork 固定数量进程, 高峰时再多 fork, 多 fork 出的进程通过 option 请求唤醒退出 web 加速: 任务分离, 提前返回 js 作用域链 prototype js RegExp lastIndex属性 js this 永远指向函数(方法)所有者 js 单线程: GUI渲染线程 GUI事件触发线程 定时触发线程 CSS Sprites 圈入效果 浏览器: DOM 规范; 结构模型; 缓存机制 `cache-control` 用户可预感体验 做互联网, 就一定要多用新的互联网产品, 遇到好玩的, 要主动去思考如何实现, 这样才能一直保证你自己的良好的互联网应用的sense. 分析能力: 发现问题 定位问题 思考能力: 找到问题合理的不造成其他影响的解决办法 兴趣是我最大的动力 「暗时间」 语言用来解决实际问题, 解决问题的经验的成长 更喜欢用自己的不足去和别人的优点做比较, 追赶他们的优点 大胆推测, 小心求证 学无止境 ## todo wiki.swoole 笔记 TP官方支持swoole: https://www.kancloud.cn/manual/thinkphp5_1/675277