In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >
Share
Shulou(Shulou.com)05/31 Report--
This article shows you how to use Netty to achieve a simple RPC, the content is concise and easy to understand, can definitely brighten your eyes, through the detailed introduction of this article, I hope you can get something.
As we all know, the underlying layer of dubbo uses Netty as the network communication framework, and we have analyzed the source code of Netty before, and we still have a good understanding of it.
Today we will implement a simple RPC framework in Netty.
1. Demand
Imitating dubbo, the consumer and provider agree on the interface and protocol, the consumer remotely invokes the provider, the provider returns a string, and the consumer prints the data returned by the provider. The underlying network communication uses Netty 4.1.16.
2. Design
Create an interface that defines abstract methods. Used for agreements between consumers and providers.
Create a provider that needs to listen to the consumer's request and return data as agreed.
To create a consumer, this class needs to transparently call methods that it does not exist, and internally needs to use Netty to request the provider to return data.
3. Realize
1. Create a maven project and import Netty 4.1.16.
Cn.thinkinjavarpc-demo1.0-SNAPSHOT io.netty netty-all 4.1.16.Final
two。 The project directory structure is as follows:
3. Design interface
=
A simple hello world:
Public interface HelloService {String hello (String msg);}
4. Provider-related implementation
=
4.1. First implement the convention interface, which is used to return client data:
/ * implementation class * / public class HelloServiceImpl implements HelloService {public String hello (String msg) {return msg! = null? Msg + "- > I am fine.": "I am fine.";}}
4.2. Implement Netty server and custom handler
Start the Netty Server code:
Private static void startServer0 (String hostName, int port) {try {ServerBootstrap bootstrap = new ServerBootstrap (); NioEventLoopGroup eventLoopGroup = new NioEventLoopGroup (); bootstrap.group (eventLoopGroup) .channel (NioServerSocketChannel.class) .childHandler (new ChannelInitializer () {@ Override protected void initChannel (SocketChannel ch) throws Exception {ChannelPipeline p = ch.pipeline (); p.addLast (new StringDecoder ()) P.addLast (new StringEncoder ()); p.addLast (new HelloServerHandler ());}}); bootstrap.bind (hostName, port). Sync ();} catch (InterruptedException e) {e.printStackTrace ();}}
The above code adds a codec handler of type String and a custom handler.
The custom handler logic is as follows:
/ * used to process request data * / public class HelloServerHandler extends ChannelInboundHandlerAdapter {@ Override public void channelRead (ChannelHandlerContext ctx, Object msg) {/ / how to comply with the convention, call the local method and return the data if (msg.toString (). StartsWith (ClientBootstrap.providerName)) {String result = new HelloServiceImpl () .hello (msg.toString (). Substring (msg.toString (). LastIndexOf ("#") + 1); ctx.writeAndFlush (result) }}}
It is shown here to determine whether or not to comply with the convention (not using a complex protocol, just a string judgment), then create a concrete implementation class and call the method to write back to the client. Why is Netty so popular? Why?
You also need a startup class:
Public class ServerBootstrap {public static void main (String [] args) {NettyServer.startServer ("localhost", 8088);}}
Well, the code about the provider is finished, mainly to create a netty server, implement a custom handler, and custom handler to determine whether it conforms to the agreement between them (it's a protocol). If so, create an implementation class for the interface and call its method to return a string.
5. Consumer-related implementation
One thing consumers need to pay attention to is that calls need to be transparent, that is, framework users do not have to care about the underlying network implementation. Here we can use JDK's dynamic proxy to do this.
Idea: the client calls the proxy method, returns a proxy object that implements the HelloService interface, calls the method of the proxy object, and returns the result.
We need to tamper with the proxy. When we call the proxy method, we need to initialize the Netty client and request data from the server and return the data.
5.1. First create a class related to the agent
Public class RpcConsumer {private static ExecutorService executor = Executors .newFixedThreadPool (Runtime.getRuntime (). AvailableProcessors ()); private static HelloClientHandler client; / * create a proxy object * / public Object createProxy (final Class serviceClass, final String providerName) {return Proxy.newProxyInstance (Thread.currentThread (). GetContextClassLoader (), new Class [] {serviceClass}, (proxy, method, args)-> {if (client = = null) {initClient ()) } / / set parameters client.setPara (providerName + args [0]); return executor.submit (client). Get ();} / * * initialize the client * / private static void initClient () {client = new HelloClientHandler (); EventLoopGroup group = new NioEventLoopGroup (); Bootstrap b = new Bootstrap () B.group (group) .channel (NioSocketChannel.class) .option (ChannelOption.TCP_NODELAY, true) .handler (new ChannelInitializer () {@ Override public void initChannel (SocketChannel ch) throws Exception {ChannelPipeline p = ch.pipeline (); p.addLast (new StringDecoder ()); p.addLast (new StringEncoder ()); p.addLast (client)) }}); try {b.connect ("localhost", 8088). Sync ();} catch (InterruptedException e) {e.printStackTrace ();}
This class has two methods to create a proxy and initialize the client.
Initialize the client logic: create a client for Netty, connect to the provider, and set up a custom handler and some String type codecs.
Create proxy logic: using JDK's dynamic proxy technology, the invoke method in the proxy object is implemented as follows: if client is not initialized, initialize client, which is both a handler and a Callback. Set the parameter to client, use the thread pool to call the call method of client and block waiting for the data to return.
Look at the implementation of HelloClientHandler:
Public class HelloClientHandler extends ChannelInboundHandlerAdapter implements Callable {private ChannelHandlerContext context; private String result; private String para; @ Override public void channelActive (ChannelHandlerContext ctx) {context = ctx;} / * Wake up waiting thread * / @ Override public synchronized void channelRead (ChannelHandlerContext ctx, Object msg) {result = msg.toString (); notify () } / * write out the data and start waiting to wake up * / @ Override public synchronized Object call () throws InterruptedException {context.writeAndFlush (para); wait (); return result;} void setPara (String para) {this.para = para;}}
This class caches ChannelHandlerContext for next use and has two properties: the return result and the request parameter.
When the connection is successful, the ChannelHandlerContext is cached, and when the call method is called, the request parameters are sent to the server and wait. When the server receives and returns the data, it calls the channelRead method, which assigns a result to the return value and wakes up the thread waiting on the call method. At this point, the proxy object returns data.
Let's take a look at the designed test class:
Public class ClientBootstrap {public static final String providerName = "HelloService#hello#"; public static void main (String [] args) throws InterruptedException {RpcConsumer consumer = new RpcConsumer (); / / create a proxy object HelloService service = (HelloService) consumer .createProxy (HelloService.class, providerName); for (;;) {Thread.sleep (1000); System.out.println (service.hello ("are you ok?"));}
The test class first creates a proxy object, then calls the proxy's hello method every other second, and prints the results returned by the server.
Test result
Print successfully.
After reading the Netty source code for such a long time, we finally implemented a Netty application of our own. Although the application is very simple, and even the code is a little rough, the function is still realized. The purpose of RPC is to allow remote services to be invoked like local services, which needs to be transparent to consumers, so we use dynamic proxies. And use the handler of Netty to send data and response data, and complete a simple RPC call.
The above content is how to use Netty to implement a simple RPC, have you learned the knowledge or skills? If you want to learn more skills or enrich your knowledge reserve, you are welcome to follow the industry information channel.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.