Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

增强底层名字服务(服务端) #77

Open
matyhtf opened this issue Feb 24, 2021 · 0 comments
Open

增强底层名字服务(服务端) #77

matyhtf opened this issue Feb 24, 2021 · 0 comments
Labels
草案 draft

Comments

@matyhtf
Copy link
Member

matyhtf commented Feb 24, 2021

参考:#76

客户端支持 name_resolver 后,服务端可以在此基础上实现服务注册。

名字服务只支持IPv4IPv6协议的端口,对UnixSocket端口无效。

接口原型

interface RegisterInterface {
    function join(string $service_name, string  $ip, int $port);
    function leave(string  $service_name, string  $ip, int $port);
}

客户端

use function Swoole\Coroutine\run;
Co::set([
    'name_resolver' => [
        new Swoole\NameService\Redis('127.0.0.1', 6379),
    ],
]);

run(function () {
    echo Http\Get("http://user_service/path")->getBody();
});

服务端

use Swoole\Coroutine\Http\Server;
use function Swoole\Coroutine\run;

run(function () {
    $server = new Server("127.0.0.1", 8080);
    $server->set([
        'service_register' => [
            new Swoole\NameService\Redis('127.0.0.1', 6379),
            new Swoole\NameService\ZooKeeper('127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183'),
        ],
        'service_name' => 'user.service',
    ]);
    $server->handle('/', function ($req, $resp) {
        $resp->end('hello');
    });
    $server->start();
});

通过配置service_register选项实现服务注册,配置service_name设置服务名称。在:

  • Server启动后,调用register对象的join()方法注册到NameServer
  • Server关闭前,调用register对象的leave()方法从NameServer中注销

包括TCPHTTPHTTP2WebSocketRedis\Server 协程和异步Server均支持此配置。

Client端不同name_resolver配置不同,service_register 配置项是的关系,底层会遍历service_register数组,依次调用每个service_registerjoin()方法。

service_registerPort级选项,某些端口如果不需要注册服务,可设置service_register => null 关闭

IP 地址

  • 某些类型的register不需要填写IP地址,如consul,它会获取请求来源IP作为服务地址
  • 当端口监听地址是非0.0.0.0::时,join()方法使用监听的地址作为服务地址
  • 当端口监听地址是0.0.0.0::时,join()方法使用swoole_get_local_ip()获取本机IP地址,选取一个局域网IP地址作为服务地址,或者调用registerwithAddress($ip)方法指定IP
$server->set([
    'service_register' => [
        (new Swoole\NameService\Redis('127.0.0.1', 6379))->withAddress('127.0.0.1'),
        new Swoole\NameService\ZooKeeper('127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183'),
    ],
   'service_name' => 'user.service',
]);

端口

Register会自动获取Server\Port的端口,不需要外部传入。

续期

Server启动后底层会每隔一定时间调用RegisterInterface::join()方法向名字服务注册节点。可以在Register对象上使用withInterval($seconds)设置间隔时间。

$server->set([
    'service_register' => [
        (new Swoole\NameService\Redis('127.0.0.1', 6379))->withAddress('127.0.0.1')->withInterval(2),
        new Swoole\NameService\ZooKeeper('127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183'),
    ],
   'service_name' => 'user.service',
]);

上面例子会每隔2秒调用join()方法注册服务

健康检查

某些服务发现组件,如 consul 不需要Node主动续期,而是由服务发现主动进行健康检查,侦测节点是否存活。这时可以将join()间隔时间设置为0,不再主动续期。

当使用consul组件时会自动设置interval0

$server->set([
    'service_register' => [
        new Swoole\NameService\Consul('http://127.0.0.1:8500')->withHealthCheck($healthCheckConfig),
    ],
   'service_name' => 'user.service',
]);

限流策略

服务端在超过最大并发时拒绝新的请求,客户端收到服务器的拒绝信号后可以故障转移至其他节点,进行重试。

  • max_concurrency:最大并发请求数量,当服务器 accept 一个新请求时 +1,完成处理发送响应之后 -1
  • max_concurrency=100:静态限制,当前正在处理的请求数量超过100后,新的请求直接返回 503 错误
  • max_concurrency=auto:自适应限流,根据请求处理耗时(latency)变化测量服务器的实际最大并发处理能力。当max_concurrency调大一定比例后,测量 latency是否大幅上涨,如果是表示需要降低max_concurrency,如果为否,表示 max_concurrency 可以继续调大
  • latency:处理耗时,从接收请求到处理完成发送响应之间的时间,单位精确到毫秒或微秒,耗时是观测服务器程序负载情况的重要指标
@matyhtf matyhtf added the 草案 draft label Oct 29, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
草案 draft
Projects
None yet
Development

No branches or pull requests

1 participant