1

Using the Elastic Beanstalk web console, I've launched a new Web Server 1.0 environment with:

  • Predefined configuration: Node.js, 64bit Amazon Linux 2014.09 v1.0.9
  • Environment type: Load balancing, autoscaling

and have set Proxy Server to none.

I've successfully compressed & uploaded via the console my code:

package.json

{
  "name": "cool",
  "version": "0.0.0",
  "dependencies": {
    "ws": "0.4.x"
  }
}

server.js

var wss = new (require('ws')).Server({port: (process.env.PORT || 3000)})
wss.on('connection', function(ws) {
  console.log('connected')
  ws.on('message', function(message) {
    console.log(message)
    ws.send(message)
  });
  ws.on('close', function() {
    console.log('disconnected')
  })
})

I also tried including the node_modules directory.

After running:

wscat -c ws://default-environment-xxxxxxxxxx.elasticbeatalk.com/

I got back:

Error: unexpected server response (200)

How can I find out more about that error?

Amazon sets the PORT environment variable to 8080. So, I also tried:

wscat -c ws://default-environment-xxxxxxxxxx.elasticbeatalk.com:8080/

But, that just hung and then returned:

Error: connect ETIMEDOUT

Also, when I do establish a WebSocket connection, I want the server to allow it to stay open indefinitely, unlike Heroku's WebSocket implementation, which times out after 60 seconds.

Is there a detailed tutorial on how to do this?

Community
  • 1
  • 1
ma11hew28
  • 121,420
  • 116
  • 450
  • 651
  • checkout my answer here: http://stackoverflow.com/questions/35713976/has-anyone-used-primus-with-websockets-behind-aws-elastic-load-balancer/36992938#36992938 – codepreneur May 02 '16 at 23:42
  • I'm having the same problem here and I'm stumped. All that Chrome returns to me when I try to connect my websocket is an "error" with the response code 200 (??) and the data says "(Opcode -1)". Couldn't find anything else. Any help would be greatly appreciated. – Simon Germain Oct 09 '16 at 00:20

2 Answers2

1

If you have set up your package.json file correctly (primarily by using --save when npm installing) then you should not have to include the node_modules directory.

Check that the process.env.PORT setting is not changing the listened port - AWS EB usually sets the port to 8081.

To find the port being reported, you can add console.log(process.env.PORT) in your code, then connect via ssh to the server and run tail -f var/log/nodejs/nodejs.log (this monitors the log output of node.js). Then hit your server again and see what port shows up in the log output on your ssh connection.

To investigate the error you are getting, add a ws.on('error',...) function and log what you want.

mwotton
  • 2,170
  • 18
  • 36
  • That's what I thought. I just edited the `dependencies` field of my `package.son` manually because I didn't know about `--save`. So, thanks for that tip! :-) – ma11hew28 Nov 10 '14 at 04:24
  • How do I check what `process.env.PORT` is? The only way I could think of was to deploy a simple HTTP server that responds with `process.env.PORT`. Then, I went to my app's URL (without specifying a port) in Safari and got back 8080, which I don't understand because I told the server to listen on `process.env.PORT` (8080), not 80 (the default port used by Safari). So, why is Safari able to reach my simple HTTP server through port 80? When I try to reach it with Safari specifying port 8080, the request just hangs. What should I specify for `port` in my code (the 1st line of `server.js`)? – ma11hew28 Nov 10 '14 at 04:36
  • Are you using nginx or Apache as a proxy on the EB environment? This will listen on port 80 and then pass the request on to node.js on whatever port has been configured. I notice you mentioned you're using load-balancing - this will also effect the port translations – mwotton Nov 10 '14 at 05:02
  • To find the port being reported, you could try doing a `console.log(process.env.PORT)` in your code, then ssh to the server and run `tail -f var/log/nodejs/nodejs.log` (this monitors the log output of node.js). Then hit your server and see what port shows up in the log output on your ssh connection. – mwotton Nov 10 '14 at 05:05
  • Neither. I've set "proxy server" to "none." Yes, I'm using load balancing. Perhaps I'll try without it. – ma11hew28 Nov 10 '14 at 05:13
  • Cool. I'll try that. I think I'll get the same result: 8080. – ma11hew28 Nov 10 '14 at 05:14
  • Working through it... added a bit more to the answer. Not sure about using a rolling question like this though - hard to write a comprehensive answer. – mwotton Nov 11 '14 at 03:41
0

Alright, after quite a bit or searching, I found a solution that works without changing anything to the ELB and without setting the proxy to none (I use nginx).

All you need is this:

  • In the root of your project, create the .ebextensions directory (if it doesn't already exist)
  • Create a file in there, I called mine 01_nginx.config
  • In this file, put the following code: container_commands:

    01_nginx_websockets:
        command: |
            sed -i '/\s*proxy_set_header\s*Connection/c \
            proxy_read_timeout 36000s; \
            proxy_set_header Upgrade $http_upgrade; \
            proxy_set_header Connection "upgrade"; \
            ' /tmp/deployment/config/#etc#nginx#conf.d#00_elastic_beanstalk_proxy.conf
    

Deploy your code to elastic beanstalk and enjoy websockets connecting!

PS: You don't really need the proxy_read_timeout property set, I just use that for my own. Also, it doesn't seem to do much so, I'll keep looking.

Simon Germain
  • 6,834
  • 1
  • 27
  • 42