我们正在开发一个车辆跟踪系统,在该系统中,几个GPS设备继续使用Tcp连接将它们的GPS位置发送到服务器。Tcp通信器对GPS位置进行解码,并将数据插入数据库,在插入之前,我们会进行一些选择和更新,但我所做的全部工作都是使用准备好的语句。现在,TCP通信器的一个线程在创建线程后为一个设备request.Immediately提供服务--我们从池中获得一个连接。在解码GPS数据之后,我们对每个数据执行多个选择、更新和插入。随着设备数量的增加,到Mysql数据库的并发连接的数量也在增加。我们现在预计会有30到5万台设备在传输数据,下面的每一个minute.Currently都是整个tcp通信器的代码片段。我知道最终我们将面临两个插入瓶颈的数据库。克服这种情况的最佳解决方案是什么?Java也能处理这么多并发性吗?
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);
}
}
} 发布于 2017-06-23 19:36:07
从评论转到这里来解释更多。
dbconn = connectionPool.getConnection();
...
while (...) {
// dbconn is held for up to 60 seconds which is not scalable
} 因此,您可以在实际需要做些什么以避免长时间的db连接时获得一个dbConn。
while (...) {
// got some more data to process - now get a dbConn
dbconn = connectionPool.getConnection();
// do inserts, etc.
// commit and release the connection!
} 另一种方法是通过发布到队列或调用REST服务来完全卸载与数据库的交互。
while (...) {
// got some more data to process
// publish the data to a JMS queue
// or post the data to a REST endpoint
// there is no database interaction here at all!
} 然后,消息使用者或REST端点处理数据并插入/更新db。这些消息/请求中的每一个都是小的,因此db连接只能从池借用几毫秒(最多几毫秒)。处理JMS消息/POST请求的服务器集群可以独立于最初接收原始套接字数据的服务器进行缩放。
发布于 2017-06-23 18:53:08
一个问题是,如果设备数量增加,每个设备都试图连接db,这是不可扩展的解决方案。一种方法是一批一批地处理.Store队列中的所有消息,直到它达到批处理大小为止,然后插入,因为batch.It将保存网络,因为您不是一个接一个地插入记录。
如果您需要进一步的可扩展解决方案,那么可以使用nosql解决方案或主主复制多节点拓扑来支持大流量和可用性。
对于select和update,您可以使用合并查询,该查询需要在使用时进行分析,如果存在,case.Merge查询将更新,如果不存在,将进行插入。
https://stackoverflow.com/questions/44727922
复制相似问题