Skip to the content.

Tars.js

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。

1. Scaffolding and automatic publishing tools

We provided Scaffolding and automatic publishing tools for Tars.js.

install:npm install -g @tars/nodetools-cli
init project:nodetools init
pack and publish:nodetools upload

2. Tars rpc server

Initialize the project like any other nodejs project.

tars protocol

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);
	};
}; 

Protocol file conversion

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.

rpc Server code implementation

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.

Package deploy publish

Code 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.

Use automatic publishing tools
By using the automatic publishing tool, you can save the operation of code packaging and publishing.
Run nodetools upload in the project directory.

3. Tars http server

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.

http server implement

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.

Packaging and deployment

Code packaging

same to code packagine of rpc server

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 publishing of rpc server

4. Tars client rpc

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.

Protocol file conversion

tars2node --client Hello.tars

Get the client agent file for the protocol

.
`-- HelloProxy.js

rpc client

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.

Operation of complex data structure

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

5. Other

Tars service template configuration

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.

Tars service business configuration

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.

One Server start multi Obj

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.