background

Nodejs 4.x project, which needed to be upgraded to 6.9.5(the latest stable release at the time) to improve performance and reliability.

Co is used in services, and processes are managed using PM2.

Upgrade the NodeJS version

Make sure the build script is able to install NodeJS 6.9.5 using NVM and run basic OK locally

Start with co

UnhandledPromiseRejectionWarning: Cannot read property 'done' of undefined
Copy the code

The above alarm message will be generated when the service is started, and the service is unavailable. It is found that there is a promise, reject, but no catch. I know the direct cause of this, but it doesn’t help. Where am I going to find code for this feature?

Consider breakpoint debugging

process.on('unhandledRejection', function(reason, p){
  console.log('=======================');
  console.log(reason);
  console.log(p);
});
Copy the code

Add the above code to the service startup, local debugging starts, and everything is fine -_-b

Do not reproduce the problem, review the entire problem, visual may be a test environment problem, first look at the NodeJS version

console.log(process.versions)
Copy the code

The NodeJS version is still an old one

The problem of pm2

The only way to determine the nodeJS version is if the process starts, and the problem falls on PM2. Check the pM2 process configuration

> pm2 show myapp_name │ interpreter │ node │ interpreter args │ harmony.... │ exec mode │ cluster_mode │ node.js version │ 4.4.2Copy the code

Considering the pM2 process management model, when daemon processes are started, worker processes are started one by one. Exec mode: Cluster_mode means that it uses nodeJS cluster module to start child processes.

Further, the cluster startup child is fork() and the version of the child and parent should be the same. That’s probably the reason.

A simple way to restart a Daemon process is to kill the daemon and all worker processes and then pm2 start. The conclusion:

  1. Daemon process update, exceptpm2 kill && pm2 pingIn addition to restarting the daemon, you canpm2 updateIt also uses the current version PM2
  2. Do you want to make your app work or do you want to add your app again?pm2 delete app.json && pm2 start app.json

After the pm2 daemon is restarted in the test environment, the startup is still the same as the previous alarm, but the Node.js version output is as expected.

It doesn’t solve the problem, but an upgrade is necessary. Keep looking, gather clues

So let’s go back to co

The nodeJS version is now consistent, but the test environment is reporting a local failure, so the interpreter args: –harmony is detected

This is a switch added by older NodeJS versions to accommodate new features, considering that the error stack is coming from CO, check the CO documentation

After v4+ does not need to add this switch, do not care about why to add this switch, the difference that can be found at present is this place, first local add this switch to run see

Results The same alarm was repeated, and the local and test environment phenomena were consistent

Pm2 delete app.json && pm2 start app.json

conclusion

  1. Pm2 cluster_mode The daemon process needs to be updated during nodeJS upgrade
  2. The configuration of worker processes also needs to be manually updated
  3. Nodejs does not guarantee compatibility with some experimental switches

The actual environmental problems encountered may be a mix of multiple key causes, all of which must be addressed in order to work properly.

Wrong is the norm, right is a series of accidental combinations

Remaining questions: — How did Harmony add it

Those of you who know about clusters should know that fork() has only one parameter environment variable, which is somewhat strange.

One possibility is that the PM2 Daemon was added when it was started, but this is illogical. Daemons may manage multiple projects, some cluster, some not.

Just guess obviously not, look at the source code

God.nodeApp = function nodeApp(env_copy, cb){ var clu = null; console.log('Starting execution sequence in -cluster mode- for app name:%s id:%s', env_copy.name, env_copy.pm_id); If (env_copy node_args && Array. IsArray (env_copy. Node_args)) {/ / pay attention to the following line of this cluster. Settings. ExecArgv = env_copy. Node_args;  } env_copy._pm2_version = pkg.version; try { // node.js cluster clients can not receive deep-level objects or arrays in the forked process, e.g.: // { "args": ["foo", "bar"], "env": { "foo1": "bar1" }} will be parsed to // { "args": "foo, bar", "env": "[object Object]"} // So we passing a stringified JSON here. clu = cluster.fork({pm2_env: JSON.stringify(env_copy)}); } catch(e) { God.logAndGenerateError(e); return cb(e); }Copy the code

Revisiting the cluster documentation shows that cluster.Settings does exist


Hello everyone, I am Cao Yu, the front-end technology expert of Maoyan Entertainment. I am mainly responsible for the front-end business of Maoyan Entertainment movie seat selection transaction. In addition to various Web pages that you can see, there are also small programs and supply chain. At the same time, be responsible for the front-end infrastructure and quality assurance of Maoyan.

Maoyan movie mini program has grown from zero to the first place in ticket category, and its main focus is online. This time, we share an online and offline linkage activity. From development to launch, we have encountered some interesting things, not only the in-depth application of mini program technology, but also the thinking of product operation.

This Saturday (October 21), I will be a guest at the Bilibili studio of the Nuggets to do a live broadcast of “The Code Guide: From cat’s Eye scan code 1 minute purchase”. We will also give away technical books, large custom mouse pads and other prizes during the live broadcast. Welcome to join us on Saturday afternoon.