bentools / mercure-php-hub
Requires
- php: >=7.4
- ext-json: *
- ext-mbstring: *
- ext-pcntl: *
- bentools/psr7-request-matcher: ^1.1
- bentools/querystring: ^1.0
- clue/block-react: ^1.4
- clue/redis-react: ^2.4
- lcobucci/jwt: 3.3.*
- predis/predis: ^1.1
- psr/http-server-middleware: ^1.0
- psr/log: ^1.1
- ramsey/uuid: ^4.0
- react/http: ^1.0.0
- rize/uri-template: ^0.3.2
- symfony/console: ^5.2
- symfony/dotenv: ^5.2
- symfony/flex: ^1.11.0
- symfony/framework-bundle: ^5.2
- symfony/string: ^5.2
- symfony/yaml: ^5.2
Requires (Dev)
- ext-dom: *
- bentools/cartesian-product: ^1.3.1
- bentools/iterable-functions: ^1.4
- bentools/shh: ^1.0
- clue/reactphp-eventsource: dev-master#e356b73fbf54a491c37d6b571ee5245206cbdc27
- friendsofphp/php-cs-fixer: ^2.16
- pestphp/pest: ^0.3.19
- phpstan/phpstan: ^0.12.25
- phpunit/phpunit: ^9.0
- ringcentral/psr7: ^1.3
- squizlabs/php_codesniffer: ^3.5
- symfony/http-client: ^5.2
- symfony/process: ^5.2
- symfony/var-dumper: ^5.2
This package is auto-updated.
Last update: 2021-12-18 13:00:05 UTC
README
Mercure PHP Hub
这个原型是一个 Mercure Hub 规范 的 PHP 实现。
由于我最近发布了 Freddie,该仓库将不再维护,Freddie 是一个全新的实现,它利用了 Framework X(底层仍然使用 ReactPHP)。
安装
要运行该 hub,需要 PHP 7.4+(以及 Redis,如果使用 Redis 转发器)。
composer create-project bentools/mercure-php-hub:dev-master
用法
./bin/mercure --jwt-key=\!ChangeMe\!
您可以使用环境变量(UPPER_SNAKE_CASE)来替换 CLI 选项,以便更方便。hub 还会检查是否存在 /etc/mercure/mercure.env
文件,然后使用 Symfony DotEnv 组件来填充变量。
请查看 configuration.php 以获取完整的配置选项。
优势和局限性
此实现不提供 SSL 或 HTTP2 终止,因此您最好在它前面放置一个反向代理。
使用 nginx 的示例
upstream mercure { server 127.0.0.1:3000; } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com; ssl_certificate /etc/ssl/certs/example.com/example.com.cert; ssl_certificate_key /etc/ssl/certs/example.com/example.com.key; ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5; location /.well-known/mercure { proxy_pass http://mercure; proxy_read_timeout 24h; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Proto $scheme; } }
默认情况下,hub 将作为简单的事件调度器运行。它可以满足基本使用的常见需求,但不可扩展(打开另一个进程不会共享相同的事件发射器)。
另一方面,您可以在 Redis 转发器(只要它们共享相同的 Redis 实例)上启动 hub,并在多个端口/服务器上使用负载均衡器来分发流量。由于 open-source Go 实现的 hub 在 bolt 转发器上的并发限制,这目前尚不可能。
upstream mercure { # 4 instances on 10.1.2.3 server 10.1.2.3:3000; server 10.1.2.3:3001; server 10.1.2.3:3002; server 10.1.2.3:3003; # 4 instances on 10.1.2.4 server 10.1.2.4:3000; server 10.1.2.4:3001; server 10.1.2.4:3002; server 10.1.2.4:3003; }
./bin/mercure --transport-url="redis://localhost" --jwt-key=\!ChangeMe\!
基准测试
在服务器 A 上模拟 1/100/1000 订阅者,在服务器 B 上有 1 个发布者发送消息,服务器 C(以及服务器 D)上的 hub。
实现 | 传输 | 服务器 | 节点 | 1 订阅者 | 100 订阅者 | 1000 订阅者 |
---|---|---|---|---|---|---|
Mercure.rocks GO Hub | Bolt | 1 | 1 | 361 / 286 | 129 / 4989 | 142 / 682 |
ReactPHP 实现 | PHP | 1 | 1 | 860 / 295 | 519 / 4526 | 45 / 322 |
ReactPHP 实现 | Redis(本地) | 1 | 1 | 1548 / 411 | 393 / 5861 | 112 / 777 |
ReactPHP 实现 | Redis(本地) | 1 | 4 | 108 / 76 | 61 / 2852 | 61 / 688 |
ReactPHP 实现 | Redis(共享) | 2 | 8 | 3035 / 144 | 1183 / 7864 | 708 / 2698 |
单位是 POSTs (发布) / s
/ 接收事件 / s
(所有订阅者的总数)。
节点是 ReactPHP 打开的端口的总数。
Hub 在廉价的服务器上托管:2GB / 2 CPU VPS(Ubuntu 20.04)。您可以使用更大尺寸的服务器和专用 CPU 达到非常高的性能。
功能覆盖范围
功能 | 覆盖 |
---|---|
通过 Authorization 头部使用 JWT |
✅ |
通过 mercureAuthorization Cookie 使用 JWT |
✅ |
为订阅者/发布者使用不同的 JWT | ✅ |
允许匿名订阅者 | ✅ |
CORS | ✅ |
私有更新 | ✅ |
主题的 URI 模板 | ✅ |
健康检查端点 | ✅ |
HMAC SHA256 JWT 签名 | ✅ |
RS512 JWT 签名 | ✅ |
环境变量配置 | ✅ |
自定义消息 ID | ✅ |
最后事件 ID | ✅️ (除了 REDIS 传输中的 earliest ) |
可定制事件类型 | ✅️ |
可定制 retry 指令 |
✅️ |
日志记录 | ❌ (WIP)️ |
度量 | ❌ (WIP)️ |
订阅事件 | ❌️ |
订阅 API | ❌️ |
使用配置文件进行配置 | ❌️ |
有效负载 | ❌️ |
心跳 | ❌️ |
Forwarded / X-Forwarded-For 头部 |
❌️ |
备用主题 | ❌️ |
附加功能
此实现提供了一些在原始规范中未定义的功能。
订阅/发布主题排除
Mercure 利用 URI Templates 基于URI模式授权订阅和/或发布权限。
{ "mercure": { "publish": [ "https://example.com/items/{id}" ], "subscribe": [ "https://example.com/items/{id}" ] } }
但是,拒绝访问与URI模板匹配的特定URL需要您显式列出授权项。
{ "mercure": { "publish": [ "https://example.com/items/1", "https://example.com/items/2", "https://example.com/items/4" ], "subscribe": [ "https://example.com/items/1", "https://example.com/items/2", "https://example.com/items/4" ] } }
当处理成千上万的可能性时,这可能会很快成为一个问题。Mercure PHP Hub 允许您通过 publish_exclude
和 subscribe_exclude
键指定拒绝列表,这些键接受任何主题选择器。
{ "mercure": { "publish": [ "https://example.com/items/{id}" ], "publish_exclude": [ "https://example.com/items/3" ], "subscribe": [ "https://example.com/items/{id}" ], "subscribe_exclude": [ "https://example.com/items/3" ] } }
Json Web Token 生成器
您可以从命令行生成一个 JWT,用于在中心使用。
./bin/mercure jwt:generate
它将交互式地询问您希望允许/拒绝哪些主题选择器用于发布/订阅,并询问您一个可选的TTL。
如果您想要原始输出(例如,将生成的 JWT 管道),请使用 --raw
选项。
要禁用交互,可以使用以下示例
./bin/mercure jwt:generate --no-interactive --publish=/foo/{id} --publish=/bar --publish-exclude=/foo/bar
它将使用您的 JWT 密钥环境变量,或者您可以使用 --jwt-key
、--publisher-jwt-key
、--subscriber-jwt-key
选项。
要获取可用选项的完整列表,请运行此
./bin/mercure jwt:generate -h
测试
此项目受到 Pest 测试的覆盖。覆盖率需要提高:请随时贡献力量。
composer tests:run
贡献力量
如果您想改进此项目,请随时提交 PR。
- CI 会大声喊叫,如果您不遵循 PSR-12 编码标准。
- 在新的功能中,它必须伴随着测试。
- PHPStan 分析必须在第 5 级通过。
在提交之前,您可以使用 composer ci:check
运行以确保所有 CI 要求都已成功满足。
许可证
GNU 通用公共许可证 v3.0。