nfarring/redisrpc

Redis 的轻量级 RPC

0.3.5 2012-04-20 19:52 UTC

This package is not auto-updated.

Last update: 2024-09-22 03:19:01 UTC


README

由 Nathan Farrington http://nathanfarrington.com

RedisRPC 是世界上最容易使用的 RPC 库。 (这不是一个小声明!) 它在 Ruby、PHP 和 Python 中都有实现。

简介

Redis 是一个强大的内存数据结构服务器,对于构建快速分布式系统非常有用。Redis 通过使用列表数据结构和 LPOPBLPOPRPUSH 命令来实现消息队列功能。RedisRPC 通过使用 Redis 消息队列来临时存储 RPC 请求和响应消息,实现了一个轻量级 RPC 机制。这些消息被编码为 JSON 字符串,以实现可移植性。

许多其他 RPC 机制要么是特定于编程语言的(例如,Java RMI),要么需要显式类型定义的样板代码(例如,Thrift)。RedisRPC 设计得非常易于使用,通过消除样板代码同时保持编程语言中立。高性能并不是 RedisRPC 的初始目标,其他 RPC 库可能具有更好的性能。相反,RedisRPC 具有更好的程序员性能;它让您可以立即让某件事运行起来。

计算器示例

每个库实现都使用基于可变计算器对象的相同客户端和服务器示例。来自不同语言的客户端和服务器可以互操作。

  1. 客户端通过使用 Redis 的 RPUSH 命令将 RPC 请求消息推入名为 calc 的 Redis 列表中来发出 RPC 请求。
  2. 服务器通过使用 Redis 的 BLPOP 命令检索 RPC 请求消息。
  3. 服务器将 RPC 请求调度到本地对象,在这个例子中是一个计算器对象。
  4. 服务器接受来自计算器对象的返回值(或异常)。
  5. 服务器通过使用 Redis 的 RPUSH 命令将 RPC 响应消息推入客户端选择的名为 calc:rpc:<RAND_STRING> 的 Redis 列表中,来发出 RPC 响应。
  6. 客户端通过使用 Redis 的 BLPOP 命令检索 RPC 响应消息。

请注意,可以通过使用 Redis 的 LPOP 命令而不是 BLPOP 来使服务器或客户端非阻塞。我目前不需要这个功能,并且还没有添加对这个功能的支持,但是欢迎补丁。

这就是全部了!

Ruby 使用方法

client.rb

redis_server = Redis.new
message_queue = 'calc'
calculator = RedisRPC::Client.new redis_server, 'calc'
calculator.clr
calculator.add 5
calculator.sub 3
calculator.mul 4
calculator.div 2
assert calculator.val == 4

server.rb

redis_server = Redis.new
message_queue = 'calc'
local_object = Calculator.new
server = RedisRPC::Server.new redis_server, message_queue, local_object
server.run

PHP 使用方法

请注意,PHP 库目前不支持命名函数参数。

client.php

$redis_server = new Predis\Client();
$message_queue = 'calc';
$calculator = new RedisRPC\Client($redis_server, $message_queue);
$calculator->clr();
$calculator->add(5);
$calculator->sub(3);
$calculator->mul(4);
$calculator->div(2);
assert($calculator->val() == 4);

server.php

$redis_server = new Predis\Client();
$message_queue = 'calc';
$local_object = new Calculator();
$server = new RedisRPC\Server($redis_server, $message_queue, $local_object);
$server->run();

Python 使用方法

client.py

redis_server = redis.Redis()
message_queue = 'calc'
calculator = redisrpc.Client(redis_server, message_queue)
calculator.clr()
calculator.add(5)
calculator.sub(3)
calculator.mul(4)
calcaultor.div(2)
assert calculator.val() == 4

Python 客户端还接受额外的关键字参数 timeouttransport。如果 transport='pickle',则可以发送 Python 对象作为函数参数,但前提是服务器也是用 Python 实现的,并且服务器有权访问相同的库来反序列化对象。

server.py

redis_server = redis.Redis()
message_queue = 'calc'
local_object = calc.Calculator()
server = redisrpc.Server(redis_server, message_queue, local_object)
server.run()

安装

Ruby 安装

需要 redis-rb 库。使用 RubyGems 安装

gem install redisrpc

PHP 安装

需要 Predis 库。

RedisRPC PHP库可以从Packagist获取:[https://packagist.org.cn/packages/nfarring/redisrpc](https://packagist.org.cn/packages/nfarring/redisrpc)。您可以使用Composer将其安装到您的PHP项目中。

Python安装

需要redis-py库。

RedisRPC Python库可以从PyPI获取:[http://pypi.python.org/pypi/redisrpc](http://pypi.python.org/pypi/redisrpc)。您可以使用安装。

pip install redisrpc

内部消息格式

所有RPC消息都是JSON对象。用户代码永远不会看到这些对象,因为它们由RedisRPC库处理。

RPC请求

RPC请求包含两个成员:一个function_call对象和一个response_queue字符串。

function_call对象有一个必需的成员:一个表示函数名称的name字符串。它还有两个可选成员:(a)一个用于位置参数的args列表,以及(b)一个用于命名参数的kwargs对象。

response_queue字符串是服务器应将相应的RPC响应消息推入的Redis列表的名称。客户端程序会通过编程方式选择该队列,以确保在Redis命名空间中没有冲突。此外,该队列仅用于单个RPC响应消息,不会用于未来的RPC响应消息。

{ "function_call" : {
      "args" : [ 1, 2, 3 ],
      "kwargs" : { "a" : 4, "b" : 5, "c" : 6 },
      "name" : "foo"
    },
  "response_queue" : "calc:rpc:X7Y2US"
}

RPC响应(成功)

如果RPC成功,则RPC响应对象将包含一个成员,即某种JSON类型的return_value

{ "return_value" : 4.0 }

RPC响应(异常)

如果RPC遇到异常情况,则RPC响应对象将包含一个成员,即一个exception字符串。请注意,exception字符串的值可能对客户端没有意义,因为客户端和服务器可能用不同的语言编写,或者客户端可能不知道服务器封装的对象。因此,最佳做法可能是向用户显示exception值。

{ "exception" : "AttributeError(\\"\'Calculator\' object has no attribute \'foo\'\\",)" }

源代码

源代码可在http://github.com/nfarring/redisrpc获取。

许可证

此软件可在GPLv3或更高版本下使用。

变更日志

版本0.3.5

  • Ruby:功能:使用multi_json gem [Ryan Biesemeyer]
  • Ruby:功能:server.run!刷新队列,但server.run不刷新 [Ryan Biesemeyer]
  • Ruby:性能:只调用一次rand,而不是八次 [Ryan Biesemeyer]
  • Ruby:错误修正:RedisRPC::VERSION [Ryan Biesemeyer]
  • Ruby:安全:删除eval [Ryan Biesemeyer]

版本0.3.4

  • 客户端现在支持可选的超时。
  • 服务器现在在启动时删除消息队列。
  • PHP:修复异常处理。

版本0.3.3

  • Ruby:添加了Ruby库实现。

版本0.3.2

  • 修复了README.markdown中的某些格式问题,这些问题在转换为reStructredText时会引起问题。
  • 向README.markdown添加了版本信息。
  • 向README.markdown添加了安装说明。
  • Python:添加了使用logging模块的RPC消息日志记录。
  • Python:将redis作为安装依赖项。
  • Python:现在使用Distribute而不是distutils。

版本0.3.1

  • PHP:更改了composer.json中predis依赖项的版本。

版本0.3.0

  • 不再传输空函数调用参数和kwargs。
  • PHP:添加了对PHP语言的支持。
  • PHP:现在可以通过PHP Composer安装。
  • Python:缩短了Client和Server类的名称。
  • Python:调试已修改为打印JSON表示。
  • Python:将README文件切换回ReStructred Text。

版本0.2.1

  • Python:修复了MANIFEST.in,以反映文件名更改。

版本0.2.0

  • 简化了JSON RPC消息格式。
  • 记录了JSON RPC消息格式。
  • Python:使用HTML文件作为README,它会工作吗?
  • Python:将calc_client重命名为client.py。
  • Python:将calc_server重命名为server.py。
  • Python:添加了RemoteException类,客户端可以抛出此异常。

版本0.1.2

  • Python:修复了setup.py中的download_url。
  • Python:将README文件重命名为README.rst以支持在GitHub上的浏览。

版本0.1.1

  • Python:添加了README。
  • Python:在setup.py中添加了long_description。
  • Python:添加了MANIFEST.in文件。
  • Python:将examples/子目录添加到MANIFEST。
  • Python:修改了examples/目录,使其与README文件保持一致。
  • Python:修复了setup.py中的download_url。

版本0.1.0

  • 改为GPL许可证。
  • Python:从python/redisrpc.py中移除了未使用的功能。
  • Python:添加了setup.py安装脚本。