1. 走读librdkafka-0.7的代码, 发现其destroy后,有内存泄露的问题;
2. 验证:通过 1000000次,创建kafka实例,释放实例;
即rk=rd_kakfa_new(); 然后rd_kafka_destroy(rk); 内存耗尽,导致程序退出;
3. 问题原因:
rk实例选用引用计数的思想来释放其资源;
对于生产者,其将引用计数设置为2:一个为为主线程(生产者线程); 一个发送线程 (消费者线程, 主线线程pthread_create 所得);
由于两者通过 互斥锁+条件变量,实现共享一个queue,实现数据的同步;
其通信模型:
1. 在rd_kafka_new中创建了消费者线程, 此时queue为空, 消费者线程阻塞pthread_cond_wait();
2. 生产者线程,每生产一个砖头,将砖头放进queue中,同时通过pthread_cond_signal 通知消费者线程;
3. 消费线程, 如果发现queue不为空,就去消费queue中砖头,直到queue为空,阻塞在pthread_cond_wait();
4. 消费者线程收到生产者的signal信号,转3.
问题,生产线程主动执行rd_kafka_destroy时,只能将引用计数减1,等待消费者线程主动退出;
此时有两个问题:
1. 消费者线程阻塞,永远不会退出,导致内存+pthread资源泄露;
2. 如果运气比较好,消费者线程恰好也退出了,但是,原有destroy并没有pthread资源的回收机制,pthread_join,回收pthread的资源,
如果,作为一个常态服务进程,如果不定期出现rd_kafka_new/destroy, 同样会导致资源泄露(内存泄露);
解决方法:
1.rdkafka的资源释放全部由生成者线程完成:通过调用rd_kafka_destroy:
1. 首先将rk的应用计数 - 1, 看消费者线程是否退出,
2. 如果消费者线程已退出,直接执行资源回收的任务;
3. 如果消费者线程还在,此时消费者线程肯定阻塞在了pthread_cond_wait,
故生产者线程向其发送信号,使消费线程退出,同时引用计数减少1;转2;
此外,值的注意的一点是,pthread_join 回收子线程的处理只能在父线程里处理;
验证:
2. 验证:通过 1000000次,创建kafka实例,释放实例;
即rk=rd_kakfa_new(); 然后rd_kafka_destroy(rk); 内存耗尽,导致程序退出;
3. 问题原因:
rk实例选用引用计数的思想来释放其资源;
对于生产者,其将引用计数设置为2:一个为为主线程(生产者线程); 一个发送线程 (消费者线程, 主线线程pthread_create 所得);
由于两者通过 互斥锁+条件变量,实现共享一个queue,实现数据的同步;
其通信模型:
1. 在rd_kafka_new中创建了消费者线程, 此时queue为空, 消费者线程阻塞pthread_cond_wait();
2. 生产者线程,每生产一个砖头,将砖头放进queue中,同时通过pthread_cond_signal 通知消费者线程;
3. 消费线程, 如果发现queue不为空,就去消费queue中砖头,直到queue为空,阻塞在pthread_cond_wait();
4. 消费者线程收到生产者的signal信号,转3.
问题,生产线程主动执行rd_kafka_destroy时,只能将引用计数减1,等待消费者线程主动退出;
此时有两个问题:
1. 消费者线程阻塞,永远不会退出,导致内存+pthread资源泄露;
2. 如果运气比较好,消费者线程恰好也退出了,但是,原有destroy并没有pthread资源的回收机制,pthread_join,回收pthread的资源,
如果,作为一个常态服务进程,如果不定期出现rd_kafka_new/destroy, 同样会导致资源泄露(内存泄露);
解决方法:
1.rdkafka的资源释放全部由生成者线程完成:通过调用rd_kafka_destroy:
1. 首先将rk的应用计数 - 1, 看消费者线程是否退出,
2. 如果消费者线程已退出,直接执行资源回收的任务;
3. 如果消费者线程还在,此时消费者线程肯定阻塞在了pthread_cond_wait,
故生产者线程向其发送信号,使消费线程退出,同时引用计数减少1;转2;
此外,值的注意的一点是,pthread_join 回收子线程的处理只能在父线程里处理;
验证:
验证:通过 1000000次,创建kafka实例,释放实例;无内存泄露的问题;