Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion build/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
<!-- The version of spring-boot for 'spring-boot-dependencies' and 'spring-boot-maven-plugin' -->
<spring-boot.version>2.7.18</spring-boot.version>
<spring-framework-bom.version>5.3.39</spring-framework-bom.version>
<netty.version>4.2.15.Final</netty.version>

<!-- server side dependency-->
<kafka-appender.version>0.2.0-RC2</kafka-appender.version>
Expand Down Expand Up @@ -111,7 +112,7 @@
<maven-checkstyle-plugin.version>3.6.0</maven-checkstyle-plugin.version>
<spotless-maven-plugin.version>2.44.3</spotless-maven-plugin.version>
<palantirJavaFormat.version>2.38.0</palantirJavaFormat.version>
<maven-enforcer-plugin.version>3.0.0-M3</maven-enforcer-plugin.version>
<maven-enforcer-plugin.version>3.6.3</maven-enforcer-plugin.version>
<dependency-check-maven.version>12.1.0</dependency-check-maven.version>
<!-- Test -->
<maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version>
Expand Down Expand Up @@ -357,6 +358,11 @@
<requireMavenVersion>
<version>[3.6.0,)</version>
</requireMavenVersion>
<dependencyConvergence>
<includes>
<include>io.netty:*</include>
</includes>
</dependencyConvergence>
</rules>
</configuration>
</execution>
Expand Down
2 changes: 2 additions & 0 deletions changes/en-us/2.x.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Add changes here for all PR submitted to the 2.x branch.
### optimize:
- [[#8054](https://github.com/apache/incubator-seata/pull/8054)] console/namingserver modules: spring-boot upgrade to 4.0.6
- [[#8137](https://github.com/apache/incubator-seata/pull/8137)] server modules: spring-boot upgrade to 4.0.6
- [[#8209](https://github.com/apache/incubator-seata/pull/8209)] Upgrade Netty to 4.2.15.Final and migrate the transport event loop implementation


### security:
Expand Down Expand Up @@ -70,6 +71,7 @@ Thanks to these contributors for their code commits. Please report an unintended
- [Seol-JY](https://github.com/Seol-JY)
- [lhozy](https://github.com/lhozy)
- [Zhengcy05](https://github.com/Zhengcy05)
- [xjlgod](https://github.com/xjlgod)
- [neu-hsc](https://github.com/neu-hsc)
- [funky-eyes](https://github.com/funky-eyes)
- [pyshiweijia](https://github.com/pyshiweijia)
Expand Down
2 changes: 2 additions & 0 deletions changes/zh-cn/2.x.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
### optimize:
- [[#8054](https://github.com/apache/incubator-seata/pull/8054)] console/namingserver 模块: spring-boot 升级到 4.0.6
- [[#8137](https://github.com/apache/incubator-seata/pull/8137)] server 模块: spring-boot 升级到 4.0.6
- [[#8209](https://github.com/apache/incubator-seata/pull/8209)] 升级 Netty 至 4.2.15.Final,并适配传输层事件循环实现


### security:
Expand Down Expand Up @@ -71,6 +72,7 @@
- [Seol-JY](https://github.com/Seol-JY)
- [lhozy](https://github.com/lhozy)
- [Zhengcy05](https://github.com/Zhengcy05)
- [xjlgod](https://github.com/xjlgod)
- [neu-hsc](https://github.com/neu-hsc)
- [funky-eyes](https://github.com/funky-eyes)
- [pyshiweijia](https://github.com/pyshiweijia)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import io.etcd.jetcd.op.Op;
import io.etcd.jetcd.options.PutOption;
import io.etcd.jetcd.watch.WatchResponse;
import io.netty.util.internal.ConcurrentSet;
import org.apache.seata.common.exception.ShouldNeverHappenException;
import org.apache.seata.common.thread.NamedThreadFactory;
import org.apache.seata.common.util.CollectionUtils;
Expand Down Expand Up @@ -314,7 +313,7 @@ private static void initSeataConfig() {

EtcdListener etcdListener = new EtcdListener(etcdConfigKey, null);
CONFIG_LISTENERS_MAP
.computeIfAbsent(etcdConfigKey, key -> new ConcurrentSet<>())
.computeIfAbsent(etcdConfigKey, key -> ConcurrentHashMap.newKeySet())
.add(etcdListener);
etcdListener.onProcessEvent(new ConfigurationChangeEvent());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ public boolean detect(ByteBuf in) {
}

private boolean startsWith(ByteBuf buffer, String prefix) {
if (buffer.readableBytes() < prefix.length()) {
return false;
}

for (int i = 0; i < prefix.length(); i++) {
if (buffer.getByte(i) != (byte) prefix.charAt(i)) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.NettyRuntime;
import io.netty.util.internal.PlatformDependent;
import org.apache.commons.lang3.StringUtils;
import org.apache.seata.config.Configuration;
import org.apache.seata.config.ConfigurationFactory;
Expand Down Expand Up @@ -100,7 +99,7 @@ public class NettyBaseConfig {
WORKER_THREAD_SIZE = WorkThreadMode.Default.getValue();
}

boolean useEpoll = !PlatformDependent.isWindows() && !PlatformDependent.isOsx() && Epoll.isAvailable();
boolean useEpoll = Epoll.isAvailable();
SERVER_CHANNEL_CLAZZ = useEpoll ? EpollServerSocketChannel.class : NioServerSocketChannel.class;
CLIENT_CHANNEL_CLAZZ = useEpoll ? EpollSocketChannel.class : NioSocketChannel.class;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.apache.seata.core.rpc.netty;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelFuture;
Expand All @@ -27,17 +28,17 @@
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.MultiThreadIoEventLoopGroup;
import io.netty.channel.epoll.Epoll;
import io.netty.channel.epoll.EpollChannelOption;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollIoHandler;
import io.netty.channel.epoll.EpollMode;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.nio.NioIoHandler;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http2.Http2FrameCodecBuilder;
import io.netty.handler.codec.http2.Http2MultiplexHandler;
import io.netty.handler.codec.http2.Http2StreamChannelBootstrap;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.internal.PlatformDependent;
import org.apache.seata.common.exception.FrameworkException;
import org.apache.seata.common.thread.NamedThreadFactory;
import org.apache.seata.core.protocol.Protocol;
Expand Down Expand Up @@ -123,14 +124,15 @@ public void start() {
.option(ChannelOption.SO_KEEPALIVE, true)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, nettyClientConfig.getConnectTimeoutMillis())
.option(ChannelOption.SO_SNDBUF, nettyClientConfig.getClientSocketSndBufSize())
.option(ChannelOption.SO_RCVBUF, nettyClientConfig.getClientSocketRcvBufSize());
.option(ChannelOption.SO_RCVBUF, nettyClientConfig.getClientSocketRcvBufSize())
.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);

if (PlatformDependent.isWindows() || PlatformDependent.isOsx()) {
LOGGER.info("client run on MacOS/Windows, fallback to NIO.");
} else if (Epoll.isAvailable()) {
if (Epoll.isAvailable()) {
bootstrap
.option(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED)
.option(EpollChannelOption.TCP_QUICKACK, true);
} else if (LOGGER.isInfoEnabled()) {
LOGGER.info("Epoll is unavailable, fallback to NIO: {}", Epoll.unavailabilityCause());
}

bootstrap.handler(new ChannelInitializer<SocketChannel>() {
Expand Down Expand Up @@ -234,17 +236,19 @@ private EventLoopGroup getOrCreateEventLoopGroupWorker(int selectorThreadSizeThr

private EventLoopGroup createEventLoopGroupWorker(int selectorThreadSizeThreadSize) {
if (NettyServerConfig.enableEpoll()) {
return new EpollEventLoopGroup(
return new MultiThreadIoEventLoopGroup(
selectorThreadSizeThreadSize,
new NamedThreadFactory(
getThreadPrefix(this.nettyClientConfig.getClientSelectorThreadPrefix()),
selectorThreadSizeThreadSize));
selectorThreadSizeThreadSize),
EpollIoHandler.newFactory());
}

return new NioEventLoopGroup(
return new MultiThreadIoEventLoopGroup(
selectorThreadSizeThreadSize,
new NamedThreadFactory(
getThreadPrefix(this.nettyClientConfig.getClientSelectorThreadPrefix()),
selectorThreadSizeThreadSize));
selectorThreadSizeThreadSize),
NioIoHandler.newFactory());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@
package org.apache.seata.core.rpc.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.MultiThreadIoEventLoopGroup;
import io.netty.channel.WriteBufferWaterMark;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.epoll.EpollIoHandler;
import io.netty.channel.nio.NioIoHandler;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.timeout.IdleStateHandler;
import org.apache.seata.common.ConfigurationKeys;
Expand Down Expand Up @@ -69,27 +71,31 @@ public class NettyServerBootstrap implements RemotingBootstrap {
public NettyServerBootstrap(NettyServerConfig nettyServerConfig) {
this.nettyServerConfig = nettyServerConfig;
if (NettyServerConfig.enableEpoll()) {
this.eventLoopGroupBoss = new EpollEventLoopGroup(
this.eventLoopGroupBoss = new MultiThreadIoEventLoopGroup(
nettyServerConfig.getBossThreadSize(),
new NamedThreadFactory(
nettyServerConfig.getBossThreadPrefix(), nettyServerConfig.getBossThreadSize(), false));
this.eventLoopGroupWorker = new EpollEventLoopGroup(
nettyServerConfig.getBossThreadPrefix(), nettyServerConfig.getBossThreadSize(), false),
EpollIoHandler.newFactory());
this.eventLoopGroupWorker = new MultiThreadIoEventLoopGroup(
nettyServerConfig.getServerWorkerThreads(),
new NamedThreadFactory(
nettyServerConfig.getWorkerThreadPrefix(),
nettyServerConfig.getServerWorkerThreads(),
false));
false),
EpollIoHandler.newFactory());
} else {
this.eventLoopGroupBoss = new NioEventLoopGroup(
this.eventLoopGroupBoss = new MultiThreadIoEventLoopGroup(
nettyServerConfig.getBossThreadSize(),
new NamedThreadFactory(
nettyServerConfig.getBossThreadPrefix(), nettyServerConfig.getBossThreadSize(), false));
this.eventLoopGroupWorker = new NioEventLoopGroup(
nettyServerConfig.getBossThreadPrefix(), nettyServerConfig.getBossThreadSize(), false),
NioIoHandler.newFactory());
this.eventLoopGroupWorker = new MultiThreadIoEventLoopGroup(
nettyServerConfig.getServerWorkerThreads(),
new NamedThreadFactory(
nettyServerConfig.getWorkerThreadPrefix(),
nettyServerConfig.getServerWorkerThreads(),
false));
false),
NioIoHandler.newFactory());
}

if (nettyServerConfig.getServerListenPort() > 0) {
Expand Down Expand Up @@ -168,8 +174,10 @@ public void start() {
.channel(NettyServerConfig.SERVER_CHANNEL_CLAZZ)
.option(ChannelOption.SO_BACKLOG, nettyServerConfig.getSoBackLogSize())
.option(ChannelOption.SO_REUSEADDR, true)
.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childOption(ChannelOption.TCP_NODELAY, true)
.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
.childOption(ChannelOption.SO_SNDBUF, nettyServerConfig.getServerSocketSendBufSize())
.childOption(ChannelOption.SO_RCVBUF, nettyServerConfig.getServerSocketResvBufSize())
.childOption(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.MultiThreadIoEventLoopGroup;
import io.netty.channel.nio.NioIoHandler;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
Expand Down Expand Up @@ -73,8 +74,8 @@ class ChannelEventHandlerIntegrationTest {

@BeforeAll
static void setupClass() throws InterruptedException {
bossGroup = new NioEventLoopGroup(1);
workerGroup = new NioEventLoopGroup();
bossGroup = new MultiThreadIoEventLoopGroup(1, NioIoHandler.newFactory());
workerGroup = new MultiThreadIoEventLoopGroup(NioIoHandler.newFactory());

ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap
Expand Down Expand Up @@ -107,7 +108,7 @@ static void tearDownClass() {
void setUp() {
channelEventHandler = new ChannelEventHandler(mockRemotingClient);

clientGroup = new NioEventLoopGroup();
clientGroup = new MultiThreadIoEventLoopGroup(NioIoHandler.newFactory());
channelActiveLatch = new CountDownLatch(1);
channelInactiveLatch = new CountDownLatch(1);
exceptionCaughtLatch = new CountDownLatch(1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,20 @@
*/
package org.apache.seata.core.rpc.netty;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.MultiThreadIoEventLoopGroup;
import io.netty.channel.epoll.Epoll;
import io.netty.channel.epoll.EpollSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.internal.PlatformDependent;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.mockito.Mockito.when;
Expand Down Expand Up @@ -67,18 +72,35 @@ void testSharedEventLoopGroupDisabled() {
void testStartWithSharedEventLoopAndChannelSelection() {
when(nettyClientConfig.getEnableClientSharedEventLoop()).thenReturn(true);
when(nettyClientConfig.getClientChannelClazz()).thenAnswer(invocation -> {
if (PlatformDependent.isWindows() || PlatformDependent.isOsx()) {
return NioSocketChannel.class;
} else if (Epoll.isAvailable()) {
if (Epoll.isAvailable()) {
return EpollSocketChannel.class;
} else {
return NioSocketChannel.class;
}
return NioSocketChannel.class;
});

NettyClientBootstrap tmNettyClientBootstrap =
new NettyClientBootstrap(nettyClientConfig, NettyPoolKey.TransactionRole.TMROLE);
tmNettyClientBootstrap.start();

Assertions.assertSame(
PooledByteBufAllocator.DEFAULT,
getBootstrap(tmNettyClientBootstrap).config().options().get(ChannelOption.ALLOCATOR));
}

@Test
void testNioEventLoopGroup() {
when(nettyClientConfig.getEnableClientSharedEventLoop()).thenReturn(false);

try (MockedStatic<NettyServerConfig> mockedConfig =
Mockito.mockStatic(NettyServerConfig.class, Mockito.CALLS_REAL_METHODS)) {
mockedConfig.when(NettyServerConfig::enableEpoll).thenReturn(false);

NettyClientBootstrap bootstrap =
new NettyClientBootstrap(nettyClientConfig, NettyPoolKey.TransactionRole.TMROLE);
EventLoopGroup eventLoopGroup = getEventLoopGroupWorker(bootstrap);
Assertions.assertInstanceOf(MultiThreadIoEventLoopGroup.class, eventLoopGroup);
eventLoopGroup.shutdownGracefully().syncUninterruptibly();
}
}

private EventLoopGroup getEventLoopGroupWorker(NettyClientBootstrap bootstrap) {
Expand All @@ -90,4 +112,14 @@ private EventLoopGroup getEventLoopGroupWorker(NettyClientBootstrap bootstrap) {
throw new RuntimeException(e);
}
}

private Bootstrap getBootstrap(NettyClientBootstrap bootstrap) {
try {
java.lang.reflect.Field field = NettyClientBootstrap.class.getDeclaredField("bootstrap");
field.setAccessible(true);
return (Bootstrap) field.get(bootstrap);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Loading
Loading