设为首页 收藏本站
查看: 769|回复: 0

[经验分享] 通过 Redis 实现 RPC 远程方法调用(支持多种编程语

[复制链接]

尚未签到

发表于 2018-11-5 12:15:08 | 显示全部楼层 |阅读模式
  转载于:http://www.itxuexiwang.com/a/shujukujishu/redis/2016/0216/101.html?1455869487
  我发现经常研究并且为之兴奋的一件事就是对系统进行扩展。现在这对不同的人有着不同的意思。作为移植Monolithic应用到Microservices架构方法中的一部分,如何处理Microservices架构是我研究RPC的原因。
  RPC(或者叫做远程进程调用)是一个已经在计算机科学领域存在较长一段时间的概念。对此一种非常简单的理解就是发送一段消息到远程进程的能力,而不论它是在同一个系统上还是远程的系统。总的来说这是非常模糊的,而且对许多的实现来说是开放的。在我看来,当谈到RPC时,会有相当多的内容可供探讨,比如消息的格式,以及你怎样将消息发送到远程进程上。有许多的方法来实现RPC,而这是我采用的一种,但对这篇文章来说,我准备使用‘JSON-RPC'来处理消息的格式,用Redis来发布消息。
  RPC和消息队列
  原理基本上都一样,但是使用RPC的话,客户端会等待一个含有RPC调用结果的返回消息。如果你的消息队列系统允许你为发送者处理回调消息,那么你很可能就可以为RPC来使用它。在大多数的消息队列中,它们被用来触发那些不再需要回复给客户端的任务。
  为什么用Redis而不是其它的?
  你应该能够在某个地主发现Redis是非常先进的技术,如果你说没有发现,你是怎么了?Redis对很多事情来说都是一个伟大的工具,你应该认真研究一下。学习之路能够平坦,并且不用学习太多的新内容,Redis都完美的符合这些想法,所以,让我们看看我们可以干些什么。
  Client
  代码如下:
  require 'redis'
  require 'securerandom'
  require 'msgpack'
  class RedisRpcClient
  def initialize(redis_url, list_name)
  @client = Redis.connect(url: redis_url)
  @list_name = list_name.to_s
  end
  def method_missing(name, *args)
  request = {
  'jsonrpc' => '2.0',
  'method' => name,
  'params' => args,
  'id' => SecureRandom.uuid
  }
  @client.lpush(@list_name, request.to_msgpack)#p#分页标题#e#
  channel, response = @client.brpop(request['id'], timeout=30)
  MessagePack.unpack(response)['result']
  end
  end
  client = RedisRpcClient.new('redis://localhost:6379', :fib)
  (1..30).each { |i| puts client.fib(i) }
  Server
  代码如下:
  require 'redis'
  require 'msgpack'
  class Fibonacci
  def fib(n)
  case n
  when 0 then 0
  when 1 then 1
  else
  fib(n - 1) + fib(n - 2)
  end
  end
  end
  class RedisRpcServer
  def initialize(redis_url, list_name, klass)
  @client = Redis.connect(url: redis_url)
  @list_name = list_name.to_s
  @klass = klass
  end
  def start
  puts "Starting RPC server for #{@list_name}"
  while true
  channel, request = @client.brpop(@list_name)
  request = MessagePack.unpack(request)
  puts "Working on request: #{request['id']}"
  args = request['params'].unshift(request['method'])
  result = @klass.send *args
  reply = {
  'jsonrpc' => '2.0',
  'result' => result,#p#分页标题#e#
  'id' => request['id']
  }
  @client.rpush(request['id'], MessagePack.pack(reply))
  @client.expire(request['id'], 30)
  end
  end
  end
  RedisRpcServer.new('redis://localhost:6379', :fib,  Fibonacci.new).start
  确是如此,它能工作是因为当你等待数据从服务器传回来时,Redis有命令能够让你阻塞等待。这是非常优秀的做法,它让你的客户端代码看上去像是在调用本地方法。
  Ruby 相当酷,可是。。。
  如果你想用其它语言怎么办?没问题,只要你的语言有很好的Redis库,你就可以做同样的事。让我们瞧一瞧用Python来建立一个服务端程序。
  代码如下:
  import redis
  import msgpack
  class Fibonacci:
  def fib(self,n):
  if n == 0:
  return 0
  elif n == 1:
  return 1
  else:
  return self.fib(n-1) + self.fib(n-2)
  class RedisRpcServer:
  def __init__(self, redis_url, list_name, klass):
  self.client = redis.from_url(redis_url)
  self.list_name = list_name
  self.klass = klass
  def start(self):
  print("Starting RPC server for " + self.list_name)
  while True:
  channel, request = self.client.brpop('fib')
  request = msgpack.unpackb(request, encoding='utf-8')
  print("Working on request: " + request['id'])#p#分页标题#e#
  result = getattr(self.klass, request['method'])(*request['params'])
  reply = {
  'jsonrpc': '2.0',
  'result': result,
  'id': request['id']
  }
  self.client.rpush(request['id'], msgpack.packb(reply, use_bin_type=True))
  self.client.expire(request['id'], 30)
  RedisRpcServer('redis://localhost:6379', 'fib', Fibonacci()).start()
  结论
  这很好的证明了你头脑中的一些想法,当然,还需要更多的工作来处理异常。如果你用这个方法遇到任何的问题,我乐意帮助你。我的确希望在同样想法的一此地方使用RabbitMQ,但如果你已经在你的项目中使用了Redis,这将会是一个非常不错的方法。


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-631104-1-1.html 上篇帖子: CentOS Linux系统下安装Redis过程和配置参数说明 下篇帖子: REDIS GEO: REDIS新增位置查询功能
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表