在写入数据库时​​用java读取tcp流

时间:2016-08-24 14:15:12

标签: java tcp message-queue

我不确定以下情况的最佳解决方案是:

我的Java程序是从tcp-stream永久读取的。同时,必须将这些数据保存到数据库中。应写入数据库的数据量可能不同

我已经阅读了很多关于消息排队系统的内容,等等。详细地说,我的解决方案将考虑使用LinkedBlockingQueue。因此,有两个线程: a)启动生产者威胁,该威胁将执行从tcp-stream读取 b)启动消费者威胁,将来自流的数据写入(解析的)数据库

(example-)代码如下所示:

Main.java

public static void main(String[] args) {
        LinkedBlockingQueue queue = new LinkedBlockingQueue(50);
        Producer producer = new Producer(queue);
        Consumer consumer = new Consumer(queue, producer);

Produer.java

public class Producer implements Runnable {
  private LinkedBlockingQueue queue;
  private boolean running;

  public Producer(LinkedBlockingQueue queue) {
        this.queue = queue;
        running = true;
    }

 @Override
  public void run() {
    //read TCP-Stream here and save parsed messages to queue
  }
  public boolean isRunning() {
        return running;
  }

Consumer.java

public class Consumer implements Runnable {
    private Producer producer;
    private LinkedBlockingQueue queue;

    public Consumer(LinkedBlockingQueue queue, Producer producer) {
        this.queue = queue;
        this.producer = producer;
    }
   @Override
   public void run() {
       //insert data into database here
       if(producer.isRunning()) {
          //while producer is running, data needs to be inserted to database
       }
   }

这是您建议使用的解决方案吗?或者你知道更好的解决方案吗?

谢谢!

1 个答案:

答案 0 :(得分:2)

你自己的建议非常好。

最终,您要解决的问题是back pressure的问题,即如果您接收的数据速度快于将数据写入数据库的速度。这可能只是因为有大量数据到达或仅仅因为您的目的地暂时不可用而发生。无论哪种方式,这都是您需要处理的情况。

在您提出的解决方案中,这由内存中的暂存区域(=您的队列)处理。只要你有足够的内存并且你不太担心丢失停电数据,那么内存中的策略对你来说会很好。 Java应用程序中的内存增长会吸收突发。本身不是问题,但请记住,当您的队列最终耗尽时,JVM GC将启动并再次从JVM堆释放内存。但是从外部,即从OS的角度来看,存储器可能永远不会被释放。 JVM非常非常保守地将内存释放回操作系统。同样,在大多数情况下,这不是问题。

如果您有更严格的需求,那么您需要考虑一个更强大的"强大的"暂存区而不是RAM,例如本地磁盘。根据我的经验,您提出的解决方案适合95%的用例。