1、我了解到进程之间都是独立的,unicorn fork 的 多个进程 数据共享是如何解决的 2、之前是做 java /c# 的 ,服务端是多线程的模型,数据都是共用 的,我们只需要关注并发带来的问题 3、这样的问题,我搜了很久,无果!如果你愿意告诉我你解决搜索资料的方法,我非常感谢!
第一个问题:unicorn 采用的是传统的 unix 多进程协作的方式处理请求,主进程负责接收请求,然后委托给子进程去处理,并且负责监控和管理子进程的状态,必要的时候可以 kill 并重启子进程。Ruby 1.9 以后开始支持 Copy-On-Write 模式,在这种模式下,fork 子进程的时候可以共享主进程的内存对象,而对象的写操作发生在子进程自己的内存空间,这样可以达到节约一部分内存的效果,比如避免子进程重复载入整个 Rails 的库对象。unicorn 的子进程之间没有进程间通信机制,各自独立处理请求,所以子进程之间不共享内存数据,但是可以通过其他方式去共享一些非内存数据,比如共享 Redis,数据库,或者文件系统中的数据。
第二个问题:Rails 4.0 之后默认开启线程安全模式,也就是说 Rails 可以跑在基于线程模式的 WebServer 比如 puma 上,以 puma 为例,派生出一个线程去处理每个请求(或者基于线程池),线程共享主进程的内存对象,但是处理请求过程中产生的新内存变量会存储在线程自己的栈帧中,基于线程模式的服务模型比基于进程模式更加节约内存,因为整个 Rails 是线程安全的,且 MRI 基于 GIL 全局锁模式保障多线程下内存变量访问的安全,所以基于同一个 Ruby VM 下的多线程模式的并发问题不是问题。
第三个问题:因为这个问题涉及到 Unix 的进程模型,线程模型,WebServer 的运行机制,以及 Ruby 本身的线程加锁的实现方式,以及 Rails 的线程安全策略(Rails 的 eager_loading 机制)等,是一个复合型问题,所以搜索资料的时候需要选取一个角度去搜索,但是本论坛充斥大量的相关讨论,建议多耐心深挖一下。
私货,在高并发方面,我推荐 @robbin 的几篇帖子,虽然写于两年前,但是结论已经概括完整且至今仍然适用。
https://ruby-china.org/topics/9851 https://ruby-china.org/topics/10832 https://ruby-china.org/topics/11249
感谢! 这类的讨论和资料我看了一些!仍然有一些困惑,我慢慢道来哈!一、假如我的应用中需要用到验证码,那么我申请一个 hash 对象把验证码都存起来,那会不会 出现 申请的时候,在一个进程里面执行,验证的时候在另一个进程里面执行? 如果是 ,那就是你说的,需要借助数据库或者文件之类的办法,共享!
那上次我提到的 session 实际上并不是 unicorn 维护的,应该是 rack 在维护 session , 所以 session ,我写 rails 程序的时候并不需要关心对吧?
感谢,感谢!
验证码问题跟 Session 问题其实可以归类为一个问题,因为 Web 服务基于请求响应模式,在两次请求之间通过 Session 去保存临时状态,所以你的验证码状态可以通过 Session 来保存,而 Rails 为了可以水平扩张,默认使用 Cookie based 的 Session 保存机制,也就是说,Session 存储在 Cookie 中,Cookie 存储在客户端,客户端每次请求的 request 都会附带 Cookie 信息,在 server 端收到 cookie 然后还原出完整的 session,取得前一次请求中的验证码状态,这个机制刚刚好解决了你提出的验证码问题。
关于其他需要共享的状态信息,一般通过数据库或者其他持久化机制去保存。
哦 cookie based