Rpc concept?
Rpc is commonly known as Remote Procedure Call. Local functions are called at the remote end.
Generally, we call a method, for example, sumadd (10, 20). The actual implementation of the sumadd method is either defined by the user or stored in the library function of the language, that is to say, the code of the sumadd method is implemented locally, and it is called locally!
"Remote Call" means that the specific implementation of the called method is not running locally, but somewhere else (distributed to various servers), but is used locally.
Rpc remote call principle:
For example, A calls the remoteAdd method provided by B:
First, establish a tcp connection between A and B;
Then A serializes the name of the method to be called (remoteAdd here) and the method parameter (10, 20) into the word throttling and sends it out;
B accepts the byte stream sent by A and deserializes it to obtain the target method name and method parameter. Then, execute the corresponding method call (probably localAdd) and return the result 30;
A accepts the remote call result and then do ().
The RPC framework encapsulates the details of the launch statement and provides users with useful APIs. (Note: for some remote calls, select the underlying socket protocol, for some remote calls, select the upper-layer HTTP protocol );
Generally, rpc works with multiple http protocols, that is, more http is used. Of course, I still look at the application. I used to share the rpc framework based on zeromq zerorpc. The speed is quite fast. Both the server and client have python gevent support, and the speed is unreasonable. (If you are interested, look at the article http://rfyiamcool.blog.51cto.com/1030776/1254000 for zerorpc) at least faster than xml-rpc in python itself. Rpc over http (http-based rpc) has two types of protocols: xml-rpc and json-rpc.
XML-RPC: XML Remote Procedure Call, XML Remote method Call, RPC Call using http + xml encapsulation. Http-based transmission and XML-based information encoding formats. An xml-rpc message is an http-post request whose request body is xml. It is also returned in xml format after being executed by the server. This standard has evolved into the following SOAP protocol. It is understandable that SOAP is an advanced version of the XML-RPC.
JSON-RPC: JSON Remote Procedure Call, which is a JSON Remote method Call. Similar to XML-RPC, the difference is that JSON is used as the information exchange format
The following is an example. We use the python rpc Library SimpleXMLRPCServer for testing, create the rpc server, and register some functions for other clients to call.
The code is as follows: |
Copy code |
From SimpleXMLRPCServer import SimpleXMLRPCServer
Original article: xiaorui. cc
Def add (x, y ): Return x + y Def subtract (x, y ): Return x-y Def multiply (x, y ): Return x * y Def divide (x, y ): Return x/y # A simple server with simple arithmetic functions Server = SimpleXMLRPCServer ("localhost", 8000 )) Print "Listening on port 8000 ..." Server. register_multicall_functions () Server. register_function (add, 'ADD ') Server. register_function (subtract, 'subtract ') Server. register_function (multiply, 'multiply ') Server. register_function (divide, 'divide ') Server. serve_forever () |
The code is as follows: |
Copy code |
Import xmlrpclib Proxy = xmlrpclib. ServerProxy ("http: // localhost: 8000 /") Multicall = xmlrpclib. MultiCall (proxy) Multicall. add (7,3) Multicall. subtract (7,3) Multicall. multiply (7,3) Multicall. divide (7,3) Result = multicall () Print "7 + 3 = % d, 7-3 = % d, 7*3 = % d, 7/3 = % d" % tuple (result) |
Rpc is originally a single task. If the task is relatively frequent, it can be set to the default of multithreading. You do not need to directly reference the threading module or something.
The code is as follows: |
Copy code |
Class AsyncXMLRPCServer (SocketServer. ThreadingMixIn, SimpleXMLRPCServer): pass |
Then change the rpc initialization method.
The code is as follows: |
Copy code |
Server = AsyncXMLRPCServer ('', 1111), SimpleXMLRPCRequestHandler) |
Next, jsonrpc, which is similar to xmlrpc, seems to use xmlrpc now, more than jsonrpc. Sometimes I go to an it forum outside China to read my post. I use xmlrpc to submit more posts. In fact, a large company has simply implemented its own rpc framework, such as Taobao Dubbo (it is difficult for a friend to develop an interface after a long time, not clear !), Baidu xxx (forgot the name ).
The code is as follows: |
Copy code |
Import jsonrpc Server = jsonrpc. Server (jsonrpc. JsonRpc20 (), jsonrpc. TransportTcpIp (addr = ("127.0.0.1", 31415), logfunc = jsonrpc. log_file ("myrpc. log "))) # Original article: xiaorui. cc # Register a function method Def echo (s ): Return s Def search (number = None, last_name = None, first_name = None ): SQL _where = [] SQL _vars = [] If number is not None: SQL _where.append ("number = % s ") SQL _vars.append (number) If last_name is not None: SQL _where.append ("last_name = % s ") SQL _vars.append (last_name) If first_name is not None: SQL _where.append ("first_name = % s ") SQL _vars.append (first_name) SQL _query = "SELECT id, last_name, first_name, number FROM mytable" If SQL _where: SQL _query + = "WHERE" + "AND". join (SQL _where) Cursor =... Cursor.exe cute (SQL _query, * SQL _vars) Return cursor. fetchall () Server. register_function (echo) Server. register_function (search) # Start server Server. serve ()
# Create a jsonrpc client Import jsonrpc Server = jsonrpc. ServerProxy (jsonrpc. JsonRpc20 (), jsonrpc. TransportTcpIp (addr = ("127.0.0.1", 31415 ))) # Call a remote function Result = server. echo ("hello world ") Found = server. search (last_name = 'Python ') |
I have done some stress tests. After the XMLRPCSERVER is enabled with async, each connection is blocked for 5 seconds, and its concurrency is about 40. That is, about 40 successes per second, and the rest is blocked and waiting. In fact, its bottleneck is not the rpc itself, but the basehttpserver that carries rpc, which is too weak.
Receive request, call method!
Now the open-source community is so developed that many people rewrite the web services that carry rpc according to the rpc protocol. For example, if you use flask, tornado, and uwsgi, you can guess what to do .... If the connection is not blocked, it is okay. If the connection is blocked, the waste material of uwsgi is highlighted. As mentioned in previous articles, uwsgi is prework and will start the process in advance, the official recommendation is to enable processes based on the number of cpu cores or hyper-threading. If too many processes are enabled, you will find that uwsgi cannot handle so many processes. Let's look at my large tornado, after using @ gen. engine. Easily Reach 500 concurrent connections.
(The above is my full and egg test. I have never heard of anyone calling so many blocking methods and self-evaluating sx behavior)
Let's not talk about it much. Let's look at the code for implementing the xmlrpc server of flask and the source code of the flask xmlrpc. It's not hard to implement it.
The code is as follows: |
Copy code |
From flask import Flask From flaskext. xmlrpc import XMLRPCHandler, Fault App = Flask (_ name __) Handler = XMLRPCHandler ('api ') Handler. connect (app, '/api ') @ Handler. register Def woca (name = "world "): If not name: Raise Fault ("fuck... fuck", "fuck shencan! ") Return "Hello, % s! "% Name Original article: xiaorui. cc App. run () |
There are multiple methods for timeout of each connection. If you use flask and tornado as the web server, write a single decorator, but the performance is poor. Or Mount nginx first, and then create client_header_timeout, client_body_timeout, proxy_connect_timeout (you know .), If python comes with xml-rpc, you need to introduce socket.
The code is as follows: |
Copy code |
Import socket Socket. Setdefatimetimeout () |
Let's talk about rpc security.
For security, if you are interested, open an ssl certificate or judge the client ip address in the program. The configuration is uniformly distributed. When you reload daemon, you will know what ip address to judge.
I personally prefer to obtain and call basic resources for rpc Applications. After all, simply using socket or mq, you need to make a parsed data in the program, then the call is performed based on the data. (Alert: I want to trigger add (). If it is rpc, I don't need to worry about it. Just pass it over. By then, mq and socket will need eval to call the function ), some complex applications prefer resource-oriented rest, and we recommend that you use this to ensure reliability.