我是用Webman做的,其实Workerman也是同样的道理。
服务端:
config/process.php
<?php
return [
'node_center' => [
// 对应的服务类
'handler' => process\NodeCenter::class,
// 监听的协议 ip 及端口 (可选)
'listen' => 'tcp://0.0.0.0:4608',
// 进程数 (可选,默认1)
'count' => 1,
// 进程运行用户 (可选,默认当前用户)
'user' => '',
// 进程运行用户组 (可选,默认当前用户组)
'group' => '',
// 当前进程是否支持reload (可选,默认true)
'reloadable' => false,
// 是否开启reusePort (可选,此选项需要php>=7.0,默认为true)
'reusePort' => false, // 异步任务的reusePort要设置为false,让任务自动分配到空闲进程中
// transport (可选,当需要开启ssl时设置为ssl,默认为tcp)
'transport' => 'tcp',
// context (可选,当transport为是ssl时,需要传递证书路径)
'context' => [],
// 进程类构造函数参数,这里为 process\Pusher::class 类的构造函数参数 (可选)
'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();
以上配置做好后,当客户端启动后,可以正常连接到服务端,但是服务端$ip = $connection->getRemoteIp();得到的是nginx的192.168.1.100,而在var_dump($_SERVER);中完全没有任何与IP有关的信息。
参照https://www.workerman.net/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的问题,但是我确实找不到相关资料去搞定,所以在社区求助。
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代理", 就默认你安装了stream_module和stream_realip_module,看来是没有
重新编译nginx吧,带上--with-stream --with-stream_realip_module进行编译
刚看到了,--with-stream_realip_module是这个模块确实没装,我试一下,谢谢
[emerg] host not found in set_real_ip_from "$proxy_protocol_addr"
Try this
tcp代理无法透传ip。http可以是因为nginx会在http头部加一个
X-Real-IP
的header。tcp是更底层的传输层协议,没办法透传