टी एल; डॉ
ClusterListener
इंटरफ़ेस एक replicaset के कुछ पहलुओं की निगरानी के लिए इस्तेमाल किया जा सकता है, लेकिन बेहतर जानकारी के लिए अगर आप चाहते हैं और/या आप किसी घटना के समय के लिए के बाहर replicaset स्थिति पूछताछ करना चाहते हैं ClusterListener
कॉलबैक प्रदान करता है तो आप replSetGetStatus
कमांड का आह्वान करना पसंद कर सकते हैं और इसके आउटपुट का निरीक्षण कर सकते हैं।
विस्तार
ClusterListener
कॉल पीठ जो आप देखना/अपने replicaset में परिवर्तन करने के लिए प्रतिक्रिया करने के लिए अनुमति देते हैं प्रदान करता है। उदाहरण के लिए, CLusterListener
निम्नलिखित ...
public class LoggingClusterListener implements ClusterListener {
private static final Logger logger = LoggerFactory.getLogger(LoggingClusterListener.class);
@Override
public void clusterOpening(final ClusterOpeningEvent clusterOpeningEvent) {
logger.info("clusterOpening: {}", clusterOpeningEvent.getClusterId().getValue());
}
@Override
public void clusterClosed(final ClusterClosedEvent clusterClosedEvent) {
logger.info("clusterClosed: {}", clusterClosedEvent.getClusterId().getValue());
}
@Override
public void clusterDescriptionChanged(final ClusterDescriptionChangedEvent event) {
logger.info("clusterDescriptionChanged: {}", event.getClusterId().getValue());
for (ServerDescription sd : event.getNewDescription().getServerDescriptions()) {
logger.info("{}/{}/{}/{}", sd.getType(), sd.getCanonicalAddress(), sd.getState().name());
}
}
}
... जब एक MongoClient
इस तरह के साथ जुड़े ...
final MongoClientOptions options = MongoClientOptions.builder()
.addClusterListener(new LoggingClusterListener())
.build();
return new MongoClient(serverAddresses, options);
... निम्न लॉगिंग फेंकना होगा:
// cluster starting up ...
2017-08-17 12:49:55,977 [main] clusterOpening: 599582e36d47c231ec963b0b
2017-08-17 12:49:56,076 [cluster-ClusterId{value='599582e36d47c231ec963b0b', description='null'}-hostA:27017] clusterDescriptionChanged: 599582e36d47c231ec963b0b
2017-08-17 12:49:56,076 [cluster-ClusterId{value='599582e36d47c231ec963b0b', description='null'}-hostB:27017] clusterDescriptionChanged: 599582e36d47c231ec963b0b
2017-08-17 12:49:56,076 [cluster-ClusterId{value='599582e36d47c231ec963b0b', description='null'}-hostC:27017] clusterDescriptionChanged: 599582e36d47c231ec963b0b
2017-08-17 12:49:56,076 [cluster-ClusterId{value='599582e36d47c231ec963b0b', description='null'}-hostA:27017] clusterDescriptionChanged 599582e36d47c231ec963b0b
2017-08-17 12:49:56,076 [cluster-ClusterId{value='599582e36d47c231ec963b0b', description='null'}-hostA:27017] REPLICA_SET_OTHER/hostB:27017/CONNECTED/{}
2017-08-17 12:49:56,077 [cluster-ClusterId{value='599582e36d47c231ec963b0b', description='null'}-hostA:27017] REPLICA_SET_OTHER/hostC:27017/CONNECTED/{}
2017-08-17 12:49:56,077 [cluster-ClusterId{value='599582e36d47c231ec963b0b', description='null'}-hostA:27017] REPLICA_SET_SECONDARY/hostA:27017/CONNECTED/{}
// ... the primary fails over to hostA:27017
2017-08-17 12:50:06,080 [cluster-ClusterId{value='599582e36d47c231ec963b0b', description='null'}-hostA:27017] clusterDescriptionChanged: 599582e36d47c231ec963b0b
2017-08-17 12:50:06,080 [cluster-ClusterId{value='599582e36d47c231ec963b0b', description='null'}-hostA:27017] REPLICA_SET_OTHER/hostB:27017/CONNECTED/{}
2017-08-17 12:50:06,080 [cluster-ClusterId{value='599582e36d47c231ec963b0b', description='null'}-hostA:27017] REPLICA_SET_SECONDARY/hostC:27017/CONNECTED/{}
2017-08-17 12:50:06,080 [cluster-ClusterId{value='599582e36d47c231ec963b0b', description='null'}-hostA:27017] REPLICA_SET_PRIMARY/hostA:27017/CONNECTED/{}
2017-08-17 12:50:07,126 [main] clusterClosed: 599582e36d47c231ec963b0b
शायद यह आपके लिए पर्याप्त है लेकिन यदि नहीं, तो उदाहरण के लिए, यदि आप निम्न में से कोई एक होता है तो केवल प्रतिक्रिया देने के बजाय आप प्रतिकृति स्थिति की सक्रिय रूप से निगरानी करना चाहते हैं ...
- क्लस्टर शुरू
- क्लस्टर रोक
- क्लस्टर वर्णन में परिवर्तन
... तो आप समय-समय पर परिणामों पर replicaset स्थिति सतर्क नमूना और रिपोर्ट करने के लिए/log/पसंद कर सकते हैं। आप इसे replSetGetStatus
कमांड निष्पादित करके और परिणामों की पूछताछ करके कर सकते हैं। यह आदेश एक BsonDocument देता है (जिसका प्रारूप here वर्णित है) जिसे पूछताछ और लॉग किया जा सकता है।
स्थिति दस्तावेज़ लॉगिंग सबसे सरल प्रतिक्रिया है, लेकिन दस्तावेज़ की सामग्री के आधार पर अलर्ट उठाकर निगरानी समाधान के आधार के रूप में उस दृष्टिकोण को बढ़ाया जा सकता है।
- replicationLag>threadhold
- lastHeartbeat> अब() के लिए कॉन्फ़िगर - कॉन्फ़िगर किया गया सीमा
- प्राथमिक की पहचान
- स्वास्थ्य बदल गया है = 1
- आदि
निम्न कोड प्रतिकृति स्थिति को पढ़ता है सहभागिता, यह पूछताछ (प्रतिकृति अंतराल की गणना सहित) और आउटपुट लॉग करता है।
MongoReplicaSetStatusLogger mongoReplicaSetStatusLogger = new MongoReplicaSetStatusLogger();
// periodically ...
MongoClient mongoClient = getMongoClient();
MongoDatabase admin = mongoClient.getDatabase("admin");
BsonDocument commandResult = admin.runCommand(new BsonDocument("replSetGetStatus", new BsonInt32(1)), BsonDocument.class);
mongoReplicaSetStatusLogger.report(commandResult);
यहाँ MongoReplicaSetStatusLogger
कार्यान्वयन है:
import org.bson.BsonDocument;
import org.bson.BsonInvalidOperationException;
import org.bson.BsonNumber;
import org.bson.BsonValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Optional;
public class MongoReplicaSetStatusLogger {
private static final Logger logger = LoggerFactory.getLogger(MongoReplicaSetStatusLogger.class);
private static final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss,SSSZ");
private static final String DEFAULT_VALUE = "UNKNOWN";
private static final String MEMBERS = "members";
public void report(BsonDocument replicasetStatusDocument) {
if (hasMembers(replicasetStatusDocument)) {
replicasetStatusDocument.getArray(MEMBERS).stream()
.filter(BsonValue::isDocument)
.map(memberDocument -> (BsonDocument) memberDocument)
.forEach(memberDocument -> logMemberDocument(memberDocument));
} else {
logger.warn("The replicaset status document does not contain a '{}' attributes, perhaps there has been " +
"a MongoDB upgrade and the format has changed!", MEMBERS);
}
}
private boolean hasMembers(BsonDocument replicasetStatusDocument) {
return replicasetStatusDocument.containsKey(MEMBERS) && replicasetStatusDocument.get(MEMBERS).isArray();
}
private void logMemberDocument(BsonDocument memberDocument) {
StringBuilder stringBuilder = new StringBuilder()
.append(logAttribute("node", getStringValue(memberDocument, "name")))
.append(logAttribute("health", getNumericValue(memberDocument, "health")))
.append(logAttribute("state", getStringValue(memberDocument, "stateStr")))
.append(logAttribute("uptime(s)", getNumericValue(memberDocument, "uptime")))
.append(logAttribute("lastOptime", getDateTimeValue(memberDocument, "optimeDate")))
.append(logAttribute("lastHeartbeat", getDateTimeValue(memberDocument, "lastHeartbeat")))
.append(logAttribute("lastHeartbeatRecv", getDateTimeValue(memberDocument, "lastHeartbeatRecv")))
.append(logAttribute("ping(ms)", getNumericValue(memberDocument, "pingMs")))
.append(logAttribute("replicationLag(s)", getReplicationLag(memberDocument)));
logger.error(stringBuilder.toString());
}
private String logAttribute(String key, Optional<String> value) {
return new StringBuilder(key).append("=").append(value.orElse(DEFAULT_VALUE)).append("|").toString();
}
private Optional<String> getStringValue(BsonDocument memberDocument, String key) {
if (memberDocument.containsKey(key)) {
try {
return Optional.of(memberDocument.getString(key).getValue().toUpperCase());
} catch (BsonInvalidOperationException e) {
logger.warn("Exception reading: {} from replicaset status document, message: {}.", key, e.getMessage());
}
}
return Optional.empty();
}
private Optional<String> getNumericValue(BsonDocument memberDocument, String key) {
if (memberDocument.containsKey(key)) {
BsonNumber bsonNumber = memberDocument.getNumber(key);
if (bsonNumber.isInt32()) {
return Optional.of(Integer.toString(bsonNumber.intValue()));
} else if (bsonNumber.isInt64()) {
return Optional.of(Long.toString(bsonNumber.longValue()));
} else if (bsonNumber.isDouble()) {
return Optional.of(Double.toString(bsonNumber.doubleValue()));
}
}
return Optional.empty();
}
private Optional<String> getDateTimeValue(BsonDocument memberDocument, String key) {
if (memberDocument.containsKey(key)) {
try {
return Optional.of(dateFormatter.format(new Date(memberDocument.getDateTime(key).getValue())));
} catch (BsonInvalidOperationException e) {
logger.warn("Exception reading: {} from replicaset status document due to: {}!", key, e.getMessage());
}
}
return Optional.empty();
}
private Optional<String> getReplicationLag(BsonDocument memberDocument) {
if (memberDocument.containsKey("optimeDate") && memberDocument.containsKey("lastHeartbeat")) {
try {
long optimeDate = memberDocument.getDateTime("optimeDate").getValue();
long lastHeartbeat = memberDocument.getDateTime("lastHeartbeat").getValue();
long replicationLag = lastHeartbeat - optimeDate;
return Optional.of(Long.toString(replicationLag));
} catch (BsonInvalidOperationException e) {
logger.warn("Exception reading 'optimeDate' or 'lastHeartbeat' from replicaset status document due to: {}!", e.getMessage());
} catch (IllegalArgumentException e) {
logger.warn("Exception calculating the replication lag due to: {}!", e.getMessage());
}
}
return Optional.empty();
}
}
यहाँ उत्पादन का एक उदाहरण है:
2017-08-17 15:44:35,192|[main]|ERROR|MongoReplicaSetStatusLogger|node=hostA:27017|health=1.0|state=PRIMARY|uptime(s)=21|lastOptime=2017-08-17T15:43:32,000+0100|lastHeartbeat=UNKNOWN|lastHeartbeatRecv=UNKNOWN|ping(ms)=UNKNOWN|replicationLag(s)=UNKNOWN|
2017-08-17 15:44:35,193|[main]|ERROR|MongoReplicaSetStatusLogger|node=hostB:27017|health=1.0|state=SECONDARY|uptime(s)=17|lastOptime=2017-08-17T15:43:20,000+0100|lastHeartbeat=2017-08-17T15:43:35,443+0100|lastHeartbeatRecv=2017-08-17T15:43:36,412+0100|ping(ms)=0|replicationLag(s)=15443|
2017-08-17 15:44:35,193|[main]|ERROR|MongoReplicaSetStatusLogger|node=hostC:27017|health=1.0|state=SECONDARY|uptime(s)=17|lastOptime=2017-08-17T15:43:20,000+0100|lastHeartbeat=2017-08-17T15:43:35,444+0100|lastHeartbeatRecv=2017-08-17T15:43:36,470+0100|ping(ms)=0|replicationLag(s)=15444|
अंतर्दृष्टि के लिए धन्यवाद। :) – nullpointer