I am using faye on my production server with Passenger and Nginx. I write this code to nginx config file of my site:
location /faye {
proxy_pass http://127.0.0.1:9292;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
In a Chrome Network/Websocket I see
Status 101.
Switching protocols
As I know it means, that I have a websocket connection.
But I dont get any messages from it. In nginx.error.log I see:
2015/05/29 13:46:38 [info] 27188#0: *32 client closed keepalive connection
How can I fix it?
Related
How to call GRPC Server which is located in docker container on Swarm cluster from NGINX reverse proxy?
GRPC Server in container/service called webui with kestrel development certificate installed
NGINX Proxy which is located outside the stack and routes access to Swarm stacks
GRPC Client is located on a separate virtual machine on another network, the browser page at https://demo.myorg.com is available
part nginx.conf
server {
listen 443 ssl;
server_name demo.myorg.com;
...
location / {
proxy_pass https://namestack_webui;
}
GRPC Client appsetting.json
{
"ConnectionStrings": {
"Database": "Data Source=Server_name;Initial Catalog=DB;User Id=user;Password=pass;MultipleActiveResultSets=True;"
}
...
"GRPCServerUri": "https://demo.myorg.com/",
...
}
}
Problem when connecting GRPC Client to Server, i get error
END] GetOpcDaServerSettingsQuery. Time spent: 7,7166ms
fail: Grpc.Net.Client.Internal.GrpcCall[6]
Error starting gRPC call.
System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
---> System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception.
---> System.ComponentModel.Win32Exception (0x80090367): No common application protocol exists between the client and the server. Application protocol negotiation failed..
--- End of inner exception stack trace ---
Tried to write and specify a kestrel development certificate (for GRPC Client) that is loaded into the Swarm stack (namestack) through which the other containers in the stack are authenticated, the error is the same.
I understand that it is necessary to specify in appsetting.json the GRPC Server container address (https://namestack_webui), but it is behind NGINX, and I can only specify the GRPC host address (https://demo.myorg.com), tell me what is wrong?
The perfect solution for such a case was not found online.
I finally figured out and found a solution to my question, and I publish it for discussion.
If there are no comments against, then mark it as correct, at least it works for me and will work for YOU.
to proxy grpc connections through NGINX in the configuration, the location section must specify something similar to the url /PackageName.ServiceName/MethodName (This is indicated here by https://learn.microsoft.com/en-aspnetus/aspnet/core/grpc/troubleshoot?view=aspnetcor7.0#unable-to-start-aspnet-core-grpc-app-on-macos )
This URL can be checked with the developer or in the logs when grpc client connects
Should be used to proxy directive grpc_pass grpcs://namecontainer;
Should use http2 protocol.
So the correct configuration file for nginx in my case should look like this
server {
listen 443 ssl **http2**;
server_name demo.myorg.com;
ssl_certificate ...;
ssl_certificate_key ...;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers RC4:HIGH:!aNULL:!MD5:!kEDH;
add_header Strict-Transport-Security 'max-age=604800';
underscores_in_headers on;
large_client_header_buffers 4 16k;
location / {
proxy_pass https://name_container;
# Configuration for WebSockets
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_cache off;
# WebSockets were implemented after http/1.0
proxy_http_version 1.1;
# Configuration for ServerSentEvents
proxy_buffering off;
# Configuration for LongPolling or if your KeepAliveInterval is longer than 60 seconds
proxy_read_timeout 100s;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-URL-SCHEME https;
}
location /App.Name.Api.Contract.ApiService/UpdateOpcDaTags {
grpc_pass grpcs://name_container;
}
}
I have a SocketIO server run inside docker swarm + Nginx for load balancing which is working fine.
But I have a small problem with duplicated emit events.
Example: I have 30 replicas (copies) of SocketIO server; 1 Nginx gateway and Everything running in Docker Swarm
My Nginx config:
server {
listen 80;
server_name 10.10.10.212;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://loadbalancer;
# enable WebSockets
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
My SocketIO server emit
socketio.emit('warehouse_scan:added', 'HB10790')
Browser result
How can I solve this?
duplicated events on emit is my false.
I set wrong parameter while setting up everything with nginx , match client versions , etc ...
Wrong config in backend:
socketio = SocketIO(app, logger=True, engineio_logger=True, policy_server=True, async_mode='eventlet', manage_session=True, cors_allowed_origins="*", message_queue=socket_io_msg_q)
The correct one that fixed duplication:
socketio = SocketIO(app, logger=True, engineio_logger=True, policy_server=True, async_mode='eventlet', manage_session=True)
The problem is at this line:
message_queue=socket_io_msg_q <-- error!
This will trigger all emit events from backend server to REDIS then get back to client. If i have 50 replicas, clients will receive the amount of message from these replicas.
I'm was exploring faye to implement websocket feature but got stuck due to following issue.
The page at was loaded over HTTPS, but requested an insecure script http://xyz/faye?message=[{"channel":"/meta/handshake","version":"1.0","supportedConnectionTypes":["websocket","eventsource","long-polling","cross-origin-long-polling","callback-polling"],"id":"1"}]&jsonp=__jsonp1. This request has been blocked; the content must be served over HTTPS
Config details
rails( 4.2.11)
faye (1.3.0)
puma (4.3.1)
Everything fine locally since everything running over HTTP.
On staging, we are getting the above issue. Not sure what are we doing wrong. Points to note are:
Puma is running using --ssl.
https://xyz/faye.js renders the client JS (Note the https)
Ran faye server using rackup faye.ru -s thin -E production
nginx config below
server {
listen 80;
root /var/app/current;
location / {
proxy_pass http://mlp;
proxy_set_header Host $host;
rewrite /favicon.ico /public/favicon.ico;
}
location /faye {
proxy_set_header Host $host;
proxy_pass http://localhost:9292;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
}
}
I have Rails 3.2 application with gem websocket-rails 0.7.
On development machine, all work fine
On production enviroment, I use Nginx/1.6 as proxy server and Unicorn as http server. Thin is used on standalone mode (following https://github.com/websocket-rails/websocket-rails/wiki/Standalone-Server-Mode).
nginx config:
location /websocket {
proxy_pass http://localhost:3001/websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
On backend side, I have the following code for send notification to clients
WebsocketRails[:callback_requests].trigger 'new', call_request
On client side, I got a connection using:
dispatcher = new WebSocketRails window.location.host + ':3001/websocket'
channel = dispatcher.subscribe 'callback_requests'
But notification doesn't come to the client.
Related issue on github - github.com/websocket-rails/websocket-rails/issues/211
Your nginx config is matching requests below /websocket/ with the trailing /. That is the directory component of /websocket/blah.
If you look in your nginx access log file you'll find your requests to /websocket are being 301 redirected to /websocket/.
Remove the trailing /
location /websocket {
proxy_pass http://localhost:3001/websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
Is this somehow possible? Is it possible to do something like this in Ruby on top of Rack? I've seen there's websockets-rack but as far as I understand, that is only a rack module to serve ONLY websocket traffic not http also.
So basically, as the question states, is it possible to serve both protocols with just one server on the same port, instead of firing of something like Faye, websockets-rack or em-websockets?
Websockets are just an in-protocol upgrade of HTTP(s), so they are not normal TCP sockets but reuse the existing HTTP(S) connection (and thus use the same port). So, in theory it should work and from what I know it works with the Perl Mojolicious framework. But I don't know if it works work ruby/rack.
The short answer is - (AFAIK) no.
Currently, a ruby HTTP server (like rails or sinatra) and a websocket server are mutually exclusive.
After saying that, you could use a third party to emulate that. Specifically Ngnix. With Nginx you can listen to a single port, but, accroding to a path, decide whether you want to dispatch the request to the HTTP server or the Websocket server.
For example, you can run the HTTP server on port 3000, and the Websocket server on port 3020, and then configure the nginx.conf like this:
upstream http_app {
server 127.0.0.1:3000;
}
upstream websocket_app {
server 127.0.0.1:3020;
}
server {
listen 80;
server_name .example.com;
access_log /var/www/myapp.example.com/log/access.log;
error_log /var/www/myapp.example.com/log/error.log;
root /var/www/myapp.example.com;
index index.html;
location /web {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://http_app;
}
location /socket {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://websocket_app;
}
}
Now any request to http://www.example.com/web/... will reach the HTTP server, and any request to http://www.example.com/socket will reach the Websocket server.