One of the things I've discovered that I've always studied and excited about is extending the system. Now this has different meanings for different people. As part of the application of porting monolithic to the microservices architecture approach, how to handle the microservices architecture is why I study RPC.
RPC (or remote process invocation) is a concept that has existed for a long time in the field of computer science. A very simple understanding of this is the ability to send a message to a remote process, whether it is on the same system or on a remote system. In general this is very vague and is open to many implementations. In my opinion, when it comes to RPC, there is quite a lot of content to explore, such as the format of messages, and how you can send messages to remote processes. There are a number of ways to implement RPC, and this is one of the things I've adopted, but for this article, I'm going to use ' json-rpc ' to process the format of the message, using Redis to post the message.
RPC and Message Queuing
The principle is essentially the same, but using RPC, the client waits for a return message containing the result of the RPC call. If your Message Queuing system allows you to process callback messages for the sender, you will probably be able to use it for RPC. In most message queues, they are used to trigger tasks that no longer need to be answered to the client.
Why use Redis instead of others?
You should be able to find Redis in a landlord is very advanced technology, if you say no find, what's wrong with you? Redis is a great tool for many things, you should study it carefully. The road to learning can be flat, and without learning too much new content, Redis is perfectly consistent with these ideas, so let's see what we can do.
Client
Copy Code code as follows:
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)
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
Copy Code code as follows:
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,
' 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
Indeed, it works because when you wait for data to be sent back from the server, Redis has an order to block the wait. This is a very good practice, and it makes your client code look like it's calling the local method.
Ruby is pretty cool, but ...
What if you want to use another language? No problem, as long as your language has a good Redis library, you can do the same thing. Let's take a look at using Python to create a server-side program.
Copy Code code as follows:
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 ')")
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 ()
Conclusion
This is a good proof of some of the ideas in your head, and of course, more work needs to be done to deal with the anomalies. If you encounter any problems with this method, I am glad to help you. I do want to use RABBITMQ at one of the same ideas, but if you've already used Redis in your project, this will be a great way to do it.