RADOS插件

自uWSGI 1.9.16起可用,自uWSGI 2.0.6起稳定

官方modifier1: 28

作者:Javier Guerra, Marcin Deranek, Roberto De Ioris, Sokolov Yura 又名funny_falcon

‘rados’插件让你可以使用librados API,直接提供存储在一个Ceph集群中的对象。

注意,不是CephFS文件系统,也不是’radosgw’ S3/Swift兼容层;RADOS是裸对象存储层。

第1步:Ceph集群和内容

如果你想尝试最小Ceph安装,那么你可以遵循这个指导:http://ceph.com/docs/master/start/。注意,你只需要OSD和MON守护进程,MDS只在CephFS文件系统的时候是必须的。

一旦运行了它,你应该有一个配置文件 (默认在/etc/ceph/ceph.con上),并且应该能够使用 rados 功能。

rados lspools

默认情况下,你应该至少拥有’data’, ‘metadata’和’rbd’池。现在添加一些内容到’data’池。例如,如果你有一个’list.html’文件和子目录’imgs/’下的图片’first.jpeg’, ‘second.jpeg’:

rados -p data put list.html list.html
rados -p data put imgs/first.jpeg imgs/first.jpeg
rados -p data put imgs/second.jpeg imgs/second.jpeg
rados -p data ls -

注意,RADOS没有目录的概念,但是对象名可以包含斜线。

第2步:uWSGI

有一个名为’rados’的构建配置文件可以用,因此你可以简单这样做:

make PROFILE=rados

或者

python uwsgiconfig.py --build rados

或者使用安装程序

# this will create a binary called /tmp/radosuwsgi that you will use instead of 'uwsgi'
curl http://uwsgi.it/install | bash -s rados /tmp/radosuwsgi

显然,你可以将rados支持当成插件构建

uwsgi --build-plugin plugins/rados/

或者旧式的:

python uwsgiconfig.py --plugin plugins/rados/

现在,你可以启动一个HTTP服务器来提供RADOS对象服务了:

[uwsgi]
; bind on port 9090
http-socket = :9090
; set the default modifier1 to the rados one
http-socket-modifier1 = 28
; mount our rados pool
rados-mount = mountpoint=/rad/,pool=data,config=/etc/ceph/ceph.conf
; spawn 30 threads
threads = 30

‘rados-mount’参数接收多个子参数:

  • mountpoint: 必需,RADOS对象将会出现的URL前缀。
  • pool: 必需,提供服务的RADOS池。
  • config: 可选,ceph配置文件的路径。
  • timeout: 可选,设置操作的超时时间,以秒为单位
  • allow_put: 允许调用 PUT HTTP方法来存储新的对象
  • allow_delete: 允许调用 DELETE HTTP方法来移除对象
  • allow_mkcol: 允许调用 MKCOL HTTP方法来创建新的池
  • allow_propfind: (要求版本uWSGI 2.1) 允许调用WebDAV PROPFIND 方法
  • buffer_size: GET 请求的最大缓冲大小,以字节为单位 (最小8192,最大的16777216,默认是131072)
  • put_buffer_size: PUT 请求的最大缓冲大小 (默认为buffer_size)

在这个例子中,你的内容地址将会是http://localhost:9090/rad/list.html, http://localhost:9090/rad/imgs/first.jpeg和http://localhost:9090/rad/imgs/second.jpeg。

高可用性

RADOS存储系统是全分布的,只要使用相同的’ceph.conf’,在多个机器上启动几个uWSGI worker,那么所有的worker都能看到同一个池。如果它们都在相同的挂载点上提供服务,那么你会得到一个抗故障的RADOS-HTTP网关。

多挂载点

你可以声明多个’rados-mount’项,每一个会定义一个新的挂载点。通过这种方式,你可以在不同的URL上公开不同的RADOS池。

HTTP方法

支持以下方法:

  • GET -> 检索资源
  • HEAD -> 和GET一样,但是没有请求体
  • OPTIONS -> (要求版本uWSGI 2.1) 返回允许的HTTP方法和WebDAV支持的列表
  • PUT -> 要求mountpoint选项中有allow_put,存储资源到ceph:curl -T /etc/services http://localhost:8080/services
  • MKCOL -> 要求mountpoint选项中有allow_mkcol,创建一个新的池:curl -X MKCOL http://localhost:8080/anewpool (将会创建池’anewpool’)
  • DELETE -> 要求mountpoint选项中有allow_delete,移除一个对象
  • PROPFIND -> 要求mountpoint选项中有allow_propfind (uWSGI 2.1+),实现WebDAV PROPFIND方法

特性

  • 支持多进程
  • 异步支持功能齐全,ugreen挂起引擎是唯一支持的引擎:
[uwsgi]
; bind on port 9090
http-socket = :9090
; set the default modifier1 to the rados one
http-socket-modifier1 = 28
; mount our rados pool
rados-mount = mountpoint=/rad/,pool=data,config=/etc/ceph/ceph.conf
; spawn 1000 async cores
async = 1000
; required !!!
ugreen = true

缓存样例

强烈建议使用缓存来改进性能和减少Ceph集群上的负载。这是一个好例子:

[uwsgi]
; create a bitmap cache with max 1000 items storable in 10000 4k blocks
cache2 = name=radoscache,items=1000,blocks=10000,blocksize=4096,bitmap=1

; check every object ending with .html in the 'radoscache' cache
route = \.html$ cache:key=${PATH_INFO},name=radoscache,content_type=text/html
; if not found, store it at the end of the request for 3600 seconds (this will automatically enable Expires header)
route = \.html$ cachestore:key=${PATH_INFO},name=radoscache,expires=3600

; general options

; master is always a good idea
master = true
; bind on http port 9090 (better to use a uwsgi socket behind a proxy like nginx)
http-socket = :9090
; set the default modifier1 to the rados one
http-socket-modifier1 = 28
; mount our rados 'htmlpages' pool
rados-mount = mountpoint=/,pool=htmlpages

; spawn multiple processes and threads
processes = 4
threads = 8

要测试缓存行为,诸如uwsgicachetop (https://pypi.python.org/pypi/uwsgicachetop) 这样的工具将非常有用。

更多关于缓存的信息在这里: CachingCookbook

安全注意事项

启用MKCOL, PUT和DELETE可能会有很高的安全风险。

将它们与内部路由框架结合,以添加鉴权/认证策略:

[uwsgi]
master = true
; bind on http port 9090 (better to use a uwsgi socket behind a proxy like nginx)
http-socket = :9090
; set the default modifier1 to the rados one
http-socket-modifier1 = 28
; mount our rados 'htmlpages' pool
rados-mount = mountpoint=/,pool=htmlpages,allow_put=1,allow_mkcol=1

; spawn multiple processes and threads
processes = 4
threads = 8

; permit PUT only to authenticated 'foo' user
route-if = equal:${REQUEST_METHOD};PUT basicauth:my secret area,foo:bar

; allow MKCOL only from 127.0.0.1
route-if = equal:${REQUEST_METHOD};MKCOL goto:check_localhost
; end of the chain
route-run = last:

route-label = check_localhost
; if REMOTE_ADDR = 127.0.0.1 -> continue to rados plugin
route-remote-addr = ^127\.0\.0\.1$ continue:
; otherwise break with 403
route-run = break:403 Forbidden

注意事项

  • 这个插件自动启用MIME type引擎。
  • 无目录索引支持。在rados/ceph上下文中,它并无意义。
  • 你应该在你的uWSGI实例中移除特权,因此,确保你把正确的权限给予了ceph keyring。
  • 如果你用它来获取/存储大对象,那么考虑提高 buffer_size 。4194304是个非常高性能的值,如果你想节约内存,那么1048576也不错。
  • 支持放入Erasure编码的池。会自动调整 put_buffer_size 来满足池对齐要求。