用swoole framework 实现远程接口调用RPC
2017-05-26 17:57
260 查看
最近用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
*/
// $AppS
4000
vr->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 输出
证明成功
针对服务端和客户端代码修改不生效的问题,则由SWOOLE特点决定,需要热部署。具体实现热部署步骤,可参考 http://blog.csdn.net/guyan0319/article/details/73656977。
利用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
*/
// $AppS
4000
vr->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。
相关文章推荐
- 用Swoole框架实现WebService和远程接口调用RPC
- Python中实现远程调用(RPC、RMI)简单例子
- 手动实现RPC远程调用
- springboot 集成dubbo,RPC 远程调用服务接口:提示服务空指针异常
- 【远程调用框架】如何实现一个简单的RPC框架(五)优化三:软负载中心设计与实现
- 网络编程 -- RPC实现原理 -- RPC -- 迭代版本V4 -- 远程方法调用 整合 Spring 自动注册
- facebook的thriff 基于rpc的远程调用实现
- 使用hadoop中的RPC框架实现远程调用
- 使用Python的multiprocessing.connections实现远程方法调用(RPC)
- 【远程调用框架】如何实现一个简单的RPC框架(三)优化一:利用动态代理改变用户服务调用方式
- android app通过Geth RPC接口实现远程调用
- 通过 Redis 实现 RPC 远程方法调用(支持多种编程语言)
- 使用接口的方式调用远程服务 ------ 利用动态调用服务,实现.net下类似Dubbo的玩法。
- 利用Castle IOC实现远程调用的接口统一(上)
- 【远程调用框架】如何实现一个简单的RPC框架(二)实现与使用
- hessian 实现远程接口调用
- 通过 Redis 实现 RPC 远程方法调用(支持多种编程语言)
- 通过 Redis 实现 RPC 远程方法调用(支持多种编程语
- RPC的实现与远程调用的实现机制
- 网络编程 -- RPC实现原理 -- RPC -- 迭代版本V3 -- 远程方法调用 整合 Spring