springboot+dubbo2.6.0关闭QOS服务

本文是基于dubbo2.6.0讲解,每个版本不一样,较新的版本可按照官方配置进行配置,如有疑惑最好自行查看相关源码(本文也记录了查看源码的方式)。

官方提供QOS服务详解和相关配置:http://dubbo.apache.org/zh-cn/docs/user/references/qos.html

dubbo中的QOS服务

拿到dubbo服务ip,通过telnet命令远程连接到你的dubbo服务(中间没有任何认证),然后可通过offline和online命令上下线你所有的服务,这种命令的安全性不言而喻,但是它的初衷是方便开发者治理服务,比如某个服务有严重错误,开发者可以直接下线该服务而不影响其它服务(offline支持正则匹配)。从2.6.4/2.7.0以前,QOS服务的远程连接默认是开启的,最新版的没有这种问题。

解决方法

  • 直接关闭QOS整个服务
  • 关闭远程连接

官方提供的相关配置命令:

dubbo.application.qosEnable=true
dubbo.application.qosPort=33333
dubbo.application.qosAcceptForeignIp=false

但是由于对于dubbo2.6.0不管怎么设置都没用,后面查看源码发现可以通过下面方式进行配置和关闭服务

//引入qos服务类
import com.alibaba.dubbo.qos.server.Server;

public class App {
	public static void main(String[] args) {
		//配置dubbo.qos.port端口
        System.setProperty(Constants.QOS_PORT,"33333");
        //配置dubbo.qos.accept.foreign.ip是否关闭远程连接
		System.setProperty(Constants.ACCEPT_FOREIGN_IP,"false");
		SpringApplication.run(App.class, args);

		//关闭QOS服务
		Server.getInstance().stop();

	}
}

源码分析

QOS服务类

public class Server {

    private static final Logger logger = LoggerFactory.getLogger(Server.class);
    private static final Server INSTANCE = new Server();

    public static final Server getInstance() {
        return INSTANCE;
    }

    private int port = Integer.parseInt(ConfigUtils.getProperty(Constants.QOS_PORT, Constants.DEFAULT_PORT + ""));

    public int getPort() {
        return port;
    }

    private EventLoopGroup boss;

    private EventLoopGroup worker;

    private Server() {
        this.welcome = DubboLogo.dubbo;
    }

    private String welcome;

    private AtomicBoolean hasStarted = new AtomicBoolean();

    /**
     * welcome message
     */
    public void setWelcome(String welcome) {
        this.welcome = welcome;
    }

    /**
     * start server, bind port
     */
    public void start() throws Throwable {
        if (!hasStarted.compareAndSet(false, true)) {
            return;
        }
        boss = new NioEventLoopGroup(0, new DefaultThreadFactory("qos-boss", true));
        worker = new NioEventLoopGroup(0, new DefaultThreadFactory("qos-worker", true));
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(boss, worker);
        serverBootstrap.channel(NioServerSocketChannel.class);
        serverBootstrap.childOption(ChannelOption.TCP_NODELAY, true);
        serverBootstrap.childOption(ChannelOption.SO_REUSEADDR, true);
        serverBootstrap.childHandler(new ChannelInitializer() {

            @Override
            protected void initChannel(Channel ch) throws Exception {
                ch.pipeline().addLast(new QosProcessHandler(welcome));
            }
        });
        try {
            serverBootstrap.bind(port).sync();
            logger.info("qos-server bind localhost:" + port);
        } catch (Throwable throwable) {
            logger.error("qos-server can not bind localhost:" + port, throwable);
            throw throwable;
        }
    }

    /**
     * close server
     */
    public void stop() {
        logger.info("qos-server stopped.");
        if (boss != null) {
            boss.shutdownGracefully();
        }
        if (worker != null) {
            worker.shutdownGracefully();
        }
    }
}

QOS服务类是通过调用start方法启动的,但是我们也发现它也提供了一个stop方法,所以只要拿到这个类的对象就可以调用stop方法关闭。可以看到Server类使用了单例提供了getInstance方法获取对象,故可以在服务开始后,通过getInstance方法获取对象调用stop方法关闭QOS服务。

QOS相关参数及配置方式

public interface Constants {

    int DEFAULT_PORT = 22222;
    // system property for specifying qos port
    String QOS_PORT = "dubbo.qos.port";
    String BR_STR = "\r\n";
    String CLOSE = "close!";

    // system property for whether to accept foreign IP to connect or not
    String ACCEPT_FOREIGN_IP = "dubbo.qos.accept.foreign.ip";
}

此类的常量中只有 dubbo.qos.port和dubbo.qos.accept.foreign.ip,故可以了解到dubbo2.6.0中还没有提供参数关闭QOS服务的。其次可以从服务类Server中看到port是通过ConfigUtils.getProperty方法获取的,进入该工具类可以发现是通过System.getProperty(key)获取参数值的,所以application.yml文件的配置没用,只能配置在application.properties文件中,或者在启动类中手动System.setProperty(Constants.ACCEPT_FOREIGN_IP,"false")赋值进去。

你可能感兴趣的:(java)