Netty 连接池的使用姿势

本文通过实例展示了如何在Netty中使用连接池管理HTTP客户端连接。主要包括连接池接口及其实现类的介绍,并提供了一个完整的客户端连接池实现案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

netty版本 4.1.9.Final

一、类介绍

1.ChannelPool ,连接池接口

2.SimpleChannelPool,实现ChannelPool接口,简单的连接池实现

3.FixedChannelPool,继承SimpleChannelPool,有大小限制的连接池实现

4.ChannelPoolMap,管理host与连接池映射的接口

5.AbstractChannelPoolMap,抽象类,实现ChannelPoolMap接口

二、具体使用

我们以http协议的实现来使用连接池,直接上代码

1.ClientPool

public class ClientPool{

    //key为目标host,value为目标host的连接池
    public ChannelPoolMap<InetSocketAddress, FixedChannelPool> poolMap = null;


    public ClientPool(){
        init();
    }

    public void init(){
        EventLoopGroup group = new NioEventLoopGroup();
        final Bootstrap cb = new Bootstrap();

        cb.group(group).channel(NioSocketChannel.class);

        poolMap = new AbstractChannelPoolMap<InetSocketAddress, FixedChannelPool>() {
            @Override
            protected FixedChannelPool newPool(InetSocketAddress key) {
                return new FixedChannelPool(cb.remoteAddress(key), new ChannelPoolHandler() {
                    public void channelReleased(Channel ch) throws Exception {
                        System.out.println("22");
                    }

                    public void channelAcquired(Channel ch) throws Exception {
                        System.out.println("33");
                    }

                    public void channelCreated(Channel ch) throws Exception {
                        //可以在此绑定channel的handler
                        ch.pipeline().addLast(new HttpClientCodec())
                                .addLast(new HttpObjectAggregator(1024 * 1024))
                                .addLast(new HttpBackendHandler());
                    }
                },20);//单个host连接池大小
            }
        };

    }

    public void getHttpClient(InetSocketAddress address,final FullHttpRequest msg) {
        if(address == null){
            throw new RuntimeException("InetSocketAddress can not be null");
        }

        final FixedChannelPool pool = this.poolMap.get(address);

        Future<Channel> f = pool.acquire();

        future.addListener(new FutureListener<Channel>() {

            public void operationComplete(Future<Channel> f) {
                if (f.isSuccess()) {
                    Channel ch = f.getNow();
                    ChannelFuture lastWriteFuture = null;

                    lastWriteFuture = ch.writeAndFlush(msg);

                    // Wait until all messages are flushed before closing the channel.
                    if (lastWriteFuture != null) {

                        try {
                            lastWriteFuture.sync();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                    pool.release(ch);
                }
            }
        });
    }

}

2.HttpBackendHandler

public class HttpBackendHandler extends SimpleChannelInboundHandler<FullHttpResponse> {


    public HttpBackendHandler() {
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("Backend Handler is Active!");
        super.channelActive(ctx);
    }

    @Override
    public void channelRead0(final ChannelHandlerContext ctx, FullHttpResponse msg) throws Exception {
         //todo something
    }
    
    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        System.out.println("Backend Handler destroyed!");
    }
    
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        if (ctx.channel().isActive()) {
            ctx.channel().writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
        }
    }
}

3.使用

public class NettyHttpClientPoolTest {

    public static void main(String[] args){
        ClientPool pool = new ClientPool();
        InetSocketAddress address = new InetSocketAddress("127.0.0.1",8080;
        FullHttpRequest request = new DefaultFullHttpRequest(..);
        pool.sendMsg(address,request);
    }

}

代码有些未完善,需要自己完善一哈,本文主要是做下学习记录

转载于:https://my.oschina.net/jayhu/blog/863572

### 配置Netty连接池的方法 在Java Netty中,为了高效管理TCP/IP连接并优化资源利用,通常会采用连接池技术。这不仅有助于减少频繁建立新连接带来的开销,还能增强系统的稳定性和响应速度。 #### 使用`PoolingChannelGroup` 对于多路复用器(NIO),可以通过`PoolingChannelGroup`来实现简单的通道组管理功能,但这不是严格意义上的连接池[^1]。真正的连接池应该能够控制并发连接的数量、超时时间等属性,并支持重试机制。 #### 利用第三方库集成高级特性 由于Netty本身并不直接提供完整的HTTP/2或其他协议下的连接池解决方案,在实际项目里往往会选择引入像Apache HttpClient 5.x系列这样的外部依赖项来进行更复杂的场景适配。HttpClient内部实现了基于Netty的异步非阻塞I/O操作的支持,同时也具备强大的路由缓存能力,适用于大规模分布式环境下的微服务调用链路追踪需求。 不过如果只是单纯想要了解基础版的自定义连接池设计思路,则可以从以下几个方面入手: - **最大活跃连接数限制**:设置允许同时存在的活动链接上限; - **最小空闲连接数目**:维持一定数量处于等待状态但随时可用的对象实例集合; - **获取连接超时时长**:当请求方尝试从池子里拿取对象失败后的最长容忍期限; - **测试连接有效性策略**:定期验证闲置成员的有效性防止僵尸进程占用公共资源; 下面给出一段简易模拟代码片段作为参考说明: ```java import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingDeque; public class SimpleConnectionPool { private final BlockingQueue<SocketChannel> pool = new LinkedBlockingDeque<>(); public SocketChannel borrowObject() throws InterruptedException { return this.pool.take(); } public void addObject(SocketChannel channel){ try{ if (channel.isActive()){ this.pool.put(channel); }else{ // handle inactive channels... } }catch(InterruptedException e){ Thread.currentThread().interrupt(); // restore interrupted status } } // 初始化若干个预分配好的连接放入队列备用 static { EventLoopGroup group = new NioEventLoopGroup(); Bootstrap b = new Bootstrap() .group(group) .channel(NioSocketChannel.class); for(int i=0;i<INITIAL_POOL_SIZE;++i){ ChannelFuture f = b.connect(HOST, PORT).syncUninterruptibly(); ((SimpleConnectionPool)INSTANCE).addObject((SocketChannel)f.channel()); } Runtime.getRuntime().addShutdownHook(new Thread(() -> { group.shutdownGracefully(); })); } } ``` 这段程序展示了如何创建一个基本形式上的连接池类`SimpleConnectionPool`,其中包含了借入(`borrowObject`)和归还(`addObject`)两个主要接口函数。需要注意的是这里仅做逻辑示意用途,并未考虑全面异常情况处理等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值