Based on Netty network framework and Springboot framework.
The target is let easy to build a network cluster server. Minimize the use of third-party dependency libraries as much as possible.
Supports message forwarding between internal and external networks
Supports distributed transactions server-message-queue
module
server-framework
: The core module
of the framework, which provides the basic configuration of the framework, and
the configuration of the network protocol, the message forwarding, and the message processing.
server-database
: The database
module of the framework, use Mybatis
and MySQL
to implement the database
operation. If you need to use a MySQL database, you can use it.that is optional
.
server-cache
: The cache
module of the framework, use Redisson
to implement the Redis
cache operation, and
use Caffeine
to implement the local cache operation. If you need to use a caching module, you can use
it.that is optional
.
server-permission
: The permission
module of the framework, Use Spring AOP
and annotations to control interface
permissions. The HTTP protocol uses the request header entrainment JWT method,
the permissions
field in the UserSession
is used for TCP and UDP and WebSocket. If you need
to use a permission
module, you can use it.that is optional
.
server-access-control
: The access control
module of the framework, Use Spring AOP
and annotations
and Guava library
to limit the rate of the interface. You can limit the rate of interfaces uniformly or based on
user granularity, and configure IP blacklists and whitelists. If you need to use a access control
module, you can
use it.that is optional
.
server-message-queue
: The message queue
module of the framework, Use the server-framework
module to develop a
message queue module that supports message subscription and message push. If you need to use a message queue
module, you can use it.that is optional
.
gateway-server
、hall-server
、room-server
: These are three sample nodes
of the cluster, and you can refer to
their configurations to get your own cluster
mvn clean install
server-framework
dependency in your project
<dependency>
<groupId>com.hbsoo</groupId>
<artifactId>server-framework</artifactId>
<version>1.0.0</version>
</dependency>
server-framework
Configuration to your Springboot project application.yml
file.hbsoo:
server:
tcpHeader: THBS # TCP header
udpHeader: UHBS # UDP header
id: 1000 #Current node id
threadPoolSize:
insideClient: 5 #inside client side business thread pool size
insideServer: 5 #inside server side business thread pool size
outsideServer: 5 #outside server side business thread pool size
outsideServer:
enable: true #Whether to enable the outside server
port: 5555 #Outside server port
protocol: "TCP,UDP,WEBSOCKET,HTTP,MQTT" #Outside server protocol,Which protocols to use.
insideServers:
- host: 192.168.1.104
port: 6000
type: gateway #Inside server type,that's namespace customized
clientSize: 1 #Connect to inside server client size
weight: 10 #Inside server weight
id: 1000 #Inside server id; At least one id in the list of insideServers is associated with the current node id
- host: 192.168.1.104
port: 6003
type: hall
clientSize: 1
id: 2000
- host: 192.168.1.104
port: 6006
type: room
clientSize: 1
id: 3000
@OutsideMessageHandler(value = 0, uri = "/index", protocol = Protocol.HTTP)
public class IndexAction extends HttpServerMessageDispatcher {
@Override
public void handle(ChannelHandlerContext ctx, HttpPacket httpPacket) {
List<String> genealogies = new ArrayList<>();
genealogies.add("zun");
responseJson(httpPacket, genealogies);
forward2InsideServerUseSender(
NetworkPacket.Builder.withDefaultHeader()
.msgType(100).writeStr(genealogies.toString()),
"hall",
"",3);
QueueMessageSender.publish("hall", "test", genealogies.toString());
}
}
@OutsideMessageHandler(value = 100, protocol = Protocol.WEBSOCKET)
public class LoginChatRoomAction extends ServerMessageDispatcher {
private static final Logger logger = LoggerFactory.getLogger(LoginChatRoomAction.class);
@Override
public void handle(ChannelHandlerContext ctx, NetworkPacket.Decoder decoder) {
String username = decoder.readStr();
String channelId = decoder.readStr();
int userId = Math.abs(username.hashCode());
logger.info("login chat room username:{},channelId:{},userId:{}", username, channelId, userId);
//notify client login success
NetworkPacket.Builder builder = decoder.toBuilder().writeInt(userId).writeStr(Permission.USER.name());
builder.sendTcpTo(ctx.channel());
//forward to room server
forward2insideServerUseSender(builder, "room", userId);
}
@Override
public Object threadKey(ChannelHandlerContext ctx, NetworkPacket.Decoder decoder) {
return decoder.readStr();
}
}
@MessageListener(topic = "test", serverType = "hall")
public class MessageQueueTest implements TransactionQueueMessageSenderHandler {
private static final Logger logger = LoggerFactory.getLogger(MessageQueueTest.class);
@Override
public void handleCallback(CallbackMessage callbackMessage) {
logger.info("callbackMessage = {}", callbackMessage);
}
@Override
public int consumerSize() {
return 2;
}
@Override
public boolean handle(Long msgId, String objJson) {
logger.debug("handle msgId = {},objJson = {}", msgId, objJson);
return true;
}
@Override
public boolean rollback(Long msgId, String objJson) {
logger.debug("rollback msgId = {},objJson = {}", msgId, objJson);
return true;
}
}
@MessageListener(topic = "test", serverType = "hall")
public class MessageQueueTest implements TransactionQueueMessageHandler {
private static final Logger logger = LoggerFactory.getLogger(MessageQueueTest.class);
@Override
public boolean handle(Long msgId, String objJson) {
logger.debug("handle msgId = {},objJson = {}", msgId, objJson);
return false;
}
@Override
public boolean rollback(Long msgId, String objJson) {
logger.debug("rollback msgId = {},objJson = {}", msgId,objJson);
return false;
}
}
@OutsideMessageHandler(value = 0, uri = "/index", protocol = Protocol.HTTP)
public class IndexAction extends HttpServerMessageDispatcher {
@Override
public void handle(ChannelHandlerContext ctx, HttpPacket httpPacket) {
List<String> genealogies = new ArrayList<>();
genealogies.add("zun");
responseJson(httpPacket, genealogies);
// publish transaction queue message
QueueMessageSender.publish("hall", "test", genealogies.toString());
}
}
-Xms512m -Xmx512m -XX:+HeapDumpOnOutOfMemoryError
@PermissionAuth(permission = {})
//@AccessLimit(userRateSize = 1, globalRateSize = 2)
@OutsideMessageHandler(value = 0, uri = "/index", protocol = Protocol.HTTP)
public class IndexAction extends HttpServerMessageDispatcher {
@Autowired
private IGenealogyService genealogyService;
@Override
public void handle(ChannelHandlerContext ctx, HttpPackage httpPacket) {
final List<Genealogy> genealogies = genealogyService.listAll();
//System.out.println("genealogies = " + genealogies);
responseJson(ctx, httpPacket, genealogies);
forward2insideServerUseSender(
NetworkPacket.Builder.withDefaultHeader()
.msgType(100).writeStr(genealogies.toString()),
"hall",
"",3);
QueueMessageSender.publish("hall", "test", genealogies.toString());
}
@Override
public Object threadKey(ChannelHandlerContext ctx, NetworkPacket.Decoder decoder) {
return null;
}
}
jmeter
, and the configuration is as follows调试资源泄露,启动时添加:-Xms12m -Xmx12m -Dio.netty.leakDetection.level=paranoid