Seit uWSGI 1.9 wird WebSocket wie in [hier] beschrieben (http://uwsgi-docs.readthedocs.io/en/latest/WebSockets.html) unterstützt. Es schien einfach zu sein, und als ich tatsächlich versuchte, die Probe auszuführen, schlug sie viele Male fehl, und nachdem ich sie untersucht und bemerkt hatte, verbrachte ich mehr als einen ganzen Tag. Ursprünglich habe ich versucht, den Inhalt zusammen mit "Nicht blockierend mit Python + uWSGI" zu veröffentlichen, aber er konnte nicht mit derselben Methode realisiert werden, sodass er auch als Memorandum dient. Ich habe beschlossen zu posten.
Führen Sie die folgenden Schritte in der Umgebung aus, in der Python3.5 und Docker installiert sind. Es wurde in einer Mac-Umgebung (macOS Sierra) erstellt.
Die Verzeichnisstruktur ist wie folgt.
nginx.conf
und nginx.repo
unter nginx-python / conf
sind "Erstellen Sie eine Umgebung von Python + uWSGI + Nginx mit Docker" Ist das gleiche, so wird es weggelassen. Dort wird auch die grundlegende Verwendung der Befehle docker-compose
und docker
beschrieben.
Erstellt in einer Mac-Umgebung. Installieren Sie zuerst openssl
mit dem Befehl brown
.
$ brew install openssl
Wenn Sie den neuesten Befehl "openssl" verwenden, der mit "brown" installiert wurde, fügen Sie der letzten Zeile von ".bashrc" Folgendes hinzu.
~/.bashrc
export PATH=$(brew --prefix openssl)/bin:$PATH
Führen Sie nach dem Hinzufügen Folgendes aus.
$ source ~/.bashrc
Ich muss einige Fragen beantworten, wenn ich "csr" erstelle, aber ich habe sie alle als Standard festgelegt (nur die Eingabetaste gedrückt).
$ openssl genrsa -out server.key 2048
$ openssl req -new -key server.key -out server.csr
$ openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
Platzieren Sie die erstellten CRT- und KEY-Dateien im Verzeichnis app
(in diesem Beispiel gibt es CSR, dies ist jedoch nicht erforderlich).
Nachdem der Handshake mit dem Client abgeschlossen ist, wartet er auf den Empfang der Daten und sendet die empfangenen Daten unverändert an den Client.
app/websocket.py
import uwsgi
def application(env, start_response):
uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', ''))
msg = uwsgi.websocket_recv()
print("receive: %s" % msg)
uwsgi.websocket_send(msg)
print("end")
Ein Beispiel, das eine Verbindung zum Server herstellt, Daten sendet und auf eine Antwort wartet, wenn die Taste gedrückt wird.
app/client/index.htm
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">
function WebSocketTest()
{
if ("WebSocket" in window) {
alert("WebSocket is supported by your Browser!");
var ws = new WebSocket("wss://127.0.0.1:8443/ws/");
ws.onopen = function() {
ws.send("Hello from client");
alert("Message is sent...");
};
ws.onmessage = function (evt) {
var received_msg = evt.data;
alert("Message is received...");
};
ws.onclose = function() {
alert("Connection is closed...");
};
} else {
alert("WebSocket NOT supported by your Browser!");
}
}
</script>
</head>
<body>
<input type="button" onClick="WebSocketTest();" value="WebSocket Test">
</body>
</html>
docker-compose.yml Forward Port Nummer 80 bis 8180 und 443 bis 8443.
docker-compose.yml
version: "2"
services:
# nginx
nginx-python:
build: ./nginx-python
ports:
- "8180:80"
- "8443:443"
volumes:
- ./app/:/var/www/html/app/
environment:
TZ: "Asia/Tokyo"
Dockerfile
Für uWSGI
wird git clone
erstellt und erstellt. Andernfalls war keine SSL-Verbindung möglich. Auch hier wird angenommen, dass "asyncio" verwendet wird und der nicht blockierende Modus ebenfalls unterstützt wird, aber "WebSocket" kann verwendet werden, selbst wenn der nicht blockierende Modus nicht unterstützt wird. In diesem Fall können Sie "CFLAGS =" - I / usr / include / python3.5m "UWSGI_PROFILE =" asyncio "sicher löschen.
nginx-python/Dockerfile
FROM centos:6.8
ADD ./conf/nginx.repo /etc/yum.repos.d/
# nginx & python
RUN yum localinstall -y http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
RUN yum install -y https://centos6.iuscommunity.org/ius-release.rpm
RUN yum install -y nginx-1.10.1
RUN yum install -y make gcc
RUN yum install -y libxml2-devel
RUN yum install -y python35u python35u-libs python35u-devel python35u-pip
RUN yum clean all
RUN yum install -y git
RUN yum install -y openssl-devel
RUN ln -s /usr/bin/python3.5 /usr/bin/python3 && \
unlink /usr/bin/python && \
ln -s /usr/bin/python3 /usr/bin/python && \
ln -s /usr/bin/pip3.5 /usr/bin/pip && \
sed -i -e 's/python/python2.6/' /usr/bin/yum
RUN pip install greenlet && \
cd /root && \
git clone https://github.com/unbit/uwsgi.git && \
cd uwsgi && \
CFLAGS="-I/usr/include/python3.5m" UWSGI_PROFILE="asyncio" python uwsgiconfig.py --build
# setting nginx
COPY conf/nginx.conf /etc/nginx/nginx.conf
ADD conf/default.conf /etc/nginx/conf.d/default.conf
RUN usermod -u 1000 nginx
EXPOSE 80
EXPOSE 443
ADD ./conf/start.sh /tmp/start.sh
CMD /bin/sh /tmp/start.sh
Ich habe den Inhalt von / usr / bin / yum
unterwegs durch den Befehl sed
ersetzt, aber wenn ich mit dem Befehl python
eine Verknüpfung zu Python 3.5 herstelle, kann yum
nicht verwendet werden.
Ich konnte einfach keinen Weg finden, es mit dem ws
-Protokoll ohne Framework zu verwenden. Da es sich um das "wss" -Protokoll handelt, ist der Reverse Proxy so eingestellt, dass er mit "https" zugreift.
nginx-python/conf/default.conf
upstream websocket {
server localhost:9090;
}
server {
listen 443;
server_name _;
ssl on;
ssl_certificate /var/www/html/app/server.crt;
ssl_certificate_key /var/www/html/app/server.key;
index index.html index.htm;
charset utf-8;
root /var/www/html/app/client;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location /ws/ {
proxy_pass https://websocket/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location = /favicon.ico {
empty_gif;
}
}
Wenn Sie "uWSGI" erstellen, um den nicht blockierenden Modus nicht zu verwenden, benötigen Sie die Option "--asyncio 10 --greenlet" nicht (falls angegeben, wird eine Fehlermeldung angezeigt). Es wird auch davon ausgegangen, dass Sie über eine HTTPS-Verbindung darauf zugreifen.
nginx-python/conf/start.sh
#!/bin/sh
/etc/init.d/nginx start
cd /var/www/html/app
chmod -R 777 .
/root/uwsgi/uwsgi --asyncio 10 --greenlet --logto uwsgi.log --https :9090,server.crt,server.key --http-websockets --wsgi-file websocket.py
Erstellen Sie und beginnen Sie mit docker-compose up --build
. Greifen Sie nach dem normalen Start auf "https: //127.0.0.1: 8443" zu.
Wenn Sie auf die Schaltfläche klicken, werden bei jedem Drücken von "OK" nacheinander Warnungen angezeigt, wie unten gezeigt.
Darüber hinaus wird Folgendes in das Protokoll auf der Serverseite ausgegeben (hier / var / www / html / app / uwsgi.log
).
receive: b'Hello from client'
end
Ich habe nicht realisiert, was ich ursprünglich ohne Blockierung tun wollte, z. B. den Socket-Empfang als separate Aufgabe zu behandeln, daher möchte ich nicht nur "asyncio", sondern auch "gevent" und "greenlet" untersuchen. .. Der Schmerz ist, dass es nicht viele Informationen über den nicht blockierenden Modus von "uWSGI" und WebSocket gibt.
Recommended Posts