private static final Logger logger = LoggerFactory.getLogger(MysqlProxyServer.class)
public static void main(String[] args) {
Vertx.vertx().deployVerticle(new MysqlProxyServerVerticle())
}
public static class MysqlProxyServerVerticle extends AbstractVerticle {
private final int port = 3306
private final String mysqlHost = "10.10.0.6"
@Override
public void start() throws Exception {
NetServer netServer = vertx.createNetServer()//创建代理服务器
NetClient netClient = vertx.createNetClient()//创建连接mysql客户端
netServer.connectHandler(socket ->netClient.connect(port, mysqlHost, result ->{
//响应来自客户端的连接请求,成功之后,在建立一个与目标mysql服务器的连接
if (result.succeeded()) {
//与目标mysql服务器成功连接连接之后,创造一个MysqlProxyConnection对象,并执行代理方法
new MysqlProxyConnection(socket, result.result()).proxy()
} else {
logger.error(result.cause().getMessage(), result.cause())
socket.close()
}
})).listen(port, listenResult ->{//代理服务器的监听端口
if (listenResult.succeeded()) {
//成功启动代理服务器
logger.info("Mysql proxy server start up.")
} else {
//启动代理服务器失败
logger.error("Mysql proxy exit. because: " + listenResult.cause().getMessage(), listenResult.cause())
System.exit(1)
}
})
}
}
public static class MysqlProxyConnection {
private final NetSocket clientSocket
private final NetSocket serverSocket
public MysqlProxyConnection(NetSocket clientSocket, NetSocket serverSocket) {
this.clientSocket = clientSocket
this.serverSocket = serverSocket
}
private void proxy() {
//当代理与mysql服务器连接关闭时,关闭client与代理的连接
serverSocket.closeHandler(v ->clientSocket.close())
//反之亦然
clientSocket.closeHandler(v ->serverSocket.close())
//不管那端的连接出现异常时,关闭两端的连接
serverSocket.exceptionHandler(e ->{
logger.error(e.getMessage(), e)
close()
})
clientSocket.exceptionHandler(e ->{
logger.error(e.getMessage(), e)
close()
})
//当收到来自客户端的数据包时,转发给mysql目标服务器
clientSocket.handler(buffer ->serverSocket.write(buffer))
//当收到来自mysql目标服务器的数据包时,转发给客户端
serverSocket.handler(buffer ->clientSocket.write(buffer))
}
private void close() {
clientSocket.close()
serverSocket.close()
}
}
}
测试一下
try {
Class.forName(name)//指定连接类型
Connection conn = DriverManager.getConnection(url, user, password)//url为代理服务器的地址
PreparedStatement pst = conn.prepareStatement("select * from test")//准备执行语句
ResultSet resultSet = pst.executeQuery()
while (resultSet.next()) {
System.out.println(resultSet.getLong(1) + ": " + resultSet.getString(2))
}
} catch (Exception e) {
e.printStackTrace()
}
不同客户端的请求分发到不同的server实现后端多租户数据库服务,当然,类似的原理还可以实现分库分表、一个请求写到多个server或者不同的源端如消息队列。监控统计客户端的请求情况,请求分布统计、请求类型等,以此来优化数据库的使用。
总之,可以实现你想要的诸多功能。
做端口映射,在代理服务器上安装端口映射工具,例如PortMap。然后进行配置,把代理服务器的数据库端口映射到数据库服务器的数据库端口上。例如sqlserver是1433,oracle是1521.这样你访问代理服务器的数据库端口就等于访问数据库服务器的对应端口了。
为了更加安全,你还可以在客户端上设置使用非默认的端口访问代理服务器,然后在代理服务器上把你指定的端口映射到数据库服务器的数据库端口。比如在代理服务器上把8000端口映射到服务器1433端口,然后在客户端上配置为使用8000端口来访问数据库。这样你就可以通过代理服务器的8000端口来连接sqlserver数据库了。
另外,也可以不用代理服务器,直接用路由器做端口映射。
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)