1
0
mirror of https://github.com/apache/dubbo.git synced 2024-10-23 07:04:37 +08:00

[3.0] improve unit test efficiency (#8877)

* speed up maven building, disable update snapshot, remove unnecessary repositories

* reduce shutdown wait time

* update maven version to fix build error such as "java.lang.IllegalStateException: Entry [id:..][route:{s}->...][state:null] has not been leased from this pool", see
 https://issues.apache.org/jira/browse/HTTPCORE-634 (httpcore 4.4.14)

* add shutdown timeout for netty4

* fix scope model

* read server shutdown wait time before destroy

* Add shutdown timeout for triple protocol

* Improve register center of tests

* set shutdown wait time as attribute of ProtocolServer

* Fix reconnect and close

* fix closePromise
This commit is contained in:
Gong Dewei 2021-09-23 17:38:19 +08:00 committed by GitHub
parent 9b83abdc7b
commit eba466e0c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 212 additions and 105 deletions

View File

@ -1 +1 @@
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.6.1/apache-maven-3.6.1-bin.zip
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip

View File

@ -0,0 +1,2 @@
dubbo.application.enable-file-cache=false
dubbo.service.shutdown.wait=200

View File

@ -98,6 +98,11 @@ public class ConfigurationUtils {
}
// FIXME
/**
* Server shutdown wait timeout mills
* @return
*/
@SuppressWarnings("deprecation")
public static int getServerShutdownTimeout(ScopeModel scopeModel) {
int timeout = DEFAULT_SERVER_SHUTDOWN_TIMEOUT;

View File

@ -16,3 +16,5 @@
#
dubbo=properties
dubbo.application.enable-file-cache=false
dubbo.service.shutdown.wait=200

View File

@ -0,0 +1,2 @@
dubbo.application.enable-file-cache=false
dubbo.service.shutdown.wait=200

View File

@ -51,8 +51,10 @@ import org.apache.dubbo.rpc.model.ModuleModel;
import org.apache.dubbo.rpc.model.ServiceMetadata;
import org.apache.dubbo.rpc.protocol.injvm.InjvmInvoker;
import org.apache.dubbo.rpc.protocol.injvm.InjvmProtocol;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@ -119,25 +121,28 @@ import static org.apache.dubbo.rpc.Constants.SCOPE_LOCAL;
import static org.apache.dubbo.rpc.Constants.SCOPE_REMOTE;
public class ReferenceConfigTest {
private String zkUrl1;
private String zkUrl2;
private String registryUrl1;
private RegistryCenter registryCenter1;
private RegistryCenter registryCenter2;
private static String zkUrl1;
private static String zkUrl2;
private static String registryUrl1;
private static RegistryCenter registryCenter1;
private static RegistryCenter registryCenter2;
@BeforeEach
public void setUp() throws Exception {
DubboBootstrap.reset();
@BeforeAll
public static void beforeAll() {
int zkServerPort1 = NetUtils.getAvailablePort(NetUtils.getRandomPort());
registryCenter1 = new ZookeeperSingleRegistryCenter(zkServerPort1);
registryCenter1.startup();
int zkServerPort2 = NetUtils.getAvailablePort(NetUtils.getRandomPort());
registryCenter2 = new ZookeeperSingleRegistryCenter(zkServerPort2);
registryCenter2.startup();
this.zkUrl1 = "zookeeper://localhost:" + zkServerPort1;
this.zkUrl2 = "zookeeper://localhost:" + zkServerPort2;
this.registryUrl1 = "registry://localhost:" + zkServerPort1 + "?registry=zookeeper";
zkUrl1 = "zookeeper://localhost:" + zkServerPort1;
zkUrl2 = "zookeeper://localhost:" + zkServerPort2;
registryUrl1 = "registry://localhost:" + zkServerPort1 + "?registry=zookeeper";
}
@BeforeEach
public void setUp() throws Exception {
DubboBootstrap.reset();
ApplicationModel.defaultModel().getApplicationConfigManager();
DubboBootstrap.getInstance();
}
@ -145,10 +150,13 @@ public class ReferenceConfigTest {
@AfterEach
public void tearDown() throws IOException {
DubboBootstrap.reset();
Mockito.framework().clearInlineMocks();
}
@AfterAll
public static void afterAll() {
registryCenter1.shutdown();
registryCenter2.shutdown();
Mockito.framework().clearInlineMocks();
}
/**

View File

@ -34,8 +34,10 @@ import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.apache.dubbo.rpc.model.FrameworkServiceRepository;
import org.apache.dubbo.rpc.model.ModuleModel;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -49,8 +51,8 @@ public class DubboBootstrapMultiInstanceTest {
private static RegistryConfig registryConfig;
@BeforeEach
public void setup() {
@BeforeAll
public static void beforeAll() {
registryCenter = new ZookeeperSingleRegistryCenter(NetUtils.getAvailablePort());
registryCenter.startup();
RegistryCenter.Instance instance = registryCenter.getRegistryCenterInstance().get(0);
@ -58,6 +60,15 @@ public class DubboBootstrapMultiInstanceTest {
instance.getType(),
instance.getHostname(),
instance.getPort()));
}
@AfterAll
public static void afterAll() {
registryCenter.shutdown();
}
@BeforeEach
public void setup() {
}
@ -65,7 +76,6 @@ public class DubboBootstrapMultiInstanceTest {
public void afterEach() {
SysProps.clear();
DubboBootstrap.reset();
registryCenter.shutdown();
}
@Test

View File

@ -1,3 +1,4 @@
dubbo.override.key2=properties
dubbo.override.protocol=properties
dubbo.application.enable-file-cache=false
dubbo.service.shutdown.wait=200

View File

@ -1 +1,2 @@
dubbo.application.enable-file-cache=false
dubbo.service.shutdown.wait=200

View File

@ -0,0 +1,2 @@
dubbo.application.enable-file-cache=false
dubbo.service.shutdown.wait=200

View File

@ -0,0 +1,2 @@
dubbo.application.enable-file-cache=false
dubbo.service.shutdown.wait=200

View File

@ -0,0 +1,2 @@
dubbo.application.enable-file-cache=false
dubbo.service.shutdown.wait=200

View File

@ -0,0 +1,2 @@
dubbo.application.enable-file-cache=false
dubbo.service.shutdown.wait=200

View File

@ -0,0 +1,2 @@
dubbo.application.enable-file-cache=false
dubbo.service.shutdown.wait=200

View File

@ -0,0 +1,2 @@
dubbo.application.enable-file-cache=false
dubbo.service.shutdown.wait=200

View File

@ -126,12 +126,22 @@ public class Connection extends AbstractReferenceCounted implements ReferenceCou
}
return null;
}
this.connectingPromise = new DefaultPromise<>(GlobalEventExecutor.INSTANCE);
createConnectingPromise();
final ChannelFuture promise = bootstrap.connect();
promise.addListener(this.connectionListener);
return promise;
}
private void createConnectingPromise() {
if (this.connectingPromise == null) {
synchronized (this) {
if (this.connectingPromise == null) {
this.connectingPromise = new DefaultPromise<>(GlobalEventExecutor.INSTANCE);
}
}
}
}
public Channel getChannel() {
return channel.get();
}
@ -151,9 +161,18 @@ public class Connection extends AbstractReferenceCounted implements ReferenceCou
}
public void onConnected(Channel channel) {
if (isClosed()) {
channel.close();
if (logger.isDebugEnabled()) {
logger.debug(String.format("%s is closed, ignoring connected event", this));
}
return;
}
this.channel.set(channel);
// This indicates that the connection is available.
this.connectingPromise.setSuccess(CONNECTED_OBJECT);
if (this.connectingPromise != null) {
this.connectingPromise.setSuccess(CONNECTED_OBJECT);
}
channel.attr(CONNECTION).set(this);
if (logger.isDebugEnabled()) {
logger.debug(String.format("%s connected ", this));
@ -173,7 +192,14 @@ public class Connection extends AbstractReferenceCounted implements ReferenceCou
connect();
}
}
this.createConnectingPromise();
this.connectingPromise.awaitUninterruptibly(this.connectTimeout, TimeUnit.MILLISECONDS);
// destroy connectingPromise after used
synchronized (this) {
this.connectingPromise = null;
}
channel = getChannel();
return channel != null && channel.isActive();
}
@ -197,21 +223,21 @@ public class Connection extends AbstractReferenceCounted implements ReferenceCou
@Override
protected void deallocate() {
if (closed.compareAndSet(false, true)) {
close();
}
closePromise.setSuccess(null);
close();
}
public void close() {
if (logger.isDebugEnabled()) {
logger.debug(String.format("Connection:%s freed ", this));
if (closed.compareAndSet(false, true)) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("Connection:%s freed ", this));
}
final Channel current = this.channel.get();
if (current != null) {
current.close();
}
this.channel.set(null);
closePromise.setSuccess(null);
}
final Channel current = this.channel.get();
if (current != null) {
current.close();
}
this.channel.set(null);
}
@Override

View File

@ -28,7 +28,9 @@ import io.netty.channel.group.ChannelGroupFuture;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.concurrent.Future;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.ConfigurationUtils;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
@ -54,6 +56,7 @@ public class PortUnificationServer {
private static final Logger logger = LoggerFactory.getLogger(PortUnificationServer.class);
private final List<WireProtocol> protocols;
private final URL url;
private final int serverShutdownTimeoutMills;
/**
* netty server bootstrap.
*/
@ -71,6 +74,8 @@ public class PortUnificationServer {
// the handler will be wrapped: MultiMessageHandler->HeartbeatHandler->handler
this.url = ExecutorUtil.setThreadName(url, "DubboPUServerHandler");
this.protocols = ExtensionLoader.getExtensionLoader(WireProtocol.class).getActivateExtension(url, new String[0]);
// read config before destroy
serverShutdownTimeoutMills = ConfigurationUtils.getServerShutdownTimeout(getUrl().getOrDefaultModuleModel());
}
public URL getUrl() {
@ -149,7 +154,7 @@ public class PortUnificationServer {
if (channelGroup != null) {
ChannelGroupFuture closeFuture = channelGroup.close();
closeFuture.await(15000);
closeFuture.await(serverShutdownTimeoutMills);
}
final long cost = System.currentTimeMillis() - st;
logger.info("Port unification server closed. cost:" + cost);
@ -163,8 +168,12 @@ public class PortUnificationServer {
try {
if (bootstrap != null) {
bossGroup.shutdownGracefully().syncUninterruptibly();
workerGroup.shutdownGracefully().syncUninterruptibly();
long timeout = serverShutdownTimeoutMills;
long quietPeriod = Math.min(2000L, timeout);
Future<?> bossGroupShutdownFuture = bossGroup.shutdownGracefully(quietPeriod, timeout, MILLISECONDS);
Future<?> workerGroupShutdownFuture = workerGroup.shutdownGracefully(quietPeriod, timeout, MILLISECONDS);
bossGroupShutdownFuture.syncUninterruptibly();
workerGroupShutdownFuture.syncUninterruptibly();
}
} catch (Throwable e) {
logger.warn(e.getMessage(), e);

View File

@ -0,0 +1,2 @@
dubbo.application.enable-file-cache=false
dubbo.service.shutdown.wait=200

View File

@ -26,4 +26,10 @@
<level value="WARN"/>
<appender-ref ref="CONSOLE"/>
</root>
</log4j:configuration>
<!-- <logger name="org.apache.dubbo.remoting" additivity="false">-->
<!-- <priority value ="debug"/>-->
<!-- <appender-ref ref="CONSOLE"/>-->
<!-- </logger>-->
</log4j:configuration>

View File

@ -16,7 +16,17 @@
*/
package org.apache.dubbo.remoting.transport.netty4;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.concurrent.Future;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.ConfigurationUtils;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.ExecutorUtil;
@ -31,15 +41,6 @@ import org.apache.dubbo.remoting.transport.AbstractServer;
import org.apache.dubbo.remoting.transport.dispatcher.ChannelHandlers;
import org.apache.dubbo.remoting.utils.UrlUtils;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.timeout.IdleStateHandler;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Collection;
@ -73,11 +74,15 @@ public class NettyServer extends AbstractServer implements RemotingServer {
private EventLoopGroup bossGroup;
private EventLoopGroup workerGroup;
private final int serverShutdownTimeoutMills;
public NettyServer(URL url, ChannelHandler handler) throws RemotingException {
// you can customize name and type of client thread pool by THREAD_NAME_KEY and THREADPOOL_KEY in CommonConstants.
// the handler will be wrapped: MultiMessageHandler->HeartbeatHandler->handler
super(ExecutorUtil.setThreadName(url, SERVER_THREAD_POOL_NAME), ChannelHandlers.wrap(handler, url));
// read config before destroy
serverShutdownTimeoutMills = ConfigurationUtils.getServerShutdownTimeout(getUrl().getOrDefaultModuleModel());
}
/**
@ -154,8 +159,12 @@ public class NettyServer extends AbstractServer implements RemotingServer {
}
try {
if (bootstrap != null) {
bossGroup.shutdownGracefully().syncUninterruptibly();
workerGroup.shutdownGracefully().syncUninterruptibly();
long timeout = serverShutdownTimeoutMills;
long quietPeriod = Math.min(2000L, timeout);
Future<?> bossGroupShutdownFuture = bossGroup.shutdownGracefully(quietPeriod, timeout, MILLISECONDS);
Future<?> workerGroupShutdownFuture = workerGroup.shutdownGracefully(quietPeriod, timeout, MILLISECONDS);
bossGroupShutdownFuture.syncUninterruptibly();
workerGroupShutdownFuture.syncUninterruptibly();
}
} catch (Throwable e) {
logger.warn(e.getMessage(), e);

View File

@ -0,0 +1,2 @@
dubbo.application.enable-file-cache=false
dubbo.service.shutdown.wait=200

View File

@ -19,6 +19,8 @@ package org.apache.dubbo.rpc;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.remoting.RemotingServer;
import java.util.Map;
/**
* Distinct from {@link RemotingServer}, each protocol holds one or more ProtocolServers(the number usually decides by port numbers),
* while each ProtocolServer holds zero or one RemotingServer.
@ -44,4 +46,6 @@ public interface ProtocolServer {
}
void close();
Map<String, Object> getAttributes();
}

View File

@ -17,6 +17,7 @@
package org.apache.dubbo.rpc.protocol;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.ConfigurationUtils;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.ConcurrentHashSet;
@ -38,6 +39,9 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_SERVER_SHUTDOWN_TIMEOUT;
import static org.apache.dubbo.common.constants.CommonConstants.SHUTDOWN_WAIT_KEY;
/**
* abstract ProtocolSupport.
*/
@ -76,6 +80,16 @@ public abstract class AbstractProtocol implements Protocol, ScopeModelAware {
return Collections.unmodifiableList(new ArrayList<>(serverMap.values()));
}
protected void loadServerProperties(ProtocolServer server) {
// read and hold config before destroy
int serverShutdownTimeout = ConfigurationUtils.getServerShutdownTimeout(server.getUrl().getScopeModel());
server.getAttributes().put(SHUTDOWN_WAIT_KEY, serverShutdownTimeout);
}
protected int getServerShutdownTimeout(ProtocolServer server) {
return (int) server.getAttributes().getOrDefault(SHUTDOWN_WAIT_KEY, DEFAULT_SERVER_SHUTDOWN_TIMEOUT);
}
@Override
public void destroy() {
for (Invoker<?> invoker : invokers) {

View File

@ -37,7 +37,9 @@ import org.apache.dubbo.rpc.RpcException;
import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY;
@ -168,6 +170,7 @@ public abstract class AbstractProxyProtocol extends AbstractProtocol {
private RemotingServer server;
private String address;
private Map<String, Object> attributes = new ConcurrentHashMap<>();
public ProxyProtocolServer(RemotingServer server) {
this.server = server;
@ -197,6 +200,11 @@ public abstract class AbstractProxyProtocol extends AbstractProtocol {
public void close() {
server.close();
}
@Override
public Map<String, Object> getAttributes() {
return attributes;
}
}
protected abstract class RemotingServerAdapter implements RemotingServer {

View File

@ -0,0 +1,2 @@
dubbo.application.enable-file-cache=false
dubbo.service.shutdown.wait=200

View File

@ -365,7 +365,9 @@ public class DubboProtocol extends AbstractProtocol {
}
}
return new DubboProtocolServer(server);
DubboProtocolServer protocolServer = new DubboProtocolServer(server);
loadServerProperties(protocolServer);
return protocolServer;
}
private void optimizeSerialization(URL url) throws RpcException {
@ -593,8 +595,11 @@ public class DubboProtocol extends AbstractProtocol {
*/
private ReferenceCountExchangeClient buildReferenceCountExchangeClient(URL url) {
ExchangeClient exchangeClient = initClient(url);
return new ReferenceCountExchangeClient(exchangeClient);
ReferenceCountExchangeClient client = new ReferenceCountExchangeClient(exchangeClient);
// read configs
int shutdownTimeout = ConfigurationUtils.getServerShutdownTimeout(url.getScopeModel());
client.setShutdownWaitTime(shutdownTimeout);
return client;
}
/**
@ -653,7 +658,7 @@ public class DubboProtocol extends AbstractProtocol {
logger.info("Closing dubbo server: " + server.getLocalAddress());
}
server.close(ConfigurationUtils.getServerShutdownTimeout(server.getUrl().getScopeModel()));
server.close(getServerShutdownTimeout(protocolServer));
} catch (Throwable t) {
logger.warn("Close dubbo server [" + server.getLocalAddress()+ "] failed: " + t.getMessage(), t);
@ -693,7 +698,7 @@ public class DubboProtocol extends AbstractProtocol {
logger.info("Close dubbo connect: " + client.getLocalAddress() + "-->" + client.getRemoteAddress());
}
client.close(ConfigurationUtils.getServerShutdownTimeout(client.getUrl().getScopeModel()));
client.close(client.getShutdownWaitTime());
// TODO
/*

View File

@ -21,10 +21,14 @@ import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.remoting.RemotingServer;
import org.apache.dubbo.rpc.ProtocolServer;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class DubboProtocolServer implements ProtocolServer {
private RemotingServer server;
private String address;
private Map<String, Object> attributes = new ConcurrentHashMap<>();
public DubboProtocolServer(RemotingServer server) {
this.server = server;
@ -59,4 +63,9 @@ public class DubboProtocolServer implements ProtocolServer {
public void close() {
server.close();
}
@Override
public Map<String, Object> getAttributes() {
return attributes;
}
}

View File

@ -31,6 +31,7 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicInteger;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_SERVER_SHUTDOWN_TIMEOUT;
import static org.apache.dubbo.remoting.Constants.SEND_RECONNECT_KEY;
import static org.apache.dubbo.rpc.protocol.dubbo.Constants.LAZY_CONNECT_INITIAL_STATE_KEY;
@ -46,6 +47,7 @@ final class ReferenceCountExchangeClient implements ExchangeClient {
private final AtomicInteger disconnectCount = new AtomicInteger(0);
private final Integer warningPeriod = 50;
private ExchangeClient client;
private int shutdownWaitTime = DEFAULT_SERVER_SHUTDOWN_TIMEOUT;
public ReferenceCountExchangeClient(ExchangeClient client) {
this.client = client;
@ -230,5 +232,13 @@ final class ReferenceCountExchangeClient implements ExchangeClient {
public int getCount(){
return referenceCount.get();
}
public int getShutdownWaitTime() {
return shutdownWaitTime;
}
public void setShutdownWaitTime(int shutdownWaitTime) {
this.shutdownWaitTime = shutdownWaitTime;
}
}

View File

@ -0,0 +1,2 @@
dubbo.application.enable-file-cache=false
dubbo.service.shutdown.wait=200

View File

@ -18,9 +18,11 @@ package org.apache.dubbo.rpc.protocol.rest;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.StringUtils;
import org.jboss.resteasy.spi.ResteasyDeployment;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN;
import static org.apache.dubbo.rpc.protocol.rest.Constants.EXTENSION_KEY;
@ -28,6 +30,8 @@ public abstract class BaseRestProtocolServer implements RestProtocolServer {
private String address;
private Map<String, Object> attributes = new ConcurrentHashMap<>();
@Override
public void start(URL url) {
getDeployment().getMediaTypeMappings().put("json", "application/json");
@ -66,6 +70,11 @@ public abstract class BaseRestProtocolServer implements RestProtocolServer {
this.address = address;
}
@Override
public Map<String, Object> getAttributes() {
return attributes;
}
protected void loadProviders(String value) {
for (String clazz : COMMA_SPLIT_PATTERN.split(value)) {
if (!StringUtils.isEmpty(clazz)) {

View File

@ -79,61 +79,8 @@
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-milestone</id>
<name>Spring Milestone</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-snapshot</id>
<name>Spring Snapshot</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>rabbit-milestone</id>
<name>Rabbit Milestone</name>
<url>https://dl.bintray.com/rabbitmq/maven-milestones</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestone</id>
<name>Spring Milestone</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-snapshot</id>
<name>Spring Snapshot</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<profiles>
<profile>
<!-- Spring Boot 2.0 -->
<id>spring-boot-2.0</id>
@ -213,4 +160,4 @@
</plugin>
</plugins>
</build>
</project>
</project>