- uWSGI 1.9.15
- 错误修复
- 新特性
- PTY插件
- strict模式
- 回退配置
- –perl-exec和–perl-exec-post-fork
- uwsgi.cache_keys([cache])
- 添加 %(ftime) 到日志格式
- 当另一个实例绑定到UNIX socket时,保护其不受破坏
- –worker-exec2
- 允许普通插件上的post_fork钩子
- –call钩子
- 插件的init_func支持,以及–need-plugin变体
- 为pecan框架添加商品加载器(commodity loader)
- UWSGI_REMOVE_INCLUDES
- router_expires
- 在重载/关机时宣布Legion的死亡
- GlusterFS插件 (beta)
- –force-gateway
- 初步的python3 profiler (测试版)
- 对OpenBSD,NetBSD,DragonFlyBSD的文件监控支持
- –cwd
- –add-gid
- Emperor和Linux名字空间改进
- –wait-for-interface
- 可用性
uWSGI 1.9.15
更新日志[20130829]
错误修复
- 修复jvm选项hashmap (#364)
- 修复python3 wsgi.file_wrapper
- 修复python3 –catch-exceptions
- 修复pypy wsgi.input.read中的类型
- 对pypy更好的符号检测
- 改进heroku上的ruby库管理
- 修复http-keepalive memleak
- 修复CPython下的spooler体管理
- 修复’fs’的unshare()使用
- 修复当使用–plugin构建插件时的UWSGI_PROFILE使用
- 改进SmartOS支持,以及添加OmniOS支持
新特性
PTY插件
这个新的插件允许你生成伪终端,并将其附加到你的worker上。
接着,通过网络 (UNIX或者TCP socket) 访问伪终端。
你可以将它们用于共享调试,或者让你的web应用拥有输入通道。
该插件出于开发初期 (特性非常少),并且不是默认构建的,但是你可以做一些像这样有趣的事:
- [uwsgi]
- plugin = pty,rack
- ; generate a new pseudoterminal on port 5000 and map it to the first worker
- pty-socket = 127.0.0.1:5000
- ; classic options
- master = true
- processes = 2
- rack = myapp.ru
- socket = /tmp/uwsgi.socket
- ; run a ruby interactive console (will use the pseudoterminal)
- ; we use pry as it kick asses
- rbshell = require 'pry';binding.pry
现在,你可以这样访问伪终端了
- uwsgi --plugin pty --pty-connect 127.0.0.1:5000
你可以在多个窗口中运行该客户端,它将由所有客户端共享 (所有都将访问同一个伪终端)。
我们相信,关于它的新的有趣的使用很快就会出现
初步文档可以在 Pty插件 这里找到
strict模式
编写uWSGI配置文件时最常见的错误之一是,选项名的拼写错误。
由于你可以添加任何选项到uWSGI配置文件中,因此系统将会接受任何你写的东东,即使它并不是一个真正的uWSGI选项。
虽然这个方法是非常强大的,允许大量有趣的hack,但是,它也有可能让你很头疼。
如果你想一步检查所有的选项,那么现在,你可以添加–strict选项了。未知选项将会触发一个致命错误。
回退配置
uWSGI非常便宜 (在资源方面), 并且支持大量的操作系统和架构,它被大量用于嵌入式系统中。
这种设备的常见特性之一就是”恢复到出厂设置”。
有了–fallback-config选项,uWSGI现在原生支持这类操作。
如果一个uWSGI实例随着exit(1)而亡,并且指定了回退配置,那么将会使用新的配置,将其作为唯一的参数,re-exec()该二进制文件。
让我们看看一个使用了不可绑定地址的配置 (非特权用户试着绑定到一个特权端口)
- [uwsgi]
- uid = 1000
- gid = 1000
- socket = :80
以及一个回退的配置 (绑定到非特权端口8080)
- [uwsgi]
- uid = 1000
- gid = 1000
- socket = :8080
(以root用户,因为我们想删除特权) 运行它:
- sudo uwsgi --ini wrong.ini --fallback-config right.ini
日志中将会是:
- ...
- bind(): Permission denied [core/socket.c line 755]
- Thu Aug 29 07:26:26 2013 - !!! /Users/roberta/uwsgi/uwsgi (pid: 12833) exited with status 1 !!!
- Thu Aug 29 07:26:26 2013 - !!! Fallback config to right.ini !!!
- [uWSGI] getting INI configuration from right.ini
- *** Starting uWSGI 1.9.15-dev-4046f76 (64bit) on [Thu Aug 29 07:26:26 2013] ***
- ...
–perl-exec和–perl-exec-post-fork
现在,你可以在fork()调用之前和之后运行自定义perl代码了。
这两个选项都简单把perl脚本当成参数。
uwsgi.cache_keys([cache])
这个api函数已经别添加到python和pypy插件中。它允许你一个本地uWSGI缓存的键。
返回一个列表。
添加 %(ftime) 到日志格式
这就像’ltime’,但它遵守–log-date格式
当另一个实例绑定到UNIX socket时,保护其不受破坏
在启动时,uWSGI现在获得刚刚创建的unix socket的inode。
在vacuum下,如果inode发生了改变,那么会跳过socket的取消链接动作。
这应该有助于避免系统管理员破坏性竞争条件或错误配置
–worker-exec2
这个就像–worker-exec,但在post_fork钩子之后运行
允许普通插件上的post_fork钩子
普通插件 (没有.request钩子的那些) 现在可以公开.post_fork钩子了
–call钩子
与exec-*钩子有着相同的精神,call钩子工作方式相同,但是它会直接在当前进程的地址空间中调用函数 (必须将其作为有效符号公开)
以这个C源码为例 (称之为hello.c):
- #include <stdio.h>
- void i_am_hello_world_for_uwsgi() {
- printf("Hello World!!!\n");
- }
并把它作为共享库编译:
- gcc -o libhello.so -shared -fPIC hello.c
现在,选择在uWSGI中何时 (以及何处) 调用它:
- ./uwsgi --help | grep -- --call-
- --call-pre-jail call the specified function before jailing
- --call-post-jail call the specified function after jailing
- --call-in-jail call the specified function in jail after initialization
- --call-as-root call the specified function before privileges drop
- --call-as-user call the specified function after privileges drop
- --call-as-user-atexit call the specified function before app exit and reload
- --call-pre-app call the specified function before app loading
- --call-post-app call the specified function after app loading
- --call-as-vassal call the specified function() before exec()ing the vassal
- --call-as-vassal1 call the specified function(char *) before exec()ing the vassal
- --call-as-vassal3 call the specified function(char *, uid_t, gid_t) before exec()ing the vassal
- --call-as-emperor call the specified function() in the emperor after the vassal has been started
- --call-as-emperor1 call the specified function(char *) in the emperor after the vassal has been started
- --call-as-emperor2 call the specified function(char *, pid_t) in the emperor after the vassal has been started
- --call-as-emperor4 call the specified function(char *, pid_t, uid_t, gid_t) in the emperor after the vassal has been started
以数字结尾的选项是期望参数的变体 (其后缀是它们接收的参数的数目)
我们想要就在应用被加载之前调用函数:
- [uwsgi]
- ; load the shared library
- dlopen = ./libhello.so
- ; set the hook
- call-pre-app = i_am_hello_world_for_uwsgi
- ...
将会就在应用加载之前调用你的自定义函数。
考虑到那些函数是在进程地址空间中调用的,因此你可以对它们施加所有类型的(黑)魔法。
注:dlopen是对dlopen()函数的封装,因此所有相同的规则都适用 (必读:适用绝对路径!!!)
插件的init_func支持,以及–need-plugin变体
在加载插件的时候,你可以在dlopen()之后立即调用插件中定义的符号:
- uwsgi --plugin "foobar|myfunc" ...
uWSGI将会调用’foobar’插件公开的’myfunc’符号
–need-plugin就像–plugin,但是当插件加载失败的时候,会exit(1)进程
为pecan框架添加商品加载器(commodity loader)
作者:Ryan Petrello
为pecan WSGI框架添加了一个新的python加载器 (–pecan)
https://uwsgi-docs.readthedocs.io/en/latest/Python.html#pecan-support
UWSGI_REMOVE_INCLUDES
在构建阶段,你可以用UWSGI_REMOVE_INCLUDES环境变量移除include头文件。
这对交叉编译有用,其中,一些自动检测的include文件可能是错误的。
router_expires
我们在uWSGI核心中已经有多个设置Expires头的选项了。
添加这个路由器,以允许你对它们自定义:
- [uwsgi]
- route = /^foobar1(.*)/ expires:filename=foo$1poo,value=30
- route = /^foobar2(.*)/ expires:unix=${time[unix]},value=30
这个路由器接收一个filename的mtime或者一个unix time,添加’value’到其上,然后将它作为一个http日期返回。
在重载/关机时宣布Legion的死亡
一旦触发了实例的重载(或者关闭),每一个legion成员现在都将会宣告它的死亡。
GlusterFS插件 (beta)
这个新的插件利用新的glusterfs c api,避免当提供存储在glusterfs服务器上的文件时的融合开销。
该插件支持多进程和多线程模式,而异步模式目前处于测试阶段。
文档在这里: GlusterFS插件
–force-gateway
所有的网关 (fastrouter, httprouter, rawrouter, sslrouter …)都必须运行在master进程之下。
通过指定–force-gateway,你可以绕过这个限制
初步的python3 profiler (测试版)
–profiler pycall/pyline profiler已添加至python3中。它们处于测试阶段 (有内存泄漏问题),但应该可用。
对OpenBSD,NetBSD,DragonFlyBSD的文件监控支持
在这些操作系统上,–fs-reload和@fmon装饰器现在都能使用。
–cwd
你可以使用这个选项强制在“当前工作目录” (由–vacuum和重载子系统使用) 下启动。
在chroot设置中有用,其中,二进制可执行文件修改它的位置。
–add-gid
这个选项允许你添加额外的组id到当前的进程中。你可以多次指定它。
Emperor和Linux名字空间改进
多亏了与pythonanywhere.com那些小伙伴的合作,已对Emperor进行了改进,使其能够与Linux名字空间更好的集成。
–emperor-use-clone选项允许你使用clone()而不是fork()来进行vassal生成。通过这种方式,你可以在一个新的名字空间中直接创建vassal。这个函数接收的参数与–unshare相同
- uwsgi --emperor /etc/vassals --emperor-use-clone pid,uts
将会在一个新的pid和uts名字空间中创建每个vassal
而
- uwsgi --emperor /etc/vassals --emperor-use-clone pid,uts,net,ipc,fs
将会基本上使用当前所有可用的名字空间。
两个新的exec (和call) 钩子现在可以用了:
–exec-as-emperor将会在生成一个vassal后立即在emperor中运行命令 (设置4个环境变量UWSGI_VASSAL_CONFIG, UWSGI_VASSAL_PID, UWSGI_VASSAL_UID和UWSGI_VASSAL_GID)
–exec-as-vassal将就在调用exec()之前,在vassal中运行命令 (所以直接在新的名字空间中)
–wait-for-interface
由于处理Linux网络名字空间引入了大量的竞争条件 (特别是当使用虚拟以太网时),这个新的选项让你暂停一个实例,直到有一个网络接口可用。
这在当等待emperor把veth移动到vassal名字空间的时候有用,避免vassal在接口可用之前在其之上运行命令
- [uwsgi]
- emperor = /etc/uwsgi/vassals
- emperor-use-clone = pid,net,fs,ipc,uts
- ; each vassal should have its veth pair, so the following commands should be improved
- exec-as-emperor = ip link del veth0
- exec-as-emperor = ip link add veth0 type veth peer name veth1
- ; do not use the $(UWSGI_VASSAL_PID) form, otherwise the config parser will expand it on startup !!!
- exec-as-emperor = ip link set veth1 netns $UWSGI_VASSAL_PID
- [uwsgi]
- ; suspend until the emperor attach veth1
- wait-for-interface = veth1
- ; the following hook will be run only after veth1 is available
- exec-as-root = hostname vassal001
- exec-as-root = ifconfig lo up
- exec-as-root = ifconfig veth1 192.168.0.2
- uid = vassal001
- gid = vassal001
- socket = :3031
- ...
可用性
uWSGI 1.9.15于2013年08月29日发布
你可以从下面地址下载它: