📜 ⬆️ ⬇️

12 tips for scaling Node.js

Node.js is already successfully operating on a global scale, as evidenced by the deployed applications on it by companies such as Netflix, Reddit, Walmart and Ebay. However, it has its own set of problems when scaling; both in terms of scaling people working on a single code base, so in terms of vertical and horizontal scaling in the cloud. In addition to my personal experience scaling Node.js when working in companies such as Reddit and Netflix, I spoke with some experts working in Microsoft Azure, and came up with some tips for you on scaling Node.js in your company.

Write a quality Node.js


The sooner you start using linters, formatting and type checking tools in your code, the better.

These things can be complicated when introduced in the middle of a project due to the potentially large amount of refactoring that may be required, it can also pollute your git history, but in the end these tools will help you make the code readable.
If you still do not use them, immediately turn your eyes towards ESLint and Prettier . ESLint protects your code from bad patterns, Prettier also helps to automatically format your code before pull request.

A more significant solution is to add tools such as Flow or TypeScript to your code base. These tools allow you to catch more subtle errors, such as calling a function with a numeric parameter instead of a string one, or calling the .filter method on objects instead of an array. Despite the complexity and the need to train your team, these tools deserve your attention: they can speed development through Intellisense and prevent runtime errors due to type protection.
')

Write tests


Tests have always been a difficult question for developers. Some thoroughly believe in test-driven development, while others rarely write tests at all. But there is a middle ground:


The starting point for writing tests is the ability to confidently deploy new code. Write tests so many that they are no less than you yourself feel it, but try to write no more than the above list.

Stateless design


The key when writing a scalable Node.js is that your servers do not have to store states for someone or something. This will prevent horizontal scaling. Move the state to another application and solve the problem elsewhere (for example, Redis, Etcd, ...). This is worth thinking in advance. Then it will be very difficult to unravel if you have not done this before. This will also help if you ever decide to decompose monoliths into microservices.

Statistics: for development - Node.js, for production - CDN


I wish companies would see an error in this error. Maintaining your static assets from your web application (in particular, through something like webpack-dev-server or Parsel's dev server) is a great developer experience because it reduces the injection cycle when writing code. However, you should never maintain your statics through Node.js. It must be shipped separately via CDN, for example Azure CDN.

The return of statics from Node.js is unnecessarily slow, because CDNs are more scattered and, therefore, physically closer to the end user, besides the CDN servers are highly optimized for small resources. Static maintenance with Node is also unnecessarily expensive, since Node.js server time is much more expensive than CDN server time.

Start Deploy early


I do not know you, but when I deblow something for the first time, it never works. This is usually because I forgot to send the correct secret keys or hardcoded the path to the local host. Small problems that work locally, remotely refuse to do it. These problems can accumulate, and something that could be easily corrected earlier, if, of course, it is too early to find them, can turn into a huge pile of incomprehensible errors that it is simply impossible to properly catch.

By the way, Visual Studio Code allows you to solve this kind of problem . It allows you to deploy your application directly to Azure with one click. This is a fairly simple way to check for problems when deployed in a different environment.

Deploy 2 servers at once


This advice comes from my hard-won knowledge and the sea of ​​heartache. The essence of the advice is that there are few differences between the deployment of two servers and ten servers, and there is not much difference between the deployment of ten servers and a hundred servers. However, there is simply a huge difference between deploying one server and two servers.
Similar to the issue of deploying servers without state storage, starting with two servers, you can quickly overcome your problems with scaling so that when a sudden increase in traffic occurs, you are ready to scale.

Do not be afraid of queues


Modern databases cope with a certain amount of reading and writing on their own, without your help. When you test your idea, feel free to rely on your database to handle the small to medium load.

Premature scaling is more likely to kill you than save you. But, at some point, your application will grow, that you will not be able to write to the database as well when faced with problems with read and write throughput. For some applications that have a lightweight recording or, if you choose a database such as Cassandra, which handles a massive scale by itself, this problem will be encountered later, for others it will be a bit earlier.

If you have, or potentially will soon have such problems, you will have options for choosing the technologies with which you will go further. One of these technologies can be a message queue. The actual standard at the moment is Apache Kafka, which allows you to organize your messages in topics, and then applications to subscribe to this topic. For example, you can accumulate messages in the application, listening to a specific topic, and then write data to your database in batch so that it does not get clogged all the time. In addition, Kafka runs easily on Azure .

Microservices for scaling


As your application grows, natural logical divisions begin to appear. One part of the application can process payments, while the other part will serve the API for your frontend. When making logical divisions, consider making them separate microservices. But be careful, as the implementation of microservices is also associated with great complexity. But it's worth it. For example, each microservice can have its own metric. Evaluating them, you can scale them independently.

Use containers


Your application may work well locally, but if you try to deploy, you may have serious problems. To avoid this problem, you can use tools like Docker and Kubernetes. Docker, which you can represent as a mini-instance (container) of Linux or Windows, in which you can run the application; and Kubernetes as a tool that connects all your containers together in the cloud.

Kubernetes can be a complex beast, but a beast that solves a difficult problem. If you are an inexperienced DevOps sorcerer, then you may have difficulties, so I recommend starting with Draft . If you are familiar with Yeoman for Javascript projects, then you can evaluate Draft as a similar tool, but for Kubernetes projects: a tool that creates a framework for your project. From there, you can use the Helm tool to install additional pieces of architecture that you need to build (for example, nginx, more Node.js, MongoDB, Kafka, etc.) servers, almost like npm for Kubernetes.

Once you understand the Kubernetes ecosystem, for you to continue to deploy in the cloud will become a child's game.

Collect metrics


If you don’t know how to answer the question “How does my application work?”, Then you will have problems or will be there soon. After all, various indicators over time will help you to constantly improve the state of your application. From the point of view of future costs, and from the point of view of user convenience in terms of improving response time. You should definitely keep up with indicators such as slow paths, page views, session time and other key indicators that are important to your business.

There are many ways to collect these indicators. Services such as New Relic and AppDynamics will provide you with invaluable information on how to improve your application.

If you are working with Azure, Application Insights also handles this need well, as well as easily plugging in other tools, such as CI / CD.

CI / CD will save you from so much pain


How many times did you spoil the deployment with FTP and knock down your server for a few minutes? It was with me. You should never trust yourself in deploying production code. How to do this with Visual Studio Code is pretty cool, but it is intended primarily for development or for demonstration purposes. When you are ready to create a production-level system, you should use continuous integration and continuous deployment (frequent integration and continuous deployment).

Continuous integration is the practice of software development, which consists of merging working copies into a common main branch of development several times a day and performing frequent automated project builds to quickly identify potential defects and solve integration problems.

Continuous deployment is committed to accepting your code, which transmitted the CI, runs the necessary steps to build, container or package them and send them to the server. A good practice is to have several levels to check. Perhaps you will first go to the internal dev server to first see it in a low-risk environment. You can check it first before sending it to the QA environment, where your QA engineers or perhaps an external service will confirm that everything works as expected. From there, you can go to a staging environment in which your application is still only internal, but works using production data and settings, so you can check it in the production environment itself before sending it directly to production. You can also allocate a small group of servers to check for new code: you and only a small percentage of real traffic should be sent to these servers to make sure that nothing breaks when working with real users. If it breaks, you know where to look for the problem. If not, you can move from a small group of users to all.

Many open source providers and projects address these needs. Jenkins, Travis and CircleCI are great options for CI. Azure has its own CI / CD service called Azure Pipelines, and it is quite intuitive to use, and again it easily connects to the Azure integrated ecosystem.

Keep secrets


Any application inevitably has some secrets. These can be keys and secret strings from credentials, databases, and much more. It would be very bad if they turned into the wrong hands. However, they are required to run the application. So what do we do? Usually in development we will use tools like dotenv to save the configuration file locally and be able to read it through process.env in Node.js. This is great for developers, but terrible for production.

Instead, it is useful to use some kind of secret management tool. Fortunately, Kubernetes has a built-in system , and it is quite simple to use. You give Kubernetes secrets on the side of the container, and then it will share them with your application as an environment that makes attack much more difficult.

Another tool that deserves your attention is Azure Key Vault . What's cool about Key Vault, even though Microsoft can't read your keys (only you have the ability to decrypt them) Azure will keep track of your journals and keep track of any questionable uses of your keys to warn you about any compromises.

Conclusion


Node.js, like any other platform, needs to be scaled. And, like any other platform, it has its own tasks and scaling features that you should know about and which should be taken into account when designing large projects.

Original article: “Eleven Tips to Scale Node.js” ( En ).

I suggest in the comments to share tips that you can give on scaling Node.js. It will be interesting to hear.

Source: https://habr.com/ru/post/425275/


All Articles