swlib/saber · 上手攻略
- 仓库:swlib/saber
- 链接:https://github.com/swlib/saber
- 分类:php · http-client · swoole · coroutine
- 作者:Tom
- 更新:2026-08-23
是什么
Saber 是基于 Swoole 协程的高性能 PHP HTTP 客户端,是 Swoole 人性化组件库的一员。底层基于 Swoole 原生协程 Client,提供了类似 Python requests 库 / JavaScript axios 的友好风格 API,同时兼容 PSR-7 标准。最大特点:用同步写法写异步高性能代码,业务层完全感知不到协程调度器的存在。
解决什么问题
传统 PHP 生态里,发 HTTP 请求的主流方案是 curl_* 系列函数,存在以下问题:
- 同步阻塞:一个请求没返回,后续代码全等着。
- 回调地狱:异步写法代码跳跃,逻辑断裂。
- 配置繁琐:设置超时、重试、代理、Cookie,每样都要手写。
- 长连接管理:手动维护连接池、复用连接。
Saber 用 Swoole 协程把上述问题全部在底层解决,暴露给业务层的接口和 requests 一样简单直观。
快速安装
# 依赖:PHP 7.1+,Swoole 2.1.2+(推荐 Swoole 4.x)
# 通过 Composer 安装
composer require swlib/saber
# 如需手动安装,下载 dist/humanize.min.js(注意这是 Saber 的发布产物,不是 HubSpot/humanize)
⚠️ Swoole 必须在 onRequest、onReceive、onConnect 等事件回调函数中调用,或者用 go() 关键字包裹(Swoole 的 swoole.use_shortname 默认开启,简写 go 可用)。
核心用法
1. 全局静态方法(SaberGM)
不需要实例,直接调用,等价于 Python 的 requests:
go(function () {
echo SaberGM::get('http://httpbin.org/get');
echo SaberGM::post('http://httpbin.org/post', ['foo' => 'bar']);
echo SaberGM::put('http://httpbin.org/put', ['foo' => 'bar']);
echo SaberGM::patch('http://httpbin.org/patch', ['foo' => 'bar']);
echo SaberGM::delete('http://httpbin.org/delete');
});
⚠️ 所有 go() 必须在 Swoole 的协程环境内;裸跑 php script.php 需要配合 Swoole Server 或 Co\run() 包装。
2. 实例方式 + Base URI
适合配置公共参数(base_uri、headers 等)后复用:
$saber = Saber::create([
'base_uri' => 'http://httpbin.org',
'headers' => [
'Accept-Language' => 'en,zh-CN;q=0.9,zh;q=0.8',
'Content-Type' => ContentType::JSON, // ContentType::JSON = 'application/json'
'DNT' => '1',
'User-Agent' => null // null = 不发 UA 头
]
]);
echo $saber->get('/get');
echo $saber->post('/post', ['foo' => 'bar']);
echo $saber->patch('/patch', ['foo' => 'bar']);
echo $saber->put('/put', ['foo' => 'bar']);
echo $saber->delete('/delete');
ContentType::JSON 等常量可查 Swlib\Http\ContentType 类。
3. Session(自动 Cookie 管理)
创建会话实例后,Cookie 自动持久化,行为等同于浏览器:
$session = Saber::session([
'base_uri' => 'http://httpbin.org',
'redirect' => 0 // 关闭重定向,便于调试
]);
// 先设 Cookie
$session->get('/cookies/set?foo=bar&k=v&apple=banana');
// 再取,确认 Cookie 携带
echo $session->get('/cookies')->body;
⚠️ 并发重定向时,多个重定向请求并发发出而非队列串行,性能更优。
4. 多请求并发(requests)
一次发起多个请求,汇总结果:
$responses = SaberGM::requests([
['uri' => 'http://github.com/'],
['uri' => 'http://github.com/'],
['uri' => 'https://github.com/']
]);
echo "multi-requests [ {$responses->success_num} ok, {$responses->error_num} error ]:\n";
echo "consuming-time: {$responses->time}s\n";
// multi-requests [ 3 ok, 0 error ]:
// consuming-time: 0.79090881347656s
5. 数据解析(list)
支持 JSON / XML / HTML / URL-Query 四种格式快速解析:
[$json, $xml, $html] = SaberGM::list([
'uri' => [
'http://httpbin.org/get',
'http://www.w3school.com.cn/example/xmle/note.xml',
'http://httpbin.org/html'
]
]);
var_dump($json->getParsedJsonArray());
var_dump($xml->getParsedXmlArray(true));
var_dump($html->getParsedDomObject()->getElementsByTagName('h1')->item(0)->textContent);
6. HTTP / SOCKS5 代理
$uri = 'http://myip.ipip.net/';
echo SaberGM::get($uri, ['proxy' => 'http://127.0.0.1:1087'])->body;
echo SaberGM::get($uri, ['proxy' => 'socks5://127.0.0.1:1086'])->body;
7. 文件上传(多文件并发)
支持三种参数风格(string / array / object)混合上传:
$file1 = __DIR__ . '/black.png';
// 风格1:字符串路径
$file2 = [
'path' => __DIR__ . '/black.png',
'name' => 'white.png',
'type' => ContentType::MAP['png'],
'offset' => null, // 断点续传用
'size' => null // 部分上传用
];
// 风格2:SwUploadFile 对象
$file3 = new SwUploadFile(__DIR__ . '/black.png', 'white.png', ContentType::MAP['png']);
echo SaberGM::post('http://httpbin.org/post', null, [
'files' => [
'image1' => $file1,
'image2' => $file2,
'image3' => $file3
]
]);
8. 超大文件下载(异步 + 断点续传)
// 底层协程调度,支持异步发送和断点续传
$saber->download('/large-file.zip', '/tmp/saved.zip', [
'offset' => 0, // 从 0 开始下载
'size' => null // null = 全文件
]);
9. 自动重试 + 超时配置
$saber = Saber::create([
'base_uri' => 'https://api.example.com',
'timeout' => 3000, // 毫秒级超时
'retry' => 3, // 自动重试 3 次
'retry_delay' => 1000 // 重试间隔 1 秒
]);
10. PSR-7 标准风格
完全兼容 PSR-7,可用标准接口链式调用:
use Swlib\SaberGM;
use Nyholm\Psr7\Uri;
$bufferStream = new BufferStream();
$bufferStream->write(json_encode(['foo' => 'bar']));
$response = SaberGM::psr()
->withMethod('POST')
->withUri(new Uri('http://httpbin.org/post?foo=bar'))
->withQueryParams(['foo' => 'option is higher-level than uri'])
->withHeader('content-type', ContentType::JSON)
->withBody($bufferStream)
->exec()->recv();
echo $response->getBody();
11. 连接池
| 模式 | 说明 |
|---|---|
| 无限连接池 | 请求来时自动创建连接,无上限 |
| 定容连接池 | 固定 N 个连接,满了排队 |
| 动态变容 | 根据负载自动扩缩容连接数 |
⚠️ 一次性脚本用完记得释放连接池,避免资源泄漏;长期运行进程(Swoole Server)则无需手动释放。
典型适用场景
- PHP 爬虫:Saber 的 Cookie 管理 + 并发请求 + 代理支持,是爬虫项目的理想底层。
- API 代理服务:用 Saber 快速搭建 API 转发/鉴权中间层,支持 session 保持。
- 微服务间 HTTP 调用:Swoole 环境下,高并发 HTTP 客户端比 Guzzle 更轻量。
- Webhook 消费者:配合 Swoole HTTP Server,消费外部 Webhook 并调用内部服务。
- 大文件上传/下载:断点续传 + 异步非阻塞,适合媒体类服务。
坑与注意
| 坑点 | 说明 |
|---|---|
| 必须在 Swoole 协程环境运行 | 裸 php script.php 不会工作,需要 go() 或 Co\run() 包装 |
| Swoole 版本依赖 | 最低 Swoole 2.1.2(发布于 2017 年),但推荐 Swoole 4.x;需确认你的 PHP 扩展环境 |
| PHP 7.1 基础语法 | composer require 默认拉最新 master,可能需要 swlib/saber:dev-master 指定版本 |
| HTTP/2 未支持 | README 明确说 HTTP/2 在 Roadmap,暂无计划;如需 HTTP/2 客户端,考虑 php-http/guzzle + Swoole 适配器 |
| 中文文档依赖机翻 | 英文 README 内容更完整;中文文档部分段落为自动翻译,可能有歧义 |
| IDE Helper 需要单独安装 | 官方提供 IDE Helper 包,写代码时自动补全;不装则无提示 |
| 连接池在 Swoole Task/Worker 间不共享 | 协程级别的连接池,不会跨 Swoole Worker 共享数据 |
与同类对比
| 工具 | 语言 | 协程 | HTTP/2 | PSR-7 | 适用场景 |
|---|---|---|---|---|---|
| Saber | PHP | ✅ Swoole 原生 | ❌ Roadmap | ✅ 完整兼容 | Swoole 环境高并发 HTTP |
| Guzzle | PHP | ❌(需 react/guzzle-adapter) | ✅ | ✅ | 通用 PHP HTTP 场景 |
| PHP cURL | PHP | ❌ | ⚠️ 部分 | ❌ | 最基础场景 |
| httpx | Python | ✅(asyncio) | ✅ | ❌ | Python 异步 HTTP |
| requests | Python | ❌ | ❌ | ❌ | Python 同步 HTTP |
Saber 在 PHP 生态的差异化优势是高性能 + 易用性兼得:基于 Swoole 的协程调度天然支持高并发,而 API 风格又比 Guzzle + Swoole Adapter 的组合简洁很多。
一句话推荐结论
如果你在 Swoole 环境下需要一个高性能 HTTP 客户端,Saber 的 API 设计友好、Cookie/重试/代理/并发开箱即用,值得直接上手——唯一需要确认的是你的 Swoole 版本 ≥ 4.x 且项目允许引入协程依赖。