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

在写入数据库时使用java读取tcp流,java,tcp,message-queue,Java,Tcp,Message Queue,我不确定以下情况的最佳解决方案是: 我的Java程序正在从tcp流中永久读取数据。同时,有必要将这些数据持久化到数据库中。应写入数据库的数据量可能会有所不同 我读过很多关于消息排队系统的书。详细地说,我的解决方案将考虑使用Link键控队列。因此,有两条线: a) 启动将从tcp流执行读取的生产者威胁 b) 启动一个消费者威胁,它将把(解析的)数据从流写入数据库 (示例-)代码如下所示: Main.java public static void main(String[] args) {

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

我的Java程序正在从tcp流中永久读取数据。同时,有必要将这些数据持久化到数据库中。应写入数据库的数据量可能会有所不同

我读过很多关于消息排队系统的书。详细地说,我的解决方案将考虑使用Link键控队列。因此,有两条线: a) 启动将从tcp流执行读取的生产者威胁 b) 启动一个消费者威胁,它将把(解析的)数据从流写入数据库

(示例-)代码如下所示:

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
       }
   }
这是您建议使用的解决方案吗?或者你知道更好的解决方案吗


谢谢大家!

你自己的建议很好

最终,您试图解决的问题是,例如,如果您接收数据的速度快于您将数据写入数据库的速度。这可能仅仅是因为有大量数据到达,或者仅仅是因为您的目的地暂时不可用。不管怎样,这都是你需要处理的情况

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


如果您有更严格的需求,那么您需要考虑一个更健壮的“分级”区域,而不是RAM,例如本地磁盘。根据我的经验,您提出的解决方案适合95%的用例

你自己的建议很好

最终,您试图解决的问题是,例如,如果您接收数据的速度快于您将数据写入数据库的速度。这可能仅仅是因为有大量数据到达,或者仅仅是因为您的目的地暂时不可用。不管怎样,这都是你需要处理的情况

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


如果您有更严格的需求,那么您需要考虑一个更健壮的“分级”区域,而不是RAM,例如本地磁盘。根据我的经验,您提出的解决方案适合95%的用例

是的,这几乎是一种标准方法。您还可以查看Executor服务。重复的(因为代码不是特定于tcp/数据库的)。我不认为有理由使用两个线程。我会一次完成这一切。没有好处。是的,这几乎是一个标准方法。您还可以查看Executor服务。重复的(因为代码不是特定于tcp/数据库的)。我不认为有理由使用两个线程。我会一次完成这一切。没有增益。TCP将通过对发送方施加自己的压力来自动处理背压。应用程序不需要参与其中。@EJP。我只是对“背压”有一个比你更宽泛的定义,不仅仅与低层次的网络内容有关。不,我们有相同的定义,我只是认为应用程序不需要参与其中。如果您有两个线程和一个队列,那么您必须绑定队列以避免内存不足,因此最终您将获得TCP背压,同时您没有完成任何有用的工作,您只是读取了大量尚未处理的数据。有什么意义?@EJP。OP的设计将处理目的地端的间歇性停机。这就是重点。这确实值得付出努力。另外:您不能假设TCP发送方仅仅能够永远增长自己的发送方端缓冲区就能够处理较慢的使用者。最好以这样的方式设计recv应用程序,以便它尽可能快地从套接字读取数据,然后拥有自己的缓冲区(例如队列)。只需我的2美分。TCP将通过对发送方施加自己的压力来自动处理背压。应用程序不需要参与其中。@EJP。我只是对“背压”有一个比你更宽泛的定义,不仅仅与低层次的网络内容有关。不,我们有相同的定义,我只是认为应用程序不需要参与其中。如果您有两个线程和一个队列,那么您必须绑定队列以避免内存不足,因此最终您将获得TCP背压,同时您没有完成任何有用的工作,您只是读取了大量尚未处理的数据。有什么意义?@EJP。OP的设计将处理目的地端的间歇性停机。这就是重点。这确实值得付出努力。另外:您不能假设TCP发送方仅仅能够永远增长自己的发送方端缓冲区就能够处理较慢的使用者。最好以这样的方式设计recv应用程序,以便它尽可能快地从套接字读取数据,然后拥有自己的缓冲区(例如队列)。只是我