What is RPC?
Remote Procedure Call (RPC), also known as Remote Procedure Call, is mainly used to solve the Call problem between services in a distributed system.
First we need to take a quick look at what distributed systems are and what problems are distributed systems designed to solve?
Distributed system, as its name implies, is to divide an overall system to complete task A into multiple modules and deploy them on different computer nodes. These modules work together to complete task A through network communication. Distributed system is mainly to use a number of ordinary performance of the computer to complete the task that a single high-performance computer is difficult to complete, after all, the performance of a single computer is also powerful upper limit, multiple ordinary computers can be expanded indefinitely in theory.
Now that we know about distribution, we need to know why RPC is needed to solve communication problems in distributed systems.
First in a distributed system, deployed in different service need to work on the machine must be mutual communication, the communication between them is not like native function calls easily, because local function call is in the same address space, so the method and parameter stack can realize the communication between each other, but the deployment of services on different machines, There is no common address space, so you can only communicate through the network.
To illustrate the following example, the services of different machines are represented by service A and service B. The scenario is that service A needs to invoke the method of service B. When it comes to network communication, many people’s first idea is to let B service be called to provide an interface, and A service request interface to implement the invocation. This method can indeed solve the problem of cross-service invocation, but from the point of view of cost, each method invocation needs the consumption of HTTP request. Each time you have to write a string of httpClient requests and other information, time-consuming and laborious.
To optimize this repeated httpClient operation, you can use proxy mode to implement the invocation, implement the httpClient request inside the proxy and a series of miscellaneous operations. At present, many RPC frameworks adopt this design concept, such as Motan, Dubbo and so on.
This shows that RPC is not only to solve the call between services, but also to make the call between services as local function call, convenient and fast.
The basic flow of RPC?
The RPC process is roughly divided into three parts: network transmission, function name mapping, serialization and deserialization.
- If A service wants to call the method of B service, it must first connect to B service through the underlying RPC framework and send the required information to B service, which is the network communication in RPC. The first thought is HTTP protocol (HTTP1.1) to carry out data transmission, but for some of the pursuit of efficiency of the scene, the transmission of data obviously do not need to use the application protocol of text transmission, the use of binary transmission is significantly faster, such as: TCP, HTTP2, etc..
- If an RPC call is analogous to a local function call, you must first know the name of the function before making the call. In RPC, all functions must have a unique identity ID that is uniquely deterministic across all processes. When service A sends A call request, it must transfer the ID to service B, and service B will find the corresponding function according to the ID to call and return the result to service A.
- Because the binary protocol is used for communication, it inevitably involves a serialization and deserialization process. In fact, this process can be understood as the process of converting the parameter object into binary bytecode.
Please refer to the following figure for specific process:
What is gRPC?
GRPC is a RPC framework developed by Google. It supports C, Python, Go, Nodejs and other languages. Use Protobuf for data serialization to improve data compression. If you don’t know Protobuf, please refer to juejin.cn/post/688552… . The NETWORK Transport protocol uses HTTP2.0, which can be found at juejin.cn/post/694313… .
There are three main steps to use gRPC:
- Compile.proto PB file and develop communication protocol.
- Use the corresponding plug-in to compile.proto PB files into the corresponding language code.
- Write business code based on the generated code.
Here is an example using the Go language:
First of all, we need to install the protobuf package for the corresponding platform, download address: github.com/protocolbuf… In this example, if the Mac platform is Catalina, download the protoc-3.16.0-RC-1-osx-x86_64. zip package and decompress the package to obtain the following directory:
If you add binaries in the bin directory to environment variables, protoc binaries are generally copied to the bin directory in the GOPATH directory for unified management
vim ~/.zshrc
alias protoc="/Users/{username}/{path}/bin/protoc"
source ./.zshrc
Copy the code
After modifying environment variables, you can run the protoc –version command to check whether the protoc is successfully installed.
Once the Protoc environment is ready, you also need to install the Go-specific Protoc generator
go get -u github.com/golang/protobuf/protoc-gen-go
Copy the code
After the installation is complete, an executable file is generated in the GOPATH directory. You can use the protoc command to invoke the plug-in to compile the PB file.
Next, you need to install the gRPC framework
Go get-u google.golang.org/grpc or go get-u github.com/grpc/grpc-goCopy the code
With the basic environment and plug-ins ready, it’s time to write the code. Start by writing the user.proto file:
syntax = "proto3";
package userRpc;
option go_package="api/protobuf-spec/user";
message UserReq {
int32 user_id = 1;
}
message UserResp {
string user_name = 1;
}
service MainService {
rpc GetUserName(UserReq) returns (UserResp);
}
Copy the code
After compiling the user.proto file, create an output directory service in the root directory and use the protoc plug-in to compile the file in the root directory: protoc -I api/ api/protobuf-spec/user/user.proto –go_out=plugins=grpc:. Get the user.pb.go file
Two points to note here:
- If output is to a specified folder, be sure to create the target output folder first, otherwise an error will be reported that the output folder is missing.
- When writing the.proto file, you must write the go_package configuration, otherwise it will compile an error.
Once you get the compiled.pb.go file, you can write the client and server code.
Server code
package main
import (
"context"
"fmt"
"google.golang.org/grpc"
"grpc/api/protobuf-spec/user"
"net"
"strconv"
)
type server struct {}
func (s *server) GetUserName(ctx context.Context, request *user.UserReq) (*user.UserResp, error){
return &user.UserResp{UserName: "name" + strconv.FormatInt(int64(request.UserId), 10)}, nil
}
func main(a) {
fmt.Print("start server...")
// listen port
lis, err := net.Listen("tcp".": 8080")
iferr ! =nil {
fmt.Printf("listen port error: %s", err)
return
}
// new api server
grpcServer := grpc.NewServer()
user.RegisterMainServiceServer(grpcServer, &server{})
iferr := grpcServer.Serve(lis); err ! =nil {
fmt.Printf("Server start error: %s", err)
return}}Copy the code
Client code
package main
import (
"context"
"fmt"
"google.golang.org/grpc"
"grpc/api/protobuf-spec/user"
)
func main(a) {
conn, err := grpc.Dial(": 8080", grpc.WithInsecure())
iferr ! =nil {
fmt.Printf("connect failure %s", err)
return
}
defer conn.Close()
// create client
cli := user.NewMainServiceClient(conn)
ret, err := cli.GetUserName(context.Background(), &user.UserReq{UserId: 13})
iferr ! =nil {
fmt.Printf("call srever func failure %s", err)
return
}
fmt.Printf("call success %s /n", ret.UserName)
}
Copy the code
Sample repository link: github.com/Monetchang/…
What is BloomRPC?
BloomRPC is a GUI tool for debugging gRPC projects, just as Postman plays a role in Restful API development.
Download: github.com/uw-labs/blo…
The BloomRPC documentation provides several ways to download:
The Mac platform can be installed directly from BREW:
brew install --cask bloomrpc
Copy the code
It can also be installed as a Clone repository:
git clone https://github.com/uw-labs/bloomrpc.git
cd bloomrpc
yarn install && ./node_modules/.bin/electron-rebuild
npm run package
Copy the code
The usage mode is very simple, the upper right corner of the left sidebar plus sign to import pb file, in the middle of the Editor input box to enter parameters, on the right side of Response to view the returned results. For details, see github address README: github.com/uw-labs/blo… .