来自mongoc(C)驱动程序的MongoDB Atlas连接间歇性故障,故障为';未找到合适的服务器';

来自mongoc(C)驱动程序的MongoDB Atlas连接间歇性故障,故障为';未找到合适的服务器';,mongodb,database-connection,Mongodb,Database Connection,我正在使用MongoDB C驱动程序(1.9.2)连接到Atlas集群(使用AWS的M5)。 我的请求通常会成功,但我有一半的时间会出现这种错误。请求之间等待的时间越长,请求成功的频率就越高 我始终能够创建mongoc_客户端,但当请求失败时,drop、insert或read操作会出现此错误 2019-12-30 23:10:50::dropCollection():mongoc_collection_drop()失败代码(13053):: 未找到合适的服务器:serverSelectionTi

我正在使用MongoDB C驱动程序(1.9.2)连接到Atlas集群(使用AWS的M5)。 我的请求通常会成功,但我有一半的时间会出现这种错误。请求之间等待的时间越长,请求成功的频率就越高

我始终能够创建mongoc_客户端,但当请求失败时,drop、insert或read操作会出现此错误

2019-12-30 23:10:50::dropCollection():mongoc_collection_drop()失败代码(13053):: 未找到合适的服务器:
serverSelectionTimeoutMS
expired:[未能从服务器接收长度标头。在'xxxxx-shard-00-01-xxxxx.mongodb.net:27017'上调用ismaster:[未能从服务器接收长度标头。在'xxxxx-shard-00-00-xxxxx.mongodb.net:27017'上调用ismaster]

这是我的(简化)代码; 我尝试使用客户端池,然后切换到“serverSelectionTryOnce=false”——它们都在超时后出现错误

    #include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <mongoc.h>
#include <bson.h>
#include <bcon.h>

#define ERROR -1
#define GOOD   0

typedef struct _MongoContext
{
    mongoc_uri_t*           uri;
    mongoc_client_t*        client;
    mongoc_database_t*      database;
    mongoc_collection_t*    collection;
    bson_error_t            error;
    char*                   uriStr;
} MongoContext;

static const char* DEFAULT_URI = "mongodb+srv://<user>:<psswd>@<host>.mongodb.net/test?retryWrites=true&w=majority&serverSelectionTryOnce=false";

int getMongoContext(MongoContext* mctx, const char* dbname, const char* collname)
{
    bson_error_t  error;

    mctx->uriStr = strdup(DEFAULT_URI);

    mctx->uri = mongoc_uri_new_with_error(mctx->uriStr, &error);                               
    if(!mctx->uri) {
        fprintf(stderr, "getMongoContext(): Unable to parse URI(%s)\n(%s)", mctx->uriStr, error.message);
        return ERROR;
    }

//    mongoc_client_pool_t *pool = mongoc_client_pool_new(mctx->uri);
//    mongoc_client_pool_set_appname(pool, "my-mongo");
//    mongoc_client_pool_set_error_api(pool, MONGOC_ERROR_API_VERSION_2);
//    mctx->client = mongoc_client_pool_pop(pool);

    mctx->client = mongoc_client_new_from_uri(mctx->uri);                                      
    if(!mctx->client) {
        fprintf(stderr, "getMongoContext(): mongoc_client_new_from_uri() failed(%s)", error.message);
       return ERROR;
    }

    mongoc_client_set_appname(mctx->client, "my-mongo");                                       

    mctx->database   = mongoc_client_get_database(mctx->client, dbname);
    if(mctx->database == NULL) {
        fprintf(stderr, "getMongoContext(): invalid database(%s)", dbname);
        return ERROR;
    }

    mctx->collection = mongoc_client_get_collection(mctx->client, dbname, collname);
    if(mctx->collection == NULL) {
        fprintf(stderr, "getMongoContext(): invalid collection(%s)", collname);
    }

    char* ptr = strchr(mctx->uriStr, '@');
    fprintf(stderr, "getMongoContext(): connection made for host(%s), db(%s), collection(%s)\n", (ptr+1), dbname, collname);

   return GOOD;
}

void closeMongoContext(MongoContext* mctx)
{
    mongoc_collection_destroy(mctx->collection);
    mongoc_database_destroy(mctx->database);
    mongoc_uri_destroy(mctx->uri);
    mongoc_client_destroy(mctx->client);
    mongoc_cleanup();

    free(mctx->uriStr);
}

/**
 * read the collection in the given MongoContext
 */
int readCollection(MongoContext* mctx)
{
    mongoc_cursor_t*    cursor;
    const bson_t*       doc;
    char*               str;
    bson_t* query = bson_new();
    cursor = mongoc_collection_find_with_opts(mctx->collection, query, NULL, NULL);

    if(cursor == NULL) {
        fprintf(stderr, "readCollection(): Unable to retrieve a cursor for collection(%s)",
               mongoc_collection_get_name(mctx->collection));
        return ERROR;
    }

    while(mongoc_cursor_next(cursor, &doc)) {
       str = bson_as_canonical_extended_json(doc, NULL);
       printf("%s\n", str);
       bson_free(str);
    }
    bson_destroy(query);
    mongoc_cursor_destroy(cursor);

    return GOOD;
}

int insertIntoCollection(MongoContext* mctx, const char* jsondata)
{
    bson_t* doc;
    bson_t  reply;
    bson_error_t error;

    doc = bson_new_from_json((const uint8_t*)jsondata, -1, &error);
    if(!doc) {
       fprintf(stderr, "insertIntoCollection(): bson_new_from_json() failed (%s)\n", error.message);
       return ERROR;
    }

    fprintf(stderr, "insertIntoCollection(): insert into collection(%s)\n", mongoc_collection_get_name(mctx->collection));
    bool b = mongoc_collection_insert_one(mctx->collection, doc, NULL, &reply, &error);

    if(!b) {
        fprintf(stderr, "insertIntoCollection(): mongoc_collection_insert_one() failed (%s)\n", error.message);
    }
    bson_destroy(doc);

    return GOOD;
}

int dropCollection(MongoContext* mctx)
{
    bson_error_t error;

    bool rval = mongoc_collection_drop(mctx->collection, &error);                              

    if(!rval) {
        fprintf(stderr, "dropCollection(): mongoc_collection_drop() failed code(%d)::%s", error.code, error.message);
        fprintf(stderr, "dropCollection(): mongoc_collection_drop() failed on collection(%s) for(%s)",
           mongoc_collection_get_name(mctx->collection), mctx->uriStr);
        return (error.code == 26) ? GOOD : ERROR;                                               
    }

    return GOOD;
}

int main(int argc, char* argv[])
{
    mongoc_init();
    MongoContext mctx = {0};
    getMongoContext(&mctx, "my-db", "my-collection");

    if(dropCollection(&mctx) == ERROR) {
        exit(1);
    }
    printf("collection dropped...\n");

    if(insertIntoCollection(&mctx, "{ \"hello\" : \"world\" }") == ERROR) {
        exit(1);
    }
    printf("inserted into collection...\n");

    if(readCollection(&mctx) == ERROR) {
        exit(1);
    }

    closeMongoContext(&mctx);
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义错误-1
#定义好的0
类型定义结构\u MongoContext
{
mongoc_uri_t*uri;
mongoc_客户_t*客户;
mongoc_数据库\u t*数据库;
mongoc_collection_t*collection;
bson_错误\u t错误;
char*uriStr;
}MongoContext;
static const char*DEFAULT_URI=“mongodb+srv://:@.mongodb.net/test?retryWrites=true&w=mailty&serverSelectionTryOnce=false”;
int getMongoContext(MongoContext*mctx,const char*dbname,const char*collname)
{
bson_错误\u t错误;
mctx->uriStr=strdup(默认URI);
mctx->uri=mongoc\u uri\u new\u带有错误(mctx->uriStr,&error);
如果(!mctx->uri){
fprintf(stderr,“getMongoContext():无法分析URI(%s)\n(%s)”,mctx->uriStr,error.message);
返回误差;
}
//mongoc\u client\u pool\u t*pool=mongoc\u client\u pool\u new(mctx->uri);
//mongoc_client_pool_set_appname(池,“我的mongo”);
//mongoc_客户端_池_集_错误_api(池,mongoc_错误_api_版本_2);
//mctx->client=mongoc\u client\u pool\u pop(pool);
mctx->client=mongoc\u client\u new\u from\u uri(mctx->uri);
如果(!mctx->client){
fprintf(stderr,“getMongoContext():mongoc_client_new_from_uri()失败(%s)”,错误消息);
返回误差;
}
mongoc_client_set_appname(mctx->client,“我的mongo”);
mctx->database=mongoc\u client\u get\u database(mctx->client,dbname);
如果(mctx->数据库==NULL){
fprintf(stderr,“getMongoContext():无效数据库(%s)”,dbname);
返回误差;
}
mctx->collection=mongoc\u client\u get\u collection(mctx->client,dbname,collname);
如果(mctx->集合==NULL){
fprintf(stderr,“getMongoContext():无效集合(%s)”,collname);
}
char*ptr=strchr(mctx->uriStr,'@');
fprintf(stderr,“getMongoContext():为主机(%s)、数据库(%s)、集合(%s)\n“,(ptr+1)、数据库名、collname建立的连接);
归还货物;
}
无效关闭MongoContext(MongoContext*mctx)
{
mongoc_收集_销毁(mctx->收集);
mongoc_数据库_销毁(mctx->数据库);
mongoc_uri_destroy(mctx->uri);
mongoc_客户端_销毁(mctx->客户端);
mongoc_cleanup();
免费(mctx->uriStr);
}
/**
*阅读给定MongoContext中的集合
*/
int readCollection(MongoContext*mctx)
{
mongoc_cursor_t*cursor;
const bson_t*doc;
char*str;
bson_t*query=bson_new();
cursor=mongoc\u collection\u find\u with\u opts(mctx->collection,query,NULL,NULL);
if(游标==NULL){
fprintf(stderr,“readCollection():无法检索集合(%s)”的游标,
mongoc_collection_get_name(mctx->collection));
返回误差;
}
while(mongoc\u游标\u下一步(游标和文档)){
str=bson_as_canonical_extended_json(doc,NULL);
printf(“%s\n”,str);
无bson_(str);
}
bson_销毁(查询);
mongoc_cursor_destroy(cursor);
归还货物;
}
int insertIntoCollection(MongoContext*mctx,const char*jsondata)
{
bson_t*文件;
b未答复;
bson_错误\u t错误;
doc=bson_new_from_json((const uint8_t*)jsondata,-1,&错误);
如果(!doc){
fprintf(stderr,“insertIntoCollection():bson\u new\u from\u json()失败(%s)\n)”,错误消息);
返回误差;
}
fprintf(stderr,“insertIntoCollection():插入到集合(%s)\n”,mongoc_collection_get_name(mctx->collection));
bool b=mongoc\u collection\u insert\u one(mctx->collection,doc,NULL,&reply,&error);
如果(!b){
fprintf(stderr,“insertIntoCollection():mongoc\u collection\u insert\u one()失败(%s)\n)”,错误消息);
}
b关于销毁(doc);
归还货物;
}
int dropCollection(MongoContext*mctx)
{
bson_错误\u t错误;
bool rval=mongoc\u collection\u drop(mctx->collection,&error);
如果(!rval){
fprintf(stderr,“dropCollection():mongoc_collection_drop()失败代码(%d):%s”,error.code,error.message);
fprintf(stderr,“dropCollection():mongoc_collection_drop()在(%s)的集合(%s)上失败),
mongoc_collection_get_name(mctx->collection),mctx->uriStr);
返回(error.code==26)?良好:错误;
}
归还货物;
}
int main(int argc,char*argv[])
{
mongoc_init();
MongoContext mctx={0};
getMongoContext(&mctx,“我的数据库”,“我的收藏”);
if(dropCollection(&mctx)=错误){
出口(1);
}
printf(“已删除收集…\n”);
if(insertIntoCollection(&mctx,{\'hello\':\'world\'})==错误){
出口(1);
}
printf(“插入到集合…\n”);
if(readCollection(&mctx)=错误){
出口(1);
}
closeMongoContext(&mctx);
}
在我的