Mysql和java socket并行压力测试

时间:2017-06-27 16:19:36

标签: java mysql multithreading tcp innodb

我有一个java tcp套接字应用程序。 Tcp通信器解码GPS位置并将该数据插入数据库,在插入之前我们做了一些选择和更新,但我只是使用预处理语句。现在,TCP通信器的一个线程服务于一个设备请求。在创建线程之后,我们立即从池中获得一个连接。在解码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();
       }
      }
    }

以下是我的服务器套接字的样子。

public class comm8888 {
    HikariDataSource connectionPool = null;
    private Socket receivedSocketConn1;
    ConnectionHandler(Socket receivedSocketConn1) {
      this.receivedSocketConn1=receivedSocketConn1;
    }
    Connection dbconn = null;
    public void run() { // etc
     DataOutputStream w = null;
     DataInputStream r = null;  
     String message="";
     receivedSocketConn1.setSoTimeout(60000);
       dbconn = connectionPool.getConnection();
     dbconn.setAutoCommit(false);
     try {
         w = new DataOutputStream(new BufferedOutputStream(receivedSocketConn1.getOutputStream()));
         r = new DataInputStream(new BufferedInputStream(receivedSocketConn1.getInputStream()));
         while ((m=r.read()) != -1){
             //multiple prepared based sql select,update and insert here.
         }
     }
     finally{
        try {
            if ( dbconn != null ) {
              dbconn.close();
            }
        }
        catch(SQLException ex){
             ex.printStackTrace();
        }
        try{
           if ( w != null ){
                w.close();
                r.close();
                receivedSocketConn1.close();
            }
        }
        catch(IOException ex){
           ex.printStackTrace(System.out);
        }
      }
   }
}
    public static void main(String[] args) {
      new comm8888();
    }
    comm8888() {
      try {
          HikariConfig config = new HikariConfig();
                config.setJdbcUrl("jdbc:mysql://localhost:3306/testdata"); 
                config.setUsername("****"); 
                config.setPassword("****");      
                config.setMaximumPoolSize(20);      
          connectionPool = new HikariDataSource(config); // setup the connection pool           
       }
          catch (Exception e) {
                e.printStackTrace(System.out);
         }
          try 
          {
                   final ServerSocket serverSocketConn = new ServerSocket(8888);                
                   while (true){
                            try {
                                    Socket socketConn1 = serverSocketConn.accept();
                                    new Thread(new ConnectionHandler(socketConn1)).start();                     
                            }
                            catch(Exception e){
                                e.printStackTrace(System.out);
                            }
                        }
          } 
          catch (Exception e) {
             e.printStackTrace(System.out);
          }
    }
} 

1 个答案:

答案 0 :(得分:0)

您的解决方案无法很好地扩展。我会将要完成的工作(设备的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;
    }


}