All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fishlikewater.schedule.client.boot.ClientStart Maven / Gradle / Ivy

The newest version!
package com.fishlikewater.schedule.client.boot;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import com.fishlikewater.schedule.client.handler.ClientHandlerInitializer;
import com.fishlikewater.schedule.client.kit.ScheduleJobContext;
import com.fishlikewater.schedule.common.entity.MessageProbuf;
import com.fishlikewater.schedule.common.entity.TaskDetail;
import com.fishlikewater.schedule.common.kit.NamedThreadFactory;
import com.fishlikewater.schedule.common.kit.ScheduleKit;
import com.fishlikewater.schedule.common.kit.StringUtils;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollSocketChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.Getter;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.PreDestroy;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.function.Supplier;

/**
 * @version V1.0
 * @a1uthor zhangx
 * @mail [email protected]
 * @ClassName ClientStart
 * @Description
 * @date 2018年12月25日 14:21
 **/
@Slf4j
@Accessors(chain = true)
public class ClientStart {

    /**
     * 处理连接
     */
    private EventLoopGroup bossGroup;
    private Bootstrap clientstrap;

    @Getter
    private Channel channel;

    private static final ClientStart build = new ClientStart();

    public static ClientStart build() {
        return build;
    }

    private ConnectionListener connectionListener = new ConnectionListener();

    private int retryCount = 3;
    private String HOST;
    private int PORT;
    private String appName;

    private ClientStart() {

    }

    public ClientStart retryOne() {
        this.retryCount -= 1;
        return this;
    }

    /**
     * 首次初始化连接
     */
    public void run() {
        registerShutdownHook(() -> {
            this.stop();
            return null;

        });
        appName = ScheduleJobContext.getInstance().getAppName();
        bootstrapConfig();
        start();
    }

    /**
     * 设置连接服务地址
     */
    private void setPortAndHost() {
        String address = ScheduleJobContext.getInstance().getAddress();
        if (StringUtils.isEmpty(address)) {
            HOST = ScheduleJobContext.getInstance().getHOST();
            PORT = ScheduleJobContext.getInstance().getPORT();
        }else{
            String[] addArr = address.split(",");
            int anInt = RandomUtil.randomInt(addArr.length);
            String add = addArr[anInt];
            String[] portAndHost = add.split(":");
            HOST = portAndHost[0];
            PORT = Integer.valueOf(portAndHost[1]);
        }
    }

    /**
     * 连接配置初始化
     * @return
     */
    private Bootstrap bootstrapConfig() {
        if (clientstrap == null) clientstrap = new Bootstrap();
        clientstrap.option(ChannelOption.SO_REUSEADDR, true);
        clientstrap.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
        if (ScheduleKit.epollIsAvailable()) {//linux系统下使用epoll
            bossGroup = new EpollEventLoopGroup(0, new NamedThreadFactory("client-epoll-boss@"));
            clientstrap.group(bossGroup).channel(EpollSocketChannel.class);
        } else {
            bossGroup = new NioEventLoopGroup(0, new NamedThreadFactory("client-nio-boss@"));
            clientstrap.group(bossGroup).channel(NioSocketChannel.class);
        }
        clientstrap.handler(new ClientHandlerInitializer());
        return clientstrap;
    }

    /**
     * 开始连接
     */
    public void start() {
        setPortAndHost();
        clientstrap.remoteAddress(new InetSocketAddress(HOST, PORT));
        try {
            ChannelFuture future = clientstrap.connect().addListener(connectionListener).sync();
            this.channel = future.channel();
            log.info("start scheduleClient this port:{} and adress:{}", PORT, HOST);
            afterConnectionSuccessful(channel);
            future.channel().closeFuture().sync();
        } catch (Exception e) {
            log.error("start scheduleClient server fail");
        }
    }


    /**
     * 连接成功后的操作
     *
     * @param channel
     */
    private void afterConnectionSuccessful(Channel channel) {
        /** 发送首先发送验证信息*/
        MessageProbuf.Message validMessage = MessageProbuf.Message
                .newBuilder()
                .setBody("token")
                .setExtend(appName)
                .setType(MessageProbuf.MessageType.VALID)
                .build();
        channel.writeAndFlush(validMessage).addListener(f -> {
            if (f.isSuccess()) {
                sendScannerInfo(channel);
            }
        });
    }

    /**
     * 当前实例 任务信息
     */
    private void sendScannerInfo(Channel channel) {
        List allJobList = ScheduleJobContext.getInstance().getAllJobList();
        String jsonString = JSONObject.toJSONString(allJobList);
        MessageProbuf.Message initMessage = MessageProbuf.Message
                .newBuilder()
                .setExtend(appName)
                .setBody(jsonString)
                .setType(MessageProbuf.MessageType.INIT)
                .build();
        channel.writeAndFlush(initMessage);
    }

    /**
     * 关闭服务
     */
    @PreDestroy
    public void stop() {
        log.info("⬢ scheduleClient shutdown ...");
        try {
            if (this.bossGroup != null) {
                this.bossGroup.shutdownGracefully();
            }
            log.info("⬢ scheduleClient shutdown successful");
        } catch (Exception e) {
            log.error("scheduleClient shutdown error", e);
        }
    }

    private void registerShutdownHook(Supplier supplier) {
        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                try {
                    System.out.println("startting shutdown working......");
                    supplier.get();
                } catch (Throwable e) {
                    log.error("shutdownHook error", e);
                } finally {
                    log.info("jvm shutdown");
                }
            }

        });
    }

    public static void main(String[] args) {
        ScheduleJobContext.getInstance().setBasePath("com.fishlikewater");
        ClientStart.build().run();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy