惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Security Archives - TechRepublic
Security Archives - TechRepublic
Forbes - Security
Forbes - Security
C
Cyber Attacks, Cyber Crime and Cyber Security
Latest news
Latest news
V2EX - 技术
V2EX - 技术
Google DeepMind News
Google DeepMind News
Cyberwarzone
Cyberwarzone
Vercel News
Vercel News
V
Vulnerabilities – Threatpost
I
InfoQ
GbyAI
GbyAI
有赞技术团队
有赞技术团队
雷峰网
雷峰网
阮一峰的网络日志
阮一峰的网络日志
A
Arctic Wolf
F
Full Disclosure
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
C
Check Point Blog
Hugging Face - Blog
Hugging Face - Blog
Simon Willison's Weblog
Simon Willison's Weblog
Google DeepMind News
Google DeepMind News
M
MIT News - Artificial intelligence
Engineering at Meta
Engineering at Meta
The Register - Security
The Register - Security
T
Tor Project blog
T
Troy Hunt's Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
S
Security Affairs
W
WeLiveSecurity
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Stack Overflow Blog
Stack Overflow Blog
Apple Machine Learning Research
Apple Machine Learning Research
H
Heimdal Security Blog
S
Secure Thoughts
Y
Y Combinator Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Security Latest
Security Latest
Martin Fowler
Martin Fowler
G
Google Developers Blog
宝玉的分享
宝玉的分享
腾讯CDC
TaoSecurity Blog
TaoSecurity Blog
T
Threatpost
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Project Zero
Project Zero
Blog — PlanetScale
Blog — PlanetScale
大猫的无限游戏
大猫的无限游戏
MongoDB | Blog
MongoDB | Blog

hsfzxjy 的博客

解决 VSCode + CMake + MSVC 编译器信息乱码的问题 使用 3090 部署 1.58bit 动态量化版 DeepSeek R1 671b 如何在 VS Code DevContainer 中配置 HTTP 代理 如何在跳板机背后的服务器上使用 VS Code Remote - Containers Cohesive Digests for Ints and Floats Rust 中的隐匿概念 —— Place(位置) 美术馆 一尺之槌,日取其半,1075日而竭 老生常谈:使用 Cloudflare 自选 IP 加速站点访问 辩义 State、Nation 与 Country 将 Base64 编码的数据快速转换为 Uint8Array 折腾 NPU·第1章 —— 搭建 Level Zero 开发环境 折腾 NPU·第0章 —— Intel NPU 概述与 Level-Zero 新增域名 monad.run CSS 中为特定字符设置不同字体 Arbitary Lifetime Transmutation via Rust Unsoundness Dijkstra 算法的延伸 Manacher 回文计数算法 硬卧 Go Fact: Zero-sized Field at the Rear of a Struct Has Non-zero Size Display *big.Rat Losslessly and Smartly in Golang 代码的仪式 Building Electron From Scratch 中式亲属称谓研究之一:构建半群 Some Notes on Kotlin Coroutines Git sparse-checkout and partial clones for Mega-Repos 辩义“封建” Diving from the CUDA Error 804 into a bug of libnvidia-container Modern Cryptography, GPG and Integration with Git(hub) Move the Root Partition of Ubuntu A New Programmer Kicks a Roadblock Git-based Dependencies in Dart and Go Reversy Naming 人类一败涂地 Invalid Golang Pointers Can Bite You Even If You Don't Dereference Side Project(副业) A Flaw of Promoting Complex Trait Bounds in Rust Initialize Process Pool Worker with Individual Value Rust - Python FFI From Scratch [Extending Hexo For My Site] Part 1 [Extending Hexo For My Site] Part 0 Debug a 'torch.tensor(1).cuda()' hanging 不自由的互联网 Retrieve Contents over HTTP without curl or wget [Unravelling mocona] Part 1 - Verbosity or Anti-Pattern [Unravelling mocona] Part 0 - Preface Understanding pickle in Python Rough Notes on Deploying Vaultwarden & NextCloud Bookmarks 语言狂热者与实用主义者 Demystify the randomness in CUDA kernels Performant Bulk Mutations in IndexedDB Auto Rebuild .pyx Files with pyximport Cython and Threads Obtain a Random Available TCP Port with Bash Information Theory: KL Divergence Information Theory: Entropy and Mutual Information 铁板烧 西郊线 Proof of the Gumbel Max Trick Option::as_ref Rc, RefCell and Interior Mutability Visualizing Correlation 三月十日杂感 三月一日杂感 二月十一日杂感 一月二十六日杂感 SS Configuration 一月七日杂感 四月·病 Haskell 笔记:State Monad Haskell 笔记:Monad 引论 Haskell 笔记:Applicative Haskell 笔记:Category Theory and Functor Haskell 笔记:data, type, newtype Haskell 笔记:folds 使用 Aria2 在 Ubuntu 中下载百度云资源 从伪并行的 Python 多线程说起 一个 Reentrant Error 引发的对 Python 信号机制的探索和思考 Linux 文件权限 午后雨·科大 最后的雨夜·广州 揭秘·变态的平方根倒数算法 神坑·Python 装饰类无限递归 Python“黑魔法”之 Encoding & Decoding Ubuntu 重新映射键盘布局 为什么我要翻墙 Python“黑魔法”之 Generator Coroutines 数学美 之 判断线段相交的最简方法 除夕杂感 17 行代码实现的简易 Javascript 字符串模板 Python“黑魔法”之 Meta Classes 诗集 生活,需要被“发现” 家书·十八岁成人礼 炫技?还是需求? 【译】响应式图片的现状 【译】“为什么有这么多的编程语言?” Wisecity 商赛总结——也谈前端自动化测试 记一次 DoS 诈骗网站的经历 那一年,我们望向星空
HSFZMUN 4.0 部署小记
2017-02-25 · via hsfzxjy 的博客

技术流水账一篇,记录踩过的坑

Channels 异构

Django Channels 官方文档宣称 channels 的最佳配置是使用其自带的服务器组件 Daphne,但在开发中我发现 daphne 处理普通请求比在 WSGI 架构下慢了好几倍,更何况使用 daphne 派发静态文件是十分不切实际的。于是我将 http.requestwebsocket.* 两个 channel 解耦,前者使用 nginx 配合 uwsgi 处理,后者使用 nginx 反向代理至 daphne 处理。这样一来便可充分利用两种架构的优势。

旧架构:

新架构:

环境

  • Ubuntu Server 16.04(与开发环境相同)
  • python 3.5.2
  • virtualenv & virtualenvwrapper
  • nginx
  • uwsgi
  • redis(作为缓存和 Channel Layer)

Channels Session-based Authentication

channels 有提供基于 HTTP Session 的认证方式,但由于 websocket 和 http 在此不是同域请求(端口号不同),主域名下的 cookies 不会随 websocket 请求发送。故在发起 websocket 链接时要带上一个 GET 参数 session_key。在模板中该参数可由 { {request.session.session_key} } 获得。

uwsgi

安装:

编写配置文件 /etc/uwsgi/sites/hsfzmun.ini

[uwsgi]
uid = git
chdir = /home/git/hsfzmun/server
module = config.wsgi:application
home = /home/git/virtualenvs/hsfzmun # Virtualenv 路径
master = true
processes = 10
socket = /var/www/hsfzmun.sock # 使用 Unix Socket 与 nginx 通信
chmod-socket = 666
vacuum = true

配置 systemd 服务(uwsgi.service):

[Unit]
Description=uWSGI Module

[Service]
ExecStartPre=/bin/bash -c 'mkdir -p /run/uwsgi; chown git:www-data /run/uwsgi'
ExecStart=/usr/local/bin/uwsgi --emperor /etc/uwsgi/sites --touch-reload=/home/git/hsfzmun/server/uwsgi_params
Restart=always
KillSignal=SIGQUIT
Type=notify
NotifyAccess=all

[Install]
WantedBy=multi-user.target

uwsgi 有个优点:可以通过 --touch-reload 参数简洁地重启服务,这样只需一条 touch 命令便可以完成新代码的部署。

daphne

daphne 有两个模块:Interface Server 和 Workers。前者负责处理 Websocket、long-polling 等请求,并将其抽象化为 channels 传递给 Workers,Workers 则负责执行具体的业务逻辑。这么做有一个好处就是 降低了底层与业务逻辑的耦合度,即使业务层崩溃也不会使连接断开,同时也减少了新代码部署对整个系统的印象。部署新代码时只需重启 Workers 即可。

daphnei.service

[Unit]
Description=Daphne Interface Server

[Service]
ExecStart=/home/git/cmd/daphnei
Restart=always
KillSignal=SIGQUIT
Type=simple
NotifyAccess=all

[Install]
WantedBy=multi-user.target

daphnew.service

[Unit]
Description=Daphne Worker

[Service]
ExecStart=/home/git/cmd/daphnew
Type=simple
KillSignal=SIGQUIT
Restart=always
NotifyAccess=all

[Install]
WantedBy=multi-user.target

此处踩了一个坑:起初 Type 处的值是 Notify,因为我是仿照 uwsgi.service 编写这两个文件的。Notify 型服务要求主进程自行通知 systemd 自己的启动/停止状态,但 daphne 没有这样的机制,从而导致 systemctl 阻塞,并以 90 秒为周期不断重启服务。幸好 StackOverflow 上的大神指出了这个错误。

这里我将具体的服务脚本独立出来,因为 ExecStart 不支持编写多行语句。

cmd/daphnei

#!/bin/bash
cd /home/git/hsfzmun/server
/home/git/virtualenvs/hsfzmun/bin/daphne -b 0.0.0.0 -p 8001 -v2 config.asgi:channel_layer --access-log=/var/www/daphnei.log

cmd/daphnew

#!/bin/bash
cd /home/git/hsfzmun/server
/home/git/virtualenvs/hsfzmun/bin/python manage.py runworker --threads 5 --only-channels=websocket.*

此处 daphne 有个 bug:理论上 verbosity 不应该影响程序的行为,但如果不加 -v2 参数 nginx 会报 502 Bad Gateway

nginx

此处的难点是反向代理 websockets,因为 nginx 默认不识别 websocket 协议。为了能正确指定协议头,只能将所有 websocket 请求路由到某一子路径下。

nginx.service

server {
listen 80;
server_name <ip> product;

# 静态文件
location /static {
alias /var/www/static;
}

# 用户上传的文件
location /m {
alias /var/www/media;
}

# uwsgi 反向代理
location / {
include /var/www/uwsgi_params;
uwsgi_pass unix:/var/www/hsfzmun.sock;
}

# daphne 反向代理
location /ws {
proxy_pass http://0.0.0.0:8001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_read_timeout 36000s;
proxy_send_timeout 36000s;
}
}

Git 自动化部署

去年的 WiseCity 3.0 采用 Github 中转的方式进行部署,这对 Github 的稳定性有很高的要求。这次则将生产服务器作为 Git Server,使用 Git Hooks 进行自动化部署,大大提高了生产效率。

创建 git 用户:

$ useradd git
$ passwd git

设置 SSH authorized_keys(略)。

创建仓库:

$ cd ~
$ git init --bare hsfzmun.git

创建钩子 hooks/post-receive

#!/bin/bash

GIT_WORK_TREE=/home/git/hsfzmun git checkout -f


cd /home/git/hsfzmun/server
export LC_ALL=C
export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3
export WORKON_HOME=~/virtualenvs
source /usr/local/bin/virtualenvwrapper.sh
workon hsfzmun


./manage.py compilemessages


./manage.py collectstatic --noinput


./manage.py migrate


touch ./uwsgi_params


sudo systemctl restart daphnew --no-block

echo "All operations done."

此钩子会在每次 push 之后执行,自动更新静态文件和数据库表并重启相关服务。

本地添加远程仓库(略)。


作者:hsfzxjy
链接:
许可:CC BY-NC-ND 4.0.
著作权归作者所有。本文不允许被用作商业用途,非商业转载请注明出处。