为自己搭建一个分布式 IM(即时通讯) 系统
CIM(CROSS-IM) 一款面向开发者的 IM(即时通讯)系统;同时提供了一些组件帮助开发者构建一款属于自己可水平扩展的 IM 。
借助 CIM 你可以实现以下需求:
下面来看看具体的架构设计。
整体主要由以下模块组成:
cim-server
IM 服务端;用于接收 client 连接、消息透传、消息推送等功能。
支持集群部署。
cim-forward-route
消息路由服务器;用于处理消息路由、消息转发、用户登录、用户下线以及一些运营工具(获取在线用户数等)。
cim-client
IM 客户端;给用户使用的消息终端,一个命令即可启动并向其他人发起通讯(群聊、私聊);同时内置了一些常用命令方便使用。
整体的流程也比较简单,流程图如下:
所以当我们自己部署时需要以下步骤:
接下来重点看看具体的实现,比如群聊、私聊消息如何流转;IM 服务端负载均衡;服务如何注册发现等等。
IM 服务端
先来看看服务端;主要是实现客户端上下线、消息下发等功能。
首先是服务启动:
由于是在 SpringBoot 中搭建的,所以在应用启动时需要启动 Netty 服务。
从 pipline 中可以看出使用了 Protobuf 的编解码(具体报文在客户端中分析)。
注册发现
需要满足 IM 服务端的水平扩展需求,所以 cim-server 是需要将自身数据发布到注册中心的。
所以在应用启动成功后需要将自身数据注册到 Zookeeper 中。
最主要的目的就是将当前应用的 ip + cim-server-port+ http-port 注册上去。
上图是我在演示环境中注册的两个 cim-server 实例(由于在一台服务器,所以只是端口不同)。
这样在客户端(监听这个 Zookeeper 节点)就能实时的知道目前可用的服务信息。
登录
当客户端请求 cim-forward-route 中的登录接口(详见下文)做完业务验证(就相当于日常登录其他网站一样)之后,客户端会向服务端发起一个长连接,如之前的流程所示:
这时客户端会发送一个特殊报文,表明当前是登录信息。
服务端收到后就需要将该客户端的 userID 和当前 Channel 通道关系保存起来。
同时也缓存了用户的信息,也就是 userID 和 用户名。
离线
当客户端断线后也需要将刚才缓存的信息清除掉。
同时也需要调用 route 接口清除相关信息(具体接口看下文)。
IM 路由
从架构图中可以看出,路由层是非常重要的一环;它提供了一系列的 HTTP 服务承接了客户端和服务端。
目前主要是以下几个接口。
注册接口
由于每一个客户端都是需要登录才能使用的,所以第一步自然是注册。
这里就设计的比较简单,直接利用 Redis 来存储用户信息;用户信息也只有 ID 和 userName 而已。
只是为了方便查询在 Redis 中的 KV 又反过来存储了一份 VK,这样 ID 和 userName 都必须唯一。
登录接口
这里的登录和 cim-server 中的登录不一样,具有业务性质,
为了实现只能一个用户登录,使用了 Redis 中的 set 来保存登录信息;利用 userID 作为 key ,重复的登录就会写入失败。
获取一台可用的路由实例也比较简单:
当然要获取 Zookeeper 中的服务实例前自然是需要监听 cim-server 之前注册上去的那个节点。
具体代码如下:
也是在应用启动之后监听 Zookeeper 中的路由节点,一旦发生变化就会更新内部缓存。
群聊接口
这是一个真正发消息的接口,实现的效果就是其中一个客户端发消息,其余所有客户端都能收到!
流程肯定是客户端发送一条消息到服务端,服务端收到后在上文介绍的 SessionSocketHolder 中遍历所有 Channel(通道)然后下发消息即可。
服务端是单机倒也可以,但现在是集群设计。所以所有的客户端会根据之前的轮询算法分配到不同的 cim-server 实例中。
因此就需要路由层来发挥作用了。
路由接口收到消息后首先遍历出所有的客户端和服务实例的关系。
路由关系在 Redis 中的存放如下:
由于 Redis 单线程的特质,当数据量大时;一旦使用 keys 匹配所有 cim-route: 数据,会导致 Redis 不能处理其他请求。
所以这里改为使用 scan 命令来遍历所有的 cim-route:。
接着会挨个调用每个客户端所在的服务端的 HTTP 接口用于推送消息。
在 cim-server 中的实现如下:
cim-server 收到消息后会在内部缓存中查询该 userID 的通道,接着只需要发消息即可。
在线用户接口
这是一个辅助接口,可以查询出当前在线用户信息。
实现也很简单,也就是查询之前保存 ”用户登录状态的那个去重 set “即可。
私聊接口
之所以说获取在线用户是一个辅助接口,其实就是用于辅助私聊使用的。
一般我们使用私聊的前提肯定得知道当前哪些用户在线,接着你才会知道你要和谁进行私聊。
类似于这样:
在我们这个场景中,私聊的前提就是需要获得在线用户的 userID。
所以私聊接口在收到消息后需要查询到接收者所在的 cim-server 实例信息,后续的步骤就和群聊一致了。调用接收者所在实例的 HTTP 接口下发信息。
只是群聊是遍历所有的在线用户,私聊只发送一个的区别。
下线接口
一旦客户端下线,我们就需要将之前存放在 Redis 中的一些信息删除掉(路由信息、登录状态)。
IM 客户端
客户端中的一些逻辑其实在上文已经谈到一些了。
登录
第一步也就是登录,需要在启动时调用 route 的登录接口,获得 cim-server 信息再创建连接。
登录过程中 route 接口会判断是否为重复登录,重复登录则会直接退出程序。
接下来是利用 route 接口返回的 cim-server 实例信息(ip+port)创建连接。
最后一步就是发送一个登录标志的信息到服务端,让它保持客户端和 Channel 的关系。
自定义协议
上文提到的一些登录报文、真正的消息报文这些其实都是在我们自定义协议中可以区别出来的。
由于是使用 Google Protocol Buffer 编解码,所以先看看原始格式。
其实这个协议中目前一共就三个字段:
目前主要是三种类型,分别对应不同的业务:
心跳
为了保持客户端和服务端的连接,每隔一段时间没有发送消息都需要自动的发送心跳。
目前的策略是每隔一分钟就是发送一个心跳包到服务端:
这样服务端每隔一分钟没有收到业务消息时就会收到 ping 的心跳包:
内置命令
客户端也内置了一些基本命令来方便使用。
比如输入 :q 就会退出客户端,同时会关闭一些系统资源。
当输入 :olu(onlineUser 的简写)就会去调用 route 的获取所有在线用户接口。
群聊
群聊的使用非常简单,只需要在控制台输入消息回车即可。
这时会去调用 route 的群聊接口。
私聊
私聊也是同理,但前提是需要触发关键字;使用 userId;;消息内容 这样的格式才会给某个用户发送消息,所以一般都需要先使用 :olu 命令获取所以在线用户才方便使用。
消息回调
为了满足一些定制需求,比如消息需要保存之类的。
所以在客户端收到消息之后会回调一个接口,在这个接口中可以自定义实现。
因此先创建了一个 caller 的 bean,这个 bean 中包含了一个 CustomMsgHandleListener 接口,需要自行处理只需要实现此接口即可。
自定义界面
由于我自己不怎么会写界面,但保不准有其他大牛会写。所以客户端中的群聊、私聊、获取在线用户、消息回调等业务(以及之后的业务)都是以接口形式提供。
也方便后面做页面集成,只需要调这些接口就行了;具体实现不用怎么关心。
cim 目前只是第一版,BUG 多,功能少(只拉了几个群友做了测试);不过后续还会接着完善,至少这一版会给那些没有相关经验的朋友带来一些思路。
欢迎工作一到五年的Java工程师朋友们加入Java程序员开发: 721575865
群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!
最开始,由于某些想法,于是在互联网上搭建了一个网站,这个时候甚至有可能主机都是租借的,但由于这篇文章我们只关注架构的演变历程,因此就假设这个时候已经是托管了一台主机,并且有一定的带宽了,这个时候由于网站具备了一定的特色,吸引了部分人访问,逐渐你发现系统的压力越来越高,响应速度越来越慢,而这个时候比较明显的是数据库和应用互相影响,应用出问题了,数据库也很容易出现问题,而数据库出问题的时候,应用也容易出问题,于是进入了第一步演变阶段:将应用和数据库从物理上分离,变成了两台机器,这个时候技术上没有什么新的要求,但你发现确实起到效果了,系统又恢复到以前的响应速度了,并且支撑住了更高的流量,并且不会因为数据库和应用形成互相的影响。
这一步架构演变对技术上的知识体系基本没有要求。
架构演变第二步:增加页面缓存
好景不长,随着访问的人越来越多,你发现响应速度又开始变慢了,查找原因,发现是访问数据库的操作太多,导致数据连接竞争激烈,所以响应变慢,但数据库连接又不能开太多,否则数据库机器压力会很高,因此考虑采用缓存机制来减少数据库连接资源的竞争和对数据库读的压力,这个时候首先也许会选择采用squid 等类似的机制来将系统中相对静态的页面(例如一两天才会有更新的页面)进行缓存(当然,也可以采用将页面静态化的方案),这样程序上可以不做修改,就能够很好的减少对webserver的压力以及减少数据库连接资源的竞争,OK,于是开始采用squid来做相对静态的页面的缓存。
前端页面缓存技术,例如squid,如想用好的话还得深入掌握下squid的实现方式以及缓存的失效算法等。
架构演变第三步:增加页面片段缓存
增加了squid做缓存后,整体系统的速度确实是提升了,webserver的压力也开始下降了,但随着访问量的增加,发现系统又开始变的有些慢了,在尝到了squid之类的动态缓存带来的好处后,开始想能不能让现在那些动态页面里相对静态的部分也缓存起来呢,因此考虑采用类似ESI之类的页面片段缓存策略,OK,于是开始采用ESI来做动态页面中相对静态的片段部分的缓存。
这一步涉及到了这些知识体系:
页面片段缓存技术,例如ESI等,想用好的话同样需要掌握ESI的实现方式等;
架构演变第四步:数据缓存
在采用ESI之类的技术再次提高了系统的缓存效果后,系统的压力确实进一步降低了,但同样,随着访问量的增加,系统还是开始变慢,经过查找,可能会发现系统中存在一些重复获取数据信息的地方,像获取用户信息等,这个时候开始考虑是不是可以将这些数据信息也缓存起来呢,于是将这些数据缓存到本地内存,改变完毕后,完全符合预期,系统的响应速度又恢复了,数据库的压力也再度降低了不少。
这一步涉及到了这些知识体系:
缓存技术,包括像Map数据结构、缓存算法、所选用的框架本身的实现机制等。
架构演变第五步: 增加webserver
好景不长,发现随着系统访问量的再度增加,webserver机器的压力在高峰期会上升到比较高,这个时候开始考虑增加一台webserver,这也是为了同时解决可用性的问题,避免单台的webserver down机的话就没法使用了,在做了这些考虑后,决定增加一台webserver,增加一台webserver时,会碰到一些问题,典型的有:
1、如何让访问分配到这两台机器上,这个时候通常会考虑的方案是Apache自带的负载均衡方案,或LVS这类的软件负载均衡方案;
2、如何保持状态信息的同步,例如用户session等,这个时候会考虑的方案有写入数据库、写入存储、cookie或同步session信息等机制等;
3、如何保持数据缓存信息的同步,例如之前缓存的用户数据等,这个时候通常会考虑的机制有缓存同步或分布式缓存;
4、如何让上传文件这些类似的功能继续正常,这个时候通常会考虑的机制是使用共享文件系统或存储等;
在解决了这些问题后,终于是把webserver增加为了两台,系统终于是又恢复到了以往的速度。
这一步涉及到了这些知识体系:
负载均衡技术(包括但不限于硬件负载均衡、软件负载均衡、负载算法、linux转发协议、所选用的技术的实现细节等)、主备技术(包括但不限于 ARP欺骗、linux heart-beat等)、状态信息或缓存同步技术(包括但不限于Cookie技术、UDP协议、状态信息广播、所选用的缓存同步技术的实现细节等)、共享文件技术(包括但不限于NFS等)、存储技术(包括但不限于存储设备等)。
架构演变第六步:分库
享受了一段时间的系统访问量高速增长的幸福后,发现系统又开始变慢了,这次又是什么状况呢,经过查找,发现数据库写入、更新的这些操作的部分数据库连接的资源竞争非常激烈,导致了系统变慢,这下怎么办呢,此时可选的方案有数据库集群和分库策略,集群方面像有些数据库支持的并不是很好,因此分库会成为比较普遍的策略,分库也就意味着要对原有程序进行修改,一通修改实现分库后,不错,目标达到了,系统恢复甚至速度比以前还快了。
这一步涉及到了这些知识体系:
这一步更多的是需要从业务上做合理的划分,以实现分库,具体技术细节上没有其他的要求;
但同时随着数据量的增大和分库的进行,在数据库的设计、调优以及维护上需要做的更好,因此对这些方面的技术还是提出了很高的要求的。
架构演变第七步:分表、DAL和分布式缓存
随着系统的不断运行,数据量开始大幅度增长,这个时候发现分库后查询仍然会有些慢,于是按照分库的思想开始做分表的工作,当然,这不可避免的会需要对程序进行一些修改,也许在这个时候就会发现应用自己要关心分库分表的规则等,还是有些复杂的,于是萌生能否增加一个通用的框架来实现分库分表的数据访问,这个在ebay的架构中对应的就是DAL,这个演变的过程相对而言需要花费较长的时间,当然,也有可能这个通用的框架会等到分表做完后才开始做,同时,在这个阶段可能会发现之前的缓存同步方案出现问题,因为数据量太大,导致现在不太可能将缓存存在本地,然后同步的方式,需要采用分布式缓存方案了,于是,又是一通考察和折磨,终于是将大量的数据缓存转移到分布式缓存上了。
这一步涉及到了这些知识体系:
分表更多的同样是业务上的划分,技术上涉及到的会有动态hash算法、consistent hash算法等;
DAL涉及到比较多的复杂技术,例如数据库连接的管理(超时、异常)、数据库操作的控制(超时、异常)、分库分表规则的封装等;
架构演变第八步:增加更多的webserver
在做完分库分表这些工作后,数据库上的压力已经降到比较低了,又开始过着每天看着访问量暴增的幸福生活了,突然有一天,发现系统的访问又开始有变慢的趋势了,这个时候首先查看数据库,压力一切正常,之后查看webserver,发现apache阻塞了很多的请求,而应用服务器对每个请求也是比较快的,看来是请求数太高导致需要排队等待,响应速度变慢,这还好办,一般来说,这个时候也会有些钱了,于是添加一些webserver服务器,在这个添加 webserver服务器的过程,有可能会出现几种挑战:
1、Apache的软负载或LVS软负载等无法承担巨大的web访问量(请求连接数、网络流量等)的调度了,这个时候如果经费允许的话,会采取的方案是购买硬件负载,例如F5、Netsclar、Athelon之类的,如经费不允许的话,会采取的方案是将应用从逻辑上做一定的分类,然后分散到不同的软负载集群中;
2、原有的一些状态信息同步、文件共享等方案可能会出现瓶颈,需要进行改进,也许这个时候会根据情况编写符合网站业务需求的分布式文件系统等;
在做完这些工作后,开始进入一个看似完美的无限伸缩的时代,当网站流量增加时,应对的解决方案就是不断的添加webserver。
这一步涉及到了这些知识体系:
到了这一步,随着机器数的不断增长、数据量的不断增长和对系统可用性的要求越来越高,这个时候要求对所采用的技术都要有更为深入的理解,并需要根据网站的需求来做更加定制性质的产品。
架构演变第九步:数据读写分离和廉价存储方案
突然有一天,发现这个完美的时代也要结束了,数据库的噩梦又一次出现在眼前了,由于添加的webserver太多了,导致数据库连接的资源还是不够用,而这个时候又已经分库分表了,开始分析数据库的压力状况,可能会发现数据库的读写比很高,这个时候通常会想到数据读写分离的方案,当然,这个方案要实现并不容易,另外,可能会发现一些数据存储在数据库上有些浪费,或者说过于占用数据库资源,因此在这个阶段可能会形成的架构演变是实现数据读写分离,同时编写一些更为廉价的存储方案,例如BigTable这种。
这一步涉及到了这些知识体系:
数据读写分离要求对数据库的复制、standby等策略有深入的掌握和理解,同时会要求具备自行实现的技术;
廉价存储方案要求对OS的文件存储有深入的掌握和理解,同时要求对采用的语言在文件这块的实现有深入的掌握。
架构演变第十步:进入大型分布式应用时代和廉价服务器群梦想时代
经过上面这个漫长而痛苦的过程,终于是再度迎来了完美的时代,不断的增加webserver就可以支撑越来越高的访问量了,对于大型网站而言,人气的重要毋庸置疑,随着人气的越来越高,各种各样的功能需求也开始爆发性的增长,这个时候突然发现,原来部署在webserver上的那个web应用已经非常庞大了,当多个团队都开始对其进行改动时,可真是相当的不方便,复用性也相当糟糕,基本是每个团队都做了或多或少重复的事情,而且部署和维护也是相当的麻烦,因为庞大的应用包在N台机器上复制、启动都需要耗费不少的时间,出问题的时候也不是很好查,另外一个更糟糕的状况是很有可能会出现某个应用上的bug就导致了全站都不可用,还有其他的像调优不好操作(因为机器上部署的应用什么都要做,根本就无法进行针对性的调优)等因素,根据这样的分析,开始痛下决心,将系统根据职责进行拆分,于是一个大型的分布式应用就诞生了,通常,这个步骤需要耗费相当长的时间,因为会碰到很多的挑战:
1、拆成分布式后需要提供一个高性能、稳定的通信框架,并且需要支持多种不同的通信和远程调用方式;
2、将一个庞大的应用拆分需要耗费很长的时间,需要进行业务的整理和系统依赖关系的控制等;
3、如何运维(依赖管理、运行状况管理、错误追踪、调优、监控和报警等)好这个庞大的分布式应用。
经过这一步,差不多系统的架构进入相对稳定的阶段,同时也能开始采用大量的廉价机器来支撑着巨大的访问量和数据量,结合这套架构以及这么多次演变过程吸取的经验来采用其他各种各样的方法来支撑着越来越高的访问量。
这一步涉及到了这些知识体系:
这一步涉及的知识体系非常的多,要求对通信、远程调用、消息机制等有深入的理解和掌握,要求的都是从理论、硬件级、操作系统级以及所采用的语言的实现都有清楚的理解。
运维这块涉及的知识体系也非常的多,多数情况下需要掌握分布式并行计算、报表、监控技术以及规则策略等等。
说起来确实不怎么费力,整个网站架构的经典演变过程都和上面比较的类似,当然,每步采取的方案,演变的步骤有可能有不同,另外,由于网站的业务不同,会有不同的专业技术的需求,这篇blog更多的是从架构的角度来讲解演变的过程,当然,其中还有很多的技术也未在此提及,像数据库集群、数据挖掘、搜索等,但在真实的演变过程中还会借助像提升硬件配置、网络环境、改造操作系统、CDN镜像等来支撑更大的流量,因此在真实的发展过程中还会有很多的不同,另外一个大型网站要做到的远远不仅仅上面这些,还有像安全、运维、运营、服务、存储等,要做好一个大型的网站真的很不容易
1什么是Docker
借用下网上传统虚拟机与Docker的对比。
传统虚拟化应用程序中,不仅包含应用程序和必要的二进制文件库,还包含一个完整的操作系统。
而Docker容器仅包含应用程序和相关依赖项,在主机的操作系统用户空间中作为一个独立进程运行,与其他容器共享内核,从而实现了虚拟机的资源隔离和分配,具有更高的可移植性和效率提高。
2为什么使用Docker
1更快速的交付和部署
开发者可以使用一个标准的镜像来构建一套开发容器,开发完成之后,运维人员可以直接 使用这个容器来部署代码。
2高效部署和扩容
Docker 容器几乎可以在任意的平台上运行,包括物理机、虚拟机、公有云、私有云、个人电脑、服务器等。
3更高的资源利用率
Docker 对系统资源的利用率很高,一台主机上可以同时运行数千个 Docker 容器。容器除了运行其中应用外,基本不消耗额外的系统资源,使得应用的性能很高,同时系统的开销尽量小。传统虚拟机方式运行 10 个不同的应用就要起 10 个虚拟机,而Docker 只需要启动 10 个隔离的应用即可。
4更简单的管理
使用 Docker,只需要小小的修改,就可以替代以往大量的更新工作。所有的修改都以增量的方式被分发和更新,从而实现自动化并且高效的管理。
3Docker的工作原理和概念
自己制作镜像然后上传仓库或使用仓库已有的镜像文件拉取到容器中部署。
为了方便Docker的说明,本次例子使用虚拟机安装CentOS 7来演示。CentOS 7的安装请等查看下篇文章或自行百度。
1安装之前的准备工作
按照顺序,执行如下操作
1、安装必要的一些系统工具
2、添加软件源信息
3、更新并安装Docker-CE
安装准备工作
2开启Docker服务
运行docker version 如果出现以下情况,说明当前用户没有 root相关操作权限
无root权限
解决思路
先查看有多少镜像
运行docker run hello-world 测试命令,如果出现下方红框内消息,证明安装成功
3查看docker基本信息和版本
1构建Nginx基础镜像
查询nginx镜像
镜像拉取
查看对外的访问路径
怎么才能访问刚才启用的nginx
nginx页面内容
我们可以进入容器,看下这个容器是什么样子
查看nginx在哪个位置
我们发现尽管启动了nginx,但是在外部还是不能访问,这是因为docker具有隔离机制,要不然怎么叫做容器化部署呢
Docker内nginx端口
对Nginx进行外网端口映射;
2构建Tomcat基础镜像
打开容器后,默认安装目录在 /usr/local/
3创建自己的专属镜像
用Dockerfile来制作镜像
创建一个新的镜像,并起名字为nywlw
查看新的镜像
运行自己创建的容器
4删除容器实例
5删除镜像
每天发布更多新鲜有含量的技术文章、总有一款适合你。
搭建一个完整的分布式系统,需要六个必要的组成部分:输入节点、输出节点、网络交换机、管理节点、控制软件和运维模块。itc分布式综合管理平台是由分布式采集器、分布式输出盒、拼接中控、分布式综合管理平台、存储服务器以及分布式综合管理平台嵌入软件组合而成,实现管理平台采集、分配、传输、交换、显示、处理和控制功能。一个分布式综合管理平台可实现中控主机、高清矩阵、拼接处理器、局域网视频会议、KVM坐席协作、会议录播等众多系统功能。
从使用的经验来看,我推荐万网的轻云服务器。轻云服务器是基于分布式计算系统构建的云服务器,只为建站而生。
是一款集云服务器的资源独占性和虚机管理的便捷性于一体的创新型服务器。轻云服务器由于独享CPU、独享内存、独享带宽、BGP多线接入、按月付费,所以访问速度远远超过虚机,轻云服务器的多重防护措施可以有效屏蔽DDos攻击,磁盘快照为数据损坏完成回滚;而虚机是资源共享,可能某些用户会占用很多资源,当某个用户流量比较大或者遭受攻击会影响到无辜的其他虚机用户;
另外轻云服务器已经预装了网站的运行环境,具有和虚机一样的图形化的控制面板,使用和安装都非常的容易,所以说相对虚机而言轻云服务器无论从性能上和价格上都略胜一筹。
跟云服务器相比,轻云主机跟云服务器采用同样的分布式云计算架构,只不过轻云服务器只能用来建站,为方便用户操作和基于安全考虑,关闭了远程桌面的权限,而服务器需要自己维护,有远程桌面权限,不仅仅可以建站,还可以安装其他应用。但因为自己要维护,所以需要具有一定的服务器维护技术背景和能力。
15台服务器不少也不算太多,搭建一个基于LAMP技术的网站绰绰有余了。我的建议是
选择其中的两台硬盘较大,内存还可以的两台作为数据库服务器。搭建一套主从热备的主从数据库,实现系统的读写分离。提高数据访问的速度。
选择硬盘最大的一台作为文件服务器,放置系统需要使用的等静态资源。这里可以看情况而定,如果文件数据量大的话可以考虑多用一两台的搭建分布式文件系统。选择内存较大的一或两台搭建缓存服务器,将网站上满足二八定律的、访问量集中的、那百分之二十的数据缓存起来。内存的访问速度比硬盘快太多。剩下的用于搭建应用服务器集群。使用一台作为负载均衡调度服务器。当请求访问时根据既定的策略将请求分发到集群中去。
如有不对请斧正。欢迎评论讨论。
0条评论