In school, we should always take something to practice, read some articles like "Write Rpc from scratch" and "Write Search Engine from scratch" can be tried. Actually, some days ago. tiny4j There are still some things to improve and continue to improve, but everyone likes the new and hates the old. They can't help opening another hole, so this time it's RPC.
Before starting to write, I did a lot of preparation to understand some basic things about RPC. I also found some RPC frameworks to try out, such as GRPC and thrift. They all provide the ability of cross-language invocation. According to some configurations written, I can automatically generate some code. In addition to these two domestic frameworks, there are also excellent ones such as Ali's open source dubbo and Weibo's motan; Weibo's Motan documents are very concise and directly support Spring's annotation form. Immediately try helloworld, Api easy to use, a few annotations to solve all the services, for the specific language of Java, this RPC is really very useful! clone code down to see that the transport layer is using netty, in order to be able to complete this and run to get the "Netty Authority Guide" gnawed most of the book, is a door.
After all, it's the first time to write, so I don't think about cross-language. It's easy to use Spring with motan. The whole RPC calling process can be divided into the following layers:
Communication includes connection establishment, message transmission, encoding and decoding of the content to be transmitted, serialization and deserialization, and finally the realization of the client and the server. The client calls a proxy implementation of a service to initiate a request to the server.
Based on netty 5.0, protostuff, kryo serialization libraries, commons-pool2 connection pool is implemented. Service agents use Proxy or Cglib of jdk itself. On such a bunch of excellent frameworks and class libraries, the whole RPC construction is much simpler.
It's also a practice of writing an RPC from scratch. Source code stamp github Limited level is only a toy level implementation, but through this project we can understand all aspects of RPC; if you have better ideas, you are welcome to exchange.
Simple invocation example
Define services and service implementations
public interface EchoService { String hello(String s); } public class EchoServiceImpl implements EchoService { @Override public String hello(String s) { return s; } }
Server:
//Configuration: port number, maximum transmission capacity (unit M), service response Handle Server server = new Server.Builder().port(9001).maxCapacity(3).build(); //Publishing service server.addService(EchoService.class, new EchoServiceImpl()); server.start();
Client:
Client client = new Client.Builder().host("127.0.0.1").port(9001).maxCapacity(3).build(); DefaultClientInterceptor interceptor = new DefaultClientInterceptor(client); ClientProxy clientProxy = new JdkClientProxy(interceptor); EchoService echoService = clientProxy.getProxy(EchoService.class); System.out.println(echoService.echo("twogoods"));
Integrating SpringBoot
Server Configuration
Use the @RpcService annotation
public interface EchoService { String echo(String s); } @RpcService public class EchoServiceImpl implements EchoService { @Override public String echo(String s) { return s; } }
application.yml configuration
tgrpc: host: 127.0.0.1 port: 9100 maxCapacity: 3 requestTimeoutMillis: 8000 maxTotal: 3 maxIdle: 3 minIdle: 0 borrowMaxWaitMillis: 5000
Start server:
@SpringBootApplication @EnableAutoConfiguration @EnableRpcServer //Enable Server @ComponentScan() public class ServerApplication { public static void main(String[] args) { ApplicationContext applicationContext = SpringApplication.run(ServerApplication.class); } }
client configuration
The caller uses the @RpcReferer annotation.
@Component public class ServiceCall { @RpcReferer private EchoService echoService; public String echo(String s) { return echoService.echo(s); } }
Start Client Initiation Call
@SpringBootApplication @EnableAutoConfiguration @EnableRpcClient //Enable Client @ComponentScan(basePackages = {"com.tg.rpc.springsupport.bean.client"}) public class ClientApplication { public static void main(String[] args) { ApplicationContext applicationContext = SpringApplication.run(ClientApplication.class); ServiceCall serviceCall = (ServiceCall) applicationContext.getBean("serviceCall"); System.out.println("echo return :" + serviceCall.echo("TgRPC")); } }
Registry Center
You can use consul, or zookeeper as the registry. It's very simple to use, just configure the registery attribute in the configuration file, with default (default), consul,zookeeper values.
tgrpc: port: 9001 registery: zookeeper zookeeperHost: 127.0.0.1 zookeeperPort: 2181 zkServicePath: /tgrpc/services tgrpc: port: 9001 registery: consul consulHost: 127.0.0.1 consulPort: 8500 ttl: 10000
TODO
netty optimization