Cleanup and throw exception if bind failed (#12987)

This commit is contained in:
Albumen Kevin 2023-09-01 13:03:33 +08:00 committed by GitHub
parent 8d9817f8af
commit 0bfd54cea4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 99 additions and 55 deletions

View File

@ -96,7 +96,9 @@ public class QosProtocolWrapper implements Protocol, ScopeModelAware {
return protocol.getServers();
}
private void startQosServer(URL url) {
private void startQosServer(URL url) throws RpcException {
boolean qosCheck = url.getParameter(QOS_CHECK, false);
try {
if (!hasStarted.compareAndSet(false, true)) {
return;
@ -132,9 +134,8 @@ public class QosProtocolWrapper implements Protocol, ScopeModelAware {
} catch (Throwable throwable) {
logger.warn(QOS_FAILED_START_SERVER, "", "", "Fail to start qos server: ", throwable);
boolean qosCheck = url.getParameter(QOS_CHECK, false);
if (qosCheck) {
throw new IllegalStateException("Fail to start qos server: " + throwable.getMessage(), throwable);
throw new RpcException(throwable);
}
}
}

View File

@ -0,0 +1,26 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.qos.server;
/**
* Indicate that if Qos Start failed
*/
public class QosBindException extends RuntimeException {
public QosBindException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -35,8 +35,6 @@ import io.netty.util.concurrent.DefaultThreadFactory;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.QOS_FAILED_START_SERVER;
/**
* A server serves for both telnet access and http access
* <ul>
@ -105,13 +103,13 @@ public class Server {
@Override
protected void initChannel(Channel ch) throws Exception {
ch.pipeline().addLast(new QosProcessHandler(frameworkModel,
QosConfiguration.builder()
.welcome(welcome)
.acceptForeignIp(acceptForeignIp)
.acceptForeignIpWhitelist(acceptForeignIpWhitelist)
.anonymousAccessPermissionLevel(anonymousAccessPermissionLevel)
.anonymousAllowCommands(anonymousAllowCommands)
.build()
QosConfiguration.builder()
.welcome(welcome)
.acceptForeignIp(acceptForeignIp)
.acceptForeignIpWhitelist(acceptForeignIpWhitelist)
.anonymousAccessPermissionLevel(anonymousAccessPermissionLevel)
.anonymousAllowCommands(anonymousAllowCommands)
.build()
));
}
});
@ -124,8 +122,7 @@ public class Server {
logger.info("qos-server bind localhost:" + port);
} catch (Throwable throwable) {
logger.error(QOS_FAILED_START_SERVER, "", "", "qos-server can not bind localhost:" + port, throwable);
throw throwable;
throw new QosBindException("qos-server can not bind localhost:" + port, throwable);
}
}

View File

@ -127,6 +127,10 @@ public interface Constants {
String BIND_PORT_KEY = "bind.port";
String BIND_RETRY_TIMES = "bind.retry.times";
String BIND_RETRY_INTERVAL = "bind.retry.interval";
String SENT_KEY = "sent";
String DISPATCHER_KEY = "dispatcher";

View File

@ -97,14 +97,14 @@ public class NettyPortUnificationServer extends AbstractPortUnificationServer {
}
}
public void bind() {
public void bind() throws Throwable {
if (channel == null) {
doOpen();
}
}
@Override
public void doOpen() {
public void doOpen() throws Throwable {
bootstrap = new ServerBootstrap();
bossGroup = NettyEventLoopFactory.eventLoopGroup(1, EVENT_LOOP_BOSS_POOL_NAME);
@ -138,9 +138,31 @@ public class NettyPortUnificationServer extends AbstractPortUnificationServer {
bindIp = ANYHOST_VALUE;
}
InetSocketAddress bindAddress = new InetSocketAddress(bindIp, bindPort);
ChannelFuture channelFuture = bootstrap.bind(bindAddress);
channelFuture.syncUninterruptibly();
channel = channelFuture.channel();
try {
ChannelFuture channelFuture = bootstrap.bind(bindAddress);
channelFuture.syncUninterruptibly();
channel = channelFuture.channel();
} catch (Throwable t) {
closeBootstrap();
throw t;
}
}
private void closeBootstrap() {
try {
if (bootstrap != null) {
long timeout = ConfigurationUtils.reCalShutdownTime(serverShutdownTimeoutMills);
long quietPeriod = Math.min(2000L, timeout);
Future<?> bossGroupShutdownFuture = bossGroup.shutdownGracefully(quietPeriod,
timeout, MILLISECONDS);
Future<?> workerGroupShutdownFuture = workerGroup.shutdownGracefully(quietPeriod,
timeout, MILLISECONDS);
bossGroupShutdownFuture.awaitUninterruptibly(timeout, MILLISECONDS);
workerGroupShutdownFuture.awaitUninterruptibly(timeout, MILLISECONDS);
}
} catch (Throwable e) {
logger.warn(TRANSPORT_FAILED_CLOSE, "", "", e.getMessage(), e);
}
}
@Override
@ -176,20 +198,7 @@ public class NettyPortUnificationServer extends AbstractPortUnificationServer {
protocol.close();
}
try {
if (bootstrap != null) {
long timeout = ConfigurationUtils.reCalShutdownTime(serverShutdownTimeoutMills);
long quietPeriod = Math.min(2000L, timeout);
Future<?> bossGroupShutdownFuture = bossGroup.shutdownGracefully(quietPeriod,
timeout, MILLISECONDS);
Future<?> workerGroupShutdownFuture = workerGroup.shutdownGracefully(quietPeriod,
timeout, MILLISECONDS);
bossGroupShutdownFuture.awaitUninterruptibly(timeout, MILLISECONDS);
workerGroupShutdownFuture.awaitUninterruptibly(timeout, MILLISECONDS);
}
} catch (Throwable e) {
logger.warn(TRANSPORT_FAILED_CLOSE, "", "", e.getMessage(), e);
}
closeBootstrap();
}
@Override

View File

@ -105,10 +105,14 @@ public class NettyServer extends AbstractServer {
initServerBootstrap(nettyServerHandler);
// bind
ChannelFuture channelFuture = bootstrap.bind(getBindAddress());
channelFuture.syncUninterruptibly();
channel = channelFuture.channel();
try {
ChannelFuture channelFuture = bootstrap.bind(getBindAddress());
channelFuture.syncUninterruptibly();
channel = channelFuture.channel();
} catch (Throwable t) {
closeBootstrap();
throw t;
}
}
protected EventLoopGroup createBossGroup() {
@ -172,6 +176,17 @@ public class NettyServer extends AbstractServer {
} catch (Throwable e) {
logger.warn(TRANSPORT_FAILED_CLOSE, "", "", e.getMessage(), e);
}
closeBootstrap();
try {
if (channels != null) {
channels.clear();
}
} catch (Throwable e) {
logger.warn(TRANSPORT_FAILED_CLOSE, "", "", e.getMessage(), e);
}
}
private void closeBootstrap() {
try {
if (bootstrap != null) {
long timeout = ConfigurationUtils.reCalShutdownTime(serverShutdownTimeoutMills);
@ -184,13 +199,6 @@ public class NettyServer extends AbstractServer {
} catch (Throwable e) {
logger.warn(TRANSPORT_FAILED_CLOSE, "", "", e.getMessage(), e);
}
try {
if (channels != null) {
channels.clear();
}
} catch (Throwable e) {
logger.warn(TRANSPORT_FAILED_CLOSE, "", "", e.getMessage(), e);
}
}
@Override

View File

@ -21,13 +21,13 @@ import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.utils.NetUtils;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.context.ConfigManager;
import org.apache.dubbo.remoting.RemotingException;
import org.apache.dubbo.remoting.api.connection.AbstractConnectionClient;
import org.apache.dubbo.remoting.api.connection.ConnectionManager;
import org.apache.dubbo.remoting.api.connection.MultiplexProtocolConnectionManager;
import org.apache.dubbo.remoting.api.pu.DefaultPuHandler;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ModuleModel;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
@ -50,7 +50,7 @@ public class ConnectionTest {
private static ConnectionManager connectionManager;
@BeforeAll
public static void init() throws RemotingException {
public static void init() throws Throwable {
int port = NetUtils.getAvailablePort();
url = URL.valueOf("empty://127.0.0.1:" + port + "?foo=bar");
ApplicationModel applicationModel = ApplicationModel.defaultModel();
@ -123,7 +123,7 @@ public class ConnectionTest {
}
@Test
void connectSyncTest() throws RemotingException {
void connectSyncTest() throws Throwable {
int port = NetUtils.getAvailablePort();
URL url = URL.valueOf("empty://127.0.0.1:" + port + "?foo=bar");
NettyPortUnificationServer nettyPortUnificationServer = new NettyPortUnificationServer(url, new DefaultPuHandler());

View File

@ -21,11 +21,10 @@ import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.utils.NetUtils;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.context.ConfigManager;
import org.apache.dubbo.remoting.RemotingException;
import org.apache.dubbo.remoting.api.pu.DefaultPuHandler;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ModuleModel;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@ -34,7 +33,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.EXECUTOR_MANAGEM
class PortUnificationServerTest {
@Test
void testBind() throws RemotingException {
void testBind() throws Throwable {
int port = NetUtils.getAvailablePort();
URL url = URL.valueOf("empty://127.0.0.1:" + port + "?foo=bar");
ApplicationModel applicationModel = ApplicationModel.defaultModel();

View File

@ -21,15 +21,14 @@ import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.context.ConfigManager;
import org.apache.dubbo.remoting.RemotingException;
import org.apache.dubbo.remoting.api.connection.AbstractConnectionClient;
import org.apache.dubbo.remoting.api.connection.ConnectionManager;
import org.apache.dubbo.remoting.api.connection.MultiplexProtocolConnectionManager;
import org.apache.dubbo.remoting.api.pu.DefaultPuHandler;
import org.apache.dubbo.remoting.transport.netty4.NettyPortUnificationServer;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ModuleModel;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
@ -52,7 +51,7 @@ public class MultiplexProtocolConnectionManagerTest {
private static ConnectionManager connectionManager;
@BeforeAll
public static void init() throws RemotingException {
public static void init() throws Throwable {
ApplicationModel applicationModel = ApplicationModel.defaultModel();
ApplicationConfig applicationConfig = new ApplicationConfig("provider-app");
applicationConfig.setExecutorManagementMode(EXECUTOR_MANAGEMENT_MODE_DEFAULT);
@ -95,7 +94,7 @@ public class MultiplexProtocolConnectionManagerTest {
}
@Test
public void testForEachConnection() throws RemotingException {
public void testForEachConnection() throws Throwable {
DefaultPuHandler handler = new DefaultPuHandler();
NettyPortUnificationServer server2 = new NettyPortUnificationServer(url2, handler);

View File

@ -31,6 +31,7 @@ import org.apache.dubbo.remoting.transport.netty4.NettyConnectionClient;
import org.apache.dubbo.remoting.transport.netty4.NettyPortUnificationServer;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ModuleModel;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
@ -51,7 +52,7 @@ public class SingleProtocolConnectionManagerTest {
private static ConnectionManager connectionManager;
@BeforeAll
public static void init() throws RemotingException {
public static void init() throws Throwable {
int port = NetUtils.getAvailablePort();
url = URL.valueOf("empty://127.0.0.1:" + port + "?foo=bar");
ApplicationModel applicationModel = ApplicationModel.defaultModel();