fastDFS遇到的并发问题 ╰+哭是因爲堅強的太久メ 2022-05-25 07:50 227阅读 0赞 ###### fastDFS遇到的并发问题recv cmd: 0 is not correct, expect cmd: 100 ###### 2018年01月16日 20:28:02 阅读数:537 此贴是我对一篇帖子[FastDFS并发会有bug,其实我也不太信][FastDFS_bug]?进行的一些测试和我自己也发现的相关问题与解决方案。 最开始我也按照帖子进行了测试,结果发现确实存在并发问题(下面代码改为单线程是木有问题的)。以下列出我尝试的几种情况: 先列出我进行测试的有main函数的FastConcurrence类: **\[java\]** [view plain][] [copy][view plain] 1. public class FastConcurrence \{ 2. private static int poolSize=2;//定义线程个数 3. public static void main(String\[\] args) throws InterruptedException \{ 4. latchTest(); 5. \} 6. private static void latchTest() throws InterruptedException \{ 7. final CountDownLatch start = new CountDownLatch(1); 8. final CountDownLatch end = new CountDownLatch(poolSize); 9. ExecutorService exce = Executors.newFixedThreadPool(poolSize); 10. for (int i = 0; i < poolSize; i++) \{ 11. Runnable run = new Runnable() \{ 12. @Override 13. public void run() \{ 14. try \{ 15. start.await(); 16. testLoad(); 17. \} catch (Exception e) \{ 18. e.printStackTrace(); 19. \} finally \{ 20. end.countDown(); 21. \} 22. \} 23. \}; 24. exce.submit(run); 25. \} 26. start.countDown(); 27. end.await(); 28. exce.shutdown(); 29. \} 30. 31. private static void testLoad() throws Exception \{ 32. String filePath="D:\\\\fastDFS\\\\ques.png"; 33. File content=new File(filePath); 34. TestFileManager test=new TestFileManager(); 35. FastDFSFile file =test.getFastFile(content,"png"); 36. for (int i=0;i<10;i++)\{ FileManager.upload(file);//里面封装了我转文件为byte\[\]和上传文件方法storageClient.upload\_file 37. \} 38. System.out.println("完成一个线程!"); 39. \} 40. \} ①把trackerClient,trackerServer,storageServer,storageClient设为全局变量。在类加载的时候,就进行了初始化,关键代码如下: **\[java\]** [view plain][] [copy][view plain] 1. private static TrackerClient trackerClient; 2. private static TrackerServer trackerServer; 3. private static StorageServer storageServer; 4. private static StorageClient storageClient; 5. 6. static \{ 7. try \{ 8. // 初始化文件资源 9. ClientGlobal.init("C:\\\\Users\\\\jianbo\\\\Downloads\\\\FastDFS\\\\conf\\\\client.conf"); 10. trackerClient = new TrackerClient(); 11. trackerServer = trackerClient.getConnection(); 12. //有并发问题,所以勿重用storageClient 13. storageClient = new StorageClient(trackerServer, storageServer); 14. \} catch (Exception e) \{ 15. logger.error(logger, e); 16. \} 17. \} 果不其然报错了: **\[java\]** [view plain][] [copy][view plain] 1. java.net.SocketException: socket closed 2. at java.net.SocketInputStream.socketRead0(Native Method) 3. at java.net.SocketInputStream.socketRead(Unknown Source) 4. at java.net.SocketInputStream.read(Unknown Source) 5. at java.net.SocketInputStream.read(Unknown Source) 6. at org.csource.fastdfs.ProtoCommon.recvPackage(ProtoCommon.java:263) 7. at org.csource.fastdfs.TrackerClient.getStoreStorage(TrackerClient.java:143) 8. at org.csource.fastdfs.StorageClient.newWritableStorageConnection(StorageClient.java:1938) 9. at org.csource.fastdfs.StorageClient.do\_upload\_file(StorageClient.java:703) 10. at org.csource.fastdfs.StorageClient.upload\_file(StorageClient.java:208) 11. at org.csource.fastdfs.StorageClient.upload\_file(StorageClient.java:226) 12. at fastdfs.FileManager.upload(FileManager.java:76) 13. at fastdfs.FastConcurrence.testLoad(FastConcurrence.java:48) 14. at fastdfs.FastConcurrence.access$0(FastConcurrence.java:42) 15. at fastdfs.FastConcurrence$1.run(FastConcurrence.java:27) 16. at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) 17. at java.util.concurrent.FutureTask.run(Unknown Source) 18. at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) 19. at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) 20. at java.lang.Thread.run(Unknown Source) 21. java.io.IOException: recv cmd: 0 is not correct, expect cmd: 100 22. at org.csource.fastdfs.ProtoCommon.recvHeader(ProtoCommon.java:219) 23. at org.csource.fastdfs.ProtoCommon.recvPackage(ProtoCommon.java:250) 24. at org.csource.fastdfs.TrackerClient.getStoreStorage(TrackerClient.java:143) 25. at org.csource.fastdfs.StorageClient.newWritableStorageConnection(StorageClient.java:1938) 26. at org.csource.fastdfs.StorageClient.do\_upload\_file(StorageClient.java:703) 27. at org.csource.fastdfs.StorageClient.upload\_file(StorageClient.java:208) 28. at org.csource.fastdfs.StorageClient.upload\_file(StorageClient.java:226) 29. at fastdfs.FileManager.upload(FileManager.java:76) 30. at fastdfs.FastConcurrence.testLoad(FastConcurrence.java:48) 31. at fastdfs.FastConcurrence.access$0(FastConcurrence.java:42) 32. at fastdfs.FastConcurrence$1.run(FastConcurrence.java:27) 33. at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) 34. at java.util.concurrent.FutureTask.run(Unknown Source) 35. at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) 36. at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) 37. at java.lang.Thread.run(Unknown Source) ②我在调用storageClient.upload\_file(byte\[\] file\_buff, String file\_ext\_name, NameValuePair\[\] meta\_list)前一句再storageClient = new StorageClient(trackerServer, storageServer); 关键代码如下: **\[java\]** [view plain][] [copy][view plain] 1. public static String\[\] upload(FastDFSFile file) \{ 2. try \{ 3. storageClient = new StorageClient(trackerServer, storageServer);//新加的 4. uploadResults = storageClient.upload\_file(file.getContent(), file.getExt(), meta\_list); 5. \} catch (Exception e) \{ 6. logger.error("Exception when uploadind the file:" + file.getName(), e); 7. \} 8. //省略一部分代码 9. return uploadResults; 10. \} 好了,出现了和上面①一样的问题。 我发现,其实这样本质没有变,还是去改了全局storageClient 。应该new个新的,所以产生了③。 ③我在调用storageClient.upload\_file(byte\[\] file\_buff, String file\_ext\_name, NameValuePair\[\] meta\_list)前一句再StorageClient storageClient = new StorageClient(trackerServer, storageServer); 就是原帖最后说明的解决办法。 **\[java\]** [view plain][] [copy][view plain] 1. public static String\[\] upload(FastDFSFile file) \{ 2. try \{ 3. StorageClient storageClient = new StorageClient(trackerServer, storageServer);//新加的 4. uploadResults = storageClient.upload\_file(file.getContent(), file.getExt(), meta\_list); 5. \} catch (Exception e) \{ 6. logger.error("Exception when uploadind the file:" + file.getName(), e); 7. \} 8. //省略一部分代码 9. return uploadResults; 10. \} 我还是报错,和前面一样的异常。原因还没有来得及找,不过我采用锁是没有问题的。 ④在调用方法的时候采用锁就能解决。例如这个方法我加了锁就没有问题了。 **\[java\]** [view plain][] [copy][view plain] 1. private synchronized static void testLoad() throws Exception \{ 2. String filePath="D:\\\\fastDFS\\\\ques.png"; 3. File content=new File(filePath); 4. TestFileManager test=new TestFileManager(); 5. FastDFSFile file =test.getFastFile(content,"png"); 6. for (int i=0;i<10;i++)\{ 7. FileManager.upload(file); 8. \} 9. System.out.println("完成一个线程!"); 10. \} 一路顺畅。不过③为什么报错了,我还要研究下。 **补:对于③我找到问题了。** 源码下载下来,然后我就查StorageClient类,发现在do\_upload\_file方法中,有一段代码: **\[java\]** [view plain][] [copy][view plain] 1. bUploadSlave = ((group\_name != null && group\_name.length() > 0) && 2. (master\_filename != null && master\_filename.length() > 0) && 3. (prefix\_name != null)); 4. if (bUploadSlave) 5. \{ 6. bNewConnection = this.newUpdatableStorageConnection(group\_name, master\_filename); 7. \} 8. else 9. \{ 10. bNewConnection = this.newWritableStorageConnection(group\_name); 11. \} 其中的 **\[java\]** [view plain][] [copy][view plain] 1. this.newWritableStorageConnection(group\_name); 具体方法是: **\[java\]** [view plain][] [copy][view plain] 1. protected boolean newWritableStorageConnection(String group\_name) throws IOException, MyException 2. \{ 3. if (this.storageServer != null) 4. \{ 5. return false; 6. \} 7. else 8. \{ 9. TrackerClient tracker = new TrackerClient(); 10. this.storageServer = tracker.getStoreStorage(this.trackerServer, group\_name); 11. if (this.storageServer == null) 12. \{ 13. throw new MyException("getStoreStorage fail, errno code: " + tracker.getErrorCode()); 14. \} 15. return true; 16. \} 17. \} 而这个方法里面的 **\[java\]** [view plain][] [copy][view plain] 1. this.storageServer = tracker.getStoreStorage(this.trackerServer, group\_name); 找进去发现每次trackerServer用完了,就关闭连接了。 trackerServer.close(); 所以后面线程都被关闭了,就报IO异常,只要在方法③中new StorageClient前面再加一句: **\[java\]** [view plain][] [copy][view plain] 1. TrackerServer trackerServer = trackerClient.getConnection(); 就解决问题了。 **\[java\]** [view plain][] [copy][view plain] 1. this.storageServer = tracker.getStoreStorage(this.trackerServer, group\_name); 文章标签: [fastDFS ][fastDFS] [并发 ][Link 1] [多线程 ][Link 2] [FastDFS_bug]: http://home.bdqn.cn/thread-114483-1-1.html [view plain]: https://blog.csdn.net/jianbo2233/article/details/79078500# [fastDFS]: http://so.csdn.net/so/search/s.do?q=fastDFS&t=blog [Link 1]: http://so.csdn.net/so/search/s.do?q=%E5%B9%B6%E5%8F%91&t=blog [Link 2]: http://so.csdn.net/so/search/s.do?q=%E5%A4%9A%E7%BA%BF%E7%A8%8B&t=blog
相关 遇到的Java并发控制问题实例分析 在Java编程中,并发控制是处理多个线程同时访问共享资源的一种重要机制。下面我们将通过一个实例来详细分析Java并发控制的问题。 实例:银行存款类应用 1. **问题描述* 朱雀/ 2024年09月27日 06:06/ 0 赞/ 53 阅读
相关 频繁遇到的Java并发问题实例 在Java并发编程中,常见的问题包括死锁、活锁、饥饿、资源泄露等。以下是一些具体的例子: 1. 死锁: 例如,有两个进程P1和P2,它们分别持有资源R1和R2,并且都等 £神魔★判官ぃ/ 2024年09月11日 22:09/ 0 赞/ 57 阅读
相关 频繁遇到的Java并发问题实例 在Java编程中,常见的并发问题包括线程安全、死锁、资源泄露、活锁等。以下是一些具体实例: 1. 线程安全问题: ```java class Counter { 你的名字/ 2024年09月11日 19:09/ 0 赞/ 48 阅读
相关 fastDFS遇到的并发问题 fastDFS遇到的并发问题recv cmd: 0 is not correct, expect cmd: 100 2018年01月16日 20:28:02 阅读数:5 ╰+哭是因爲堅強的太久メ/ 2022年05月25日 07:50/ 0 赞/ 228 阅读
相关 分布式项目遇到的并发问题 acs-socket-app项目部署在两台服务器,暂时就是是28,29结尾的服务器 当我远程开门的时候,采取的是轮询的机制: 第一次下发指令随机下发到了28的服务器,然后从 今天药忘吃喽~/ 2022年05月10日 07:54/ 0 赞/ 212 阅读
相关 Nodejs Client for FastDFS 使用中的遇到的问题 \使用获取storage信息函数 fdfs.listStorages('group1').then(function(storages) { cons 傷城~/ 2022年04月05日 15:35/ 0 赞/ 244 阅读
相关 fastDFS遇到的并发问题recv cmd: 0 is not correct, expect cmd: 100 这种异常一般发生在 多线程同时使用一个StorageClient操作文件的情况下。 有两种解决办法: 1、对StorageClient对象加锁,变成单线程 2、每次 青旅半醒/ 2021年11月17日 02:04/ 0 赞/ 666 阅读
相关 并发压测遇到的问题 问题 socket too many open files ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shado 野性酷女/ 2021年08月28日 14:24/ 0 赞/ 440 阅读
还没有评论,来说两句吧...