集群聊天服务器项目(三)——负载均衡模块与跨服务器聊天

news/2024/5/14 4:30:35/文章来源:https://blog.csdn.net/qq_42120843/article/details/130273639

负载均衡模块

为什么要加入负载均衡模块

原因是:单台服务器并发量最多两三万,不够大。

负载均衡器 Nginx的用处或意义**(面试题)**

  • 把client请求按负载算法分发到具体业务服务器Chatserver
  • 能和ChatServer保持心跳机制,检测ChatServer保持心跳机制,检测ChatServer故障
  • 能发现新添加的ChatServer设备方便服务器扩展数量

客户端和某台服务器可建立IP隧道

想要更大并发量可以对负载均衡器再做集群

负载均衡模块在整个程序中的位置如下图

在这里插入图片描述

如何配置nginx的TCP负载均衡模块

首先解压nginx的安装包 (tar zxvf);

进入nginx安装包中编译加入--with-stream参数激活tcp负载均衡模块

~/package/nginx-1.12.2# ./configure --with-stream
~/package/nginx-1.12.2# make && make install

编译完成后,默认安装在 /usr/local/nginx

$ cd /usr/local/nginx/
/usr/local/nginx$ ls

可执行文件在sbin目录里面,配置文件在conf目录里面。

nginx -s reload #重新加载配置文件启动
nginx -s stop #停止nginx服务

nginx.conf的补充内容如下

events {worker_connections  1024; #最大连接数1024,默认为512
}
#-------------------------------添加的内容------------------------stream {upstream MyServer {# max_fails最大失败次数,若超过则判断连接失败# fail_timeout,发出心跳包超过改时间没收到回包就算一次失败server 127.0.0.1:6000 weight=1 max_fails=3 fail_timeout=30s;server 127.0.0.1:6002 weight=1 max_fails=3 fail_timeout=30s;}server {      proxy_connect_timeout 1s;listen 8000;proxy_pass MyServer; # 所有连接到8000端口的请求都往MyServer指定的主机里负载均衡tcp_nodelay on;}}
#---------------------------------------------------------------

其中 weight表示权重

上面配置也就是说,客户端连接服务器时端口号填8000就是连接到负载均衡器上,它会帮助我们把请求分发到 127.0.0.1:6000127.0.0.1:6002端口上.

配置修改后可用 ./nginx -s reload平滑重启。

注意:这么修改了之后,客户端连接服务端的地址都要为127.0.0.1:8000,也就是连接到负载均衡器上而不是确定的服务器端口上。

sudo netstat -anp查看nginx进程是否启动在80端口监听

在这里插入图片描述

服务器通过负载均衡器按权重分别接收一个连接

在这里插入图片描述

redis发布订阅消息队列

背景

当客户端登录到不同的服务器时,应该如何解决跨服务器通信问题?

假如采用两两服务器之间建立连接

在这里插入图片描述

上图设计相当于在服务器网络之间进行广播。这样的设计使得各个服务器之间耦合度太高,不利于系统扩展,并且会占用系统大量的socket资源,各服务器之间的带宽压力很大,不能够节省资源给更多的客户端提供服务,因此绝对不是一个好的设计。
集群部署的服务器之间进行通信,最好的方式就是引入中间件消息队列解耦各个服务器,使整个系统松耦合,提高服务器的响应能力,节省服务器的带宽资源,如下图所示:

在这里插入图片描述

集群分布式环境中,经常使用的中间件消息队列ActiveMQRabbitMQKafka等,都是应用场景广泛并且性能很好的消息队列,供集群服务器之间,分布式服务之间进行消息通信。

发布订阅是观察者模式的使用场景。

消息队列是长连接跨服务器聊天通用方法,工作流程大致如下

客户端c1在某个服务器上连接后,要把该连接在redis队列上订阅一个通道ch1

别的客户端c2在不同的服务器上登录要给c1发消息,会直接发到redis队列上的通道ch1,客户端c1可接受到信息发布到通道ch1

要开一个单独线程进行监听通道上的事件,有消息给业务层上报。

当服务器发现发送的对象id没有在自己的_userConnMap上,就要往消息队列上publish,消息队列就会把消息发布给订阅者。

redis服务器后台运行输入如下指令

redis-server --daemonize yes

发布订阅功能要开两条redis连接即两个redisContext *,一条用于订阅和接收消息,一条用于发布消息,这么做的原因是因为订阅 SUBSCRIBE时会进入阻塞状态,代码如下

// 向redis指定通道channel发布消息
bool Redis::publish(int channel, string message)
{redisReply *reply = (redisReply *)redisCommand(_publish_context, "PUBLISH %d %s", channel, message);if (nullptr == reply){cerr << "publish command failed!" << endl;return false;}freeReplyObject(reply);return true;
}// 向redis指定通道subscribe订阅消息
bool Redis::subscribe(int channel)
{// SUBSCRIBE命令本身会造成线程阻塞等待通道里发生消息,这里只做订阅通道,不接受通道消息// 通道消息接收专门在 observer_channel_message 函数中的独立线程中进行// 只负责发送命令,不阻塞接收redis server响应消息,否则和notifyMsg线程抢占响应资源if (REDIS_ERR == redisAppendCommand(this->_subscribe_context, "SUBSCRIBE %d", channel)){cerr << "subscribe command failed!" << endl;return false;}// redisBufferWrite可循环发送缓冲区累积的命令,知道缓冲区数据发送完毕(done被置1)int done = 0;while (!done){if (REDIS_ERR == redisBufferWrite(this->_subscribe_context, &done)){cerr << "subscribe command failed!" << endl;return false;}}return true;
}

本项目使用hiredis进行redis编程,加入redis的发布订阅消息队列后,业务层的改动大致如下:

  • chatservice构造中连接redis即调用connect,并设置上报消息的回调,connect中会开启一条新线程调用 observer_channel_message函数进行循环接收订阅通道上的消息,有消息到来给业务层上报。
  • 登录时订阅subscribe channel
  • 聊天时遇到用户在别的服务器上登录(userid不在map中,但状态为online)就publish
  • 注销就取消订阅 unsubscribe channel

杂项

  • 若不满意Nginx负载均衡效果前面可加LVS(Linux Virtual Server)

  • 负载均衡器 - 一致性哈希算法学有余力可了解

  • IP隧道

    IP隧道(IP Tunnel)是一种虚拟的网络连接方式,它允许将一个IP数据包传输到另一个IP网络中,同时保留原始数据包的源和目的地址。它通常用于将两个不同的IP网络连接起来,使它们看起来像一个单一的网络。IP隧道的主要目的是为了解决网络互联问题,特别是当两个不兼容的网络需要进行通信时。

    在IP隧道中,数据包被封装在另一个IP数据包中,以便在一个网络上传输到另一个网络。这个封装过程称为“隧道ing”,隧道的两端点被称为“入口”和“出口”。入口点将原始IP数据包封装在另一个IP数据包中,将其发送到出口点。出口点接收到封装后的数据包,然后解封装出原始的IP数据包,并将其传送到目的地。

    IP隧道的优点是它可以让不同的网络连接起来,同时保持原有的网络拓扑结构和地址分配。但是,它也会带来一些缺点,例如会增加网络延迟和降低网络性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_291324.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入浅出JS定时器:从setTimeout到setInterval

前言 当谈到 JavaScript 编程语言最基本的概念时&#xff0c;定时器就是一个必须掌握的知识点。在编写网站时&#xff0c;你经常会遇到需要在一定时间间隔内执行一些代码的情况。这时候&#xff0c;JavaScript 定时器就可以派上用场了。 什么是定时器&#xff1f; JS 定时器是…

@Configuration 和 @Component 注解的区别

一句话概括就是 Configuration 中所有带 Bean 注解的方法都会被动态代理&#xff0c;因此调用该方法返回的都是同一个实例。 理解&#xff1a;调用Configuration类中的Bean注解的方法&#xff0c;返回的是同一个示例&#xff1b; 而调用Component类中的Bean注解的方法&#x…

JavaEE-一文了解IP协议与IP地址

目录 IP协议什么是IP地址IP地址的组成动态分配IPNAT机制(网络地址转换) IP协议 IP协议是不可靠、无连接的 不可靠:表示IP协议不能保证IP数据报能成功的到达目的地。IP仅提供传输服务&#xff0c;任何可靠性的要求都必须由上层来提供&#xff08;如TCP&#xff09;。如果传输过…

【Cpp】手撕搜索二叉树(KV模型)

文章目录 二叉搜索树的应用搜索二叉树(KV模型)代码:二叉搜索树的性能分析 二叉搜索树的应用 K模型&#xff1a;K模型即只有key作为关键码&#xff0c;结构中只需要存储Key即可&#xff0c;关键码即为需要搜索到的值。 比如&#xff1a;给一个单词word&#xff0c;判断该单词是…

QGIS--开发OpenSCENARIO动态场景(三)--制作动态场景

一、添加scenario&#xff0c;carla的环境变量 export CARLA_ROOT/path/to/your/carla/installation export SCENARIO_RUNNER_ROOT/path/to/your/scenario/runner/installation export PYTHONPATH$PYTHONPATH:${CARLA_ROOT}/PythonAPI/carla/dist/carla-<VERSION>.egg ex…

Java核心技术 卷1-总结-12

Java核心技术 卷1-总结-12 具体的集合链表数组列表 具体的集合 下表中除了以 Map结尾的类之外&#xff0c; 其他类都实现了 Collection 接口&#xff0c;而以 Map结尾的类实现了 Map 接口。 集合类型描述ArrayList一种可以动态增长和缩减的索引序列LinkedList一种可以在任何位…

MySql知识

架构分层 模块详解 Connector&#xff1a;支持各种语言和SQL的交互&#xff0c;如PHP&#xff0c;Python&#xff0c;JAVA JDBC Management Services & Utilities&#xff1a;系统管理和控制工具&#xff0c;包括备份恢复&#xff0c;MySQL复制&#xff0c;集群等 Connec…

机器学习算法 随机森林

文章目录 一、概述1.1 集成学习1.2 决策树1.3 随机森林 二、Sklearn中的随机森林2.1 分类树API2.2 参数 2.2 回归树API2.2.1 重要参数 2.3 随机森林调参 三、总结 一、概述 1.1 集成学习 多个模型集成成为的模型叫做集成评估器&#xff08;ensemble estimator&#xff09;&am…

一文带你入门MySQL

目录 一、MySQL登陆1.配置MySQL环境变量2.MySQL登陆命令 二、MySQL基础知识1.数据类型&#xff08;1&#xff09;整型&#xff08;2&#xff09;浮点型&#xff08;3&#xff09;日期型&#xff08;4&#xff09;字符型&#xff08;5&#xff09;数据类型小结 2.MySQL的约束【重…

图解PMP项目管理马斯洛需求层次理论在公司管理中的应用!

马斯洛的需求层次结构是心理学中的激励理论&#xff0c;包括人类需求的五级模型&#xff0c;通常被描绘成金字塔内的等级。 从层次结构的底部向上&#xff0c;需求分别为&#xff1a;生理&#xff08;食物和衣服&#xff09;&#xff0c;安全&#xff08;工作保障&#xff09;…

【UE】保存游戏的demo

效果 注意左上角的打印信息&#xff0c;每当我按下k键&#xff0c;值就加1。当我关闭后重进游戏&#xff0c;按下k键&#xff0c;值是从上次退出游戏的值开始累加的。 步骤 1.新建蓝图&#xff0c;父类为“SaveGame” 命名为“MySaveGame”并打开 新建一个整型变量&#xff0c…

CentOS7(二)Go、Java、Python、Node开发环境配置

文章目录 Go环境配置Java环境配置Python环境配置Node 环境配置 CentOS7&#xff08;一&#xff09;安装和基础配置 CentOS7&#xff08;二&#xff09;Go、Java、Python、Node开发环境配置 根据前文&#xff0c;我们将所有的自定义环境变量&#xff0c;都收拢在了 /root/.bash_…

可视化Echarts 柱状图、饼状图、折线图的设置

柱状图 饼状图 折线图 柱状图 基本的柱状图设置 <template> <div ref"ec" id"ec"></div> </template><script> import * as echarts from "echarts"; //引用echartsexport default {mounted(){let mc ech…

【ONE·C++ || 模板进阶】

总言 主要介绍模板相关内容&#xff1a;非类型模板参数、类模板特化、模板的分离编译。 文章目录 总言1、非类型模板参数1.1、主要介绍1.2、std::array 简要说明 2、模板的特化2.1、基本介绍2.2、函数模板特化2.3、类模板特化2.3.1、基本说明2.3.2、用途举例2.3.3、分类&#…

反垃圾邮件产品技术要求和测试评价方法

声明 本文是学习信息安全技术 反垃圾邮件产品技术要求和测试评价方法. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 反垃圾邮件产品等级划分 根据产品功能要求和安全保证要求的不同&#xff0c;以及反垃圾邮件产品适用应用环境的不同&#xff0c;将…

android studio 页面布局(1)

<?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http://schemas.android.com/apk/res-auto"xmlns:tools"http://schemas.android.com/too…

大孔树脂型号,A-722,ADS500,ADS600,ADS750,ADS800

一、产品介绍 基于吸附功能的聚苯乙烯特种树脂 Tulsimer ADS-600 是一款没有离子官能基的&#xff0c;由交联聚苯乙烯合成的功能强大的吸附型树脂。 Tulsimer ADS-600 主要应用于水溶液中吸附酚及其化合物&#xff0c;氯代烃等含氯物质&#xff0c;表面活性剂&#xff0…

60 openEuler 22.03-LTS 搭建MySQL数据库服务器-安装、运行和卸载

文章目录 60 openEuler 22.03-LTS 搭建MySQL数据库服务器-安装、运行和卸载60.1 安装60.2 运行60.3 卸载 60 openEuler 22.03-LTS 搭建MySQL数据库服务器-安装、运行和卸载 60.1 安装 配置本地yum源&#xff0c;详细信息请参考《openEuler 22.03-LTS 搭建repo服务器》。 清除…

【Android入门到项目实战-- 6.1】—— 如何申请用户权限

目录 一、申请权限 1、布局文件 2、MainActivity类 3、AndroidManifest文件 你在使用安卓APP时可能经历过以下场景&#xff1a;使用APP的拍照功能时需要你授权使用相机。那么APP是如何完成申请权限功能的&#xff1f; 访问&#xff1a;https://developer.android.google.cn/…

SpringCloud --- Eureka注册中心

一、场景 假如我们的服务提供者user-service部署了多个实例&#xff0c;如图 思考几个问题&#xff1a; order-service在发起远程调用的时候&#xff0c;该如何得知user-service实例的ip地址和端口&#xff1f; 有多个user-service实例地址&#xff0c;order-service调用时该…