既然提倡去 Rails 化我很想介绍一下 Rails 之外的 Web 框架,懒得长篇大论写文章了,简单写个帖子。
比较适合写 Web 服务接口的轻量级 Web 框架我推荐两个:Grape 和 Sinatra,两个的区别主要是:
Grape 是个纯粹的写 API 的框架,提供了很多写 API 很方便的功能,用 Grape 写 API 很爽,应该是首选,他只提供 json/xml/txt 格式输出。
Sinatra 是个相对完善点的 Web 框架,带有模板渲染功能,但单纯写 API 的话,没有 Grape 爽。不过如果你的 API Server 有可能输出 HTML 页面片段,需要模板功能的话,还是 Sinatra 更合适,否则用 Grape 在代码里面拼字符串还是很麻烦的事情。
Grape 和 Sinatra 都是基于 Rack 之上很轻量级的封装,我做了框架处理请求速度的测试,以及多线程并发的简单测试,基本上性能差异非常小,Grape 稍微快一点点,但不超过 5%。测试结果
比较适合写 Website 的框架,功能最完善的当然是 Rails,不过我用 Padrino 做了自己的网站项目,发现也很不错,推荐大家用用。
最后说到并发性能,我自己的测试结果表明,Ruby 的多线程性能在并发量并不是超高的情况下,还是很不错的,对比 Fiber 的来说,性能差异非常小。我做了 Goliath(raw code), Goliath(Grape), Rainbows(Grape), Puma(Grape), Rainbows(Sinatra), Puma(Sinatra), 的并发性能测试,基本在同一水平线上。测试结果
所以如果用 Ruby 写高并发的 API Server,即使不用 Goliath 也行,用 Grape/Sinatra 写 API,用 Rainbows 来跑即可,性能也非常好,而且 Rainbows 的可管理性也非常棒,和 Unicorn 一样方便。
#14 楼 @blacktulip 哈哈,在一个群里大家讨论时,说移动互联网时代,用户会突然暴增!还没等优化,服务器已经受不了了。 所以,当时,群里就说推荐学习 Go。
其实,我挺喜欢 Ruby,虽然刚刚开始学。所以,看看 Ruby 以后会不会有更好的发展。啊哈
我错把移动互联网时代说成云时代。抱歉!哈哈
Grape 一直用,配合 Grape Entity 做 json 的渲染很方便。我还 hack 了一点点,基本上满足了大部分的开发需求。唯一不方便的是多模块的使用,不能很好的 reload。
@robbin 肉饼问个问题,如果用了 Goliath,是否有必要用 Nginx 来做前端的代理,或者后面启动多个 Goliath Server 进程,用 Nginx 来做负载均衡。由于 Goliath 本来就是为了高并发设计的,再用 Nginx 做代理是否有必要或者是否能明显的提高并发能力?谢谢。
@robbin 你做的这个太棒了:https://github.com/robbin/grape-goliath-example 我一直对新版本的 Goliath 没有个好的路由解决方案头痛不已。
#43 楼 @jimrokliu 是的,用了 nginx 确实会让很多事情处理起来更加方便。只是不知道,用与不用,只考虑单纯的 api call 的情况下有多少区别,是不是用了 nginx 后,能提高并发能力?
#45 楼 @jimrokliu 由于 Goliath 本身就支持高并发了,所以我一直觉得,在前面放个代理貌似作用不大,除非你用代理,做负载均衡。
原来你们都不会 socket 啊...
不希望 Goliath 以 root 身份运行在 80 端口。
你可以先以 root 去 bind 80 端口,setuid 成 appuser,再去执行 Goliath...
比如用老土的 supervisord 就可以,假如你放心用 root 运行 supervisord,那么你可以用那个fcgi-program
的功能,这个名字起得不好,其实所有 TCP/Unix domain socket 都可以。
而且用于 Unix domain socket 的时候,你可以把user
设置成 appuser,把socket_owner
设置成nginx
,这样两者就完全隔离开了,并且以其他非 root 用户运行的程序也 connect 不了这个 unix domain socket。
当然,这样就需要 supervisord 是 root 了,这显然不是很好。当然也可以尝试去获得连进来的 socket 的 uid,gid 来判断,如果不是 nginx 的直接关掉。但这里要用到一些高级的 socket 操作,而且判断 uid/gid 的逻辑和应用代码搅在一起,这么做是否值得也说不好。
而且最新的 Linux 内核也支持 capability 了,完全可以只给一个仅用于占端口的 capability,bind 完了之后 drop 掉就是了。
可以让 nginx 和 Goliath 通过 socket 进行通讯。不一定非得走 http。
通过 TCP Socket 还是 Unix domain Socket 和用啥协议没啥关系。两种 socket 上面都可以是 HTTP/FastCGI/SCGI 等协议。
在多核服务器上,你需要启动多个 Goliath 进程,分别监听不同的 tcp port,所以前面需要 nginx 做请求分发。
所有的 Goliath 进程当然可以监听同一个 tcp port 了。最简单的办法就是,先 bind 到某个 tcp 端口,fork 成多个进程就好了。但要想动态调整就得写点代码了。
假如你不想自己 fork,你可以试试 supervisord 的fcgi-program
,这个名字起得不好,其实所有 TCP/Unix domain socket 都可以。把numprocs_start
改成 5,在进程里面都listen
fd=0 的那个 socket,看是不是 5 个进程都在监听同一个 tcp 端口了呢...
http://supervisord.org/configuration.html#fcgi-program-x-section-settings