RPC calls
Similar to Ajax
The first similarity: in short, it is between two devices to call 1. Ajax is browser to server 2. RPC is server to serverCopy the code
The second similarity is that both parties need to agree on a data formatCopy the code
Different from Ajax
1. Ajax uses DNS as the addressing service. 2. 1. Ajax application layer uses HTTP (HTML/JSON) 2. RPC communication generally uses binary protocolCopy the code
Addressing/load balancing
The Ajax addressing process takes the domain name to DNS for resolution, and then initiates the actual requestCopy the code
RPC also requires addressing before making a network request, because IP is not necessarily used for the request, but a uniform identifier such as ID (L5, VIP) may be used, which is parsed by the addressing server, and then the actual request is made through the returned IPCopy the code
TCP communications
Simplex communication: always sending data from one end to the other (client -- server)Copy the code
Half duplex communication: Both parties can send data, but only one end can send data at a time, also known as' round simplex communication 'Copy the code
Full-duplex communication: When the client sends data, the server can also send dataCopy the code
Binary protocol
. Smaller packet size. Faster encoding speed RPC [0001 0000 1111 0101]Copy the code
Node.js Buffer codec binary packets
Introduction to buffer Module
There are three ways to create buffers: Alloc 2. buffer. from 3. buffer. allocUnsafe // From creates a Buffer from an existing data structure const buffer1 = Buffer.from('test'); const buffer2 = Buffer.from([1, 2, 3]); · const buffer3 = buffer. alloc(10); console.log(buffer1); // <Buffer 74 65 73 74> console.log(buffer2); // <Buffer 01 02 03> console.log(buffer3); // <Buffer 00 00 00 00 00 00 00 00 00 00>Copy the code
Buffer.allocUnsafe: This method addresses the memory management mechanism of the Buffer module
Const buffer2 = buffer. from([1, 2, 3]); buffer2.writeInt8(12, 0) console.log(buffer2); // <Buffer 0c 02 03> buffer2.writeInt16BE(512, 1) console.log(buffer2); WriteInt16LE (512, 1) console.log(buffer2); // <Buffer 0c 02 00> BE/LE // <Buffer 0c 00 02> 00 02 // <Buffer 0c 00 02> 00 02 //Copy the code
Protocol buffers library:
Can achieve similar JSON. Stringfly as simple operation, do not need like the one above the trouble to write binary https://github.com/protocolbuffers/protobuf this is compatible with the front end, so there is no above the wellCopy the code
// test.proto
message Test {
required float num = 1;
required string payload = 2;
}
Copy the code
// index.js
const fs = require('fs');
const protobuf = require('protocol-buffers');
const schema = protobuf(fs.readFileSync(__dirname + '/test.proto', 'utf-8'));
console.log(schema)
// Messages {
// Test: {
// type: 2,
// message: true,
// name: 'Test',
// buffer: true,
// encode: [Function: encode] { bytes: 0 },
// decode: [Function: decode] { bytes: 0 },
// encodingLength: [Function: encodingLength],
// dependencies: [ [Object], [Object] ]
// }
// }
const buffer = schema.Test.encode({
num: 2,
payload: 'test'
})
console.log(buffer) // <Buffer 0d 00 00 00 40 12 04 74 65 73 74>
console.log(schema.Test.decode(buffer)) // { num: 2, payload: 'test' }
Copy the code
Node.js net builds multiplexed RPC channels
Net module
Net module is similar to HTTP module, which is relatively simple. Since it is a channel, it has two ends, which are represented by Clinet and ServerCopy the code
Simplex communication case
Half duplex communication case
Full duplex communication
- server.js
const net = require('net'); const server = net.createServer((socket) => { let oldBuffer = null; Socket. on('data', function (buffer) {if (oldBuffer) {buffer = buffer. concat([oldBuffer, buffer]); } let packageLength = 0; While (packageLength = checkComplete(buffer)) {const package = buffer.slice(0, packageLength); buffer = buffer.slice(packageLength); // unpack this package into data and seq const result = decode(package); Socket. write(encode(LESSON_DATA[result.data], result.seq)); } oldBuffer = buffer; })}); server.listen(4000); Function encode(data, seq) {function encode(data, seq) { Const body = buffer. from(data) const body = buffer. from(data) const body = buffer. from(data) Const header = buffer.alloc (6); const header = buffer.alloc (6); const header = buffer.alloc (6); header.writeInt16BE(seq) header.writeInt32BE(body.length, 2); const buffer = Buffer.concat([header, body]) return buffer; } /** * Binary packet decoding function */ function decode(buffer) {const header = buffer.slice(0, 6); const seq = header.readInt16BE(); // In order not to confuse the point, this example is relatively simple, Const body = buffer.slice(6).readint32be () const body = buffer.slice(6).readint32be () return {seq, data: Body}} /** * Checks if a buffer is a complete packet. * If the buffer is longer than the bodyLength of the header and body, the buffer length is returned, indicating that the buffer is complete. * @param {} buffer */ function checkComplete(buffer) {if (buffer.length < 6) {return 0; } const bodyLength = buffer.readInt32BE(2); Return 6 + bodyLength} / / false data const LESSON_DATA = {136797: "01 | course is an introduction," 136798:02 | content review, 136799: What is "03 | Node. Js"?" 04, 136800: "| Node. Js can be used to do?" 05, 136801: "| course introduces practical project", 136803: "06 | what is technical pre-research?" , 136804: "07 | Node. Js development environment installed", 136806: "08 | the first Node. Js program: rock-paper-scissors game", 136807: "09 | module: CommonJS standard", 136808: "10 | module: using transformation module specification rock-paper-scissors game", 136809:11 | module: NPM, 141994: "12 | module: Node. Js built-in module", 143517: "13 | asynchronous, non-blocking I/O", 143557: "Callback" of 14 | asynchronous: asynchronous programming, 143564: "15 | asynchronous: event loop", 143644: "the Promise of 16 | asynchronous: asynchronous programming", 146470: "17 | asynchronous: the async/await" of asynchronous programming, 146569: "18 | HTTP: HTTP server is what?" 19, 146582: "| HTTP: simple implementation a HTTP server"}Copy the code
- client.js
const net = require('net'); const socket = new net.Socket({}); Socket.connect ({host: '127.0.0.1', port: 4000}); const LESSON_IDS = [ "136797", "136798", "136799", "136800", "136801", "136803", "136804", "136806", "136807", "136808", "136809", "141994", "143517", "143557", "143564", "143644", "146470", "146569", "146582" ] let id = Math.floor(Math.random() * LESSON_IDS.length); let oldBuffer = null; Socket. on('data', (buffer) => {// Connect the last data event to the residual buffer if (oldBuffer) {buffer = buffer. concat([oldBuffer, buffer]); } let completeLength = 0; While (completeLength = checkComplete(buffer)) {const package = buffer.slice(0, completeLength); buffer = buffer.slice(completeLength); // unpack this package into data and seq const result = decode(package); Console. log(' package ${result.seq}, return value ${result.data} '); } oldBuffer = buffer; }) let seq = 0; Function encode(data) {function encode(data) {function encode(data) { Const body = buffer.alloc (4); const body = buffer.alloc (4); const body = buffer.alloc (4); body.writeInt32BE(LESSON_IDS[data.id]); Const header = buffer.alloc (6); const header = buffer.alloc (6); const header = buffer.alloc (6); header.writeInt16BE(seq) header.writeInt32BE(body.length, 2); // const buffer = buffer.concat ([header, body]) console.log(' package ${seq} is ${LESSON_IDS[data.id]} '); seq++; return buffer; } /** * Binary packet decoding function */ function decode(buffer) {const header = buffer.slice(0, 6); const seq = header.readInt16BE(); Const body = buffer.slice(6) return {seq, data: body.tostring ()}} /** * Checks if a buffer is a complete packet. * If the buffer is longer than the bodyLength of the header and body, the buffer length is returned, indicating that the buffer is complete. * @param {} buffer */ function checkComplete(buffer) {if (buffer.length < 6) {return 0; } const bodyLength = buffer.readInt32BE(2); return 6 + bodyLength } for (let k = 0; k < 100; k++) { id = Math.floor(Math.random() * LESSON_IDS.length); socket.write(encode({ id })); }Copy the code