How does Netty work in Dubbo?

Keywords: Java Dubbo Netty Spring

Author: Mona Rudow
https://www.cnblogs.com/stateis0/p/9062171.html

As we all know, the bottom layer of Dubbo, a well-known domestic framework, is Netty  As a network communication, how on earth is it used internally?Today we'll explore.

1. How Dubbo's Customer uses Netty

Note: This code uses the dubbo-demo example from the Dubbo source of clone on github.

The code is as follows:

System.setProperty("java.net.preferIPv4Stack", "true");
   ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-consumer.xml"});
   context.start();
    // @1
   DemoService demoService = (DemoService) context.getBean("demoService"); // get remote service proxy
   int a = 0;
   while (true) {
       try {
           Thread.sleep(1000);
           System.err.println( ++ a + " ");

           String hello = demoService.sayHello("world"); // call remote method
           System.out.println(hello); // get result

       } catch (Throwable throwable) {
           throwable.printStackTrace();
       }
   }

When code reaches @1, the Spring container's getBean method is called, and dubbo extends FactoryBean, so the getObject method is called, which creates the proxy object.

This process calls the getClients (URL url) method of the DubboProtocol instance, creates the client for the given URL when it is not initialized, and puts it into the cache with the following code:

This initClient method is used to create Netty's client.

The final call is the construction method of the abstract parent AbstractClient, which includes behavior such as creating a Socket client, connecting a client, and so on.

public AbstractClient(URL url, ChannelHandler handler) throws RemotingException {
   doOpen();
   connect();
}

The doOpent method is used to create a bootstrap for Netty:

protected void doOpen() throws Throwable {
   NettyHelper.setNettyLoggerFactory();
   bootstrap = new ClientBootstrap(channelFactory);
   bootstrap.setOption("keepAlive", true);
   bootstrap.setOption("tcpNoDelay", true);
   bootstrap.setOption("connectTimeoutMillis", getTimeout());
   final NettyHandler nettyHandler = new NettyHandler(getUrl(), this);
   bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
       public ChannelPipeline getPipeline() {
           NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyClient.this);
           ChannelPipeline pipeline = Channels.pipeline();
           pipeline.addLast("decoder", adapter.getDecoder());
           pipeline.addLast("encoder", adapter.getEncoder());
           pipeline.addLast("handler", nettyHandler);
           return pipeline;
       }
   });
}

The connect method is used to connect to the provider:

protected void doConnect() throws Throwable {
   long start = System.currentTimeMillis();
   ChannelFuture future = bootstrap.connect(getConnectAddress());
   boolean ret = future.awaitUninterruptibly(getConnectTimeout(), TimeUnit.MILLISECONDS);
   if (ret && future.isSuccess()) {
       Channel newChannel = future.getChannel();
       newChannel.setInterestOps(Channel.OP_READ_WRITE);
   }
}

In the code above, the bootstrap connection method is called, familiar with the Netty connection operation.Of course, jbox's netty3 is used here, which is slightly different.Click on this: Teach you how to implement a simple RPC with Netty .When the connection succeeds, register the write event and prepare to start delivering data to the provider.

When demoService.sayHello("world") is called in the main method, the HeaderExchangeChannel's request method is finally called to make the request through the channel.

public ResponseFuture request(Object request, int timeout) throws RemotingException {
   Request req = new Request();
   req.setVersion("2.0.0");
   req.setTwoWay(true);
   req.setData(request);
   DefaultFuture future = new DefaultFuture(channel, req, timeout);
   channel.send(req);
   return future;
}

The send method finally calls the write method of NoClientSocketChannel inherited from NioSocketChannel in jboss Netty.A data transfer has been completed.

2. How Dubbo's Provider provider uses Netty

Provider demo code:

System.setProperty("java.net.preferIPv4Stack", "true");
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-provider.xml"});
context.start();
System.in.read(); // press any key to exit

Provider, as the accessee, must be a Server-mode Socket.How to start?

When the Spring container starts, some extension class initialization methods are called, such as InitializingBean, ApplicationContextAware, ApplicationListener.

dubbo created a ServiceBean that inherits a listener.Spring calls his onApplicationEvent method, which has an export method for opening a ServerSocket.

The DubboProtocol createServer method is then executed, and a NettyServer object is created.NettyServer objects are also constructed using the doOpen method and the.

The code is as follows:

protected void doOpen() throws Throwable {
   NettyHelper.setNettyLoggerFactory();
   ExecutorService boss = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerBoss", true));
   ExecutorService worker = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerWorker", true));
   ChannelFactory channelFactory = new NioServerSocketChannelFactory(boss, worker, getUrl().getPositiveParameter(Constants.IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS));
   bootstrap = new ServerBootstrap(channelFactory);

   final NettyHandler nettyHandler = new NettyHandler(getUrl(), this);
   channels = nettyHandler.getChannels();
   bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
       public ChannelPipeline getPipeline() {
           NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyServer.this);
           ChannelPipeline pipeline = Channels.pipeline();
           pipeline.addLast("decoder", adapter.getDecoder());
           pipeline.addLast("encoder", adapter.getEncoder());
           pipeline.addLast("handler", nettyHandler);
           return pipeline;
       }
   });
   channel = bootstrap.bind(getBindAddress());
}

In this method, you see familiar boss threads, worker threads, and ServerBootstrap, add a NettyHandler after adding a codec handler, and call the bind method to finish binding the port.It's the same way we use Netty.

3. Summary

You can see that dubbo is easy to use Netty. Consumers use NettyClient, providers use NettyServer, providers start with port monitoring, in the same way that we normally start Netty.

Client creates Client when Spring getBean, sends data to NettyServer via dubbo protocol encoding when calling remote methods, then NettServer receives data, decodes it, calls local methods, returns data, and completes a perfect RPC call.

Okay, here's a brief introduction to how dubbo uses Netty.

Recommend going to my blog to read more:

1.Java JVM, Collections, Multithreaded, New Features Series Tutorial

2.Spring MVC, Spring Boot, Spring Cloud series tutorials

3.Maven, Git, Eclipse, Intellij IDEA Series Tools Tutorial

4.Latest Interview Questions for Java, Backend, Architecture, Alibaba, etc.

Feel good, don't forget to say yes + forward!

Posted by DaveMate on Wed, 06 May 2020 19:59:44 -0700