workerman/http-client
Giới thiệu
workerman/http-client là một thành phần client http bất đồng bộ. Tất cả các yêu cầu phản hồi đều bất đồng bộ không chặn, có tích hợp sẵn pool kết nối, yêu cầu và phản hồi tin nhắn tuân thủ tiêu chuẩn PSR7.
Cài đặt:
composer require workerman/http-client
Ví dụ:
Cách sử dụng yêu cầu GET và POST
use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';
$worker = new Worker();
$worker->onWorkerStart = function () {
$http = new Workerman\Http\Client();
$http->get('https://example.com/', function ($response) {
var_dump($response->getStatusCode());
echo $response->getBody();
}, function ($exception) {
echo $exception;
});
$http->post('https://example.com/', ['key1' => 'value1', 'key2' => 'value2'], function ($response) {
var_dump($response->getStatusCode());
echo $response->getBody();
}, function ($exception) {
echo $exception;
});
$http->request('https://example.com/', [
'method' => 'POST',
'version' => '1.1',
'headers' => ['Connection' => 'keep-alive'],
'data' => ['key1' => 'value1', 'key2' => 'value2'],
'success' => function ($response) {
echo $response->getBody();
},
'error' => function ($exception) {
echo $exception;
}
]);
};
Worker::runAll();
Tải lên tập tin
<?php
use Workerman\Worker;
require_once 'vendor/autoload.php';
$worker = new Worker();
$worker->onWorkerStart = function () {
$http = new Workerman\Http\Client();
// Tải lên tập tin
$multipart = new \Workerman\Psr7\MultipartStream([
[
'name' => 'file',
'contents' => fopen(__FILE__, 'r')
],
[
'name' => 'json',
'contents' => json_encode(['a'=>1, 'b'=>2])
]
]);
$boundary = $multipart->getBoundary();
$http->request('http://127.0.0.1:8787', [
'method' => 'POST',
'version' => '1.1',
'headers' => ['Connection' => 'keep-alive', 'Content-Type' => "multipart/form-data; boundary=$boundary"],
'data' => $multipart,
'success' => function ($response) {
echo $response->getBody();
},
'error' => function ($exception) {
echo $exception;
}
]);
};
Worker::runAll();
Trả về theo luồng tiến độ
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Workerman\Connection\TcpConnection;
use Workerman\Http\Client;
use Workerman\Protocols\Http\Chunk;
use Workerman\Protocols\Http\Request;
use Workerman\Protocols\Http\Response;
use Workerman\Worker;
$worker = new Worker('http://0.0.0.0:1234');
$worker->onMessage = function (TcpConnection $connection, Request $request) {
$http = new Client();
$http->request('https://api.ai.com/v1/chat/completions', [
'method' => 'POST',
'data' => json_encode([
'model' => 'gpt-3.5-turbo',
'temperature' => 1,
'stream' => true,
'messages' => [['role' => 'user', 'content' => 'hello']],
]),
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer sk-xxx',
],
'progress' => function($buffer) use ($connection) {
$connection->send(new Chunk($buffer));
},
'success' => function($response) use ($connection) {
$connection->send(new Chunk('')); // Gửi chunk rỗng để biểu thị phản hồi đã kết thúc
},
]);
$connection->send(new Response(200, [
//"Content-Type" => "application/octet-stream",
"Transfer-Encoding" => "chunked",
], ''));
};
Worker::runAll();
Tùy chọn Opions
<?php
require __DIR__ . '/vendor/autoload.php';
use Workerman\Worker;
$worker = new Worker();
$worker->onWorkerStart = function(){
$options = [
'max_conn_per_addr' => 128, // Số lượng kết nối đồng thời tối đa cho mỗi tên miền
'keepalive_timeout' => 15, // Thời gian không giao tiếp trước khi đóng kết nối
'connect_timeout' => 30, // Thời gian chờ kết nối
'timeout' => 30, // Thời gian chờ phản hồi sau khi gửi yêu cầu
];
$http = new Workerman\Http\Client($options);
$http->get('http://example.com/', function($response){
var_dump($response->getStatusCode());
echo $response->getBody();
}, function($exception){
echo $exception;
});
};
Worker::runAll();
Cách sử dụng với coroutine
Lưu ý
Cách sử dụng với coroutine yêu cầu workerman>=5.1, http-client>=3.0, cài đặt mở rộngswoolehoặcswow, hoặc cài đặtcomposer require revolt/event-loopđể hỗ trợ trình điều khiển Fiber.
use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';
$worker = new Worker();
$worker->eventLoop = \Workerman\Events\Swoole::class; // Hoặc \Workerman\Events\Swow::class hoặc \Workerman\Events\Fiber::class
$worker->onWorkerStart = function () {
$http = new Workerman\Http\Client();
$response = $http->get('https://example.com/');
var_dump($response->getStatusCode());
echo $response->getBody();
$response = $http->post('https://example.com/', ['key1' => 'value1', 'key2' => 'value2']);
var_dump($response->getStatusCode());
echo $response->getBody();
$response = $http->request('https://example.com/', [
'method' => 'POST',
'version' => '1.1',
'headers' => ['Connection' => 'keep-alive'],
'data' => ['key1' => 'value1', 'key2' => 'value2'],
]);
echo $response->getBody();
};
Worker::runAll();
Khi không đặt hàm callback, client sẽ trả về kết quả yêu cầu bất đồng bộ theo cách đồng bộ, quá trình yêu cầu không chặn tiến trình hiện tại, nghĩa là có thể xử lý đồng thời các yêu cầu.
Lưu ý:
-
Dự án trước tiên cần phải tải
require __DIR__ . '/vendor/autoload.php'; -
Tất cả mã bất đồng bộ chỉ có thể chạy trong môi trường sau khi workerman được khởi động
-
Hỗ trợ tất cả các dự án phát triển dựa trên workerman, bao gồm Webman, GatewayWorker, PHPSocket.io, v.v.
-
Nên lưu trữ đối tượng client để tái sử dụng, điều này sẽ giúp tận dụng pool kết nối để cải thiện hiệu suất, không nên tạo lại đối tượng
new Workerman\Http\Client()mỗi lần.
Cách sử dụng trong webman
Nếu bạn cần sử dụng yêu cầu http bất đồng bộ trong webman và trả kết quả cho phía trước, tham khảo cách sử dụng sau
<?php
namespace app\controller;
use support\Request;
use support\Response;
use Workerman\Protocols\Http\Chunk;
class IndexController
{
public function index(Request $request)
{
// Lưu trữ đối tượng client để tái sử dụng, có thể nâng cao hiệu suất đáng kể
static $http;
$connection = $request->connection;
$http = $http ?: new \Workerman\Http\Client();
$http->get('https://example.com/', function ($response) use ($connection) {
$connection->send(new Chunk($response->getBody()));
$connection->send(new Chunk('')); // Gửi chunk rỗng để biểu thị phản hồi đã kết thúc
});
return response()->withHeaders([
"Transfer-Encoding" => "chunked",
]);
}
}
Cách sử dụng trên là trước tiên gửi cho client một tiêu đề http có chunked, sau đó gửi dữ liệu dưới dạng chunk cho client, dĩ nhiên cũng có thể tham khảo cách sử dụng coroutine ở trên.
Lưu ý
Mã ở trên đã lưu trữ đối tượng client trong biến tĩnh của phạm vi phương thức để tái sử dụng, thực tế cũng có thể lưu trữ trong thành viên tĩnh của lớp hoặc trong đối tượng toàn cục.
Gửi yêu cầu đến API OpenAI trong webman và trả về theo luồng
Tham khảo https://www.workerman.net/plugin/157