Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to understand RPC remote invocation

2025-03-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)05/31 Report--

This article shows you how to understand RPC remote calls, the content is concise and easy to understand, can definitely brighten your eyes, through the detailed introduction of this article, I hope you can get something.

Today, I dug a hole for myself again. I planned to sort out the knowledge of rpc remote calls, and it took me two whole days over the weekend.

What is RPC?

The explanation given by Baidu Encyclopedia is as follows: "RPC (Remote Procedure Call Protocol)-remote procedure call protocol, which is a protocol that requests services from remote computer programs over the network without knowing the underlying network technology." This concept still sounds abstract, it doesn't matter, continue to look back, later on the conceptual things, I will be clear enough to give you a complete grasp of the basics of RPC. In the following chapter, combined with its practical application in OpenStack, we will unveil the mystery of rpc step by step.

# # 01\. Since REST, he RPC?

There are two main ways of inter-process communication in OpenStack, one is RESTFul API based on HTTP protocol, and the other is RPC call.

So what is the difference between the two approaches in application scenarios?

People who have experience in using it will know:

* the former (RESTful) is mainly used for the communication between * * components (such as the communication between nova and glance), or for components to provide calling interfaces.

* the latter (RPC) is used for the communication between different modules in the same component (such as the communication between nova-compute and nova-scheduler in the nova component).

About OpenStack RESTful API-based communication is mainly the application of WSGI, this knowledge, I explained in depth in the previous article, you can click to view.

For those who are not familiar with OpenStack, don't worry about not understanding. Let me ask you two questions:

1. What is the difference between RPC and REST?

two。 Why use RPC?

* * first question: what is the difference between RPC and REST? **

You must think this question is very strange, yes, including me, but if you search the Internet, you will find similar comparisons everywhere. I am thinking that many beginners may have a weak foundation to compare the irrelevant two. Since this is the case, in order to let you know more about the unfamiliar RPC, start with the REST that you are too familiar with.

* * 01, different categories * *

REST, short for Representational State Transfer, describes declarative state transfer in Chinese (refers to a snapshot of resource data in an instantaneous state, including the content of resource data, presentation format (XML, JSON) and other information. )

REST is a style of software architecture. A typical application of this style is HTTP. It is widely favored by developers because of its simplicity and strong expansibility.

RPC, on the other hand, is the abbreviation of Remote Procedure Call Protocol, and the Chinese description is remote procedure call, which enables the client to invoke the server's service (method) like a local service (method).

RPC is a communication protocol based on TCP. In theory, it and REST are not on the same level and should not be discussed together, but who made REST so popular? it is the most popular set of API design standards for Internet applications. In a sense, when we say REST can actually refer to the HTTP protocol.

* * 02. Different ways of use * *

* * in terms of usage * *, the HTTP API only cares about the service provider and does not care about how the client invokes it. The API only needs to return the corresponding data when it is called by the client. RPC requires the client interface to be consistent with the server.

* REST means that the server writes the method, but the client does not know the specific method. The client only wants to get the resources, so it initiates the HTTP request, and the server receives the request and locates it to the method after a series of routes according to the URI.

* PRC means that the server provides a good method for the client to call. The client needs to know the specific class and method of the server, and then call it directly as if it were a local method.

* * 03. Object-oriented is different * *

From a design point of view, RPC, the so-called remote procedure call, is method-oriented, and REST: the so-called Representational state transfer, is resource-oriented. in addition, there is also a so-called SOA, the so-called service-oriented architecture, which is message-oriented.

* * 04. Different serialization protocols * *

The interface call usually consists of two parts, serialization and communication protocol.

Communication protocol, as mentioned above, REST is based on HTTP protocol, while RPC can be transmitted based on TCP/UDP or HTTP protocol.

Common serialization protocols are: json, xml, hession, protobuf, thrift, text, bytes, etc. REST usually uses JSON or XML, while RPC uses JSON-RPC, or XML-RPC.

From the above, we know that there is an obvious difference between REST and RPC.

* * second question: why use RPC? **

Then why on earth should we use RPC? can't we rely solely on RESTful API? Why do we have to make so many complicated agreements? the slag said that it was really impossible to learn.

On this point, the following points are just my personal conjecture, for communication only:

1. The positioning of RPC and REST is different. REST is resource-oriented and pays more attention to the specification of interfaces. To ensure greater versatility, it is best to use REST for external users. On the other hand, RPC is method-oriented, which is mainly used for the call of function methods, and can be suitable for scenarios with more complex communication requirements.

2. The synchronization mechanism is used between the RESTful API client and the server. When sending the HTTP request, the client needs to wait for the response from the server. Of course, there are some techniques that can be used to implement the asynchronous mechanism.

3. With RESTful API, although the client and server can be developed independently, there is still coupling. For example, when sending a request, the client must know the address of the server and must ensure that the server is working properly. Rpc + ralbbimq middleware can realize low-coupling distributed cluster architecture.

Having said so much, how should we choose the two? I have summarized the following two points for your reference:

* REST has more standardized interfaces and high requirements for general adaptability. It is recommended that all external interfaces be unified as REST (there are exceptions. For example, I have come into contact with zabbix, and its API is based on JSON-RPC 2.0 protocol). For each module within the component, you can choose RPC. One is that you don't have to spend too much energy developing and maintaining multiple sets of HTTP interfaces, and one RPC has higher call performance (see next section).

* from a performance point of view, HTTP itself provides rich status features and extended features, but it is precisely because there are too many features provided by HTTP that it needs to carry more information during network transmission, which is relatively inefficient from a performance point of view. On the other hand, the RPC service network only transmits the data related to the business content, so the transmission data is smaller and the performance is higher.

# # 02\. Three ways to realize remote invocation

"remote call" means that the specific implementation of the called method is not local to the program, but somewhere else (distributed to each server). The caller only wants the result of the function operation, but does not need to implement the details of the function.

* * 01, based on xml-rpc**

Python implements rpc and can use SimpleXMLRPCServer in the standard library, which is based on the XML-RPC protocol.

With this module, it becomes quite easy to open a rpc server. Execute the following code:

`

Import SimpleXMLRPCServer

Class calculate:

Def add (self, x, y):

Return x + y

Def multiply (self, x, y):

Return x * y

Def subtract (self, x, y):

Return abs (xMury)

Def divide (self, x, y):

Return x/y

Obj = calculate ()

Server = SimpleXMLRPCServer.SimpleXMLRPCServer (("localhost", 8088))

# registering the instance with rpc server

Server.register_instance (obj)

Print "Listening on port 8088"

Server.serve_forever ()

`

With rpc server, there is rpc client, and since we are using XML-RPC above, rpc clinet needs to use the library xmlrpclib.

`

Import xmlrpclib

Server = xmlrpclib.ServerProxy ("http://localhost:8088")

`

Then we can call the function of the previous rpc server remotely through the server_proxy object.

`

> > server.add (2,3)

five

> server.multiply (2,3)

six

> server.subtract (2,3)

one

> server.divide (2,3)

0

`

SimpleXMLRPCServer is a single-threaded server. This means that if several clients make multiple requests at the same time, other requests must wait for the first request to complete before continuing.

If you have to use SimpleXMLRPCServer to achieve multithreaded concurrency, it is not difficult. Just change the code to the following.

`

From SimpleXMLRPCServer import SimpleXMLRPCServer

From SocketServer import ThreadingMixIn

Class ThreadXMLRPCServer (ThreadingMixIn, SimpleXMLRPCServer): pass

Class MyObject:

Def hello (self):

Return "hello xmlprc"

Obj = MyObject ()

Server = ThreadXMLRPCServer ("localhost", 8088), allow_none=True)

Server.register_instance (obj)

Print "Listening on port 8088"

Server.serve_forever ()

`

* * 02, based on json-rpc**

SimpleXMLRPCServer is a remote call based on xml-rpc, and we mentioned above that in addition to xml-rpc, there is also the json-rpc protocol.

So how does python implement based on the json-rpc protocol?

The answer is that many web frameworks implement json-rpc on their own, but we have to look for a cleaner solution in addition to these frameworks. I have found two options.

The first is `jsonrpclib`

`

Pip install jsonrpclib-I https://pypi.douban.com/simple

`

The second is `python- jsonrpc`

`

Pip install python-jsonrpc-I https://pypi.douban.com/simple

`

Let's take a look at the first [jsonrpclib] (https://github.com/joshmarshall/jsonrpclib/)).

It is very similar to the SimpleXMLRPCServer of the Python standard library (because its class name is SimpleJSONRPCServer, people who don't know the truth really think they are brothers). Perhaps it can be said that jsonrpclib is written after the SimpleXMLRPCServer standard library.

Its import is slightly different from SimpleXMLRPCServer because SimpleJSONRPCServer is distributed in the jsonrpclib library.

Server side

`

From jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer

Server = SimpleJSONRPCServer (('localhost', 8080))

Server.register_function (lambda XBI y: XBY, 'add')

Server.serve_forever ()

`

Client

`

Import jsonrpclib

Server = jsonrpclib.Server ("http://localhost:8080")

`

[picture uploaded... (image-e0730d-1610601786095-15)]

Let's take a look at the second kind of python-jsonrpc, which seems a little complicated to write.

Server side

`

Import pyjsonrpc

Class RequestHandler (pyjsonrpc.HttpRequestHandler):

@ pyjsonrpc.rpcmethod

Def add (self, a, b):

"" Test method "

Return a + b

Http_server = pyjsonrpc.ThreadingHttpServer (

Server_address= ('localhost', 8080)

RequestHandlerClass=RequestHandler

)

Print "Starting HTTP server..."

Print "URL: http://localhost:8080"

Http_server.serve_forever ()

`

Client

`

Import pyjsonrpc

Http_client = pyjsonrpc.HttpClient (

Url= "http://localhost:8080/jsonrpc"

)

`

[picture uploaded... (image-a950f0-1610601786095-14)]

I still remember the zabbix API I mentioned above, because I have been in contact with it, so I also brought it out to talk about it. Zabbix API is also implemented based on the json-rpc 2.0 protocol.

Because there is a lot of content, I will only give you a note on how zabbix is called: directly specify which method of zabbix server to call and what parameters to pass to this method.

[picture uploaded... (image-9bf5a6-1610601786095-13)]

* * 03. Based on zerorpc**

The two rpc remote call methods described above, if you are careful enough, you can find that they are a combination of http+rpc and the two protocols.

Next, the kind we are going to introduce ([zerorpc] (https://github.com/0rpc/zerorpc-python) no longer uses walking http.

[zerorpc] (https://github.com/0rpc/zerorpc-python), a third-party library based on TCP protocol, ZeroMQ and MessagePack, has relatively fast speed, short response time and high concurrency. Zerorpc, like pyjsonrpc, requires additional installation, and although SimpleXMLRPCServer does not require additional installation, SimpleXMLRPCServer performance is relatively poor.

`

Pip install zerorpc-I https://pypi.douban.com/simple

`

Server code

`

Import zerorpc

Class caculate (object):

Def hello (self, name):

Return 'hello, {}' .format (name)

Def add (self, x, y):

Return x + y

Def multiply (self, x, y):

Return x * y

Def subtract (self, x, y):

Return abs (xMury)

Def divide (self, x, y):

Return x/y

S = zerorpc.Server (caculate ())

S.bind ("tcp://0.0.0.0:4242")

S.run ()

`

Client

`

Import zerorpc

C = zerorpc.Client ()

C.connect ("tcp://127.0.0.1:4242")

`

[picture uploaded... (image-47df9-1610601786095-12)]

In addition to using the zerorpc framework to implement code calls, the client also supports the use of "command line" calls.

[picture uploaded... (image-df586b-1610601786095-11)]

The client can use the command line, so can the server also?

Yes, you can experience that this third-party library is really good at doing it through a few demo documents on Github.

For example, we can use the following command to create a rpc server. For the time module in the `time` Python standard library, zerorpc will register and bind the time for client to call.

`

Zerorpc-server-bind tcp://127.0.0.1:1234 time

`

On the client side, you can use this command to call the time function remotely.

`

Zerorpc-client-connect tcp://127.0.0.1:1234 strftime% Y/%m/%d

`

[picture uploaded... (image-6cb105-1610601786095-10)]

# # 03\. Introducing message Middleware into rpc

After learning above, we have learned how to implement rpc remote calls in a variety of ways.

By comparison, zerorpc can be said to stand out, a unique show.

But why is it that in OpenStack, instead of rpc calling rpc server directly, rpc client first sends the rpc call request to RabbitMQ, and then the subscriber (rpc server) fetches the message, and finally implements the remote call?

To this end, I have also done some thinking:

There are many OpenStack components, and each component in a large cluster communicates frequently through rpc. If rpc is directly connected, the number of connections will be very large and the overhead will be high. If some server is in single-threaded mode, the timeout will be very serious.

OpenStack is a complex distributed cluster architecture, and multiple rpc server will work at the same time. Suppose there are three server of server01,server02,server03. When rpc client wants to issue a rpc request, which one should be sent? This is question one.

You might say round robin or random, which is fair to everyone. This leads to another problem. If the request happens to be sent to server01 and the server01 happens to be out of luck, the rpc message may fail directly because the machine or other service is not working. You know, as a cluster, high availability is a basic requirement, and it would be embarrassing to have a situation like that. This is question two.

It is possible for the cluster to expand the number of nodes according to the actual needs. If direct calls are used, the coupling degree is too high, which is not conducive to deployment and production. This is question three.

The introduction of message middleware can solve these problems very well.

* * problem solving one * *: there is only one message, and the recipient is determined by the load algorithm of AMQP. By default, it is sent evenly in all Receiver (round robin).

* * problem solving 2 * *: with message middleware as a buffer, client can be sent at will, and server is dead? It doesn't matter, when server is working properly, you can pick up the message middleware yourself.

* * solve problem 3 * *: no matter how many nodes there are, they only need to know the message middleware as an intermediary.

# # 04. What should you know about message queues?

Since later, I'll show you how to use rpc and mq broker together in OpenStack.

Before that, you must have an idea of some of the basics of message queuing.

First of all, RPC only defines a communication interface, and its underlying implementation can be different, either socket or AMQP.

AMQP (Advanced Message Queuing Protocol) is a reliable queue-based message service protocol. As a communication protocol, AMQP also has multiple implementations, such as Apache Qpid,RabbitMQ and so on.

Here are a few must-know concepts in AMQP:

* Publisher: message publisher

* Receiver: message receiver. In RabbitMQ, call subscriber: Subscriber.

* Queue: the storage space used to store messages. Messages are stored in queues before they are receiver.

* Exchange: it is used to receive messages sent by Publisher and forward messages to the corresponding Message Queue according to Routing key. As to which queue to transfer to, this routing algorithm is determined by exchange type.

Exchange type: there are four main types that describe exchange.

Direct: messages are routed to queues that meet this condition (queue, there can be multiple): routing key = binding key

Topic: messages are routed to queues that meet this condition (queue, there can be multiple): routing key matches binding pattern. Binding pattern is a string similar to a regular expression that satisfies complex routing conditions.

Fanout: messages are routed to queues that are bound to the exchange.

* binding: binding is a concept used to describe the relationship between exchange and queue. An exchang can be bound to multiple queues, and these relationships are established by binding. The binding key / binding pattern mentioned earlier is also given in binding.

I found a picture on the Internet, which can clearly describe the relationship of several nouns.

[picture uploaded... (image-3f97d6-1610601786095-9)]

With regard to AMQP, there are a few points to note:

1. Each receiver/subscriber needs to create a binding before receiving a message.

two。 A queue can have multiple receiver, and a message in the queue can only be sent to one receiver.

3. A message can be sent to a queue or to multiple columns. In the case of multiple queues, a message can be received and processed by multiple receiver. Both of these situations are used in Openstack RPC.

# # 05\. How to use RPC in OpenStack?

After laying the groundwork for so long, we finally came to the scene of real application. How is RPC applied in production?

I don't know about other models, but the application model in OpenStack is like this.

[picture uploaded... (image-ecd481-1610601786095-8)]

As for why it is designed in this way, I have already given my own point of view.

Next, the source code interprets OpenStack to see how it makes remote calls through rpc. If you're not interested (I know a lot of people aren't interested, so don't waste your time), you can just skip this section and move on to the next section.

There are currently two RPC implementations in Openstack, one in oslo messaging and the other in openstack.common.rpc.

Openstack.common.rpc is the old implementation, and oslo messaging is the refactoring of openstack.common.rpc. Openstack.common.rpc has a copy in each project, and oslo messaging extracts this common code to form a new project. Oslo messaging also redesigned RPC API, further encapsulated a variety of transport, and used kombu as an AMQP library at the bottom. (note: Kombu is the messaging library in Python. Kombu aims to make messaging in Python as simple as possible by providing the usual high-level interface to the AMQ protocol, and to provide validated and tested solutions to common messaging problems. )

With regard to the oslo_messaging library, two separate API are mainly provided:

1. Oslo.messaging.rpc (client-server remote procedure call is implemented)

2. Oslo.messaging.notify (implements the event notification mechanism)

Because the notify implementation is too simple, so I will not say much here, if someone wants to see this content, you can collect my blog ([python-online.cn] (http://python-online.cn))), I will update and supplement the content of notify.

The OpenStack RPC module provides three RPC calling methods, rpc.call,rpc.cast and rpc.fanout_cast, to send and receive RPC requests.

* rpc.call sends RPC * * synchronization request * * and returns the request processing result.

* rpc.cast sends RPC * * asynchronous request * *. Unlike rpc.call, it does not need to request the return of the processing result.

* rpc.fanout_cast is used to send RPC broadcast messages and no result is returned.

From the point of view of the implementation code, there is little difference between rpc.call and rpc.rpc.cast, that is, call calls with wait_for_reply=True parameters, while cast does not.

To understand the calling mechanism of rpc, you must first know several concepts of oslo_messaging

* the underlying implementation of transport:RPC function. Here is the access path of rabbitmq's message queue.

Transport defines how you can access and connect to message middleware. For example, if you are using Rabbitmq, there should be a line of `transport_ url` configuration in nova.conf. You can clearly see that rabbitmq is specified as message middleware, and user,passwd, host and port are configured to connect to rabbitmq.

`

Transport_url=rabbit://user:passwd@host:5672

`

[picture uploaded... (image-cefa55-1610601786090-6)]

`

Def get_transport (conf, url=None, allowed_remote_exmods=None):

Return _ get_transport (conf, url, allowed_remote_exmods

Transport_cls=RPCTransport)

`

* target: specify the matching information of the RPC topic switch and bind the host.

Target is used to indicate whether the RPC server listens to the topic,server name and the exchange that the server listens to, and whether to broadcast the fanout.

`

Class Target (object):

Def _ _ init__ (self, exchange=None, topic=None, namespace=None

Version=None, server=None, fanout=None

Legacy_namespaces=None):

Self.exchange = exchange

Self.topic = topic

Self.namespace = namespace

Self.version = version

Self.server = server

Self.fanout = fanout

Self.accepted_namespaces = [namespace] + (legacy_namespaces or [])

`

To get a message, rpc server needs to define a target, just like a house number.

[picture uploaded... (image-dbec91-1610601786090-5)]

For rpc client to send a message, you also need a target to indicate where the message is going.

[picture uploaded... (image-c46d56-1610601786090-4)]

* endpoints: an object that can be called remotely by others

The RPC server exposes endpoint, and each endpoint contains a series of methods that can be called by remote clients through transport. For intuitive understanding, you can refer to nova-conductor 's code for creating rpc server. The endpoints here is `nova/manager.py:ConductorManager () `.

[picture uploaded... (image-80ed4a-1610601786090-3)]

* dispatcher: dispenser, which is a concept unique to rpc server

[picture uploaded... (image-78c3ac-1610601786089-2)]

Only through it does the server side know the received rpc request, who should be handed over to handle it, and how to handle it?

On the client side, this is how you specify which method to call.

[picture uploaded... (image-ca81ed-1610601786089-1)]

On the server side, how do you know to execute this method? This is what dispatcher does. It finds the method in endpoint, executes it, and returns.

[picture uploaded... (image-9c965e-1610601786089-0)]

* Serializer: the base class for serialization or deserialization of data between python objects and message (notification).

There are four main methods:

1. Deserialize_context (ctxt): change the dictionary to request contenxt.

2. Deserialize_entity (ctxt, entity): deserialize entity, where ctxt is already deserialize and entity is to be processed.

3. Serialize_context (ctxt): change Request context to dictionary type

4. Serialize_entity (ctxt, entity): serialize entity, where ctxt is already deserialize and entity is to be processed.

* executor: how the service runs, single-threaded or multithreaded

Each notification listener is bound to an executor to control how the received notification is allocated. By default, blocking executor is used (see the executor section for specific features)

`

Oslo_messaging.get_notification_listener (transport, targets, endpoints, executor='blocking', serializer=None, allow_requeue=False, pool=None)

`

Four important methods of rpc server and rpc client

1. `reset () `: Reset service.

2. `start () `: after the method is called, server starts poll, receives message from transport, and forwards it to dispatcher. The message processing continues until the stop method is called. Executor determines the IO processing strategy of server. It may be to use a new process, a new co-program to do the poll operation, or simply register a callback in a loop. Similarly, executor also decides how to allocate message, either in a new thread dispatch or. *

3. `stop () `: when stop is called, the new message will not be processed. However, server may still be dealing with some previously unfinished message, and the underlying driver resources have not been released.

4. `wait () `: after the stop call, another message may be being processed. Use the wait method to block the current process until all message are processed. After that, the underlying driver resources are released.

# # 06\. Imitate OpenStack to write rpc call

Imitation is a very efficient learning method. Here, according to the way OpenStack is called, extract the core content and write it into a simple demo. If you are interested in OpenStack, you can learn about it. * * most people can also skip this chapter directly * *.

The following code can not be run directly, you also need to configure the connection mode of rabbitmq, you can write it in the configuration file, read it from cfg.CONF through get_transport, or you can directly write it into url format to make parameters and pass it to get_transport.

* * simple rpc client**

`

# coding=utf-8

Import oslo_messaging

From oslo_config import cfg

# create rpc client

Transport = oslo_messaging.get_transport (cfg.CONF, url= "")

Target = oslo_messaging.Target (topic='test', version='2.0')

Client = oslo_messaging.RPCClient (transport, target)

# rpc synchronous call

Client.call (ctxt, 'test', arg=arg)

`

* * simple rpc server**

`

# coding=utf-8

From oslo_config import cfg

Import oslo_messaging

Import time

# define endpoint class

Class ServerControlEndpoint (object):

Target = oslo_messaging.Target (namespace='control'

Version='2.0')

Def _ _ init__ (self, server):

Self.server = server

Def stop (self, ctx):

If self.server:

Self.server.stop ()

Class TestEndpoint (object):

Def test (self, ctx, arg):

Return arg

# create rpc server

Transport = oslo_messaging.get_transport (cfg.CONF, url= "")

Target = oslo_messaging.Target (topic='test', server='server1')

Endpoints = [

ServerControlEndpoint (None)

TestEndpoint ()

]

Server = oslo_messaging.get_rpc_server (transport, target,endpoints,executor='blocking')

Try:

Server.start ()

While True:

Time.sleep (1)

Except KeyboardInterrupt:

Print ("Stopping server")

Server.stop ()

Server.wait ()

`

The above is how to understand RPC remote calls. Have you learned any knowledge or skills? If you want to learn more skills or enrich your knowledge reserve, you are welcome to follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Servers

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report