由于Windows服务之间有很强的相互依存关系,当RPC服务被禁用后,很多依赖于RPC服务的系统服务也不能正常运行(见图),如Messenger服务、Windows Installer服务等;另外,还可能导致某些应用程序运行失败和系统异常.下面笔者就介绍三种启动该服务的方法.
方法一:修改注册表法
方法二:使用sc.exe命令
方法三:使用故障恢复控制台
以Windows XP系统为例,在光驱中放入安装光盘,并且在BIOS参数中设置为从CD-ROM启动;启动电脑后,系统进入到Windows XP安装界面,按下"R"键登录到故障恢复控制台.在故障恢复控制台下,键入"enable RpcSs service_auto_start"命令,然后再键入"exit"命令,重新启动系统,以正常模式登录,即可成功启动RPC服务.
注意:"Enable"是故障恢复控制台提供的一个用来启动系统服务和设备驱动程序的命令,只能在故障恢复控制台下使用.
=============================
使用上面的几种方法都不成功的话,看来只有自己动手解决了.我想注册表中的某些键值一定要变,这样才能启用.
把禁用前的备份注册表恢复到被禁用后的注册表中,提示无法导入,不成功.无法启用.
把禁用前和禁用后的两个注册表(只取HKEY_LOCAL_MACHINE\SYSTEM分支)内容转化成Word文档,再使用Word中的"比较并合并文档"功能,就能自动找到两个注册表的不同之处.我通过比较分析,发现禁用后的注册表中有以下分支:
① HKEY_LOCAL_MACHINE\SYSTEM\Curr-
entControlSet\HardwareProfiles\0001\System\CurrentControlSet\Enum\ROOT\LEGACY_RPCSS
禁用前的注册表中没有以上两个分支.通过进一步操作,发现只要删除第1个分支即可重新起用RPC服务.
智能合约调用是实现一个 DApp 的关键,一个完整的 DApp 包括前端、后端、智能合约及区块 链系统,智能合约的调用是连接区块链与前后端的关键.
我们先来了解一下智能合约调用的基础原理.智能合约运行在以太坊节点的 EVM 中.所以呢要 想调用合约必须要访问某个节点.
以后端程序为例,后端服务若想连接节点有两种可能,一种是双 方在同一主机,此时后端连接节点可以采用 本地 IPC(Inter-Process Communication,进 程间通信)机制,也可以采用 RPC(Remote Procedure Call,远程过程调用)机制;另 一种情况是双方不在同一台主机,此时只能采用 RPC 机制进行通信.
接着,我们来了解一下智能合约运行的过程.
智能合约的运行过程是后端服务连接某节点,将 智能合约的调用(交易)发送给节点,节点在验证了交易的合法性后进行全网广播,被矿工打包到 区块中代表此交易得到确认,至此交易才算完成.
就像数据库一样,每个区块链平台都会提供主流 开发语言的 SDK(Software Development Kit,软件开发工具包),由于 Geth 本身就是用 Go 语言 编写的,所以呢若想使用 Go 语言连接节点、发交易,直接在工程内导入 go-ethereum(Geth 源码) 包就可以了,剩下的问题就是流程和 API 的事情了.
最后提醒一下大家,智能合约被调用的两个关键点是节点和 SDK.
此时此刻呢介绍如何使用 Go 语言,借助 go-ethereum 源码库来实现智能合约的调用.这是有固定 步骤的,我们先来说一下总体步骤,以下面的合约为例.
步骤 01:编译合约,获取合约 ABI(Application Binary Interface,应用二进制接口). 单击【ABI】按钮拷贝合约 ABI 信息,将其粘贴到文件 calldemo.abi 中(可使用 Go 语言IDE 创建该文件,文件名可自定义,后缀最好使用 abi).
最好能将 calldemo.abi 单独保存在一个目录下,输入"ls"命令只能看到 calldemo.abi 文件,参 考效果如下:
此时此刻呢设置 module 生效和 GOPROXY,命令如下:
在项目工程内,执行初始化,calldemo 可以自定义名称.
责编 | 胡巍巍
什么是RPC呢?百度百科给出的解释是这样的:"RPC(Remote Procedure Call Protocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议".
这个概念听起来还是比较抽象,没关系,继续往后看,后面概念性的东西,我会讲得足够清楚,让你完全掌握 RPC 的基础内容.
在 OpenStack 里的进程间通信方式主要有两种,一种是基于HTTP协议的RESTFul API方式,另一种则是RPC调用.
那么这两种方式在应用场景上有何区别呢?
有使用经验的人,就会知道:
首先,给你提两个问题,带着这两个问题再往下看:
首先,第一个问题:RPC 和 REST 区别是什么?
你一定会觉得这个问题很奇怪,是的,包括我,但是你在网络上一搜,会发现类似对比的文章比比皆是,我在想可能很多初学者由于基础不牢固,才会将不相干的二者拿出来对比吧.既然是这样,那为了让你更加了解陌生的RPC,就从你熟悉得不能再熟悉的 REST 入手吧.
01、所属类别不同
REST,是Representational State Transfer 的简写,中文描述表述性状态传递(是指某个瞬间状态的资源数据的快照,包括资源数据的内容、表述格式(XML、JSON)等信息.)
REST 是一种软件架构风格.这种风格的典型应用,就是HTTP.其因为简单、扩展性强的特点而广受开发者的青睐.
而 RPC 可以基于 TCP/UDP,也可以基于 HTTP 协议进行传输的,按理说它和REST不是一个层面意义上的东西,不应该放在一起讨论,但是谁让REST这么流行呢,它是目前最流行的一套互联网应用程序的API设计标准,某种意义下,我们说 REST 可以其实就是指代 HTTP 协议.
从设计上来看,RPC,所谓的远程过程调用 ,是面向方法的 ,REST:所谓的 Representational state transfer ,是面向资源的,除此之外,还有一种叫做 SOA,所谓的面向服务的架构,它是面向消息的,这个接触不多,就不多说了.
接口调用通常包含两个部分,序列化和通信协议.
通信协议,上面已经提及了,REST 是 基于 HTTP 协议,而 RPC 可以基于 TCP/UDP,也可以基于 HTTP 协议进行传输的.
常见的序列化协议,有:json、xml、hession、protobuf、thrift、text、bytes等,REST 通常使用的是 JSON或者XML,而 RPC 使用的是 JSON-RPC,或者 XML-RPC.
通过以上几点,我们知道了 REST 和 RPC 之间有很明显的差异.
然后第二个问题:为什么要采用RPC呢?
那到底为何要使用 RPC,单纯的依靠RESTful API不可以吗?为什么要搞这么多复杂的协议,渣渣表示真的学不过来了.
关于这一点,以下几点仅是我的个人猜想,仅供交流哈:
说了这么多,我们该如何选择这两者呢?我总结了如下两点,供你参考:
"远程调用"意思就是:被调用方法的具体实现不在程序运行本地,而是在别的某个地方(分布到各个服务器),调用者只想要函数运算的结果,却不需要实现函数的具体细节.
光说不练嘴把式,此时此刻呢,我将分别用三种不同的方式全面地让你搞明白 rpc 远程调用是如何实现的.
01、基于 xml-rpc
Python实现 rpc,可以使用标准库里的 SimpleXMLRPCServer,它是基于XML-RPC 协议的.
有了这个模块,开启一个 rpc server,就变得相当简单了.执行以下代码:
有了 rpc server,此时此刻呢就是 rpc client,由于我们上面使用的是 XML-RPC,所以 rpc clinet 需要使用xmlrpclib 这个库.
然后,我们通过 server_proxy 对象就可以远程调用之前的rpc server的函数了.
若非要使用 SimpleXMLRPCServer 实现多线程并发,其实也不难.只要将代码改成如下即可.
SimpleXMLRPCServer 是基于 xml-rpc 实现的远程调用,上面我们也提到 除了 xml-rpc 之外,还有 json-rpc 协议.
那 python 如何实现基于 json-rpc 协议呢?
答案是很多,很多web框架其自身都自己实现了json-rpc,但我们要独立这些框架之外,要寻求一种较为干净的解决方案,我查找到的选择有两种
第一种是 jsonrpclib
第二种是 python-jsonrpc
先来看第一种 jsonrpclib
它与 Python 标准库的 SimpleXMLRPCServer 很类似(因为它的类名就叫做 SimpleJSONRPCServer ,不明真相的人真以为它们是亲兄弟).或许可以说,jsonrpclib 就是仿照 SimpleXMLRPCServer 标准库来进行编写的.
它的导入与 SimpleXMLRPCServer 略有不同,因为SimpleJSONRPCServer分布在jsonrpclib库中.
服务端
再来看第二种python-jsonrpc,写起来貌似有些复杂.
调用过程如下
因为内容较多,这里只带大家打个,zabbix 是如何调用的:直接指明要调用 zabbix server 的哪个方法,要传给这个方法的参数有哪些.
以上介绍的两种rpc远程调用方式,如果你足够细心,可以发现他们都是http+rpc 两种协议结合实现的.
此时此刻呢,我们要介绍的这种(zerorpc),就不再使用走 http 了.
zerorpc 这个第三方库,它是基于TCP协议、 ZeroMQ 和 MessagePack的,速度相对快,响应时间短,并发高.zerorpc 和 pyjsonrpc 一样,需要额外安装,虽然SimpleXMLRPCServer不需要额外安装,但是SimpleXMLRPCServer性能相对差一些.
是的,通过 Github 上的文档几个 demo 可以体验到这个第三方库做真的是优秀.
比如我们可以用下面这个命令,创建一个rpc server,后面这个 time Python 标准库中的 time 模块,zerorpc 会将 time 注册绑定以供client调用.
经过了上面的学习,我们已经学会了如何使用多种方式实现rpc远程调用.
通过对比,zerorpc 可以说是脱颖而出,一支独秀.
为此,我也做了一番思考:
OpenStack 组件繁多,在一个较大的集群内部每个组件内部通过rpc通信频繁,如果都采用rpc直连调用的方式,连接数会非常地多,开销大,若有些 server 是单线程的模式,超时会非常的严重.
你可能会说轮循或者随机,这样对大家都公平.这样的话还会引出另一个问题,倘若请求刚好发到server01,而server01刚好不凑巧,可能由于机器或者其他因为导致服务没在工作,那这个rpc消息可就直接失败了呀.要知道做为一个集群,高可用是基本要求,如果出现刚刚那样的情况其实是很尴尬的.这是问题二.
集群有可能根据实际需要扩充节点数量,如果使用直接调用,耦合度太高,不利于部署和生产.这是问题三.
引入消息中间件,可以很好的解决这些问题.
解决问题一:消息只有一份,接收者由AMQP的负载算法决定,默认为在所有Receiver中均匀发送(round robin).
解决问题二:有了消息中间件做缓冲站,client 可以任性随意的发,server 都挂掉了?没有关系,等 server 正常工作后,自己来消息中间件取就行了.
解决问题三:无论有多少节点,它们只要认识消息中间件这一个中介就足够了.
既然讲到了消息队列,如果你之前没有接触过这块内容,最好花几分钟的时间跟我好好过下关于消息队列的几个基础概念.
首先,RPC只是定义了一个通信接口,其底层的实现可以各不相同,可以是 socket,也可以是今天要讲的 AMQP.
AMQP(Advanced Message Queuing Protocol)是一种基于队列的可靠消息服务协议,作为一种通信协议,AMQP同样存在多个实现,如Apache Qpid,RabbitMQ等.
以下是 AMQP 中的几个必知的概念:
Publisher:消息发布者
Queue:用来保存消息的存储空间,消息没有被receiver前,保存在队列中.
Exchange:用来接收Publisher发出的消息,根据Routing key 转发消息到对应的Message Queue中,至于转到哪个队列里,这个路由算法又由exchange type决定的.
Exchange type:主要四种描述exchange的类型.
direct:消息路由到满足此条件的队列中(queue,可以有多个):routing key = binding key
topic:消息路由到满足此条件的队列中(queue,可以有多个):routing key 匹配 binding pattern. binding pattern是类似正则表达式的字符串,可以满足复杂的路由条件.
fanout:消息路由到多有绑定到该exchange的队列中.
binding :binding是用来描述exchange和queue之间的关系的概念,一个exchang可以绑定多个队列,这些关系由binding建立.前面说的binding key /binding pattern也是在binding中给出.
为了让你明白这几者的关系,我画了一张模型图.
关于AMQP,有几下几点值得注意:
前面铺垫了那么久,终于到了讲真实应用的场景.在生产中RPC是如何应用的呢?
其他模型我不太清楚,在 OpenStack 中的应用模型是这样的
至于为什么要如此设计,前面我已经给出了自己的观点.
此时此刻呢,就是源码解读 OpenStack ,看看其是如何通过rpc进行远程调用的.如若你对此没有兴趣(我知道很多人对此都没有兴趣,所以不浪费大家时间),可以直接跳过这一节,进入下一节.
目前Openstack中有两种RPC实现,一种是在oslo messaging,一种是在openstack.common.rpc.
openstack.common.rpc是旧的实现,oslo messaging是对openstack.common.rpc的重构.openstack.common.rpc在每个项目中都存在一份拷贝,oslo messaging即将这些公共代码抽取出来,形成一个新的项目.oslo messaging也对RPC API 进行了重新设计,对多种 transport 做了进一步封装,底层也是用到了kombu这个AMQP库.(注:Kombu 是Python中的messaging库.Kombu旨在通过为AMQ协议提供惯用的高级接口,使Python中的消息传递尽可能简单,并为常见的消息传递问题提供经过验证和测试的解决方案.)
关于oslo_messaging库,主要提供了两种独立的API:
因为 notify 实现是太简单了,所以这里我就不多说了,如果有人想要看这方面内容,可以收藏我的博客() ,我会更新补充 notify 的内容.
OpenStack RPC 模块提供了 rpc.call,rpc.cast, rpc.fanout_cast 三种 RPC 调用方法,发送和接收 RPC 请求.
rpc.call 和 .rpc.cast 从实现代码上看,他们的区别很小,就是call调用时候会带有wait_for_reply=True参数,而cast不带.
要了解 rpc 的调用机制呢,首先要知道 oslo_messaging 的几个概念主要方法有四个:
transport:RPC功能的底层实现方法,这里是rabbitmq的消息队列的访问路径
transport 就是定义你如何访连接消息中间件,比如你使用的是 Rabbitmq,那在 nova.conf中应该有一行transport_url的配置,可以很清楚地看出指定了 rabbitmq 为消息中间件,并配置了连接rabbitmq的user,passwd,主机,端口.
target用来表述 RPC 服务器监听topic,server名称和server监听的exchange,是否广播fanout.
rpc server 要获取消息,需要定义target,就像一个门牌号一样.
rpc client 要发送消息,也需要有target,说明消息要发到哪去.
endpoints:是可供别人远程调用的对象
dispatcher:分发器,这是 rpc server 才有的概念
只有通过它 server 端才知道接收到的rpc请求,要交给谁处理,怎么处理?
在client端,是这样指定要调用哪个方法的.
而在server端,是如何知道要执行这个方法的呢?这就是dispatcher 要干的事,它从 endpoint 里找到这个方法,然后执行,最后返回.
Serializer:在 python 对象和message(notification) 之间数据做序列化或是反序列化的基类.
主要方法有四个:
每个notification listener都和一个executor绑定,来控制收到的notification如何分配.默认情况下,使用的是blocking executor(具体特性参加executor一节)
模仿是一种很高效的学习方法,我这里根据 OpenStack 的调用方式,抽取出核心内容,写成一个简单的 demo,有对 OpenStack 感兴趣的可以了解一下,大部分人也可以直接跳过这章节.
注意以下代码不能直接运行,你还需要配置 rabbitmq 的连接方式,你可以写在配置文件中,通过 get_transport 从cfg.CONF 中读取,也可以直接将其写成url的格式做成参数,传给 get_transport .而且还要nova或者其他openstack组件的环境中运行(因为需要有ctxt这个环境变量)
简单的 rpc client
简单的 rpc server
【End】
热 文 推 荐
WebRTC 将一统实时音视频天下?
小米崔宝秋:小米 AIoT 深度拥抱开源
华为在美研发机构 Futurewei 意欲分家?
老司机教你如何写出没人敢维护的代码!
Python有哪些技术上的优点?比其他语言好在哪儿?
上不了北大"图灵"、清华"姚班",AI专业还能去哪上?
公链史记 | 从鸿蒙初辟到万物生长的十年激荡......
边缘计算容器化是否有必要?
你点的每个"在看",我都认真当成了喜欢
近几年诞生了很多微服务框架,比如JAVA的Spring Cloud、Dubbo;Golang的GoKit和GoMicro以及NodeJs的Seneca.几乎每种主流语言都有其对应的微服务框架.
Go在微服务框架中有其独特的优势,至于优势在哪,自行google.
①.、GoKit框架
这是一个工具包的集合,可以帮助攻城狮构建强大、可靠和可维护的微服务.提供了用于实现系统监控和弹性模式组件的库,例如日志、跟踪、限流、熔断等.
基于这个框架的应用程序架构由三个主要的部分组成:
传输层:用于网络通信,服务通常使用HTTP或者gRPC等网络传输协议,或者使用NATS等发布订阅系统相互通信.
服务成:具体的业务逻辑实现
这是一个基于Go语言实现的插件化RPC微服务框架.提供了服务发现、负载均衡、同步传输、异步通信以及事件驱动等机制,尝试简化分布式系统之间的通信,让开发者更专注于自身业务逻辑的开发.
GoMicro的设计哲学是可插拔的架构理念,提供了可快速构建系统的组件,并且可以根据自身的需求对GoMicro提供的默认实现进行定制.所有插件都可在仓库github.com/micro/go-plugins 中找到.
Remote Procedure Calls
远程过程调用 (RPC) 是一种协议,程序可使用这种协议向网络中的另一台计算机上的程序请求服务.由于使用 RPC 的程序不必了解支持通信的网络协议的情况,所以呢 RPC 提高了程序的互操作性.在 RPC 中,发出请求的程序是客户程序,而提供服务的程序是服务器.
RPC是指远程过程调用,也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据.
为什么要用RPC呢?就是无法在一个进程内,甚至一个计算机内通过本地调用的方式完成的需求,比如不同的系统间的通讯,甚至不同的组织间的通讯,由于计算能力需要横向扩展,需要在多台机器组成的集群上部署应用.
RPC就是要像调用本地的函数一样去调远程函数.在研究RPC前,我们先看看本地调用是怎么调的.假设我们要调用函数Multiply来计算lvalue * rvalue的结果:
①. int Multiply(int l, int r) {
将 lvalue 和 rvalue 的值压栈
将 y 的值压栈,然后从Multiply返回
在远程调用时,我们需要执行的函数体是在远程的机器上的,也就是说,Multiply是在另一个进程中执行的.这就带来了几个新问题:
所以,要实现一个RPC框架,其实只需要把以上三点实现了就基本完成了.Call ID映射可以直接使用函数字符串,也可以使用整数ID.映射表一般就是一个哈希表.序列化反序列化可以自己写,也可以使用Protobuf或者FlatBuffers之类的.网络传输库可以自己写socket,或者用asio,ZeroMQ,Netty之类.