V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
georgetso
V2EX  ›  问与答

多进程+进程锁,还是一个进程?

  •  
  •   georgetso · 2014-08-10 18:08:10 +08:00 · 4737 次点击
    这是一个创建于 3769 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我过去参与的一个项目的服务端为了处理高并发设计如下:
    1个linux系统 with 4 cores
    1个nginx with 4 worker_processes
    1个mysql 实例
    4个业务进程

    nginx将接受到的请求随机分配给4个业务进程,每个业务进程如果有mysql写入操作,则在 /tmp 产生 project.sock 文件,内容是进程号,待操作完成后,该业务进程负责销毁文件。

    我是移动端开发人员,对 iOS_GCD 熟悉,然后也看过 golang_goroutine,所以想如果用 golang 写服务端的话,这个问题怎么解决? 还是多进程+进程锁?

    ------------------------------------------------------------------

    附加问题:
    1. nginx 有4个 worker_processes 意思是不是有4个消息队列,虽然能接受每秒十万次请求,但是同时最多只有4个消息被处理?
    2. 整个处理流程是不是,一个http请求到达nginx,被nginx通过fcgi转发到业务进程(阻塞nginx的一个worker_process),业务进程接受该请求并进行处理,然后将处理结果返回给nginx,nginx再返回给客户端?如果是这样,那实际上这种架构最多只能同时处理4个请求?再考虑到数据库写操作的锁,那业务效率不是很低么?
    16 条回复    2014-08-12 18:09:13 +08:00
    clino
        1
    clino  
       2014-08-10 19:44:54 +08:00 via Android
    怎么可能才4个,nginx worker接受到一个请求转发给应用以后在返回前就可以去处理其他请求了,并发数可以很高的
    georgetso
        2
    georgetso  
    OP
       2014-08-10 20:01:10 +08:00
    @clino 哦,原来是这样啊。那是否有可能出现这种情况:
    worker1 接收到请求,转发给业务进程,然后 worker1 就玩儿蛋去了
    业务进程处理好这个请求后,将结果返回给nginx, 但是却是 worker2 这个接盘侠接收,并将结果返回给客户端?
    georgetso
        3
    georgetso  
    OP
       2014-08-10 20:03:11 +08:00
    如果 nginx 能用各种方式实现真正的超高并发,但是业务进程怎么做到这点呢?
    假如服务器每秒收到1万个请求,难道要创建1万个业务进程去处理请求?
    jasontse
        4
    jasontse  
       2014-08-10 20:06:25 +08:00 via Android
    nginx 使用 epoll 它是非阻塞的
    georgetso
        5
    georgetso  
    OP
       2014-08-10 20:09:34 +08:00
    @jasontse 感觉回复。但是我2/3楼提到的问题呢?golang哪怕有协程这种并发机制,但是业务进程始终只能一次处理一个请求吧?这个如何做到高并发呢?
    以及,哪怕做到了业务进程高并发,但是数据库写操作锁又怎么解决呢
    clino
        6
    clino  
       2014-08-10 21:14:18 +08:00 via Android
    @georgetso 我的理解是高并发要在每个环节都要能高并发,nginx能高并发只是说在你的应用环境下它不会成为瓶颈而已,其他环节还要你一一考虑解决
    georgetso
        7
    georgetso  
    OP
       2014-08-10 22:17:04 +08:00
    @clino 是的,我在3楼和5楼也说到了这个。

    那么,业务进程怎样做到并发呢?不管是golang的goroutine,还是ios的gcd,都是在一个进程内的并发方案。那么,对于这种成千上万的web请求,有没有办法在1个或少量进程的情况下实现并发处理多个请求呢?
    clino
        8
    clino  
       2014-08-10 22:34:18 +08:00 via Android
    @georgetso 当然可以了,event类的没问题,协程类的在一个进程里开几万个协程就好了
    defia
        9
    defia  
       2014-08-11 02:56:11 +08:00 via Android
    1。利用channel通讯 少用锁
    2。设置GOMAXPROC,这个你可以理解为最大线程数,就可以把goroutine分布到不同的核心上去了。

    还有为毛要用fastcgi。直接把特定url丢给golang处理就行了。
    defia
        10
    defia  
       2014-08-11 02:58:11 +08:00 via Android
    还有就是一个进程当然是可以同时照顾nnn个请求的,照顾一个那是apache或者php这种阻塞模型。。
    sqbing
        11
    sqbing  
       2014-08-11 10:15:19 +08:00
    分析你的业务流程,分解,使用消息队列分发业务请求
    为了让nginx最大程度的发挥高并发特性,最好将业务进程中的IO处理也做成异步
    georgetso
        12
    georgetso  
    OP
       2014-08-12 15:18:01 +08:00
    @defia @clino 好,我现在知道 golang 的非阻塞了。但是,数据库锁怎么解决呢?
    要么建立一个线程专门做数据库操作,所有协程最终都以 FIFO 方式排队?这样会不会太慢?
    可是如果多个写操作同时操作数据库,那交给数据库自行解决?还是业务负责锁机制?
    defia
        13
    defia  
       2014-08-12 17:46:08 +08:00
    @georgetso 数据库这个就跟语言无关了啊..取决于你的具体业务,具体哪些地方需要锁需要事务咯,说全这个可以拿出来单独写一章了..

    golang是以同步的形式写异步程序,逻辑上是同步阻塞的,但是底层实际是异步的.
    clino
        14
    clino  
       2014-08-12 17:50:19 +08:00 via Android
    这部分我只是了解皮毛,没实践经验,只能抛下砖,一般来说写才会锁数据库,读不会,所以读的并发会比较高,要再高可以用cache/主从数据库 等,要不就用非关系型数据库
    clino
        15
    clino  
       2014-08-12 17:57:53 +08:00 via Android
    当然像前面写的,要提高并发,最好将所有环节都用异步的方式实现,包括数据库的访问
    clino
        16
    clino  
       2014-08-12 18:09:13 +08:00 via Android
    上面写错了,是非阻塞不是异步
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5920 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 02:29 · PVG 10:29 · LAX 18:29 · JFK 21:29
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.