preparestatement方法用多次_如何用java 5分钟实现一个最简单的mysql代理服务器?
用java8基于vert.x3 快速實(shí)現(xiàn)一個(gè)最簡(jiǎn)單的mysql代理服務(wù)器,只需要5分鐘時(shí)間。
什么是mysql 代理?
mysql代理是介于client端和mysql服務(wù)端中間層服務(wù),如下圖所示:
這里寫(xiě)圖片描述
為什么要使用代理?
大部人都知道使用代理的好處,畢竟,隨著互聯(lián)網(wǎng)越來(lái)越普及,互聯(lián)網(wǎng)系統(tǒng)越來(lái)越龐大、復(fù)雜,性能要求越來(lái)越高,為了讓整個(gè)系統(tǒng)具有更好的擴(kuò)展性、更高的性能、解藕等多種特性,在數(shù)據(jù)庫(kù)層面引入代理層是目前互聯(lián)網(wǎng)系統(tǒng)常見(jiàn)的架構(gòu)設(shè)計(jì)方案。總的來(lái)說(shuō),在數(shù)據(jù)庫(kù)層面引入代理會(huì)帶來(lái)以下好處:
- 將不同類型的請(qǐng)求分發(fā)的不同的server以此實(shí)現(xiàn)讀寫(xiě)分離、負(fù)載均衡。
- 來(lái)自不同客戶端的請(qǐng)求分發(fā)到不同的server實(shí)現(xiàn)后端多租戶數(shù)據(jù)庫(kù)服務(wù),當(dāng)然,類似的原理還可以實(shí)現(xiàn)分庫(kù)分表、一個(gè)請(qǐng)求寫(xiě)到多個(gè)server或者不同的源端如消息隊(duì)列。
- 監(jiān)控統(tǒng)計(jì)客戶端的請(qǐng)求情況,請(qǐng)求分布統(tǒng)計(jì)、請(qǐng)求類型等,以此來(lái)優(yōu)化數(shù)據(jù)庫(kù)的使用。
- 總之,可以實(shí)現(xiàn)你想要的諸多功能。
如何用java快速實(shí)現(xiàn)一個(gè)最簡(jiǎn)單的代理呢?
首先,準(zhǔn)備開(kāi)發(fā)工具套件,我們并不會(huì)引入過(guò)多工具包,僅僅需要:
- java8
- vert.x 3
如果你是用maven做為項(xiàng)目管理工具,請(qǐng)將vert.x 3引入:
io.vertx vertx-core 3.3.2代碼實(shí)現(xiàn):
package com.maxleap.mysqlproxy;import io.vertx.core.AbstractVerticle;import io.vertx.core.Vertx;import io.vertx.core.logging.Logger;import io.vertx.core.logging.LoggerFactory;import io.vertx.core.net.NetClient;import io.vertx.core.net.NetServer;import io.vertx.core.net.NetSocket;/** * @author sneaky * @since 1.0.0 */public class MysqlProxyServer { 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();//創(chuàng)建代理服務(wù)器 NetClient netClient = vertx.createNetClient();//創(chuàng)建連接mysql客戶端 netServer.connectHandler(socket -> netClient.connect(port, mysqlHost, result -> { //響應(yīng)來(lái)自客戶端的連接請(qǐng)求,成功之后,在建立一個(gè)與目標(biāo)mysql服務(wù)器的連接 if (result.succeeded()) { //與目標(biāo)mysql服務(wù)器成功連接連接之后,創(chuàng)造一個(gè)MysqlProxyConnection對(duì)象,并執(zhí)行代理方法 new MysqlProxyConnection(socket, result.result()).proxy(); } else { logger.error(result.cause().getMessage(), result.cause()); socket.close(); } })).listen(port, listenResult -> {//代理服務(wù)器的監(jiān)聽(tīng)端口 if (listenResult.succeeded()) { //成功啟動(dòng)代理服務(wù)器 logger.info("Mysql proxy server start up."); } else { //啟動(dòng)代理服務(wù)器失敗 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() { //當(dāng)代理與mysql服務(wù)器連接關(guān)閉時(shí),關(guān)閉client與代理的連接 serverSocket.closeHandler(v -> clientSocket.close()); //反之亦然 clientSocket.closeHandler(v -> serverSocket.close()); //不管那端的連接出現(xiàn)異常時(shí),關(guān)閉兩端的連接 serverSocket.exceptionHandler(e -> { logger.error(e.getMessage(), e); close(); }); clientSocket.exceptionHandler(e -> { logger.error(e.getMessage(), e); close(); }); //當(dāng)收到來(lái)自客戶端的數(shù)據(jù)包時(shí),轉(zhuǎn)發(fā)給mysql目標(biāo)服務(wù)器 clientSocket.handler(buffer -> serverSocket.write(buffer)); //當(dāng)收到來(lái)自mysql目標(biāo)服務(wù)器的數(shù)據(jù)包時(shí),轉(zhuǎn)發(fā)給客戶端 serverSocket.handler(buffer -> clientSocket.write(buffer)); } private void close() { clientSocket.close(); serverSocket.close(); } }}測(cè)試一下
try { Class.forName(name);//指定連接類型 Connection conn = DriverManager.getConnection(url, user, password);//url為代理服務(wù)器的地址 PreparedStatement pst = conn.prepareStatement("select * from test;");//準(zhǔn)備執(zhí)行語(yǔ)句 ResultSet resultSet = pst.executeQuery(); while (resultSet.next()) { System.out.println(resultSet.getLong(1) + ": " + resultSet.getString(2)); }} catch (Exception e) { e.printStackTrace();}不出意外,一切運(yùn)行正常,恭喜你,你已經(jīng)實(shí)現(xiàn)了一個(gè)最簡(jiǎn)單的mysql代理服務(wù)器。
寫(xiě)在最后
vert.x是基于jvm、事件驅(qū)動(dòng)、異步IO、響應(yīng)式編程工具套件,底層網(wǎng)絡(luò)通信使用netty4,是一個(gè)非常優(yōu)秀的java開(kāi)發(fā)框架(當(dāng)然,嚴(yán)格意義上講是工具套件),使用vert.x可以快速構(gòu)建的各種應(yīng)用,并且天生分布式,集群管理。
另外,實(shí)現(xiàn)一個(gè)代理服務(wù)器遠(yuǎn)沒(méi)有如此簡(jiǎn)單,根據(jù)需求的不同,復(fù)雜度也不同,這里僅僅是展示實(shí)現(xiàn)代理的核心代碼,實(shí)現(xiàn)了最基本的代理功能,當(dāng)然了,一切復(fù)雜的需求都可以基于上面的代碼進(jìn)行改造擴(kuò)展。
總結(jié)
以上是生活随笔為你收集整理的preparestatement方法用多次_如何用java 5分钟实现一个最简单的mysql代理服务器?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: ieee期刊_IEEE期刊的双栏排版中的
- 下一篇: mysql 先排序再去重_有人说先学会三