Search Unity

anyone using Node.js as server?

Discussion in 'Multiplayer' started by mindlube, Jan 31, 2012.

  1. mindlube

    mindlube

    Joined:
    Oct 3, 2008
    Posts:
    993
    Thanks this looks really awesome thanks for posting. http://spicypixel.com/developer/concurrency-kit/
    The Concurrent* collections are one of my favorite features in .NET4 so it's exciting to check out this library for Unity!

    Yeah! Glad to hear your experiences and that too!

    Cheers,
    Alex
     
  2. seand88

    seand88

    Joined:
    Aug 30, 2013
    Posts:
    13
    sorry to bring this topic back but node.js also does udp so its basically capable of doing anything you need.
    Its not doing anything new but it has a good following behind it so wouldn't be surprised to see it more used with unity soon.
     
  3. Treaded

    Treaded

    Joined:
    Nov 11, 2015
    Posts:
    2
    It's November 2015, technology has progressed. Node.js is now very mature and enterprise ready - latest version is v5.

    I'd like to point out that node.js excels at networking due to its non-blocking asynchronous event based model. It runs on one thread and optimizes I/O intensive tasks such as networking using callbacks. CPU intensive tasks can also be handled by spawning multiple node.js processes using the cluster module - which is very mature and effectively being used in production environments.

    See how a single core node.js server can out maneuver a 5 core Java server in a production environment:
    https://www.paypal-engineering.com/2013/11/22/node-js-at-paypal/

    Before someone comments about HTTP for gaming, yes it is not ideal for higher frame rates, that is why node.js has UDP support built in to perform low level packet transmissions for better latency. It's called the dgram module:
    http://vbo.name/building-multiplayer-game-nodejs-node-webkit-networking-general/

    It's all there ready to be consumed, it just requires the right mind to build it.
     
  4. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    What a lot of people don't remember is the history of event based frameworks, and even less know the current state of them compared to modern threading.

    The event model became popular primarily because at one time linux threads were so bad they were unusable for anything at scale. We had no choice but to go with an event based model. But that was another time, and modern threads on linux (linux was always the real problem here not windows) are very different. There really is no benefit to using an event based model vs threads for most use cases, unless you are talking something like memcache where it actually fits well.

    Context switching overhead is basically not an issue anymore even with hundreds of threads. And anyone who has written large codebases using an event model, you really enjoy that? I don't.

    And that Paypal link is not really a fair comparison. Spring is not the state of the art in java http, not even close by a long shot. For a more balanced review against a modern architecture see http://www.slideshare.net/brikis98/nodejs-vs-play-framework.
     
  5. Treaded

    Treaded

    Joined:
    Nov 11, 2015
    Posts:
    2
    Slide 159 of the link you posted clearly gives node.js the upperhand "use node.js if your app is near real-time, use node.js if your app is I/O bound" - a game server is a good candidate for this.

    What you're saying is that because CPUs have advanced, threading is no longer a problem. Yes it is true you can have hundreds or thousands of threads being spawned but it doesn't make it any more performant than an event based model.

    In fact If you want to compare apples to apples, threading and event based models are nearly identical in performance, given the same scheduling strategies.

    But you pointed out something important, you said that context switching is "no longer an issue", I am sorry but threading has not changed and this concept is still in effect for modern computing.

    You also missed another important part of threading, huge numbers of threads require large amounts of memory due to their thread stacks. The usage of locks also yields an additional overhead.

    You also stated that event based codebases are harder to maintain... Really? Handling mutexes is easy? In large codebases it becomes increasingly more difficult to understand threading. It actually becomes easier to maintain an event based model.

    Unless your writing code in a functional language, you will have undesired side effects from multi threading due to mutablilty and shared state.
     
  6. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    You are picking and choosing and simply not up to speed with modern approaches to concurrency.

    Slide 159 was one of many points made you picked what suited your opinion and left out a lot of others.

    Threads are different now not because of CPU's but because of implementation in the linux kernel. That was the core problem I was referencing. The cost of context switching in modern kernel implementations is vastly different then it used to be.

    And no one uses mutexes and locking in modern concurrency architectures. No one that knows what they are doing has done that in nearly a decade. Platforms like Akka and Orleans use largely lock free approaches that can push upwards of a million messages per second per core at high levels of concurrency using relatively small thread pools, and Erlang was doing it even earlier. And if you want to really push the limits take a look at LMAX Disruptor and it's approach.

    My issue with node is not that it uses event based IO, it's that it doesn't have threads. You don't have the choice to use the right tool for the job, and in any large complex game it's a mix. In my own Game Machine platform I use an event based library for the networking, but testing I've done has shown that one connection per thread is actually more efficient up to around 1000 threads, which is really way past the limit of how many players you would even have connected to a single server. Now i'm not replacing Netty with a threaded model because the differences are just not enough to really have much of an impact.
     
  7. o1o101

    o1o101

    Joined:
    Jan 19, 2014
    Posts:
    639
    We've tested a node.js multiplayer server that ran pretty fast. I remember it being super easy to set up the node server and the c# code in Unity was easy also. It uses the UDP protocol and you have to do everything yourself, but it worked pretty good. Thats was about 4 years ago now, but I still have some client code kicking around:
    Code (CSharp):
    1. using UnityEngine;
    2. using System;
    3. using System.Net;
    4. using System.Text;
    5. using System.Net.Sockets;
    6. using System.Threading;
    7. using System.Collections;
    8.  
    9. public class udpc1 : MonoBehaviour {
    10.     // used to communicate
    11.     Socket sckCommunication;
    12.     EndPoint epLocal, epRemote;
    13.     string txtLocalIp;
    14.     string txtServerIp;
    15.     int txtLocalPort;
    16.     int txtServerPort;
    17.     int delay=200;
    18.     string receivedUDPmessage;
    19.     GameObject gameman;
    20.     gamemanager gm;
    21.     string txtgui;
    22.     // buffer to receive info
    23.     byte[] buffer;
    24.     int numberBytes;
    25.     // Use this for initialization
    26.     void Start () {
    27.         numberBytes=1464;
    28.  
    29.         print("UDPmanager start...");
    30.         gameman = GameObject.Find ("GameManager");
    31.         gm=gameman.GetComponent<gamemanager>();
    32.         Application.runInBackground = true;
    33.         // set up socket
    34.         sckCommunication = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
    35.         sckCommunication.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
    36.  
    37.         txtLocalIp=gm.clientIp;
    38.         txtLocalIp=GetLocalIP();
    39.  
    40.         txtServerIp=gm.serverIp;
    41.      
    42.         txtLocalPort=gm.clientPort;
    43.  
    44.         txtServerPort=gm.serverPort;
    45.  
    46.         txtLocalPort=new System.Random().Next( 50000, 51000);
    47.  
    48.  
    49.         txtgui="port="+txtLocalPort+','+txtLocalIp;
    50.         // bind socket                      
    51.         epLocal = new IPEndPoint(IPAddress.Parse(txtLocalIp), txtLocalPort);
    52.         sckCommunication.Bind(epLocal);
    53.      
    54.         // connect to remote ip and port
    55.         epRemote = new IPEndPoint(IPAddress.Parse(txtServerIp), txtServerPort);
    56.         sckCommunication.Connect(epRemote);
    57.      
    58.         // starts to listen to an specific port
    59.         print("UDPmanager listening on port "+gm.clientPort);
    60.  
    61.         //buffer = new byte[numberBytes];
    62.         buffer = new byte[numberBytes];
    63.  
    64.  
    65.         sckCommunication.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None,
    66.                                           ref epRemote, new AsyncCallback(OperatorCallBack), buffer);
    67.  
    68.     }
    69.     // Update is called once per frame
    70.     void Update () {
    71.     if (gm.qmessage!="") {
    72.       //print("UDPmanager found message :"+gm.qmessage);
    73.       sendmsg(gm.qmessage);
    74.       gm.qmessage="";
    75.     }
    76.     if (receivedUDPmessage!="") {
    77.       //print("UDPmanager received message :"+ receivedUDPmessage);
    78.       gm.udpstring(receivedUDPmessage);
    79.       receivedUDPmessage="";
    80.     }
    81.     }
    82.     void OnGUI () {
    83.         GUI.Label(new Rect (25, 25, 400, 150), txtgui);
    84.     }
    85.     private string GetLocalIP()
    86.     {
    87.         IPHostEntry host;
    88.         host = Dns.GetHostEntry(Dns.GetHostName());
    89.         foreach (IPAddress ip in host.AddressList)
    90.         {
    91.             if (ip.AddressFamily == AddressFamily.InterNetwork)
    92.             {
    93.                 return ip.ToString();
    94.             }
    95.         }
    96.         return "192.168.0.11";
    97.     }
    98.  
    99.     private void OperatorCallBack(IAsyncResult ar)
    100.     {
    101.  
    102.         try
    103.         {
    104.             int size = sckCommunication.EndReceiveFrom(ar, ref epRemote);
    105.          
    106.             // check if theres actually information
    107.             if (size > 0)
    108.             {
    109.                 // used to help us on getting the data
    110.                 byte[] aux = new byte[numberBytes];
    111.              
    112.                 // gets the data
    113.                 aux = (byte[])ar.AsyncState;
    114.              
    115.                 // converts from data[] to string
    116.                 System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
    117.                 string msg = enc.GetString(aux);
    118.                 receivedUDPmessage=msg;
    119.                 // adds to listbox
    120.                 //listBox1.Items.Add("Friend: " + msg);                
    121.                 //print("Friend: " + msg);
    122.  
    123.             }
    124.          
    125.             // starts to listen
    126.             //buffer = new byte[numberBytes];
    127.             buffer = new byte[numberBytes];
    128.  
    129.             sckCommunication.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None,
    130.                                               ref epRemote, new AsyncCallback(OperatorCallBack), buffer);
    131.         }
    132.         catch (Exception exp)
    133.         {
    134.             print(exp.ToString());
    135.             txtgui+=exp.ToString();
    136.         }
    137.     }
    138.     private void sendmsg(string themessage) {                    
    139.         // converts from string to byte[]
    140.         System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
    141.         //byte[] msg = new byte[numberBytes];
    142.         byte[] msg = new byte[numberBytes];
    143.  
    144.         msg = enc.GetBytes(themessage);
    145.         //print("Player sending msg: "+themessage);
    146.         // sending the message
    147.         sckCommunication.Send(msg);
    148.     }
    149. }
     
    Last edited: Nov 12, 2015
    jason-fisher likes this.
  8. mhernandez88

    mhernandez88

    Joined:
    Jul 20, 2016
    Posts:
    38
    I know this is late but....

    I should mention that GC Pauses can be hell for your latency in a low latency environment. With that said, nodejs would make writing a server much easier, and scaleable. Hell I can even see writing an MMO platform in nodejs.

    I should also mention that Golang is a much better choice for low latency and high performance. They introduced a new GC that scales with ram and hardware such that as you throw better machines at it, the GC cost and GC pause is reduced.
     
  9. Dillybob

    Dillybob

    Joined:
    Nov 1, 2016
    Posts:
    3

    Eh, what a bunch of bologna. Really sick of the hatred nodejs gets.

    Of course writing your own server in C++ or another high level language will yield the best performance. However, that person will need to be very skilled in that language for stuff to work correctly. Nodejs bypasses that certain level of knowledge and you said it the best "dumbs it down". Which is perfectly fine. In fact, it's awesome because now that opens the door for other developers who are not god tier programmers to create their own server for multiplayer purposes.

    Just an example: http://wilds.io/ Uses the uWebsocket library (fastest one out there for node), and houses over 150-200+ active players at a 30hz server 24/7.

    Proof:




    So, spending 5-7$/m for a digital ocean VPS to house a game that can handle over 150 players at 30fps is bad because it's "nodejs". I disagree, sir.

    This is a good thing, and opens the door for indie developers to spend more time working on the front-end instead of their server. You are not wrong though, yeah, do it in a high level language and gain what, 100 more active players per node? Big deal. At that point, I'd rather just spend another 7$ for another VPS.

    Now, in regards to high, high level stuff like a 60hz server (think of Path of Exile), then yes, nodejs could probably do < 25 players per node. But if a game like that is being created by a full team they are already well deep in C++ and know everything so the server part isn't really the problem. Not everyone are in those shoes, I'd argue most people are just indie developers fiddling around and wanting a working server, which nodejs is more than capable of.
     
    knickerbocker and sleeprunner like this.
  10. sleeprunner

    sleeprunner

    Joined:
    Apr 20, 2017
    Posts:
    1
    Just wanted to write the same.
    Thanks for closing this discussion, mister :3