中文见 README_CHI
MinerRPC is a pure GO language RPC framework based on Socket+Zookeeper.
MinerRPC supports dynamic proxy, network transmission, serialization, service registration, service discovery, and service invocation.
Currently, MinerRPC is suitable for learning and small projects, and its performance and stability have been verified in MinerDB.
MinerRPC is implemented purely in the Go language. Go is a compiled static language, which means it cannot dynamically retrieve Interface/class information from .class files generated by javac like Java can. However, we can use reflection to obtain information about class objects, and dynamically modify the implementation logic of function fields that only provide input and output types in class objects. This allows us to achieve dynamic proxy for class objects.
Specifically, the implementation logic is modified to call zk to obtain the service address and execute the service call through the client stub.
MinerRPC uses Zookeeper to implement service registration and discovery. When the server starts, it registers the method names and addresses (ip+port) of the implemented class objects to Zookeeper through reflection. The client finds the corresponding service address through the request service name of the proxy object, thereby realizing service invocation.
When the client requests a service, it selects the corresponding service address according to the load balancing strategy and supports dynamic vertical scaling.
Currently supports JSON serialization, and is modularly designed for easy custom extension.
Uses Socket for network transmission.
- Use NIO to replace BIO for network transmission
- Support more load balancing strategies
- Support more serialization methods
docker run -d --name zookeeper -p 2181:2181 zookeeper:3.5.8
Define class information for requesting services on the client side
type Test struct {
Ping func() (string, error)
Hello func() (string, error)
}
Implement this type of object, create a dynamic proxy entity, and execute service calls
package main
import (
"fmt"
"minerrpc/rpc_api/services"
"minerrpc/rpc_core/transport/client"
)
func main() {
client := transport_client.NewDefaultSocketClient()
proxy := transport_client.NewRpcClientProxy(client)
testService := proxy.NewProxyInstance(&api_services.Test{}).(*api_services.Test)
res, _ := testService.Ping()
fmt.Println("The result is: ", res)
res, _ = testService.Hello()
fmt.Println("The result is: ", res)
}
Implement the methods in the class information defined by the client side on the server side
type TestImpl struct{}
func (s *TestImpl) Ping() (string, error) {
return "pong", nil
}
func (s *TestImpl) Hello() (string, error) {
return "name ", nil
}
Register the object and start the service
package main
import (
"fmt"
"minerrpc/rpc_core/transport/server"
"minerrpc/rpc_server/servers/services"
"os"
"os/signal"
)
func main() {
srv, err := transport_server.NewDefaultSocketServer("localhost:3212")
if err != nil {
panic(err)
}
ss := servers_services.TestImpl{}
srv.Register(&ss)
go srv.Start()
stopChan := make(chan os.Signal, 1)
signal.Notify(stopChan, os.Interrupt)
sig := <-stopChan
fmt.Printf("Received %v, initiating shutdown...\n", sig)
}
MinerRPC is inspired by rrpc and boot4go-proxy, many thanks 🙏