이 글에서는 주로 클러스터 공유 메모리를 구현하기 위해 프로세스 통신을 사용하는 노드를 소개합니다. 편집자는 꽤 좋다고 생각하므로 지금 공유하고 참고용으로 제공하겠습니다. 편집자를 따라 살펴보겠습니다. 모두에게 도움이 되기를 바랍니다.
Node.js의 표준 API는 프로세스 공유 메모리를 제공하지 않습니다. 그러나 IPC 인터페이스의 전송 방법과 메시지 이벤트 모니터링을 통해 여러 프로세스 간의 협업 메커니즘을 구현하여 통신을 통해 공유 메모리를 운영할 수 있습니다.
##IPC 기본 사용법:
// worker进程 发送消息 process.send(‘读取共享内存'); // master进程 接收消息 -> 处理 -> 发送回信 cluster.on('online', function (worker) { // 有worker进程建立,即开始监听message事件 worker.on(‘message', function(data) { // 处理来自worker的请求 // 回传结果 worker.send(‘result') }); });
Node.js에서 send와 on('message', callback)을 통해 구현된 IPC 통신은 몇 가지 특징을 가지고 있습니다. 우선 마스터와 워커는 서로 통신이 가능하지만 워커는 직접적으로 통신할 수는 없지만 마스터 포워딩을 통해 워커는 간접적으로 통신할 수 있다. 또한 send 메소드를 통해 전달된 데이터는 JSON.stringify로 처리된 후 전달됩니다. 따라서 Buffer 객체는 전달된 후 배열이 되지만 함수를 직접 전달할 수는 없습니다. 반면에 버퍼와 함수를 제외한 모든 데이터 유형은 직접 전송할 수 있습니다(이미 매우 강력하며 버퍼와 함수는 대체 방법을 사용하여 전송할 수도 있습니다).
위의 특성을 바탕으로 IPC를 통해 메모리를 공유하는 솔루션을 설계할 수 있습니다.
1. 공유 메모리의 사용자로서 작업자 프로세스는 공유 메모리를 직접 운영하지 않고 마스터 프로세스에 이를 통해 쓰도록 알립니다. 메소드 전송(설정) 또는 읽기(가져오기) 작업.
2. 마스터 프로세스는 Object 개체를 공유 메모리로 초기화하고 작업자가 보낸 메시지에 따라 개체의 키 값을 읽고 씁니다.
3. 크로스 프로세스 통신이 사용되므로 작업자가 시작한 설정 및 가져오기는 요청에 따라 실제 읽기 및 쓰기 작업을 수행한 다음 결과를 작업자에게 반환합니다(즉, 전송). 결과 데이터를 작업자에게 보냅니다).
##데이터 형식
프로세스 간 비동기 읽기 및 쓰기 기능을 구현하려면 통신 데이터 형식을 표준화해야 합니다.
첫 번째는 작업자의 요청 데이터입니다.
requestMessage = { isSharedMemoryMessage: true, // 表示这是一次共享内存的操作通信 method: ‘set', // or ‘get' 操作的方法 id: cluster.worker.id, // 发起操作的进程(在一些特殊场景下,用于保证master可以回信) uuid: uuid, // 此次操作的(用于注册/调用回调函数) key: key, // 要操作的键 value: value // 键对应的值(写入) }
데이터를 받은 후 마스터는 메서드에 따라 해당 작업을 수행한 다음 requestMessage.id에 따라 해당 작업자에게 결과 데이터를 보냅니다. 데이터 형식은 다음과 같습니다.
responseMessage = { isSharedMemoryMessage: true, // 标记这是一次共享内存通信 uuid: requestMessage.uuid, // 此次操作的唯一标示 value: value // 返回值。get操作为key对应的值,set操作为成功或失败 }
데이터 형식 표준화의 의의는 마스터가 요청을 받은 후 처리 결과를 해당 작업자에게 보낼 수 있고, 작업자가 반환된 결과를 받은 후에는 이 통신에 해당하는 콜백을 호출하여 협업을 달성합니다.
데이터 형식을 표준화한 후 다음으로 해야 할 일은 마스터 프로세스와 작업자 프로세스에 대해 각각 두 개의 코드 세트를 설계하여 통신을 모니터링하고 통신 데이터를 처리하여 공유 메모리 기능을 구현하는 것입니다.
##User 클래스
User 클래스의 인스턴스는 작업자 프로세스에서 작동하며 공유 메모리 작동 요청을 보내고 마스터의 응답을 수신하는 일을 담당합니다.
var User = function() { var self = this; self.__uuid__ = 0; // 缓存回调函数 self.__getCallbacks__ = {}; // 接收每次操作请求的回信 process.on('message', function(data) { if (!data.isSharedMemoryMessage) return; // 通过uuid找到相应的回调函数 var cb = self.__getCallbacks__[data.uuid]; if (cb && typeof cb == 'function') { cb(data.value) } // 卸载回调函数 self.__getCallbacks__[data.uuid] = undefined; }); }; // 处理操作 User.prototype.handle = function(method, key, value, callback) { var self = this; var uuid = self.__uuid__++; process.send({ isSharedMemoryMessage: true, method: method, id: cluster.worker.id, uuid: uuid, key: key, value: value }); // 注册回调函数 self.__getCallbacks__[uuid] = callback; }; User.prototype.set = function(key, value, callback) { this.handle('set', key, value, callback); }; User.prototype.get = function(key, callback) { this.handle('get', key, null, callback); };
##Manager 클래스
Manager 클래스의 인스턴스는 마스터 프로세스에서 작동하며 개체를 공유 메모리로 초기화하고 키-값 쌍을 공유 메모리에 추가하는 데 사용됩니다. 사용자 인스턴스 또는 키 값을 읽고 결과를 다시 보냅니다.
var Manager = function() { var self = this; // 初始化共享内存 self.__sharedMemory__ = {}; // 监听并处理来自worker的请求 cluster.on('online', function(worker) { worker.on('message', function(data) { // isSharedMemoryMessage是操作共享内存的通信标记 if (!data.isSharedMemoryMessage) return; self.handle(data); }); }); }; Manager.prototype.handle = function(data) { var self = this; var value = this[data.method](data); var msg = { // 标记这是一次共享内存通信 isSharedMemoryMessage: true, // 此次操作的唯一标示 uuid: data.uuid, // 返回值 value: value }; cluster.workers[data.id].send(msg); }; // set操作返回ok表示成功 Manager.prototype.set = function(data) { this.__sharedMemory__[data.key] = data.value; return 'OK'; }; // get操作返回key对应的值 Manager.prototype.get = function(data) { return this.__sharedMemory__[data.key]; };
##사용방법
if (cluster.isMaster) { // 初始化Manager的实例 var sharedMemoryManager = new Manager(); // fork第一个worker cluster.fork(); // 1秒后fork第二个worker setTimeout(function() { cluster.fork(); }, 1000); } else { // 初始化User类的实例 var sharedMemoryUser = new User(); if (cluster.worker.id == 1) { // 第一个worker向共享内存写入一组数据,用a标记 sharedMemoryUser.set('a', [0, 1, 2, 3]); } if (cluster.worker.id == 2) { // 第二个worker从共享内存读取a的值 sharedMemoryUser.get('a', function(data) { console.log(data); // => [0, 1, 2, 3] }); } }
위는 IPC 통신을 통해 구현된 다중 프로세스 공유 메모리 기능인데, 이 방법은 마스터의 메모리에 직접 데이터를 캐시한다는 점에 유의해야 합니다. 프로세스에서는 메모리 사용에 주의를 기울여야 합니다. 여기서는 메모리 사용을 최적화하기 위한 몇 가지 간단한 제거 전략을 추가하는 것을 고려할 수 있습니다. 또한, 한 번에 읽고 쓴 데이터의 양이 상대적으로 많으면 그에 따라 IPC 통신에 소요되는 시간도 늘어납니다.
전체 코드: https://github.com/x6doooo/sharedmemory
관련 권장 사항:
laravel5.2 및 redis_cluster 구성 소개
MySQL-Cluster 클러스터 구성(수동 컴파일 및 설치 기반) 패키지) 상세 설명
위 내용은 클러스터 공유 메모리의 노드 구현에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!