我是用Webman做的,其實Workerman也是同樣的道理。
服務(wù)端:
config/process.php
<?php
return [
'node_center' => [
// 對應(yīng)的服務(wù)類
'handler' => process\NodeCenter::class,
// 監(jiān)聽的協(xié)議 ip 及端口 (可選)
'listen' => 'tcp://0.0.0.0:4608',
// 進程數(shù) (可選,默認(rèn)1)
'count' => 1,
// 進程運行用戶 (可選,默認(rèn)當(dāng)前用戶)
'user' => '',
// 進程運行用戶組 (可選,默認(rèn)當(dāng)前用戶組)
'group' => '',
// 當(dāng)前進程是否支持reload (可選,默認(rèn)true)
'reloadable' => false,
// 是否開啟reusePort (可選,此選項需要php>=7.0,默認(rèn)為true)
'reusePort' => false, // 異步任務(wù)的reusePort要設(shè)置為false,讓任務(wù)自動分配到空閑進程中
// transport (可選,當(dāng)需要開啟ssl時設(shè)置為ssl,默認(rèn)為tcp)
'transport' => 'tcp',
// context (可選,當(dāng)transport為是ssl時,需要傳遞證書路徑)
'context' => [],
// 進程類構(gòu)造函數(shù)參數(shù),這里為 process\Pusher::class 類的構(gòu)造函數(shù)參數(shù) (可選)
'constructor' => [],
],
];
process/NodeCenter.php
<?php
namespace process;
use Workerman\Connection\TcpConnection;
use Workerman\Worker;
class NodeCenter
{
public function onWorkerStart(Worker $worker)
{
}
public function onConnect(TcpConnection $connection)
{
$ip = $connection->getRemoteIp();
var_dump($ip); // 得到的是nginx的ip
var_dump($_SERVER);
}
public function onMessage(TcpConnection $connection, $data)
{
}
public function onClose(TcpConnection $connection)
{
}
}
nginx做tcp代理的配置(nginx的ip是192.168.1.100)
upstream callserver-center {
server 192.168.1.101:4608;
}
server {
listen 24608;
proxy_pass callserver-center;
}
客戶端(偽代碼):
$url = "tcp://192.168.1.100:24608";
$con = new AsyncTcpConnection($url);
$con->onConnect = function ($connection) {
$data = [
'command' => 'register',
'handler' => env('NODE_HANDLER', 1000),
];
$connection->send(json_encode($data));
};
$con->onClose = function ($connection) {
$connection->reConnect(5);
};
$con->onError = function ($connection) {
$connection->reConnect(5);
};
$con->connect();
以上配置做好后,當(dāng)客戶端啟動后,可以正常連接到服務(wù)端,但是服務(wù)端$ip = $connection->getRemoteIp();得到的是nginx的192.168.1.100,而在var_dump($_SERVER);中完全沒有任何與IP有關(guān)的信息。
參照http://wtbis.cn/doc/workerman/faq/get-real-ip-from-proxy.html
試著做proxy_set_header X-Real-IP $remote_addr;配置,但是在nginx的stream段做tcp代理時不支持proxy_set_header配置,把我難住了。
我知道這是nginx的問題而不是workerman的問題,但是我確實找不到相關(guān)資料去搞定,所以在社區(qū)求助。
server {
listen 24608 proxy_protocol;
proxy_pass callserver-center;
proxy_protocol on;
set_real_ip_from $proxy_protocol_addr;
}
nginx: [emerg] "set_real_ip_from" directive is not allowed here in /www/server/panel/vhost/nginx/tcp/center.conf:9
nginx: configuration file /www/server/nginx/conf/nginx.conf test failed
我看你既然說了"四層tcp代理", 就默認(rèn)你安裝了stream_module和stream_realip_module,看來是沒有
重新編譯nginx吧,帶上--with-stream --with-stream_realip_module進行編譯
Try this
stream {
server {
listen 24608 ;
proxy_pass 192.168.1.101:4608;
proxy_protocol on;
}
}
tcp代理無法透傳ip。http可以是因為nginx會在http頭部加一個X-Real-IP
的header。
tcp是更底層的傳輸層協(xié)議,沒辦法透傳