基于Netty的长连接客户端

来源:互联网 发布:什么叫seo营销 编辑:程序博客网 时间:2024/05/21 14:52

客户端工厂

import java.util.List;/** * 接口描述:长连接客户端工厂类 *  * @author ruipeng.lrp * @since 2017/11/26 *  **/public interface ClientFactory {    // ------------ 查询和新增 ------------    Client get(final RemotingUrl url) throws Exception;    // ------------ 查询 ------------    List<Client> getAllClients() throws Exception;    // ------------ 删除 ------------    void remove(final RemotingUrl url) throws Exception;}
import java.util.ArrayList;import java.util.List;import java.util.concurrent.Callable;import java.util.concurrent.TimeUnit;import com.google.common.cache.Cache;import com.google.common.cache.CacheBuilder;import com.google.common.cache.RemovalListener;import com.google.common.cache.RemovalNotification;public abstract class AbstractClientFactory implements ClientFactory {    // 长连接缓存,一个域名对应一个长连接    private final Cache<RemotingUrl, Client> cacherClients = CacheBuilder.newBuilder()//            .maximumSize(65535) // 单机长连接上限,超过上限采用LRU淘汰            .expireAfterAccess(27, TimeUnit.MINUTES)// 连接长时间没有读写则删除            .removalListener(new RemovalListener<RemotingUrl, Client>() {                @Override                public void onRemoval(RemovalNotification<RemotingUrl, Client> notification) {                    // 关闭连接                }            })//            .build();    protected abstract Client createClient(RemotingUrl domain) throws Exception;    @Override    public Client get(RemotingUrl url) throws Exception {        Client client = cacherClients.get(url, new Callable<Client>() {            @Override            public Client call() throws Exception {                Client client = createClient(url);                if (null != client) {                    client.startHeartBeat();                }                return client;            }        });        return client;    }    @Override    public List<Client> getAllClients() throws Exception {        List<Client> result = new ArrayList<Client>((int) cacherClients.size());        result.addAll(cacherClients.asMap().values());        return result;    }    @Override    public void remove(RemotingUrl url) throws Exception {        cacherClients.invalidate(url);    }}
import java.net.InetSocketAddress;import io.netty.bootstrap.Bootstrap;import io.netty.buffer.ByteBufAllocator;import io.netty.buffer.PooledByteBufAllocator;import io.netty.buffer.UnpooledByteBufAllocator;import io.netty.channel.Channel;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelOption;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.nio.NioSocketChannel;import io.netty.util.internal.SystemPropertyUtil;public class NettyClientFactory extends AbstractClientFactory {    /**     * 共享IO线程     **/    public static final NioEventLoopGroup workerGroup = new NioEventLoopGroup();    public static final ByteBufAllocator byteBufAllocator;    static {        workerGroup.setIoRatio(SystemPropertyUtil.getInt("ioratio", 100));        if (SystemPropertyUtil.getBoolean("bytebuf.pool", false)) {            byteBufAllocator = PooledByteBufAllocator.DEFAULT;        } else {            byteBufAllocator = UnpooledByteBufAllocator.DEFAULT;        }    }    @Override    protected Client createClient(RemotingUrl url) throws Exception {        final Bootstrap bootstrap = new Bootstrap();        bootstrap.group(NettyClientFactory.workerGroup)//                .option(ChannelOption.TCP_NODELAY, true)//                .option(ChannelOption.SO_REUSEADDR, true)//                .option(ChannelOption.SO_KEEPALIVE, false)//                .option(ChannelOption.ALLOCATOR, NettyClientFactory.byteBufAllocator)//                .channel(NioSocketChannel.class)//                .handler(new ChannelInitializer<NioSocketChannel>(){                    @Override                    protected void initChannel(NioSocketChannel ch) throws Exception {                        ch.pipeline().addLast("decoder", null)//                            .addLast("encoder", null)//                            .addLast("handler", null);                    }                });        int connectTimeout = url.getConnectionTimeout();        if (connectTimeout < 1000) {            bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000);        } else {            bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectTimeout);        }        String targetIP = url.getDomain();        int targetPort = url.getPort();        ChannelFuture future = bootstrap.connect(new InetSocketAddress(targetIP, targetPort));        if (future.awaitUninterruptibly(connectTimeout) && future.isSuccess() && future.channel().isActive()) {            Channel channel = future.channel();            Client client = new NettyClient(url, channel);            return client;        } else {            future.cancel(true);            future.channel().close();            throw new Exception(targetIP);        }    }}

客户端

public interface Client {    //启动心跳检测    public void startHeartBeat() throws Exception;    //发送请求    public void sendRequest(Object msg) throws Exception;    public String getDomain();    public boolean isConnected();}
import java.util.concurrent.TimeUnit;import io.netty.channel.Channel;import io.netty.util.HashedWheelTimer;import io.netty.util.Timeout;import io.netty.util.Timer;import io.netty.util.TimerTask;public class NettyClient implements Client {    /**     * 共享定时器     **/    public static final Timer timer = new HashedWheelTimer();    public static final int DEFAULT_HEARTBEAT_PERIOD = 3000;    private Channel ch;    private RemotingUrl url;    public NettyClient(RemotingUrl url, Channel ch) {        this.ch = ch;        this.url = url;    }    @Override    public void startHeartBeat() throws Exception {        timer.newTimeout(new TimerTask() {            @Override            public void run(Timeout timeout) throws Exception {                try {                    // 发送心跳请求                } catch (Throwable t) {                } finally {                    timer.newTimeout(this, DEFAULT_HEARTBEAT_PERIOD, TimeUnit.SECONDS);                }            }        }, DEFAULT_HEARTBEAT_PERIOD, TimeUnit.SECONDS);    }    @Override    public String getDomain() {        return url.getDomain();    }    @Override    public boolean isConnected() {        return ch.isActive();    }    @Override    public void sendRequest(Object msg) throws Exception {        ch.writeAndFlush(msg);    }}

URL信息

public class RemotingUrl {    /**     * 域名     **/    private String domain;    /**     * 端口     **/    private int port;    /**     * 超时时间,默认3s     **/    private int connectionTimeout = 3000;    public String getDomain() {        return domain;    }    public void setDomain(String domain) {        this.domain = domain;    }    public int getPort() {        return port;    }    public void setPort(int port) {        this.port = port;    }    public int getConnectionTimeout() {        return connectionTimeout;    }    public void setConnectionTimeout(int connectionTimeout) {        this.connectionTimeout = connectionTimeout;    }    @Override    public int hashCode() {        final int prime = 31;        int result = 1;        result = prime * result + ((domain == null) ? 0 : domain.hashCode());        return result;    }    @Override    public boolean equals(Object obj) {        return this.domain.equalsIgnoreCase((String) obj);    }}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 五年级孩子太叛逆怎么办 二年级话唠孩子怎么办 家有老人带孩子怎么办 不会看孩子。孩子一哭就害怕怎么办 孩子不老实爱动怎么办 4周孩子脾气大怎么办 老公脾气暴躁爱骂人怎么办? 当妈妈了脾气不好怎么办 父亲很坏不顾家很会赌钱怎么办 妈妈骂我很难听怎么办 父母管的太严怎么办 2岁宝宝哭闹不止怎么办 8岁儿童叛逆期怎么办 两岁宝宝叛逆期怎么办 4个月小孩哭怎么办 2个月孩子爱哭怎么办 小孩挑衅大人被大人打怎么办 在学校犯了错怎么办 孩子在学校爱捣乱怎么办 小孩老是在学校捣乱怎么办 孩子不听话每天会发火怎么办 孩子不听话控制不住发火怎么办 儿子不听话我总会发火怎么办 小孩好动精力不集中怎么办 孩子好动精力不集中怎么办 一岁半宝宝咳嗽半个月了怎么办 6岁儿童上课调皮怎么办 小孩挨揍后精神失控怎么办 孩子不听话把我胃气疼了怎么办 因为孩子不听话夫妻经常吵架怎么办 11岁儿子不听话了怎么办 二十岁的儿子还不听话怎么办 幼儿园小班幼儿不听老师的话怎么办 幼师对待不听话的孩子该怎么办 2岁宝宝不吃饭只喝奶怎么办 孩子哭着喊妈妈不睡觉怎么办 孩子晚上不睡觉一直哭怎么办 孩子不睡觉还哭怎么办 孩子晚上不睡觉老哭怎么办? 4岁宝宝叛逆期怎么办 驾考紧张脚抖怎么办