我是一个节点菜鸟,试图了解如何在node.js应用程序中实现auto discovery。我将使用cluster module并希望每个工作进程保持最新(并持久连接到)弹性缓存节点。
由于没有共享内存的概念(如PHP APC),您是否必须拥有在每个工作程序中运行的代码,每X秒唤醒一次并以某种方式更新IP列表并重新连接内存缓存客户端? / p>
今天人们如何解决这个问题?示例代码将非常感激。
答案 0 :(得分:3)
请注意,此时,Auto Discovery仅适用于运行memcached引擎的缓存群集。
对于缓存引擎版本1.4.14或更高版本,您需要为缓存群集配置端点(或任何缓存节点端点)创建TCP / IP套接字并发送此命令:
config get cluster
使用Node.js,您可以使用net.Socket class来实现。
答复由两行组成:
配置信息的版本号。每次在缓存集群中添加或删除节点时,版本号都会增加一个。
缓存节点列表。列表中的每个节点由主机名| ip-address |端口组表示,每个节点由空格分隔。
回车符和换行符(CR + LF)出现在每一行的末尾。
您可以在此处找到有关如何add Auto Discovery to your client library的详尽说明。
使用群集模块,您需要在每个进程(即子进程)中存储相同的信息,我将使用" setInterval"每个孩子定期检查(例如每60秒)节点列表,如果列表已经改变,则重新连接 (这不应经常发生)。
您可以选择仅更新主服务器上的列表并使用" worker.send"更新工人。这可以使单个服务器中运行的所有进程保持同步,但在多服务器体系结构中无济于事,因此使用一致哈希非常重要,以便能够更改节点列表和松散的"最小值"存储在memcached群集中的密钥数量。
我会使用全局变量来存储这种配置。
您可以使用适用于Node.js的AWS SDK 来获取ElastiCache节点列表(这也适用于Redis引擎)。
在这种情况下,代码将类似于:
var util = require('util'),
AWS = require('aws-sdk'),
Memcached = require('memcached');
global.AWS_REGION = 'eu-west-1'; // Just as a sample I'm using the EU West region
global.CACHE_CLUSTER_ID = 'test';
global.CACHE_ENDPOINTS = [];
global.MEMCACHED = null;
function init() {
AWS.config.update({
region: global.AWS_REGION
});
elasticache = new AWS.ElastiCache();
function getElastiCacheEndpoints() {
function sameEndpoints(list1, list2) {
if (list1.length != list2.length)
return false;
return list1.every(
function(e) {
return list2.indexOf(e) > -1;
});
}
function logElastiCacheEndpoints() {
global.CACHE_ENDPOINTS.forEach(
function(e) {
util.log('Memcached Endpoint: ' + e);
});
}
elasticache.describeCacheClusters({
CacheClusterId: global.CACHE_CLUSTER_ID,
ShowCacheNodeInfo: true
},
function(err, data) {
if (!err) {
util.log('Describe Cache Cluster Id:' + global.CACHE_CLUSTER_ID);
if (data.CacheClusters[0].CacheClusterStatus == 'available') {
var endpoints = [];
data.CacheClusters[0].CacheNodes.forEach(
function(n) {
var e = n.Endpoint.Address + ':' + n.Endpoint.Port;
endpoints.push(e);
});
if (!sameEndpoints(endpoints, global.CACHE_ENDPOINTS)) {
util.log('Memached Endpoints changed');
global.CACHE_ENDPOINTS = endpoints;
if (global.MEMCACHED)
global.MEMCACHED.end();
global.MEMCACHED = new Memcached(global.CACHE_ENDPOINTS);
process.nextTick(logElastiCacheEndpoints);
setInterval(getElastiCacheEndpoints, 60000); // From now on, update every 60 seconds
}
} else {
setTimeout(getElastiCacheEndpoints, 10000); // Try again after 10 seconds until 'available'
}
} else {
util.log('Error describing Cache Cluster:' + err);
}
});
}
getElastiCacheEndpoints();
}
init();