This document provides a quick start to step by step for several development scenarios of tars nodejs.
For more details and features, please refer to tars nodejs development document, And readme documents of each sub module。
Initialize the project like any other nodejs project.
Firstly, the protocol file is compiled with reference to tars protocol language document to specify the data structure and calling interface of the communication between the two sides.
This example implements a simple: Hello.tars:
module Hello
{
interface Test
{
int add(int a, int b, out int c);
};
};
After the protocol is written, it is converted to RPC server code through tars2node tool.
After the conversion, the code directory is as follows:
.
|-- Hello.js
|-- Hello.tars
|-- HelloImp.js
|-- node_modules
|-- package-lock.json
`-- package.json
Among them, 'hello.js' and' helloImp.js' are automatically generated server-side code.
To develop with typescript, you can use the command 'tars2node -- server -- TS hello. Tar' to convert.
At present, the tars2node tool only supports Linux system and has no other dependencies. If there is no Linux development environment, you can use docker to start a CentOS or Ubuntu container, download the tools and convert them.
After the protocol conversion, you only need to complete the interface logic code in the 'helloImp.js' file and write a service entry function to complete the RPC server code writing.
HelloImp.js interface:
"use strict";
var Hello = require("./Hello.js").Hello;
module.exports.Hello = Hello;
Hello.HelloProxyImp.prototype.initialize = function () {
//TODO::
};
Hello.HelloProxyImp.prototype.initialize = function () {
//TODO::
};
Hello.HelloProxyImp.prototype.add = function (current, a, b, c) {
c = a + b;
current.sendResponse(0, c);
};
In the code implemented by the interface, only two lines of code in the add function body need to be implemented by the developer himself.
Then implement a service entry file app.js:
const Tars = require("@tars/rpc");
const Hello = require("./HelloImp.js").Hello;
const APP_NAME = "Hello", SERVER_NAME = "HelloServer", OBJ_NAME = "HelloObj";
let servantName = `${APP_NAME}.${SERVER_NAME}.${OBJ_NAME}`;
let impMap = {
[servantName] : Hello.TestImp
};
Tars.server.getServant(process.env.TARS_CONFIG || `./${APP_NAME}.${SERVER_NAME}.config.conf`).forEach(function (config){
let svr = Tars.server.createServer(impMap[config.servant]);
svr.start(config);
});
With the success, this service can run on the tars platform.
app name
,SERVER_NAME is seerver name
,OBJ_NAME is Obj name
, Remember these three variables, which need to be used in service deploymentCode packing
The tars nodejs publishing package uses the tars-deploy module, which runs from the command line and needs to be installed globally: npm install @tars/deploy -g
After installation, run 'tars-deploy servicename' in the service root directory to generate a 'servicename.tgz' Publishing package in the service root directory. Note that the service name here and the service name in the entry point file, as well as the service name used for deployment on the platform, should be consistent.
Server Deploy
Log in to the tars management platform and access the Operation - & gt; deployment.
App = Application name in entry point file
Server Name = Service name in entry point file
Server Type = tars_nodejs
Template = tars.default
NodeName = tarsnode node ip
Port = server port
Protocol = TARS
Submit
Publishing
Access service management - & gt; service management - & gt; in the left menu, select the deployed Service - & gt; publishing management - & gt; check the node - & gt; publish the selected node - & gt; upload publishing package - & gt; publish
After publishing successfully, you can see that the node status is active on the service management page. At this point, the process of packaging, deploying and publishing is completed, and an RPC server of tars-nodejs can provide services.
Section 1 describes how to develop a tars service and deploy it to the tars platform. There are no restrictions on the application communication protocol in the tars platform. We can also run a nodejs service that provides HTTP protocol on the tars platform. In addition to data encoding and decoding, packet forming protocol and tars protocol are different, process management, monitoring and reporting, log collection and other features can be enjoyed.
Select the framework according to business needs and your preferences (! Tars does not limit the framework you use!) , write business code:
Node.js web HTTP Server demo:
const http = require('http');
const hostname = process.env.IP || '127.0.0.1';
const port = process.env.PORT || 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
Koa web HTTP Server demo:
const Koa = require('koa');
const app = new Koa();
const hostname = process.env.IP || '127.0.0.1';
const port = process.env.PORT || 3000;
app.use(async ctx => {
ctx.body = 'Hello World';
});
app.listen(hostname, port);
The above example program, running on the tars platform, only needs to modify the IP and port, which can be obtained from the environment variables.
Code packaging
same to 1.4 chart
Server Deploy
Log in to the tars management platform and access the Operation - & gt; deployment.
App = Application name
Server Name = Service name
Server Type = tars_nodejs
Template = tars.default
NodeName = tarsnode node ip
Port = server port
Protocol = NOT TARS
Publishing
same to 1.4 chart
This section describes how to call tars RPC through the tars RPC client.
The RPC server being called is not limited to languages. Here, take the HelloServer published in Section 1 as an example.
tars2node --client Hello.tars
Get the client agent file for the protocol
.
`-- HelloProxy.js
const Tars = require("@tars/rpc").client;
const Hello = require("./HelloProxy.js").Hello;
const proxy = Tars.stringToProxy(Hello.TestProxy, "Hello.HelloServer.HelloObj");
proxy.add(6, 7).then((data)=>{
console.log("response return:", data.response.return)
console.log("response arguments:", data.response.arguments.c)
console.log("costtime", data.response.costtime)
}).catch((e)=>{
console.log("error code:", e.response.error.code)
console.log("error message:", e.response.error.message)
console.log("costtime", e.response.costtime)
})
In the actual development, it should be noted that the proxy object should be made into a singleton, instead of generating a proxy object every time.
The Example protocol in Section 1 only contains a very simple int type data structure, which will be quite complex and changeable in practical application. Tars nodejs uses @tars/stream module to process data encoding and decoding.
To remember, in the process of interface call in tars RPC, except that the basic type data can directly use the js native type, the data of struct/map/list type must be operated by the type encapsulated by the codec module, such as the input and output parameters of add interface
module Hello
{
struct AddReq {
0 require iNum1;
1 require iNum2;
2 optional map<string, string> mContext;
};
struct AddRsp {
0 require iRet;
1 require iResult;
2 optional map<string, string> mContext;
};
interface Test
{
int add(AddReq stReq, out AddRsp stRsp);
};
};
When we call the interface, the input parameter needs to be converted from js object to addreq structure class. The most convenient method is to convert it through the 'readFromObject' member function of the structure class
let stReq = new Hello.AddReq()
stReq.readFromObject({
iNum1: 1,
iNum2: 2
})
proxy.add(stReq)...
When you get the result, you get the object of addrsp class. If you want to use js native object, you need to convert it. You can convert it through the 'toObject' member function of the structure class
proxy.add(stReq).then((data)=>{
let rsp = data.response.arguments.stRsp.toObject()
...
})...
Not only struct data type, vector and map also have this pair of native functions of tars object conversion. In addition to these two functions, the @tars/stream module provides more detailed codec functions. If necessary, please refer to its readme documentation
When starting the tars service, you need to specify a template configuration file. All the properties we set when deploying the service on the platform, as well as some system default configuration items, will be written to this configuration file. You can see the contents of various parent templates in tars template configuration document.
We can add our own private template according to the template configuration format in the service management - & gt; service list - & gt; editing. When the service is published, the private template will also be merged into the template configuration file.
The content of template configuration can be parsed through utils module template parser in the service. When the service is running on the tar platform, the file path of template configuration can be obtained through process.env.TARS_CONFIG
.
In addition to the template configuration files generated by the tars platform for each service, each service may also have its own configuration files, such as business DB configuration, an open platform key configuration, etc.
The tars platform provides the function of business profile management. The way to add the profile is service management - & gt; service configuration - & gt; add configuration
The configuration file can be in any format. Tars nodejs reads the business configuration file added in the platform through the tars config module. We will not go into details here. We can see the detailed usage in the module readme.
When we want to start more than one Obj in a service, some implement the tars protocol to provide RPC calling service, and some implement the HTTP protocol, we can operate as follows:
On the platform, service management - & gt; service list - & gt; management service - & gt; add service, fill in the service information to be added, for example, add a not-tars protocol service to the service in Section 1.
After adding and republishing the service, the template configuration of the service becomes like this:
<server>
node=tars.tarsnode.ServerObj@tcp -h 172.17.0.4 -p 19386 -t 60000
app=Hello
server=HelloServer
localip=172.17.0.4
local=tcp -h 127.0.0.1 -p 3032 -t 3000
basepath=/usr/local/app/tars/tarsnode/data/Hello.HelloServer/bin/
datapath=/usr/local/app/tars/tarsnode/data/Hello.HelloServer/data/
logpath=/usr/local/app/tars/app_log/
logsize=10M
config=tars.tarsconfig.ConfigObj
notify=tars.tarsnotify.NotifyObj
log=tars.tarslog.LogObj
deactivating-timeout=3000
logLevel=DEBUG
<Hello.HelloServer.HelloObjAdapter>
allow
endpoint=tcp -h 172.17.0.4 -p 3031 -t 60000
handlegroup=Hello.HelloServer.HelloObjAdapter
maxconns=200000
protocol=tars
queuecap=10000
queuetimeout=60000
servant=Hello.HelloServer.HelloObj
threads=5
</Hello.HelloServer.HelloObjAdapter>
<Hello.HelloServer.HelloHttpObjAdapter>
allow
endpoint=tcp -h 172.17.0.4 -p 3032 -t 60000
handlegroup=Hello.HelloServer.HelloHttpObjAdapter
maxconns=200000
protocol=not_tars
queuecap=10000
queuetimeout=60000
servant=Hello.HelloServer.HelloHttpObj
threads=3
</Hello.HelloServer.HelloHttpObjAdapter>
</server>
Compared with the previous section, the configuration section <Hello.HelloServer.HelloHttpObjAdapter>
is added, which is the embodiment of adding servant in template configuration on the management platform.
Next, modify the service entry point code:
const Tars = require("@tars/rpc");
Tars.server.getServant(process.env.TARS_CONFIG).forEach(function (config){
if(config.protocol === "tars"){
//TODO implement tars rpc server start code
} else {
//TODO implement http server start code
}
});
After parsing the template configuration file, the config returned by Tars.server.getServant is the attribute in each adapter configuration section. Developers can listen to the port according to the endpoint attribute.
At this point, the service starts two obj and implements two different protocols on two ports.