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