com.mongodb.MongoSocketReadException: Prematurely reached end of stream

異常情況描述com.mongodb.MongoSocketReadException: Prematurely reached end of stream

一、異常發生場景

當使用mongodb的一主一從一備節點構建的集羣,使用java代碼連接集羣時候,測試主節點master和備用節點slave切換的時候;

2019-10-23 20:21:05,972 WARN [org.mongodb.driver.connection] - Got socket exception on connection [connectionId{localValue:4, serverValue:15}] to 172.19.32.142:27017. All connections to 172.19.32.142:27017 will be closed.
com.mongodb.MongoSocketReadException: Prematurely reached end of stream
	at com.mongodb.connection.SocketStream.read(SocketStream.java:88)
	at com.mongodb.connection.InternalStreamConnection.receiveResponseBuffers(InternalStreamConnection.java:494)
	at com.mongodb.connection.InternalStreamConnection.receiveMessage(InternalStreamConnection.java:224)
	at com.mongodb.connection.UsageTrackingInternalConnection.receiveMessage(UsageTrackingInternalConnection.java:96)
	at com.mongodb.connection.DefaultConnectionPool$PooledConnection.receiveMessage(DefaultConnectionPool.java:440)
	at com.mongodb.connection.WriteCommandProtocol.receiveMessage(WriteCommandProtocol.java:262)
	at com.mongodb.connection.WriteCommandProtocol.execute(WriteCommandProtocol.java:104)
	at com.mongodb.connection.InsertCommandProtocol.execute(InsertCommandProtocol.java:67)
	at com.mongodb.connection.InsertCommandProtocol.execute(InsertCommandProtocol.java:37)
	at com.mongodb.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:168)
	at com.mongodb.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:289)
	at com.mongodb.connection.DefaultServerConnection.insertCommand(DefaultServerConnection.java:118)
	at com.mongodb.operation.MixedBulkWriteOperation$Run$2.executeWriteCommandProtocol(MixedBulkWriteOperation.java:465)
	at com.mongodb.operation.MixedBulkWriteOperation$Run$RunExecutor.execute(MixedBulkWriteOperation.java:656)
	at com.mongodb.operation.MixedBulkWriteOperation$Run.execute(MixedBulkWriteOperation.java:411)
	at com.mongodb.operation.MixedBulkWriteOperation$1.call(MixedBulkWriteOperation.java:177)
	at com.mongodb.operation.MixedBulkWriteOperation$1.call(MixedBulkWriteOperation.java:168)
	at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.java:426)
	at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:417)
	at com.mongodb.operation.MixedBulkWriteOperation.execute(MixedBulkWriteOperation.java:168)
	at com.mongodb.operation.MixedBulkWriteOperation.execute(MixedBulkWriteOperation.java:74)
	at com.mongodb.Mongo.execute(Mongo.java:845)
	at com.mongodb.Mongo$2.execute(Mongo.java:828)
	at com.mongodb.MongoCollectionImpl.executeSingleWriteRequest(MongoCollectionImpl.java:550)
	at com.mongodb.MongoCollectionImpl.insertOne(MongoCollectionImpl.java:317)
	at com.mongodb.MongoCollectionImpl.insertOne(MongoCollectionImpl.java:307)
	at mongotest.TestMongoDBReplSet.main(TestMongoDBReplSet.java:39)

二、原因分析

Got socket exception on connection [connectionId{localValue:4, serverValue:15}] to 172.19.32.142:27017. All connections to 172.19.32.142:27017 will be closed.

這段代碼錯誤提示表明:主備容災切換之後,原來的master不再提供寫服務,寫服務轉移到另外一臺機器中,此時java驅動連接元信息中沒有感知到這種變化,集羣中改變的元信息沒有同步到當前的mongodb連接池中的連接中,導致連接失敗!

三、解決方案

原始連接的java代碼,沒有加上try-catch{},導致主備切換之後出現錯誤,現在加上之後,一斤可以正常的瞭解上集羣了。

package mongotest;

import com.mongodb.*;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;

import java.util.ArrayList;
import java.util.List;

/**
 * 描述: java連接mongdb集羣;測試高可用性
 * @author: fangchangtan
 * @version 創建時間:2018年11月26日 下午7:45:29
 */
public class TestMongoDBReplSet1 {

    public static void main(String[] args) {
        ArrayList<ServerAddress> arrayList = new ArrayList<>();
            //mongpdb的java連接配置爲一個集羣模式
            List<ServerAddress> addresses = new ArrayList<ServerAddress>();
            ServerAddress address1 = new ServerAddress("172.19.32.141" , 27017);
            ServerAddress address2 = new ServerAddress("172.19.32.141" , 27027);
            ServerAddress address3 = new ServerAddress("172.19.32.141" , 27037);
            addresses.add(address1);
            addresses.add(address2);
            addresses.add(address3);

            // 3.用來做mongo複製集的基本配置
            MongoClientOptions.Builder builder = new MongoClientOptions.Builder();
//            //線程等待連接變爲可用的最長時間.
//            builder.maxWaitTime(20000);
//            //連接超時時間,必須大於0
//            builder.connectTimeout(1000 * 5);
//            //設置服務器選擇超時(以毫秒爲單位),它定義驅動程序在拋出異常之前等待服務器選擇成功的時間
//            //值爲0表示如果沒有可用的服務器,它將立即超時。 負值意味着無限期等待
//            builder.serverSelectionTimeout(1000 * 30);
//            // 4.自動重連
//            // 7.每個連接上的線程數
//            builder.threadsAllowedToBlockForConnectionMultiplier(50);
//            builder.maxConnectionIdleTime(5000);//set the max wait time in (ms)

            MongoClient mongoClient = new MongoClient(addresses,builder.build());
            MongoDatabase database = mongoClient.getDatabase("test");
            MongoCollection<Document> collection = database.getCollection("testdb");

            for (int i = 0; i < 1000; i++) {
                System.out.println("==========================");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //向集羣中插入文檔數據
//                collection.insertOne(new Document("name","dog"+i));
                try {
                    collection.deleteMany(new BasicDBObject("_id", new BasicDBObject("$ne", null)));
                    collection.insertOne(new Document("name","dog"+i));
                }catch (MongoSocketException e){
                    System.out.println("++++++++++++++++++++++");
                    System.out.println(e);
                    mongoClient = new MongoClient(addresses,builder.build());
                }

                //查詢集羣中的數據記錄
                FindIterable<Document> find = collection.find();
                MongoCursor<Document> iterator = find.iterator();
                while (iterator.hasNext()) {
                    final Document document = iterator.next();
                    System.out.println(document);

                }

            }
    }

}


小夥伴們:如果解決了你的問題,麻煩給點個贊! 本人最新需要你的鼓勵!-V- 在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章