Introduction

We know that the foundation of netty is channel and selector on top of channel. Of course, as a nio framework, channel and selector are not only the foundation of netty, but also the foundation of all nio implementations.

Similarly, we know that netty has many different protocols, and these protocols communicate on the channel, so for different protocols, will the channel and selector used be different?

With this question in mind, let's delve into it together.

The basic way of building a netty service

Netty can be divided into client side and server side. In fact, the construction methods of client side and server side are not very different. For the sake of simplicity, the construction of server side in netty is used as an example to study.

Looking back at the netty server we built at the beginning, the corresponding code is as follows:

 //建立两个EventloopGroup用来处理连接和消息
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline().addLast(new FirstServerHandler());
                        }
                    })
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true);

            // 绑定端口并开始接收连接
            ChannelFuture f = b.bind(port).sync();

We should pay attention to two places, one is the group method of ServerBootstrap, and the other is its channel method.

EventLoopGroup

There are two implementations of group, which can take one parameter or two parameters. The parameters are EventLoopGroup, EventLoopGroup is mainly used to register the channel for subsequent Selector to choose.

If the form of one parameter is used, an EventLoopGroup handles both acceptor and client events, and if two parameters are used, the two are separated.

Of course, this is not the focus of today's talk. Today's talk is about the differences in the construction of EventLoopGroup in different protocols.

EventLoopGroup itself is an interface. It has many implementations, but there are essentially two EventLoops: SingleThreadEventLoop and MultithreadEventLoopGroup.

That is, single-threaded EventLoop processing and multi-threaded EventLoop processing.

For example, the NioEventLoopGroup we commonly used above is a single-threaded EventLoop.

NioEventLoopGroup usually uses a parameterless constructor. In fact, NioEventLoopGroup can pass in ThreadFactory, the number of threads, SelectorProvider and SelectStrategyFactory.

Netty only provides an implementation of SelectStrategyFactory: DefaultSelectStrategyFactory.

For SelectorProvider, the default implementation is SelectorProvider.provider(). Let's take a look at the specific implementation of this method:

    public static SelectorProvider provider() {
        synchronized (lock) {
            if (provider != null)
                return provider;
            return AccessController.doPrivileged(
                new PrivilegedAction<SelectorProvider>() {
                    public SelectorProvider run() {
                            if (loadProviderFromProperty())
                                return provider;
                            if (loadProviderAsService())
                                return provider;
                            provider = sun.nio.ch.DefaultSelectorProvider.create();
                            return provider;
                        }
                    });
        }
    }

You can see that by default, SelectorProvider has three creation methods.

The first is to find it from the system properties: java.nio.channels.spi.SelectorProvider:

String cn = System.getProperty("java.nio.channels.spi.SelectorProvider");
Class<?> c = Class.forName(cn, true,
                                       ClassLoader.getSystemClassLoader());
            provider = (SelectorProvider)c.newInstance();

If defined, create an instance to return.

If not, the service Loader will be loaded from "META-INF/services/":

    private static boolean loadProviderAsService() {

        ServiceLoader<SelectorProvider> sl =
            ServiceLoader.load(SelectorProvider.class,
                               ClassLoader.getSystemClassLoader());
        Iterator<SelectorProvider> i = sl.iterator();

If the servie is not found, it will use the last default sun.nio.ch.DefaultSelectorProvider.

channel

By default we are using NioServerSocketChannel. It is actually created from the default SelectorProvider mentioned above.

private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider();
return DEFAULT_SELECTOR_PROVIDER.openServerSocketChannel();

So the channel used needs to match the selector.

We can use channels directly, or we can use ChannelFactory to generate channels through these factories.

If you want to use ChannelFactory, you can call ServerBootstrap's channelFactory method.

Multiple ways to build

The most basic netty server construction method is mentioned above. Corresponding to the socket protocol.

If you want to make a UDP connection, the corresponding channel should be replaced with NioDatagramChannel, as follows:

EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
             .channel(NioDatagramChannel.class)
             .option(ChannelOption.SO_BROADCAST, true)
             .handler(new UDPServerHandler());

            b.bind(PORT).sync().channel().closeFuture().await();

EventLoopGroup can remain unchanged.

Because the bottom layer of netty is based on Socket for communication, and the bottom layer of socket is based on TCP or UDP protocol, so the http or http2 or SOCKS protocol implemented in netty is carried out on the basis of socket connection.

So for http or http2, the channel is still NioServerSocketChannel.

It can be seen that only the UDP protocol differs. The same UDT protocol based on the UDP protocol is also different, and its use is as follows:

 final NioEventLoopGroup acceptGroup = new NioEventLoopGroup(1, acceptFactory, NioUdtProvider.BYTE_PROVIDER);
        final NioEventLoopGroup connectGroup = new NioEventLoopGroup(1, connectFactory, NioUdtProvider.BYTE_PROVIDER);

 final ServerBootstrap boot = new ServerBootstrap();
            boot.group(acceptGroup, connectGroup)
                    .channelFactory(NioUdtProvider.BYTE_ACCEPTOR)
                    .option(ChannelOption.SO_BACKLOG, 10)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer<UdtChannel>() {
                        @Override
                        public void initChannel(final UdtChannel ch) {
                            ch.pipeline().addLast(
                                    new LoggingHandler(LogLevel.INFO),
                                    new UDTEchoServerHandler());
                        }
                    });

UDT uses BYTE_PROVIDER and BYTE_ACCEPTOR provided in NioUdtProvider as selector and channelFactory respectively.

other channels

In addition to NioSocketChannel, there are EpollChannel, KQueueChannel, SctpChannel, these channels are used for different protocols. We will introduce it in detail in subsequent articles.

Summarize

Channel and selector are the basis of netty. On this basis, netty can be extended and adapted to all protocols based on tcp and udp, which can be said to be very powerful.

This article has been included in http://www.flydean.com/39-netty-selecto…r-channelfactory/

The most popular interpretation, the most profound dry goods, the most concise tutorials, and many tricks you don't know are waiting for you to discover!

Welcome to pay attention to my official account: "Program those things", understand technology, understand you better!


flydean
890 声望433 粉丝

欢迎访问我的个人网站:www.flydean.com