用swoole framework 实现远程接口调用RPC

唐博文
2023-12-01

最近用swoole framework开发个项目,想实现远程接口调用RPC,无奈swoole框架坑点太多,资料又少的可怜,只能自己研究。

利用swoole框架的RPCServer类 实现服务端,RPC类实现客户端。

实现步骤如下:

服务端

在examples/  目录下创建

rpc_server.php 

PHP代码

<?php
define('DEBUG', 'on');
define('WEBPATH', realpath(__DIR__ . '/../'));
require_once dirname(__DIR__) . '/libs/lib_config.php';

use  Swoole\Protocol\RPCServer;


//设置PID文件的存储路径
Swoole\Network\Server::setPidFile(__DIR__ . '/rpc_server.pid');
/**
 * 显示Usage界面
 * php app_server.php start|stop|reload
 */
Swoole\Network\Server::start(function ()
{
    $AppSvr = new RPCServer;
    $AppSvr->setLogger(new \Swoole\Log\EchoLog(true)); //Logger

    /**
     * 注册一个自定义的命名空间到SOA服务器
     * 默认使用 apps/classes
     */

    // $AppSvr->addNameSpace('App', WEBPATH . '/apps/models');
    // $AppSvr->addNameSpace('App', WEBPATH . '/apps/models');
    // $AppSvr->addNameSpace('BL', __DIR__ . '/class');
    /**
     * IP白名单设置
     */
    
    $AppSvr->addAllowIP('127.0.0.1');
    $AppSvr->addAllowIP('127.0.0.2');

    /**
     * 设置用户名密码
     */
    $AppSvr->addAllowUser('rpcname', 'rpc@123456');

    Swoole\Error::$echo_html = false;
    $server = Swoole\Network\Server::autoCreate('0.0.0.0', 8888);
    $server->setProtocol($AppSvr);
    //$server->daemonize(); //作为守护进程
    $server->run(
        array(
            //TODO: 实际使用中必须调大进程数
            'worker_num' => 4,
            'max_request' => 5000,
            'dispatch_mode' => 3,
            'open_length_check' => 1,
            'package_max_length' => $AppSvr->packet_maxlen,
            'package_length_type' => 'N',
            'package_body_offset' => \Swoole\Protocol\RPCServer::HEADER_SIZE,
            'package_length_offset' => 0,
        )
    );
});


在 apps/classes/ 目录下创建 RPCApi.php

<?php
namespace App;

/**
 * RPC Server 接口
 *
 * @author 郭志强
 * @return void
 * @throws Exception
 *
 */
class RPCApi
{
    /**
     * 暂无说明
     *
     * @author 郭志强
     * @return void
     * @throws Exception
     * @access public
     */
    public static function api(array $condition)
    {
        $default = [
            //model名字
            'model' => '',
            //方法名
            'action' => '',
            //参数
            'param' => [],
        ];
        $condition = array_merge($default, $condition);
        if (!$condition['model']) {
            return "Error Model Not Found ";
        }
        if (!$condition['action']) {
            return "Error Action Not Found ";
        }
         $action = $condition['action'];
        if ($condition['param']) {
            return model($condition['model'])->$action($condition['param']);
        }
        return model($condition['model'])->$action();
    }
}


运行服务端程序

nohup php /var/www/examples/rpc_server.php start </dev/null &>/dev/null &


客户端

在 apps/classes/ 目录下创建  

RPCClient.php

代码

<?php
namespace App;
use Swoole;
/**
 * RPC client 接口
 *
 * @author 郭志强
 * @return void
 * @throws Exception
 *
 */
class RPCClient
{
    /**
     * API
     *
     * @author 郭志强
     * @return void
     * @throws Exception
     * @param namespace:空间名称,如"App\\Test::hello" ,hello为方法 。param传参
     * @access public
     */
    public static function api( array $condition)
    {

        $default = [
            'namespace' => "App\\RPCApi::api",
            'param' => [],
        ];
		$condition = array_merge($default,$condition);
		if (!$condition['namespace'] || empty($condition['param'])) {
			return ;
		}
        $client = Swoole\Client\RPC::getInstance();
        // //$client->setEncodeType(false, true);
        // // $client->putEnv('app', 'test');
        $client->auth('rpcname', 'rpc@123456');//认证账号和密码
        $client->addServers(array('host' => '127.0.0.1', 'port' => 8888));
        $ret = $client->task($condition['namespace'], [$condition['param']]);
 		$client->wait(0.5); //500ms超时
 		unset($client);
 		return  $ret->data;
    }
}

在 apps/model/  目录下创建 

Test.php


代码

<?php
namespace App\Model;
use Swoole;

class Test extends Swoole\Model
{

    /**
     * 表名
     * @var string
     */
    public $table = 'a';

    function demo($data)
    {
      return $data;

    }
}


测试代码

修改  apps/controllers/Page.php

代码

<?php
namespace App\Controller;
use Swoole;
use App\Base;
use App\RPCClient;
class Home extends Base
{
    public function __construct($swoole)
    {
        parent::__construct($swoole);
    }

    public function index()
    {
  
        $default = [
            'namespace' => "App\\RPCApi::api",
            'param' => ['model'=>'Test','action'=>'demo','param'=>['a'=>'bd']],
        ];

        echo "<pre>";
        var_dump( RPCClient::api($default));
        echo "</pre>";



    }

}



启动客户端程序


nohup php /var/www/examples/app_server.php start </dev/null &>/dev/null &


访问

http://xxxxx/page/index

输出

 
array(1) {
  ["a"]=>
  string(2) "bd"
}



证明成功


针对服务端和客户端代码修改不生效的问题,则由SWOOLE特点决定,需要热部署。具体实现热部署步骤,可参考 http://blog.csdn.net/guyan0319/article/details/73656977。


 类似资料: