Dubbo Qos端口占用問題


前幾天部署環境的時候,啟動幾個dubbo服務的時候,報了qos端口22222被占用。

貌似以前沒遇到過這個錯呢?

Qos是啥?

qos是dubbo的在線運維命令。

dubbo2.5.8新版本重構了telnet模塊,提供了新的telnet命令支持,新版本的telnet端口與dubbo協議的端口是不同的端口,默認為22222。可以對dubbo服務上/下線。

qos使用示例參考

QoS參數配置

可以通過如下方式進行配置

  • JVM系統屬性
  • dubbo.properties(在項目的src/main/resources目錄下添加dubbo.properties文件)
  • XML方式
  • Spring-boot自動裝配方式

其中,上述方式的優先順序為 JVM系統屬性 > dubbo.properties > XML/Spring-boot自動裝配方式。

dubbo 2.5.9 版本

如果要修改qos.port,可以通過如下方式達到目的:【類QosProtocolWrapper】

方法一:在spring-dubbo.xml中配置如下

<dubbo:application name="${project.name}">
    <!-- 關閉qos -->
    <dubbo:parameter key="qos.enable" value="false"/>
    <dubbo:parameter key="qos.port" value="22223"/>
</dubbo:application>

方法二:配置啟動參數

-Ddubbo.application.qos.port=33333 -Ddubbo.application.qos.enable=false

dubbo 2.6.0版本

取qos.port 是 【-Ddubbo.qos.port=33333】, 且無法通過配置關閉。

在com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper中有啟動qos

public class ProtocolListenerWrapper implements Protocol {
    static {
        try {
            Class serverClass = Protocol.class.getClassLoader().loadClass("com.alibaba.dubbo.qos.server.Server");
            Method serverGetInstanceMethod = serverClass.getMethod("getInstance");
            Object serverInstance = serverGetInstanceMethod.invoke(null);
            Method startMethod = serverClass.getMethod("start");
            // 這里沒有判斷配置,直接反射調用start了
            startMethod.invoke(serverInstance);
        }catch (Throwable throwable){

        }
    }
    // ...
}

不過可以在qos-server啟動之后,再關掉它。

// 關閉dubbo qos service
com.alibaba.dubbo.qos.server.Server.getInstance().stop();

在com.alibaba.dubbo.qos.server.Server中,有如下代碼段:

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 + ""));

    // ...略部分代碼...
    
   /**
     * 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<Channel>() {
            @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;
        }
    }
}

為什么以前沒遇到22222端口占用問題

之前依賴的是dubbo-2.5.9。在這個版本的QosProtocolWrapper中,可以看到:

private void startQosServer(URL url) {
        if (!hasStarted.compareAndSet(false, true)) {
            return;
        }

        try {
            boolean qosEnable = Boolean.parseBoolean(url.getParameter(QOS_ENABLE,"true"));
            if (!qosEnable) {
                return;
            }

            int port = Integer.parseInt(url.getParameter(QOS_PORT,"22222"));
            boolean acceptForeignIp = Boolean.parseBoolean(url.getParameter(ACCEPT_FOREIGN_IP,"true"));
            // 如果沒有netty4,下面這行代碼就會報錯
            Server server = com.alibaba.dubbo.qos.server.Server.getInstance();
            server.setPort(port);
            server.setAcceptForeignIp(acceptForeignIp);
            server.start();
        } catch (Throwable throwable) {
            // 這里錯誤直接吃掉了,沒往外部拋出來
            //throw new RpcException("fail to start qos server", throwable);
        }
    }

qos-server 需要netty4版本的支持,默認情況下dubbo不會引用netty4的依賴包。

而最近新加的功能確實間接引入了netty4。

關閉qos

對於2.5.9的版本,可以通過如下方式關閉qos

<dubbo:parameter key="qos.enable" value="false"/>

或者

-Ddubbo.application.qos.enable=false

對於2.6.0的版本,沒辦法通過配置關閉,只能是Server有stop方法了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM