The overall design idea of the framework is layered + interface programming, in order to achieve the same is the flow, change is the details of the effect.
- Layering means that the framework defines an RPC process. For example, if the client wants to call a function of the server, it needs to go through the steps of service discovery, load balancing, serialization of parameters, and network transmission. After receiving a request package, the server needs to deserialize, invoke the service, and return the response. Each step has its own responsibilities, such as service discovery to find available nodes for a service, and load balancing decides which node to send the request to.
- Programming for interfaces means that the interaction between each layer is done through the interface, without implementation. That is, there can be multiple concrete implementations of each layer, and they can be replaced with each other without changing the code at the top. For example, we implemented multiple load balancing algorithms, including polling, randomization, hash residuals, dynamic weights, and so on, but the process used the same interface
SelectServer
, the concrete implementation is throughDependency injection. This approach also provides the framework with a certain amount ofscalability: If users need to implement their own load balancing algorithm, just implement itSelectServer
Interface, and register it to the specified place.
In addition, the framework follows the following principles:
-
Inversion of control. When implementing the service discovery feature, we discovered that there are two modes of active polling and passive notification for node changes, both in local profiles and remote registries. To support both modes, we give control to the user, who calls the interface to notify us when a node changes, rather than the framework fetching it.
-
Make your interface as easy to use as possible, and a lot depends on whether users want to use your framework. Now that we want to call a remote function, we simply specify the service name, method name, method parameters, and optional callback functions. In fact, there are many parameters that can be configured inside the framework, but we try to give reasonable defaults. If you are familiar with the framework, you can control the behavior of the framework through some of the keyword parameters supported by the interface, such as setting the timeout, number of retries, and retry policy. In general, we want the framework to be easy for the average user to use and somewhat playable for power users.