• 单机服务器、集群和分布式


    单机服务器、集群和分布式

    单机服务器,故名思意,就是一台服务器提供所有功能,所有客户端的连接都在一台服务器上。
    集群:每一台服务器独立运行一个工程的所有模块。
    分布式:一个工程拆分了很多模块,每一个模块独立部署运行在一个服务器主机上,所有服务器协同工作共同提供服务,每一台服务器称作分布式的一个节点,根据节点的并发要求,对一个节点可以再做节点模块集群部署。
    以聊天服务器为例,假设一个聊天服务器有以下功能:

    在这里插入图片描述
    ChatServer把用户管理、好友管理、群组管理、消息管理、后台管理都做了模块化处理,这些模块构成了完整的ChatServer,每个模块都包含特定的业务。
    用户管理模块有用户登录,用户注册,用户注销,用户退出等功能业务。好友管理有添加好友,删除好友等功能业务。群组管理有添加群,创建群,解散群,群里踢人等功能业务。消息管理有离线消息,一对一的消息,群组消息等和功能业务。后台管理有广播消息,公告消息,活动消息等功能业务。

    对单台物理机器来说,它的硬件资源是有限的。因为我们只有一台服务器,聊天服务器所能承受的用户的并发量是有限的。假设我们使用32位linux,给一个进程把资源开满,最多支持2万多人的在线。用户量上不去了。硬件资源不够,socket资源不够。
    假设这个服务聊天器有5个模块,每个模块有几十上百个功能业务,这一套项目编译得花2个小时,部署得花3个小时。现在如果我们突然发现用户管理模块有个注销的业务里面有bug,但是改起来特别简单,就几行代码。但是这是一整套系统,得把整个项目的所有代码全部重新编译!这样又得花2个小时编译,运维部署3个小时!服务器还得停止服务。
    系统中有些模块是属于CPU密集型(计算量大),有些模块是属于I/O密集型的(设备驱动 输入输出,网络I/O),造成各模块对硬件资源的需求是不一样。 有些模块是CPU密集型的,这些模块应该部署在CPU资源非常好的机器上,有些模块是I/O密集型的,这些模块应该部署在内存大,带宽好的机器上,不需要太强的CPU资源。不同模块属于不同的型,对硬件的需求不一样,打包在一套机器上,只能综合所有模块,提出平衡的供给需求,没办法针对性。

    单机服务器存在以下缺点:

    • ‌受限于单台机器硬件资源,服务器所能承受的用户并发量有限
    • ‌任意模块的修改,都会导致整个项目代码重新编译,部署
    • 各模块对硬件资源的需求不一样,有些事IO密集型,有些是CPU密集型,需要全部考虑

    服务器集群

    每一台服务器都是独立的系统
    在这里插入图片描述
    集群就是通过扩充多台服务器,解决单台机器硬件资源受限问题,横向扩充机器数量,每台机器都能提供所有的服务,假如ChatServer1崩了,只有ChatServer2和ChatServer3没问题,就不影响服务。

    集群解决了单台机器硬件资源受限的问题,可以通过扩充机器来提高性能,让硬件资源可以扩充,单台服务器崩溃不影响其他服务器的运行。

    ‌但模块修改会导致整个项目要重新在每台服务器上重新编译,部署,代价比单台服务器还大

    ‌各模块硬件资源需求不同的问题还是没有解决,同时也带来一个新问题:有些模块并发需求不大,根本不需要集群部署。比如后台管理模块,使用的用户只有管理员,服务频次肯定不高,但把这个模块也做集群部署到多台机器上,就显得太多余了。

    分布式

    各模块进行拆分组合,单独部署在不同的机器上,对于并发量需求高的服务模块进行集群部署,IO密集型的服务模块选择在内存大,带宽好的机器上部署,多个机器构成一个完整系统,各服务节点协同为客户端提供服务。
    假设ChatServer用户管理和消息管理对并发要求较高,就把这两个服务抽取出来组合到一起,对这两个服务组合单独做集群部署。
    好友群组用户管理需要的频繁的读写磁盘,选择在内存大,带宽好的机器上部署。
    而后台管理两者要求都不高,就做普通部署即可。

    在这里插入图片描述
    假设图中的后台管理节点机器崩了,ChatServer就无法提供后台管理服务,但其他不依赖后台管理的服务同样可以照常运行。
    假设后台管理的某个业务除了BUG,需要修复,只需要把后台管理这个服务模块重新部署,其他服务并不需要重新部署更新。
    ‌对于并发量高的模块,拓充多个分布式结点(集群),提高并发量。有的模块并发能力小,部署在一台机器就可以。
    把CPU密集型的模块部署在CPU资源好的机器上。把内存小的模块部署在硬盘资源少的机器上。把I/O密集型的模块部署在CPU不是很好的机器上。

    分布式需要客服的问题

    ‌软件模块怎么划分?
    要做到各服务间完全解耦是不可能的,模块和模块间的界限不清晰,模块服务的提供需要依赖另一个模块业务逻辑(需要调用另一个模块的函数代码),各模块可能会出现大量重复的代码逻辑。
    处理不好就会造成大量的代码重复,如果各模块间对重复代码做不同的更新,提供的业务就会造成冲突。

    ‌各模块之间怎么访问(跨进程访问)?

    假设用户登录成功了,想展示好友列表,但是用户管理模块只负责用户的登录,退出,修改密码等业务功能,它并不知道好友列表,负责管理好友的是好友管理模块。通过传入用户id,得出好友列表。在单机或者集群中,这些模块是运行在一个服务器进程当中,相当于自己调用自己。但是在分布式中,用户管理和好友管理部署在不同的进程中,用户管理进程如何调用另一个模块上的业务呢?就需要实现RPC(Remove Procedure Call)远程方法调用通信实现。

  • 相关阅读:
    Docker容器管理
    『抽丝剥茧』手把手快速上带你开启文心大模型的奇妙冒险
    7-3 最低通行费
    基于粒子群优化算法的UAV三维路径规划研究付Matlab代码
    Java异步记录日志-2022新项目
    【计算机网络】 心跳机制
    【LeetCode】3. 无重复字符的最长子串
    ajax通过post方式和后端建立连接传输数据
    基于Dockerfile创建镜像
    101. 对称二叉树
  • 原文地址:https://blog.csdn.net/weixin_43973403/article/details/126317022