A SDK for nacos service written in PHP. 简单的php版本nacos客户端

v1.1.3 2025-07-31 08:46 UTC

This package is auto-updated.

Last update: 2025-07-31 08:47:04 UTC


README

简单的php版本nacos客户端

安装

composer require xiaosongshu/nacos

项目地址

https://github.com/2723659854/nacos

客户端示例

<?php

require_once __DIR__.'/vendor/autoload.php';


$dataId      = 'CalculatorService';
$group       = 'api';
$serviceName = 'father';
$namespace   = 'public';

$client      = new \Xiaosongshu\Nacos\Client('http://127.0.0.1:8848','nacos','nacos');

/** 发布配置 */
$client->publishConfig($dataId, $group, json_encode(['name' => 'fool', 'bar' => 'ha']));
/** 创建实例 */
$client->createInstance($serviceName, "192.168.4.110", '9506', $namespace, ['name' => 'tom', 'age' => 15], 50, 1, true)

应用举例

注册发布服务,监听配置示例

本项目提供已编写好的服务端Xiaosongshu\Nacos\Server和客户端Xiaosongshu\Nacos\JsonRpcClient

服务端配置文件

其中配置文件config.php,内容如下:

<?php

return [

    /** 连接服务器的基本配置 */
    'server' => [
        'host' => 'http://127.0.0.1:8848',
        'username' => 'nacos',
        'password' => 'nacos',
        'heartbeat_interval' => 5, // 心跳间隔(秒,默认5秒)
    ],

    /** 服务提供者实例的配置 */
    'instance' => [
        'ip' => '127.0.0.1',
        'port' => '8000',
        'weight' => 99, // 初始权重(降级时会动态调整)
        'timeout_threshold' => 1000, // 超时阈值(毫秒,超过此时间视为超时,用于计算超时率)
    ],

    /** 健康检查与熔断降级配置 */
    'health' => [
        'stat_window_size' => 10, // 统计窗口大小(最近100个请求用于计算超时率/错误率)
        'adjust_cool_down' => 10, // 调整冷却时间(秒,避免频繁调整,默认30秒)
    ],

    /** 需要监听的配置 作为配置,你可能需要尽可能将配置合并到比较少的文件,一个项目一个配置文件最多两个配置文件就足够了。 */
    'config' => [
        'app' => [
            # 是否开启监听
            'enable' => true,
            'dataId' => 'default',
            'group' => 'default',
            # 需要配监听的配置文件
            'file' => __DIR__ . '/application.yaml',
            # 监听到配置发生变化的回调
            'callback' => function ($content) {
                // todo 根据你的应用场景,将配置刷新到内存,或者重启应用,此处仅做示例演示将配置写入文件
                file_put_contents(__DIR__ . "/application.yaml", $content);
                
            }
        ],
    ],

    /** 需要注册的服务 */
    'service' => [
        // 服务标识:demo
        'demo' => [
            'enable' => true,
            'serviceName' => \Xiaosongshu\Nacos\Samples\DemoService::class,
            'namespace' => 'public',
        ],

        // 服务标识:login
        'login' => [
            'enable' => true,
            'serviceName' => \Xiaosongshu\Nacos\Samples\LoginService::class,
            'namespace' => 'public',
            'contract' => [
                'out' => 'logout'
            ]
        ]
    ]
];

如果需要监听配置,如上面文件的配置application.yaml,假设文件内容如下:

app=demo
debug=true

DB_HOST=127.0.0.1
DB_PORT=3306
DB_USER=root
DB_PASS=root
DB_DATABASE=demo

REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASS=123456
服务端代码

你可以编写一个server.php文件,内容如下

<?php

require_once __DIR__.'/vendor/autoload.php';
require_once __DIR__."/DemoService.php";
require_once __DIR__."/LoginService.php";

use Xiaosongshu\Nacos\Server;

// 加载配置文件
$config = require 'config.php';

// 启动服务

try{
    $server = new Server($config);
    $server->run();
}catch (\Throwable $exception){
    var_dump($exception->getMessage(),$exception->getLine(),$exception->getFile());
}

而服务提供者DemoService.php内容如下

<?php
namespace Xiaosongshu\Nacos\Samples;

/**
 * @purpose 示例服务提供者
 * @author yanglong
 * @time 2025年7月25日12:16:19
 */
class DemoService
{

    /**
     * 示例方法:添加用户信息
     * @param string $name 姓名
     * @param int $age 年龄
     * @return string
     */
    public function add(string $name, int $age): string
    {
        return "用户添加成功!姓名:{$name},年龄:{$age}(服务端处理时间:" . date('H:i:s') . "";
    }

    /**
     * 示例方法:获取用户信息
     * @param string $name 姓名
     * @return array
     */
    public function get(string $name): array
    {
        return [
            'name' => $name,
            'age' => 25,
            'message' => "查询成功(服务端时间:" . date('H:i:s') . ""
        ];
    }
}

服务提供者LoginService.php内容如下:

<?php

namespace Xiaosongshu\Nacos\Samples;

/**
 * @purpose 用户登录服务
 * @author yanglong
 * @time 2025年7月25日17:32:27
 */
class LoginService
{
    /**
     * 用户登录接口
     * @param string $username 用户名(必填,长度≥3)
     * @param string $password 密码(必填,长度≥6)
     * @return array 登录结果,包含token
     */
    public function login(string $username, string $password): array
    {
        // 模拟业务逻辑:验证用户名密码
        if (strlen($username) < 3) {
            return ['success' => false, 'message' => '用户名长度不能少于3位'];
        }
        if (strlen($password) < 6) {
            return ['success' => false, 'message' => '密码长度不能少于6位'];
        }

        // 模拟生成token
        $token = md5($username . time() . 'secret');
        return [
            'success' => true,
            'message' => '登录成功',
            'token' => $token,
            'expire' => 3600 // token有效期(秒)
        ];
    }

    /**
     * 退出登录
     * @param string $token
     * @return array
     */
    public function logout(string $token): array{
        return [
            'success' => true,
            'message' => '退出登录成功',
            'token' => $token,
        ];
    }
}

编写完以上文件后,开启服务,命令如下:

php server.php
客户端代码

这个时候我们再编写一个客户端client.php,用来测试调用服务。内容如下:

<?php

// 使用示例
require_once __DIR__ . '/vendor/autoload.php';

use Xiaosongshu\Nacos\JsonRpcClient;

// Nacos配置(与服务端一致)
$nacosConfig = [
    'host' => 'http://192.168.110.72:8848',
    'username' => 'nacos',
    'password' => 'nacos'
];


$client = new JsonRpcClient($nacosConfig);

// 调用login服务(仅需传入服务标识和业务参数)
$loginResult = $client->call('login', [
    'username' => 'zhangsan',
    'password' => '123456'
]);

// 打印结果
if ($loginResult['success']) {
    echo "登录成功:\n";
    echo "Token:{$loginResult['result']['token']}\n";
    echo "有效期:{$loginResult['result']['expire']}\n";
    echo "调用实例:{$loginResult['instance']}\n";
} else {
    echo "登录失败:{$loginResult['error']}\n";
}


// 退出登录 使用契约
$logoutRes = $client->call('login', ['token' => $loginResult['result']['token']], 'out');
if ($logoutRes['success']) {
    echo "退出登录成功:\n";
    echo "Token:{$logoutRes['result']['token']}\n";
    echo "调用实例:{$logoutRes['instance']}\n";
} else {
    echo "退出登录失败:{$logoutRes['error']}\n";
}


/** 测试请求超时,是否会触发服务降级 */
for ($i=0;$i<=10;$i++) {
// 3. 调用DemoService的add方法(添加用户)
    $addResult = $client->call(
        'demo', // 服务标识(对应服务端配置中的serviceKey)
        [
            'name' => '张三'.$i,  // 对应add方法的$name参数
            'age' => 20        // 对应add方法的$age参数
        ],
        'add' // 要调用的方法名(DemoService的add方法)
    );

// 处理add方法结果
    if ($addResult['success']) {
        echo "添加用户结果:{$addResult['result']}\n";
        echo "调用的服务实例:{$addResult['instance']}\n\n";
    } else {
        echo "添加用户失败:{$addResult['error']}\n\n";
    }
}

// 4. 调用DemoService的get方法(查询用户)
$getResult = $client->call(
    'demo', // 服务标识(不变)
    [
        'name' => '张三'  // 对应get方法的$name参数
    ],
    'get' // 要调用的方法名(DemoService的get方法)
);

// 处理get方法结果
if ($getResult['success']) {
    echo "查询用户结果:\n";
    print_r($getResult['result']); // 打印数组结果
    echo "调用的服务实例:{$getResult['instance']}\n";
} else {
    echo "查询用户失败:{$getResult['error']}\n";
}

现在需要启动客户端来测试服务是否可用。命令如下:

php client.php
服务端运行效果

那么服务端测试结果大概效果是这样子的

PS D:\php\nacosServer> php .\server.php
2025-07-31 15:57:30 [warn]系统已启动debug模式,你可以设置isDebug=false关闭调试模式
2025-07-31 15:57:30 [init] 已加载服务:demo -> Xiaosongshu\Nacos\Samples\DemoService(元数据解析完成)
2025-07-31 15:57:30 [init] 已加载服务:login -> Xiaosongshu\Nacos\Samples\LoginService(元数据解析完成)
2025-07-31 15:57:30 [init] 已加载配置:app -> D:\php\nacosServer/application.yaml
2025-07-31 15:57:30 [config] 启动监听流:app(ID: 18)
2025-07-31 15:57:30 [service] 已注册服务:demo -> SERVICE@@demo(IP:127.0.0.1:8000)
2025-07-31 15:57:30 [service] 已注册服务:login -> SERVICE@@login(IP:127.0.0.1:8000)
2025-07-31 15:57:30 [init] 已发布配置:app(本地配置发布完毕)
2025-07-31 15:57:30 [init] 已启动,监听:127.0.0.1:8000(JSON-RPC协议)
2025-07-31 15:57:30 [heartbeat] 成功(demo)->Xiaosongshu\Nacos\Samples\DemoService
2025-07-31 15:57:30 [heartbeat] 成功(login)->Xiaosongshu\Nacos\Samples\LoginService
2025-07-31 15:57:30 [debug] 原始响应: default%02default%01 | 解码后: defaultdefault | 监听配置: dataId=default, group=default
2025-07-31 15:57:30 [config] app 配置发生变化(dataId: default, group: default)
2025-07-31 15:57:32 [config] 启动监听流:app(ID: 27)
2025-07-31 15:57:35 [heartbeat] 成功(demo)->Xiaosongshu\Nacos\Samples\DemoService
2025-07-31 15:57:35 [heartbeat] 成功(login)->Xiaosongshu\Nacos\Samples\LoginService
2025-07-31 15:57:37 [tcp] 新客户端连接:127.0.0.1:56684(clientId:30)
2025-07-31 15:57:37 [tcp] 收到请求(127.0.0.1:56684):{"jsonrpc":"2.0","method":"login.login","params":["zhangsan","123456"],"id":"rpc_688b21f0dc968"}
2025-07-31 15:57:37 [tcp] 发送响应(127.0.0.1:56684):{"jsonrpc":"2.0","id":"rpc_688b21f0dc968","result":{"success":true,"message":"登录成功","token":"68fe7ea8cbec945cec906ce3b48172dc","expire":3600}}
2025-07-31 15:57:37 [tcp] 新客户端连接:127.0.0.1:56685(clientId:31)
2025-07-31 15:57:37 [tcp] 客户端断开(127.0.0.1:56684)
2025-07-31 15:57:37 [tcp] 收到请求(127.0.0.1:56685):{"jsonrpc":"2.0","method":"login.out","params":["68fe7ea8cbec945cec906ce3b48172dc"],"id":"rpc_688b21f15a126"}
2025-07-31 15:57:37 [tcp] 发送响应(127.0.0.1:56685):{"jsonrpc":"2.0","id":"rpc_688b21f15a126","result":{"success":true,"message":"退出登录成功","token":"68fe7ea8cbec945cec906ce3b48172dc"}}
2025-07-31 15:57:37 [tcp] 新客户端连接:127.0.0.1:56689(clientId:32)
2025-07-31 15:57:37 [tcp] 客户端断开(127.0.0.1:56685)
2025-07-31 15:57:37 [tcp] 收到请求(127.0.0.1:56689):{"jsonrpc":"2.0","method":"demo.add","params":["张三0",20],"id":"rpc_688b21f1b7950"}
2025-07-31 15:57:38 [tcp] 发送响应(127.0.0.1:56689):{"jsonrpc":"2.0","id":"rpc_688b21f1b7950","result":"用户添加成功!姓名:张三0,年龄:20(服务端处理时间:15:57:37)"}
2025-07-31 15:57:38 [tcp] 新客户端连接:127.0.0.1:56690(clientId:33)
2025-07-31 15:57:38 [tcp] 客户端断开(127.0.0.1:56689)
2025-07-31 15:57:38 [tcp] 收到请求(127.0.0.1:56690):{"jsonrpc":"2.0","method":"demo.add","params":["张三1",20],"id":"rpc_688b21f21cd01"}
2025-07-31 15:57:38 [tcp] 发送响应(127.0.0.1:56690):{"jsonrpc":"2.0","id":"rpc_688b21f21cd01","result":"用户添加成功!姓名:张三1,年龄:20(服务端处理时间:15:57:38)"}
2025-07-31 15:57:38 [tcp] 新客户端连接:127.0.0.1:56691(clientId:34)
2025-07-31 15:57:38 [tcp] 客户端断开(127.0.0.1:56690)
2025-07-31 15:57:38 [tcp] 收到请求(127.0.0.1:56691):{"jsonrpc":"2.0","method":"demo.add","params":["张三2",20],"id":"rpc_688b21f2778d6"}
2025-07-31 15:57:38 [tcp] 发送响应(127.0.0.1:56691):{"jsonrpc":"2.0","id":"rpc_688b21f2778d6","result":"用户添加成功!姓名:张三2,年龄:20(服务端处理时间:15:57:38)"}
2025-07-31 15:57:38 [tcp] 新客户端连接:127.0.0.1:56692(clientId:35)
2025-07-31 15:57:38 [tcp] 客户端断开(127.0.0.1:56691)
2025-07-31 15:57:39 [tcp] 收到请求(127.0.0.1:56692):{"jsonrpc":"2.0","method":"demo.add","params":["张三3",20],"id":"rpc_688b21f2d3cfb"}
2025-07-31 15:57:39 [tcp] 发送响应(127.0.0.1:56692):{"jsonrpc":"2.0","id":"rpc_688b21f2d3cfb","result":"用户添加成功!姓名:张三3,年龄:20(服务端处理时间:15:57:39)"}
2025-07-31 15:57:39 [tcp] 新客户端连接:127.0.0.1:56694(clientId:36)
2025-07-31 15:57:39 [tcp] 客户端断开(127.0.0.1:56692)
2025-07-31 15:57:39 [tcp] 收到请求(127.0.0.1:56694):{"jsonrpc":"2.0","method":"demo.add","params":["张三4",20],"id":"rpc_688b21f33ac20"}
2025-07-31 15:57:39 [tcp] 发送响应(127.0.0.1:56694):{"jsonrpc":"2.0","id":"rpc_688b21f33ac20","result":"用户添加成功!姓名:张三4,年龄:20(服务端处理时间:15:57:39)"}
2025-07-31 15:57:39 [tcp] 新客户端连接:127.0.0.1:56695(clientId:37)
2025-07-31 15:57:39 [tcp] 客户端断开(127.0.0.1:56694)
2025-07-31 15:57:39 [tcp] 收到请求(127.0.0.1:56695):{"jsonrpc":"2.0","method":"demo.add","params":["张三5",20],"id":"rpc_688b21f396de1"}
2025-07-31 15:57:39 [tcp] 发送响应(127.0.0.1:56695):{"jsonrpc":"2.0","id":"rpc_688b21f396de1","result":"用户添加成功!姓名:张三5,年龄:20(服务端处理时间:15:57:39)"}
2025-07-31 15:57:40 [heartbeat] 成功(demo)->Xiaosongshu\Nacos\Samples\DemoService
2025-07-31 15:57:40 [heartbeat] 成功(login)->Xiaosongshu\Nacos\Samples\LoginService
2025-07-31 15:57:40 [tcp] 新客户端连接:127.0.0.1:56696(clientId:40)
2025-07-31 15:57:40 [tcp] 客户端断开(127.0.0.1:56695)
2025-07-31 15:57:40 [tcp] 收到请求(127.0.0.1:56696):{"jsonrpc":"2.0","method":"demo.add","params":["张三6",20],"id":"rpc_688b21f3f2711"}
2025-07-31 15:57:40 [tcp] 发送响应(127.0.0.1:56696):{"jsonrpc":"2.0","id":"rpc_688b21f3f2711","result":"用户添加成功!姓名:张三6,年龄:20(服务端处理时间:15:57:40)"}
2025-07-31 15:57:40 [tcp] 新客户端连接:127.0.0.1:56703(clientId:41)
2025-07-31 15:57:40 [tcp] 客户端断开(127.0.0.1:56696)
2025-07-31 15:57:40 [tcp] 收到请求(127.0.0.1:56703):{"jsonrpc":"2.0","method":"demo.add","params":["张三7",20],"id":"rpc_688b21f460c2d"}
2025-07-31 15:57:40 [tcp] 发送响应(127.0.0.1:56703):{"jsonrpc":"2.0","id":"rpc_688b21f460c2d","result":"用户添加成功!姓名:张三7,年龄:20(服务端处理时间:15:57:40)"}
2025-07-31 15:57:40 [tcp] 新客户端连接:127.0.0.1:56704(clientId:42)
2025-07-31 15:57:40 [tcp] 客户端断开(127.0.0.1:56703)
2025-07-31 15:57:41 [tcp] 收到请求(127.0.0.1:56704):{"jsonrpc":"2.0","method":"demo.add","params":["张三8",20],"id":"rpc_688b21f4bc128"}
2025-07-31 15:57:41 [tcp] 发送响应(127.0.0.1:56704):{"jsonrpc":"2.0","id":"rpc_688b21f4bc128","result":"用户添加成功!姓名:张三8,年龄:20(服务端处理时间:15:57:41)"}
2025-07-31 15:57:41 [tcp] 新客户端连接:127.0.0.1:56707(clientId:43)
2025-07-31 15:57:41 [tcp] 客户端断开(127.0.0.1:56704)
2025-07-31 15:57:41 [tcp] 收到请求(127.0.0.1:56707):{"jsonrpc":"2.0","method":"demo.add","params":["张三9",20],"id":"rpc_688b21f523d36"}
2025-07-31 15:57:41 [tcp] 发送响应(127.0.0.1:56707):{"jsonrpc":"2.0","id":"rpc_688b21f523d36","result":"用户添加成功!姓名:张三9,年龄:20(服务端处理时间:15:57:41)"}
2025-07-31 15:57:41 [tcp] 新客户端连接:127.0.0.1:56708(clientId:44)
2025-07-31 15:57:41 [tcp] 客户端断开(127.0.0.1:56707)
2025-07-31 15:57:41 [tcp] 收到请求(127.0.0.1:56708):{"jsonrpc":"2.0","method":"demo.add","params":["张三10",20],"id":"rpc_688b21f58026e"}
2025-07-31 15:57:41 [tcp] 发送响应(127.0.0.1:56708):{"jsonrpc":"2.0","id":"rpc_688b21f58026e","result":"用户添加成功!姓名:张三10,年龄:20(服务端处理时间:15:57:41)"}
2025-07-31 15:57:42 [tcp] 新客户端连接:127.0.0.1:56709(clientId:45)
2025-07-31 15:57:42 [tcp] 客户端断开(127.0.0.1:56708)
2025-07-31 15:57:42 [tcp] 收到请求(127.0.0.1:56709):{"jsonrpc":"2.0","method":"demo.get","params":["张三"],"id":"rpc_688b21f5dafd0"}
2025-07-31 15:57:42 [tcp] 发送响应(127.0.0.1:56709):{"jsonrpc":"2.0","id":"rpc_688b21f5dafd0","result":{"name":"张三","age":25,"message":"查询成功(服务端时间:15:57:42)"}}
2025-07-31 15:57:42 [tcp] 客户端断开(127.0.0.1:56709)
2025-07-31 15:57:45 [heartbeat] 成功(demo)->Xiaosongshu\Nacos\Samples\DemoService
2025-07-31 15:57:45 [heartbeat] 成功(login)->Xiaosongshu\Nacos\Samples\LoginService
2025-07-31 15:57:50 [heartbeat] 成功(demo)->Xiaosongshu\Nacos\Samples\DemoService
2025-07-31 15:57:50 [heartbeat] 成功(login)->Xiaosongshu\Nacos\Samples\LoginService

客户端的效果是这个样子的

PS D:\php\nacosServer> php .\client.php
登录成功:
Token:68fe7ea8cbec945cec906ce3b48172dc
有效期:3600秒
调用实例:127.0.0.1:8000
退出登录成功:
Token:68fe7ea8cbec945cec906ce3b48172dc
调用实例:127.0.0.1:8000
添加用户结果:用户添加成功!姓名:张三0,年龄:20(服务端处理时间:15:57:37)
调用的服务实例:127.0.0.1:8000

添加用户结果:用户添加成功!姓名:张三1,年龄:20(服务端处理时间:15:57:38)
调用的服务实例:127.0.0.1:8000

添加用户结果:用户添加成功!姓名:张三2,年龄:20(服务端处理时间:15:57:38)
调用的服务实例:127.0.0.1:8000

添加用户结果:用户添加成功!姓名:张三3,年龄:20(服务端处理时间:15:57:39)
调用的服务实例:127.0.0.1:8000

添加用户结果:用户添加成功!姓名:张三4,年龄:20(服务端处理时间:15:57:39)
调用的服务实例:127.0.0.1:8000

添加用户结果:用户添加成功!姓名:张三5,年龄:20(服务端处理时间:15:57:39)
调用的服务实例:127.0.0.1:8000

添加用户结果:用户添加成功!姓名:张三6,年龄:20(服务端处理时间:15:57:40)
调用的服务实例:127.0.0.1:8000

添加用户结果:用户添加成功!姓名:张三7,年龄:20(服务端处理时间:15:57:40)
调用的服务实例:127.0.0.1:8000

添加用户结果:用户添加成功!姓名:张三8,年龄:20(服务端处理时间:15:57:41)
调用的服务实例:127.0.0.1:8000

添加用户结果:用户添加成功!姓名:张三9,年龄:20(服务端处理时间:15:57:41)
调用的服务实例:127.0.0.1:8000

添加用户结果:用户添加成功!姓名:张三10,年龄:20(服务端处理时间:15:57:41)
调用的服务实例:127.0.0.1:8000

查询用户结果:
Array
(
    [name] => 张三
    [age] => 25
    [message] => 查询成功(服务端时间:15:57:42)
)
调用的服务实例:127.0.0.1:8000
所有请求处理完毕

服务降级和熔断

系统默认超时率大于等于50%的时候,会对服务进行降级处理,当超时率低于50%的时候会逐步恢复。当服务的错误率高于50%的时候,会对服务进行熔断处理,然后系统会尝试自动恢复服务。

一键搭建nacos服务

docker run --name nacos -e MODE=standalone --env NACOS_AUTH_ENABLE=true -p 8848:8848 -p 31181:31181 -d nacos/nacos-server:1.3.1