Маршрут Mongos с ReadPreference = NEAREST

У меня возникла проблема с диагностикой проблемы, когда мои запросы Java-приложения к MongoDB не попадают в ближайшую реплику, и я надеюсь, что кто-то может помочь. Позвольте мне начать с объяснения моей конфигурации.

Конфигурация:

Я запускаю экземпляр MongoDB, который является Sharded ReplicaSet. В настоящее время это всего лишь один осколок (он еще недостаточно развит, но требует раскола). Этот одинарный осколок поддерживается набором реплик 3 node. В нашем основном центре обработки данных находятся 2 узла набора реплик. Третий node живет в нашем вторичном центре данных и ему запрещено становиться мастером node.

Мы запускаем наше производственное приложение одновременно в обоих центрах обработки данных, однако экземпляр в нашем вторичном центре обработки данных работает в режиме "только для чтения" и никогда не записывает данные в MongoDB. Он обслуживает только клиентские запросы для чтения существующих данных. Цель этой конфигурации - обеспечить, чтобы, если наш основной центр обработки данных снизился, мы все равно можем обслуживать трафик чтения клиента.

Мы не хотим тратить все это оборудование в нашем вторичном центре обработки данных, поэтому даже в счастливые времена мы активно загружаем баланс части нашего трафика только для чтения в экземпляр нашего приложения, работающего во вторичном центре обработки данных. Этот экземпляр приложения настроен с помощью readPreference = NEAREST и указывается на экземпляр mongos, запущенный на localhost (версия 2.6.7). Экземпляр mongos, очевидно, настроен так, чтобы указывать на наш набор реплик < node.

Из монго:

mongos> sh.status()
--- Sharding Status --- 
sharding version: {
"_id" : 1,
"version" : 4,
"minCompatibleVersion" : 4,
"currentVersion" : 5,
"clusterId" : ObjectId("52a8932af72e9bf3caad17b5")
}
shards:
{  "_id" : "shard1",  "host" : "shard1/failover1.com:27028,primary1.com:27028,primary2.com:27028" }
databases:
{  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }
{  "_id" : "test",  "partitioned" : false,  "primary" : "shard1" }
{  "_id" : "MyApplicationData",  "partitioned" : false,  "primary" : "shard1" }

В режиме восстановления node репликатора:

shard1:SECONDARY> rs.status()
{
"set" : "shard1",
"date" : ISODate("2015-09-03T13:26:18Z"),
"myState" : 2,
"syncingTo" : "primary1.com:27028",
"members" : [
{
    "_id" : 3,
    "name" : "primary1.com:27028",
    "health" : 1,
    "state" : 1,
    "stateStr" : "PRIMARY",
    "uptime" : 674841,
    "optime" : Timestamp(1441286776, 2),
    "optimeDate" : ISODate("2015-09-03T13:26:16Z"),
    "lastHeartbeat" : ISODate("2015-09-03T13:26:16Z"),
    "lastHeartbeatRecv" : ISODate("2015-09-03T13:26:18Z"),
    "pingMs" : 49,
    "electionTime" : Timestamp(1433952764, 1),
    "electionDate" : ISODate("2015-06-10T16:12:44Z")
},
{
    "_id" : 4,
    "name" : "primary2.com:27028",
    "health" : 1,
    "state" : 2,
    "stateStr" : "SECONDARY",
    "uptime" : 674846,
    "optime" : Timestamp(1441286777, 4),
    "optimeDate" : ISODate("2015-09-03T13:26:17Z"),
    "lastHeartbeat" : ISODate("2015-09-03T13:26:18Z"),
    "lastHeartbeatRecv" : ISODate("2015-09-03T13:26:18Z"),
    "pingMs" : 53,
    "syncingTo" : "primary1.com:27028"
},
{
    "_id" : 5,
    "name" : "failover1.com:27028",
    "health" : 1,
    "state" : 2,
    "stateStr" : "SECONDARY",
    "uptime" : 8629159,
    "optime" : Timestamp(1441286778, 1),
    "optimeDate" : ISODate("2015-09-03T13:26:18Z"),
    "self" : true
}
],
"ok" : 1
}


shard1:SECONDARY> rs.conf()
{
    "_id" : "shard1",
    "version" : 15,
    "members" : [
    {
        "_id" : 3,
        "host" : "primary1.com:27028",
        "tags" : {
            "dc" : "primary"
        }
    },
    {
        "_id" : 4,
        "host" : "primary2.com:27028",
        "tags" : {
            "dc" : "primary"
        }
    },
    {
        "_id" : 5,
        "host" : "failover1.com:27028",
        "priority" : 0,
        "tags" : {
            "dc" : "failover"
        }
    }
    ],
    "settings" : {
        "getLastErrorModes" : {"ACKNOWLEDGED" : {}}
    }
}

Проблема:

Проблема заключается в том, что запросы, которые попадают в этот монго в нашем вторичном центре обработки данных, как представляется, направляются на реплику, запущенную в нашем основном центре обработки данных, а не на ближайший node, который работает во вторичном центре данных. Это приводит к значительным задержкам в сети и приводит к плохой производительности чтения.

Мое понимание заключается в том, что mongos решает, какой node в наборе реплик должен направить запрос, и он должен соблюдать ReadPreference из моего запроса драйвера java. Есть ли команда, которую я могу запустить в оболочке mongos, чтобы увидеть статус набора реплик, включая время ping для узлов? Или каким-то способом увидеть входные запросы, указывающие на node в выбранном реплике, и почему? Любой совет вообще о том, как диагностировать первопричину моей проблемы?

Ответ 1

Если я запускаю mongos с флагом -vvvv (4x verbose), то мне представляется информация о маршрутизации запроса в файлах журнала, включая информацию об используемом предпочтении чтения и хост, на который были направлены запросы. например:

2015-09-10T17:17:28.020+0000 [conn3] dbclient_rs say 
using secondary or tagged node selection in shard1, 
read pref is { pref: "nearest", tags: [ {} ] } 
    (primary : primary1.com:27028, 
    lastTagged : failover1.com:27028)

Ответ 2

При настройке предпочтения чтения, когда ReadPreference = NEAREST, система не ищет минимальную задержку сети, так как она может выбрать первичный как ближайший, если подключение к сети правильное. Однако ближайший режим чтения в сочетании с набором тегов выбирает соответствующий член с наименьшей задержкой сети. Даже ближайшим может быть любой из первичных или вторичных. Поведение монго при настройке настроек и с точки зрения латентности сети не так четко объяснено в официальных документах.

http://docs.mongodb.org/manual/core/read-preference/#replica-set-read-preference-tag-sets

надеюсь, что это поможет