연구 노트 - RPC 서버
proxies.user.test.service.echo(routeParam, 'hello', function(err, resp) {
if(err) {
console.error(err.stack);
return;
}
console.log(resp);
});
위의 RPC 호출은 다음과 같이 이해할 수 있다. namespace 형식은user, 서버 형식은test의 서비스 모듈을 호출하는 echo 인터페이스는 지금 듣기에 약간 까다롭다. 괜찮다. 그리고 내가 천천히 분석하는 것을 들어라.)
서버 원본 분석
pomelo-rpc의 원본 코드는 제가 +debug를 30번 읽었습니다. 다음은 베이스 데이터 교환 모듈에서 상부 업무 논리 분배 처리 방식에 따라 서버와 클라이언트의 원본 코드 구조를 순서대로 소개하겠습니다.
1. 소켓 기반.io 모듈의 데이터 통신 모듈
socket , :
pomelo-rpc 。nodejs events 。 :
var Acceptor = function(opts, cb) {
EventEmitter.call(this);
this.bufferMsg = opts.bufferMsg;
this.interval = opts.interval || 300;
this.whitelist= opts.whitelist;
this._interval = null;
this.sockets = {};
this.msgQueues = {};
this.server = null;
this.notify = cb;
};
util.inherits(Acceptor, EventEmitter);
node에 내장된 util이 제공하는 계승 함수를 이용하여 간단한 두 마디로 Acceptor는 이벤트를 계승합니다.nodejs 소스 코드
inherits
함수를 펼치는 것도 상당히 간단하다.var inherits = function(sub, super) {
var tmp = function() {}
tmp.prototype = super.prototype;
sub.prototype = new tmp();
}
이런 기생 조합식의 계승을 통해 부류의 구조 함수를 두 번 호출하는 것을 피할 수 있기 때문에 이곳은 많이 전개되지 않는다.
Acceptor :
bufferMsg
: 버퍼 대기열 설정 여부interval
: 시간 데이터 전송 모듈의 간격을 설정합니다. Acceptor가 감청을 켤 때 설정 정보에 따라 타이머를 켤지 여부를 결정합니다. 시간 리셋 버퍼: if(this.bufferMsg) {
this._interval = setInterval(function() {
flush(self);
}, this.interval);
}
flush 함수는 주로 버퍼링 데이터를 socket을 통과하는 것을 책임집니다.io 인터페이스 쓰기:
var flush = function(acceptor) {
var sockets = acceptor.sockets;
var queues = acceptor.msgQueues;
var queue, socket;
for(var socketId in queues) {
socket = sockets[socketId];
if(!socket) {
delete queues[socketId];
continue;
}
queue = queues[socketId];
if(!queue.length) {
continue;
}
socket.emit('message', queue);
queues[socketId] = [];
}
};
모든 클라이언트 링크는 데이터 버퍼 대기열에 대응하여'메시지'메시지를 보내는 방식으로 데이터를 보냅니다.
IP 주소 필터링 감청 오픈 후 클라이언트 링크(onconnection 이벤트)가 있으면 첫 번째 일은 IP 주소 필터입니다. IP 주소 화이트리스트도 구조 함수를 통해 주입됩니다.
whitelist
.IP 주소가 올바르지 않으면 링크를 닫고 경고 메시지를 내보냅니다.데이터 처리 모듈 상부 모듈은 설정 정보를
notify
리셋 함수에 주입하고 acceptor
데이터를 감청한 후 먼저 데이터를 상부에 던진다.상부 처리가 끝난 후 버퍼가 필요하면 대기열에 기록합니다. 그렇지 않으면 바로 발송합니다. acceptor.notify.call(null, pkg.msg, function() {
var args = Array.prototype.slice.call(arguments);
for(var i = 0, l = args.length; i < l; i++) {
if(args[i] instanceof Error) {
args[i] = cloneError(args[i]);
}
}
var resp = {id: pkg.id, resp: Array.prototype.slice.call(args)};
if(acceptor.bufferMsg) {
enqueue(socket, acceptor, resp);
}
else {
socket.emit('message', resp);
}
});
2. 라우팅 요청 배포 모듈
acceptor 모듈 위에 있는 것은
gateway
모듈로 이 모듈은 주로 acceptor 모듈의 창설과 폐기, 상태 제어를 책임진다.먼저 acceptor 모듈을 만들 때 함수를 전달합니다.this.acceptor = this.acceptorFactory.create(opts, function(msg, cb) {
dispatcher.route(msg, cb);
});
공장 방법을 통해acctpor 실례를 구축하면 베이스 데이터 처리 모듈이 통신 프로토콜을 편리하게 교체할 수 있다.여기서 함수를 리셋하는 작업은 배달 함수를 호출하여 구체적인 서비스 제공자에게 요청을 전달하는 것이다.디스패치의 실현을 살펴보자.
var Dispatcher = function(services) {
EventEmitter.call('this');
var self = this;
this.on('reload', function(services) {
self.services = services;
});
this.services = services;
};
util.inherits(Dispatcher, EventEmitter);
Dispatcher 모듈도 이벤트 트랜시버가 됩니다.동시에 구조기는
services
파라미터를 수신한다.매개 변수가 루트 요청에 협조할 때 전송된 매개 변수에 따라 요청을 구체적인 하위 모듈에 전달할 수 있다.그래서 dispatcher.route(msg, cb);
매개 변수와 일치하여 대응하는 인터페이스를 호출하는 것에 불과하다.구조기가 reload
사건을 감청하는 것을 보면 이 사건은 어떤 작용을 합니까?이것은 사실 포멜로의 RPC 핫플러그 모듈의 실현이다.구현이 간단합니다.var watchServices = function(gateway, dispatcher) {
var paths = gateway.opts.paths;
var app = gateway.opts.context;
for(var i = 0; i < paths.length; i++) {
(function(index) {
fs.watch(paths[index].path, function(event, name) {
if(event === 'change') {
var res = {};
var item = paths[index];
var m = Loader.load(item.path, app);
if(m) {
res[namespace] = res[namespace] || {};
for(var s in m) {
res[item.namespace][s] = m[s];
}
}
dispatcher.emit('reload', res);
}
});
})(i);
}
};
gateway
모듈은 시작할 때 설정 정보에 따라 watchServices
감청 모듈의 변화를 호출합니다.데이터 파일이 변경되면 다시 로드services
하고 라우팅 배포 모듈에 알립니다.서버와 클라이언트의 정상적인 통신을 확보하기 위해 하부 데이터 형식의 일치를 제외하고 또 하나는 루트 정보의 일치이다.Gateway를 호출하여 전송되는 구성 경로는 다음과 같습니다.var paths = [
{namespace: 'user', path: __dirname + '/remote/test'}
];
현재 디렉터리에
/remote/test/service.js
파일이 있고 파일에는 두 개의 인터페이스 test1/test2
가 포함되어 있다고 가정하십시오.load
이후 반환되는 객체는 다음과 같습니다.{
service: {
test1: 'function xxx',
test2: 'function yyy'
}
}
또한 포멜로에서는 시스템 RPC 서비스와 사용자 정의 RPC 서비스가 있습니다. 완전한 루트 정보는 다음과 같습니다.
services: {
sys: {
sys_module1: {
sys_module1_interface1: 'xxx'
}
},
user: {
user_module1: {
user_module1_interface1: 'yyy'
}
}
}
서비스 측의 다른 것들은 모두 비교적 간단하다. 맥락을 분명히 하기 위해 상기 코드는 삭제를 거친 것이기 때문에 흥미가 있으면 여기에 가서 찾을 수 있다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
OpenStack-RPC-server 구축 (4)상술한 설명에 의하면, 우리는 ConnectionContext 클래스가 사실 모든 oslo 에 해당한다는 것을 안다메시지 층의connection 의뢰 에이전트 클래스입니다.ConnectionContext 객체를 사용...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.