Mysql和java套接字并行压力测试

Mysql和java套接字并行压力测试,java,mysql,multithreading,tcp,innodb,Java,Mysql,Multithreading,Tcp,Innodb,我有一个java tcp套接字应用程序。Tcp communicator解码GPS位置并将数据插入数据库,在插入之前,我们进行一些选择和更新,但我使用准备好的语句来完成。现在,TCP communicator的一个线程提供一个设备请求。创建线程后,我们立即从池中获得一个连接。解码GPS数据后,我们对每个数据执行多重选择、更新和插入。随着设备数量的增加,到Mysql数据库的并发连接数量也在增加。问题是,这是顺序测试,但在实际环境中,设备将并行出现。如何让mysql和java都处于近乎真实的压力状态

我有一个java tcp套接字应用程序。Tcp communicator解码GPS位置并将数据插入数据库,在插入之前,我们进行一些选择和更新,但我使用准备好的语句来完成。现在,TCP communicator的一个线程提供一个设备请求。创建线程后,我们立即从池中获得一个连接。解码GPS数据后,我们对每个数据执行多重选择、更新和插入。随着设备数量的增加,到Mysql数据库的并发连接数量也在增加。问题是,这是顺序测试,但在实际环境中,设备将并行出现。如何让mysql和java都处于近乎真实的压力状态,以找出mysql在第二个时间段可以插入多少个插件

 public class stress1 extends Thread {
    public static void main(String[] argv) {
        try {
            for (int i = 0; i < 5000; i++) {
            Socket socket = new Socket("192.168.2.102", 8000);
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(new InputStreamReader(
            socket.getInputStream()));
            out.println("$A12345,30061104075130528955N10024852E000068*03A1*");
            System.out.println(in.readLine() + i);
            out.close();
            in.close();
            socket.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
       }
      }
    }

您的解决方案不能很好地扩展。我将要完成的工作(设备的GPS位置)封装在某个类的对象中,然后将每个工作单元放入队列中。最后,一个线程可以按顺序处理所有工作,一次处理一个请求

如果一个线程无法跟上,而您的队列已满,那么通过添加更多的工作人员来处理队列中的作业,就很容易进行扩展。(或者,如果MySQL的一个实例无法处理所有插入,您也可以尝试对数据进行水平切分并添加多个MySQL实例)

这是一些示例代码:

import java.sql.Connection;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;


public class QueueingDatabaseProcessingExample {

    public static void main(String[] args) throws InterruptedException {
        QueueingDatabaseProcessingExample a = new QueueingDatabaseProcessingExample();
        a.doTheWork();
    }

    private void doTheWork() throws InterruptedException {

        BlockingQueue<TcpCommunicatorUnitOfWork> blockingQueue = new ArrayBlockingQueue(1000);

        // add work to queue as needed
        blockingQueue.put(new TcpCommunicatorUnitOfWork("device id", 40.7143528, -74.0059731, 10));  // blocks if queue is full


        Connection connection;

        // get connection to the database from database pool

        // process requests one by one sequentially
        while (true) {
            TcpCommunicatorUnitOfWork tcpCommunicatorUnitOfWork = blockingQueue.take(); // blocks if queue is empty

            proccess(tcpCommunicatorUnitOfWork);
        }
    }

    private void proccess(TcpCommunicatorUnitOfWork tcpCommunicatorUnitOfWork) {
        // do queries, inserts, deletes to database
    }

}


/**
 * this class should have all the information needed to query/update the database
 */
class TcpCommunicatorUnitOfWork {

    private final String deviceId;
    private final double latitude;
    private final double longitude;
    private final int seaLevel;

    public TcpCommunicatorUnitOfWork(String deviceId, double latitude, double longitude, int seaLevel) {
        this.deviceId = deviceId;
        this.latitude = latitude;
        this.longitude = longitude;
        this.seaLevel = seaLevel;
    }


}
导入java.sql.Connection;
导入java.util.concurrent.ArrayBlockingQueue;
导入java.util.concurrent.BlockingQueue;
公共类QueueingDatabaseProcessingExample{
公共静态void main(字符串[]args)引发InterruptedException{
QueueingDatabaseProcessingExample a=新的QueueingDatabaseProcessingExample();
a、 doTheWork();
}
private void doTheWork()引发InterruptedException{
BlockingQueue BlockingQueue=新阵列BlockingQueue(1000);
//根据需要将工作添加到队列
blockingQueue.put(新的TcpCommunicatorUnitOfWork(“设备id”,40.7143528,-74.0059731,10));//如果队列已满,则阻塞
连接;
//从数据库池获取到数据库的连接
//按顺序逐个处理请求
while(true){
TcpCommunicatorUnitOfWork TcpCommunicatorUnitOfWork=blockingQueue.take();//如果队列为空,则阻塞
过程(TCP通信运行工作);
}
}
专用无效进程(TCPCommunicationRunitofWork TCPCommunicationRunitofWork){
//对数据库执行查询、插入和删除操作
}
}
/**
*此类应具有查询/更新数据库所需的所有信息
*/
类TcpCommunicatorUnitOfWork{
专用最终字符串设备ID;
私人最终双纬度;
私人最终双经度;
国际海平面私人决赛;
公共TcpCommunicatorUnitOfWork(字符串设备ID、双纬度、双经度、国际海平面){
this.deviceId=deviceId;
这个。纬度=纬度;
这个经度=经度;
this.sealivel=海平面;
}
}

Insert语句非常慢。我不会那样做的。我首先将所有数据保存在一个arraylist中,然后使用类似于在文件中加载数据的方法将其加载到数据库中。你不能那样做吗?如果您想知道创建insert语句有多糟糕,只需将它们包含在循环中,您就会看到乱七八糟的情况。@Arminius我可以将它们保存在一个数组中。它们是几千个单元的问题将在一分钟内连接起来。因此,每个都将发送单独的数据。但在此之前,我需要运行一些select和update语句,然后最终执行这些insert语句。谢谢您的想法。实际上,目前我正在连接每个客户端的服务器上运行多线程应用程序,它会打开一个新线程。那么,与你的建议相比,缺点是什么呢?你的建议是对数据库进行大容量插入,是吗?我想最终还是一样的,排队的人数会增加,对吗?那么,套接字连接在哪里呢?问题是设备没有很长时间关闭套接字,这是好事还是坏事?为每个客户端创建和启动一个新线程将导致计算机资源耗尽,这是不必要的开销,因为计算机不能同时执行太多线程。使用我的解决方案,您可以控制执行实际工作(处理、连接到数据库)的线程总数,因此您的想法是,套接字仍然使用多线程?因为我看不到插座?所以,我猜在你收到数据后,你会将数据注入一个队列,但这不会减慢进程。因此,如果我停止此应用程序,队列中的所有内容都会丢失吗?我担心所有的插入都会变慢,对吗?我已经更新了下面的问题,我已经插入了如何使用我的服务器套接字,所以也许你可以根据你的解决方案给我你的想法,在我的解决方案上临时做些什么?如果我从你的代码中理解正确,您正在保持客户端和服务器之间的连接打开,直到服务器应答为止(这是一种错误的方法)。如果服务器的回复时间超过1秒,则需要不同的方式在客户端和服务器之间进行通信(例如使用消息队列)
import java.sql.Connection;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;


public class QueueingDatabaseProcessingExample {

    public static void main(String[] args) throws InterruptedException {
        QueueingDatabaseProcessingExample a = new QueueingDatabaseProcessingExample();
        a.doTheWork();
    }

    private void doTheWork() throws InterruptedException {

        BlockingQueue<TcpCommunicatorUnitOfWork> blockingQueue = new ArrayBlockingQueue(1000);

        // add work to queue as needed
        blockingQueue.put(new TcpCommunicatorUnitOfWork("device id", 40.7143528, -74.0059731, 10));  // blocks if queue is full


        Connection connection;

        // get connection to the database from database pool

        // process requests one by one sequentially
        while (true) {
            TcpCommunicatorUnitOfWork tcpCommunicatorUnitOfWork = blockingQueue.take(); // blocks if queue is empty

            proccess(tcpCommunicatorUnitOfWork);
        }
    }

    private void proccess(TcpCommunicatorUnitOfWork tcpCommunicatorUnitOfWork) {
        // do queries, inserts, deletes to database
    }

}


/**
 * this class should have all the information needed to query/update the database
 */
class TcpCommunicatorUnitOfWork {

    private final String deviceId;
    private final double latitude;
    private final double longitude;
    private final int seaLevel;

    public TcpCommunicatorUnitOfWork(String deviceId, double latitude, double longitude, int seaLevel) {
        this.deviceId = deviceId;
        this.latitude = latitude;
        this.longitude = longitude;
        this.seaLevel = seaLevel;
    }


}