使用LVS+NGinx+Netty实现数据接入

数据接入

链接参考文档 LVS+Keepalived项目

车辆数据上收,TBox通过TCP协议连接到TSP平台 建立连接后进行数据上传。也可借由该连接实现远程控制等操作。

通过搭建 LV—NGinx—Netty实现高并发数据接入

  • LVS:四层负载均衡(位于内核层):根据请求报文中的目标地址和端口进行调度
  • NGinx:七层负载均衡(位于应用层):根据请求报文的内容进行调度,这种调度属于「代理」的方式
组件角色主机名称虚拟ip/端口
LVS+keepalivedactive-0007
LVS+keepalivedbackup-0006
Nginx负载-00058050
Nginx负载-00048050
Netty真实服务器-00038050
Netty真实服务器-00028050
Netty真实服务器-00038092
Netty真实服务器-00028092
Netty真实服务器-00018092
Netty真实服务器-00018092

使用华为云服务器 安装LVS 需要有VPC服务(免费),在控制台页面做虚拟ip绑定在这里插入图片描述

一、安装LVS 服务

使用的是 DR 模式

  • NET模式:LVS将数据请求包转发给真实服务器的时候,会修改成真实服务器的IP地址;在回复时真实服务器会把回复包发往LVS调度服务器 再发往客户端。
  • TUN隧道模式:将原始数据包封装并添加新的包头(内容包括新的源地址及端口、目标地址及端口),从而实现将一个目标为调度器的VIP地址的数据包封装,通过隧道转发给后端的真实服务器(RealServer)感觉很复杂。
  • DR模式:要求LVS调度服务器要和后端服务器在同一局域网下,为后端服务器添加lo回环地址为VIP(虚拟IP地址)这样回复给客户端 客户端会以为是连接的VIP进行回复的

DR模式不支持端口映射

#查看网卡 eth0
ifconfig
#执行 虚拟ip:172.25.94.187    广播地址(不变):172.25.94.191 子网掩码(不变):255.255.255.192 up:立即启用vip(虚拟ip)
ifconfig eth0:1 172.25.94.187 broadcast 172.25.94.191 netmask 255.255.255.192 up
#查看当前网卡信息
ip a
#安装keepalived
sudo yum install keepalived
#启动keepalived
systemctl start keepalived
#加入开机启动keepalived
systemctl enable keepalived
#重新启动keepalived
systemctl restart keepalived  
#查看keepalived状态
systemctl status keepalived

在这里插入图片描述

LVS 模块内嵌lvs模块,只需要ipvsadm和keepalived安装

#查看Linux 内核版本
uname -r
#查看内核是否集成lvs模块
find /lib/modules/$(uname -r)/ -iname "**.ko*" | cut -d/ -f5- 
#安装LVS管理工具:ipvsadm
yum install -y gcc gcc-c++ makepcre pcre-devel kernel-devel openssl-devel libnl-devel popt*  
yum -y install ipvsadm  
#启动ipvs
sudo ipvsadm
#查看是否支持lvs
sudo lsmod |grep ip_vs
#查看ipvsadm 版本
ipvsadm -v
#服务器添加路由规则
route add -host 172.25.94.187 dev ens33:0
route add -host 172.25.110.124 dev eth:0#启用系统的包转发功能 #1:启用ip转发,0:禁止ip转发
echo "1" >/proc/sys/net/ipv4/ip_forward 
#清除原有转发规则
systemctl restart keepalived 
systemctl status ipvsadm
ipvsadm --clear
#添加虚拟ip规则 rr:负载均衡算法 轮询ipvsadm -A -t 172.25.94.187:8043 -s rripvsadm -a -t 172.25.94.187:8043 -r 172.25.94.151:8043 -gipvsadm -a -t 172.25.94.187:8043 -r 172.25.94.152:8043 -gipvsadm -l#配置tcp/tcpfin/udp超时时间ipvsadm --set 900 120 300#添加虚机IP规则也可以通过修改文件实现vim /etc/keepalived/keepalived.conf
global_defs {router_id chery_21
}
vrrp_instance VI_1 {state MASTERinterface eth0virtual_router_id 51priority 100advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {172.25.110.124}
}
virtual_server 172.25.110.124 8050 {delay_loop 6lb_algo rrlb_kind DRpersistence_timeout 50protocol TCPreal_server 172.25.110.19 8050 {weight 1TCP_CHECK {connect_timeout 30delay_before_retry 3}
}real_server 172.25.110.18 8050 {weight 2TCP_CHECK {connect_timeout 30}
}
}

全局定义(global_defs)

  • router_id chery_21:定义了当前Keepalived实例的路由ID,这是唯一的标识符,用于在VRRP组中区分不同的Keepalived实例。

VRRP实例(vrrp_instance VI_1)

  • state MASTER:设置当前实例的初始状态为MASTER。在VRRP组中,MASTER负责处理对虚拟IP的流量。

  • interface eth0:指定VRRP通信使用的网络接口。

  • virtual_router_id 51:虚拟路由的ID,用于在VRRP组中标识不同的虚拟路由器。

  • priority 100:设置当前实例的优先级,优先级高的实例将成为MASTER。

  • advert_int 1:VRRP通告的间隔时间,单位为秒。MASTER每隔这个时间会向其他节点发送VRRP通告。

  • authentication
    

    :VRRP认证配置,确保只有授权的设备可以加入VRRP组。

    • auth_type PASS:使用密码认证。
    • auth_pass 1111:认证密码。
  • virtual_ipaddress:定义了虚拟IP地址,即VIP,客户端将访问此IP地址来访问服务。

虚拟服务器(virtual_server)

  • 172.25.110.124 8050:定义了虚拟服务器的IP地址和端口号,这里与VRRP的VIP相同,表明这个虚拟服务器是通过VIP来访问的。
  • delay_loop 6:健康检查的时间间隔,单位为秒。
  • lb_algo rr:负载均衡算法,这里使用的是轮询(rr)。
  • lb_kind DR:负载均衡类型,这里使用的是直接路由(DR),需要确保后端服务器(real_server)配置正确以支持DR模式。
  • persistence_timeout 50:会话保持时间,单位为秒。在指定时间内,来自同一客户端的请求将被转发到同一台后端服务器。
  • protocol TCP:使用TCP协议进行健康检查和负载均衡。

后端服务器(real_server)

  • 定义了多个后端服务器,每个服务器都配置了IP地址、端口号、权重和健康检查设置。

  • weight:权重,用于负载均衡时决定服务器的优先级。

  • TCP_CHECK
    

    :TCP健康检查配置。

    • connect_timeout 30:连接超时时间,单位为秒。
    • delay_before_retry 3:在重试之前等待的时间,单位为秒。

LVS负载均衡(LVS简介、三种工作模式、十种调度算法)

#列出当前LVS表中的所有配置,包括虚拟服务器和真实服务器的信息。
ipvsadm -Ln
#显示统计信息,包括已转发的连接数、入包个数、出包个数等。
ipvsadm -L --stats
#显示转发速率信息,包括每秒连接数、每秒入包个数、每秒出包个数等
ipvsadm -L --rate
#keepalived 日志
vim /var/log/message

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、安装nginx 服务

在nginx服务器和后端服务器 配置lo回环地址 否则回复将不成功

服务器上一般还需要修改lo网卡 配置成虚拟IP。华为云服务器使用的是Centos 8版本 没有 lo配置文件,通过 ifconfig lo:0 172.25.94.187 netmask 255.255.255.255 broadcast 172.25.94.187 up 华为云服务器不支持修改网卡,所以修改了 eth0网卡配置 ip addr add 172.25.94.187/24 dev eth0

在这里插入图片描述

yum -y nginx
#检查是否有 stream
nginx -V 2>&1 | grep --color -o with-stream
#如果没有stream需要对nginx源码安装进行二次编译 
tar -zxvf nginx-*.tar.gz  
cd nginx-*  
./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-stream  
make  
sudo make install
#重新加载Nginx配置文件
nginx -s reload 
#强制停止Nginx服务
nginx -s stop
#重启nginx
nginx -s reopen
#修改配置文件
vim /etc/nginx/nginx.confnetstat -anput | grep nginxnginx -c nginx.conf

在这里插入图片描述

三、Netty服务

**1、在Linux上部署启用了 epoll **

epoll:是Linux内核为处理大批量文件描述符而作的改进的poll,是Linux下多路复用IO接口select/poll的增强版本
应用于Linux系统下的应用程序,特别是需要处理大量并发连接的高性能网络服务器。

BIO:同步阻塞IO,也就是传统阻塞型的IO,服务器实现模式是一个连接对应一个线程。客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个链接不做任何事情会造成不必要的线程开销。

NIO:同步非阻塞IO,服务器实现模式是一个线程处理多个请求,客户端发送的链接请求都会注册到多路复用器上,多路复用器轮询到链接有IO请求就进行处理。

AIO:异步非阻塞,AIO引入了异步通道的概念,采用了Proactor模式,简化了程序编写,有效的请求才启动线程,他的特点是先由操作系统完成后才通知服务端程序启动线程去处理,一般适用于连接数较多且链接时间较长的应用。

public class NettyServer {private static final Logger logger = LoggerFactory.getLogger(NettyServer.class);@Resourceprivate NettyServerInitializer nettyServerInitializer;ServerBootstrap serverBootstrap = new ServerBootstrap();EventLoopGroup boss = null;EventLoopGroup worker = null;ChannelFuture future = null;ChannelFuture future2 = null;//厂商编码Integer factoryCode = null;@Value("${netty.server.use-epoll}")boolean epoll = false;@Value("${netty.server.port1}")private int port = 8030;@Value("${netty.server.port2}")private int port2 = 8050;@PreDestroypublic void stop() {if (future != null) {future.channel().close().addListener(ChannelFutureListener.CLOSE);future.awaitUninterruptibly();boss.shutdownGracefully();worker.shutdownGracefully();future = null;logger.info(" 服务关闭 ");}}public void start() {logger.info(" nettyServer 正在启动");if (epoll) {logger.info(" nettyServer 使用epoll模式");boss = new EpollEventLoopGroup(4);//指定线程32worker = new EpollEventLoopGroup(32);} else {logger.info(" nettyServer 使用nio模式");boss = new NioEventLoopGroup(4);worker = new NioEventLoopGroup(32);}logger.info("netty服务器在[" + this.port + "]端口启动监听");logger.info("netty服务器在[" + this.port2 + "]端口启动监听");serverBootstrap.group(boss, worker)// tcp缓冲区:将不能处理的客户端连接请求放到队列里等待.option(ChannelOption.SO_BACKLOG, 10240)//多个进程或者线程绑定到同一端口,提高服务器程序的性能.option(EpollChannelOption.SO_REUSEPORT, true)//打印info级别的日志
//                .handler(new LoggingHandler(LogLevel.INFO))// 将网络数据积累到一定的数量后,服务器端才发送出去,会造成一定的延迟。希望服务是低延迟的,建议将TCP_NODELAY设置为true.childOption(ChannelOption.TCP_NODELAY, true)// 可以确保连接在因网络问题中断时能够被及时检测并处理。.childOption(ChannelOption.SO_KEEPALIVE, false)// 配置ByteBuf内存分配器.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)// 配置 编码器、解码器、业务处理.childHandler(nettyServerInitializer);if (epoll) {serverBootstrap.channel(EpollServerSocketChannel.class);} else {serverBootstrap.channel(NioServerSocketChannel.class);}try {future = serverBootstrap.bind(port).sync();future2 = serverBootstrap.bind(port2).sync();future.channel().closeFuture().addListener(new ChannelFutureListener() {@Overridepublic void operationComplete(ChannelFuture future) throws Exception {       //通过回调只关闭自己监听的channelfuture.channel().close();}});future2.channel().closeFuture().addListener(new ChannelFutureListener() {@Overridepublic void operationComplete(ChannelFuture future) throws Exception {future.channel().close();}});// 等待服务端监听端口关闭// future.channel().closeFuture().sync();} catch (Exception e) {logger.info("nettyServer 启动时发生异常---------------{}", e);logger.info(e.getMessage());} finally {//这里一定要注释,因为上面没有阻塞了,不注释的话,这里会直接关闭的//boss.shutdownGracefully();//worker.shutdownGracefully();}}

2、超时配置

    protected void initChannel(SocketChannel socketChannel) throws Exception {ChannelPipeline pipeline = socketChannel.pipeline();// readerIdleTimeSeconds 读超时;writerIdleTimeSeconds 写超时;allIdaleTimes 读写全超时 300 秒;断开连接pipeline.addLast(new IdleStateHandler(0, 0, 300, TimeUnit.SECONDS));pipeline.addLast(new LengthFieldBasedFrameDecoder(64 * 1024, 22, 2, 1, 0));//根据端口动态的选择解码器Integer localPort = socketChannel.localAddress().getPort();if (localPort == 8050 || localPort == 8055) {pipeline.addLast("authHandler", authHandler);pipeline.addLast("messageHandler", messageHandler);} else if (localPort == 8030 || localPort == 8035) {pipeline.addLast("authHandler", authHandler2);pipeline.addLast("messageHandler", messageHandler2);}}

在处理器中的应用

/*** 用户事件触发,发现读超时会调用 根据心跳检测状态去关闭连接*/@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {if (evt instanceof IdleStateEvent) {IdleStateEvent event = (IdleStateEvent) evt;String clientId = ChannelStore.getClientId(ctx);Attribute<Integer> timesAttr = ctx.channel().attr(AttributeKey.valueOf("times"));Integer timeInt = timesAttr.get();if (timeInt == null) {timeInt = 0;}String eventDesc = null;switch (event.state()) {case READER_IDLE:eventDesc = "读空闲";break;case WRITER_IDLE:eventDesc = "写空闲";break;case ALL_IDLE:eventDesc = "读写空闲";break;}//获取ip地址信息InetAddress ip = InetAddress.getLocalHost();String hostAddress = ip.getHostAddress();log.info(clientId + " 地址:" + hostAddress + "发生超时事件--" + eventDesc);timeInt++;timesAttr.set(timeInt);if (timeInt > 1) {//删除ip地址信息String redisIpAddress = redisTemplateNew.get(clientId + "_IP");boolean hostBoolean = hostAddress.equals(redisIpAddress);log.info(hostBoolean + "check :" + clientId + " redisTemplateNewDelete:" + hostAddress + "redisIP:" + redisIpAddress);if (redisIpAddress != null && hostBoolean) {redisTemplateNew.delete(clientId + "_IP");}log.info(clientId + " 地址:" + hostAddress + ":" + ctx.channel().remoteAddress() + "空闲次数为" + timeInt + "次 关闭连接 " + clientId);ctx.channel().close();}}}

3、下行API

public class SendApi {@Resourceprivate RedisTemplateNew redisTemplateNew;@Resourceprivate KafkaTemplate<String, String> kafkaTemplate;@GetMapping(value = "/userinfo")public UserDto gerUserInfo() {UserDto user = new UserDto();user.setUserId("888888");user.setUserName("holmium");user.setSex("1");return user;}
}

}
}
}


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

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

相关文章

Odoo17架构概述

多层架构 Odoo遵循多层架构&#xff0c;这意味着演示&#xff0c;业务逻辑和数据存储是分开的。更具体地说&#xff0c;它使用三层架构。 UI展示层 UI表示层是 HTML5、JavaScript 和 CSS 的组合。 应用程序的最顶层是用户界面。界面的主要功能是将任务和结果转换为用户可以理…

【数据结构】二叉树———Lesson2

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f4a5;&#x1f4a5;个人主页&#xff1a;奋斗的小羊 &#x1f4a5;&#x1f4a5;所属专栏&#xff1a;C语言 &#x1f680;本系列文章为个人学习…

Uniapp 组件 props 属性为 undefined

问题 props 里的属性值都是 undefined 代码 可能的原因 组件的名字要这样写&#xff0c;这个官方文档有说明

【Django】网上蛋糕商城后台-商品管理

1.商品管理功能 当管理员点击商品管理时&#xff0c;发送服务器请求 path(admin/goods_list/, viewsAdmin.goods_list), # 处理商品列表请求 def goods_list(request):try:type request.GET["type"]except:type 0try:ym request.GET["ym"]except:ym …

Spring Cloud Loadbalancer 的使用

一、默认负载均衡策略 Spring Cloud LoadBalancer 默认的负载均衡策略是轮询。 轮询效果示例 我们需要示例一个请求分发到不同的模块上&#xff0c;所以我们需要创建多模块项目。 新建 Spring Boot &#xff08;3.0.2&#xff09;的 Maven 项目&#xff08;JDK 17&#xff09…

ETL数据集成丨通过ETLCloud工具,将Oracle数据实时同步至Doris中

ETLCloud是一个全面的数据集成平台&#xff0c;专注于解决大数据量和高合规要求环境下的数据集成需求。采用先进的技术架构&#xff0c;如微服务和全Web可视化的集成设计&#xff0c;为用户提供了一站式的数据处理解决方案。 主要特点和功能包括&#xff1a; 实时数据处理&…

【已解决】Django连接MySQL启动报错Did you install mysqlclient?

在终端执行python manage.py makemigrations报错问题汇总 错误1&#xff1a;已安装mysqlclient&#xff0c;提示Did you install mysqlclient? 当你看到这样的错误信息&#xff0c;表明Django尝试加载MySQLdb模块但未找到&#xff0c;因为MySQLdb已被mysqlclient替代。 【解…

Linux——Shell脚本和Nginx反向代理服务器

1. Linux中的shell脚本【了解】 1.1 什么是shell Shell是一个用C语言编写的程序&#xff0c;它是用户使用Linux的桥梁 Shell 既是一种命令语言&#xff0c;有是一种程序设计语言 Shell是指一种应用程序&#xff0c;这个应用程序提供了一个界面&#xff0c;用户通过这个界面访问…

PyTorch 深度学习实践-处理多维特征的输入

视频指路 参考博客笔记 参考笔记二 通过多个线性模型来模拟非线性的空间变换&#xff0c;矩阵计算就是不同维度之间的空间转换 说明&#xff1a;1、乘的权重(w)都一样&#xff0c;加的偏置(b)也一样。b变成矩阵时使用广播机制。神经网络的参数w和b是网络需要学习的&#xff0c…

MybatisPlusException: Error: Method queryTotal execution error of sql 的报错解决

项目场景&#xff1a; 相关背景&#xff1a; 开发环境 开发系统时 系统页面加载正常 &#xff0c;发布运行环境后运行一段时间&#xff0c;前端页面 突然出现 报错信息&#xff0c; 报错信息如下&#xff1a; MybatisPlusException: Error: Method queryTotal execution erro…

如何在AWS上构建Apache DolphinScheduler

引言 随着云计算技术的发展&#xff0c;Amazon Web Services (AWS) 作为一个开放的平台&#xff0c;一直在帮助开发者更好的在云上构建和使用开源软件&#xff0c;同时也与开源社区紧密合作&#xff0c;推动开源项目的发展。 本文主要探讨2024年值得关注的一些开源软件及其在…

PDF转Word怎么快速转换?格式转换技巧分享

PDF文件和Word文档是我们日常工作中不可或缺的文件格式&#xff0c;同时文件之间的格式转换也十分常见。不同的格式有着不同的优点&#xff0c;将PDF文件改为Word文档后&#xff0c;在编辑或修改文件内容时更为方便。 下面小编就来给大家介绍几种常用的PDF转Word的转换方法&am…

Android 使用FFmpeg解析RTSP流,ANativeWindow渲染 使用SurfaceView播放流程详解

文章目录 ANativeWindow 介绍ANativeWindow 的主要功能和特点ANativeWindow 的常用函数工作流程原理图通过ANativeWindow渲染RGB纯色示例 播放RTSP流工作流程图关键步骤解析自定义SurfaceView组件native 层解码渲染 效果展示注意事项 这篇文章涉及到jni层&#xff0c;以及Ffmpe…

Linux-开机自动挂载(文件系统、交换空间)

准备磁盘 添加三块磁盘&#xff08;两块SATA&#xff0c;一块NVMe&#xff09; 查看设备&#xff1a; [rootlocalhost jian]# ll /dev/sd* [rootlocalhost jian]# ll /dev/nvme0n2 扩&#xff1a;查看当前主机上的所有块设备&#xff0c;通过如下指令实现&#xff1a; [root…

基于语音识别的会议记录系统

文章目录 核心功能页面展示使用技术方案功能结构设计数据库表展示 核心功能页面展示 视频展示功能 1.创建会议 在开始会议之前需要管理员先创建一个会议&#xff0c;为了能够快速开始会议&#xff0c;仅需填写会议的名称、会议举办小组、会议背景等简要会议信息即可成功创建。…

c# .net core中间件,生命周期

某些模块和处理程序具有存储在 Web.config 中的配置选项。但是在 ASP.NET Core 中&#xff0c;使用新配置模型取代了 Web.config。 HTTP 模块和处理程序如何工作 官网地址&#xff1a; 将 HTTP 处理程序和模块迁移到 ASP.NET Core 中间件 | Microsoft Learn 处理程序是&#xf…

【iOS】——内存分区

内存管理 程序运行的过程中往往会涉及到创建对象、定义变量、调用函数或方法&#xff0c;而这些行为都会增加程序的内存占用。为了防止内存占用过多影响到程序的正常运行就需要对内存进行管理。 移动端的内存管理机制&#xff0c;主要有三种&#xff1a; 自动垃圾收集(GC)手…

两台电脑之间如何进行数据传输?两台电脑数据传输攻略

在数字化时代&#xff0c;电脑之间的数据传输变得日益重要。无论是个人用户还是企业用户&#xff0c;经常需要在不同的电脑之间共享或迁移数据。那么&#xff0c;两台电脑之间如何进行数据传输呢&#xff1f;本文将详细介绍两台电脑之间进行数据传输的几种常见方法&#xff0c;…

CI/CD的node.js编译报错npm ERR! network request to https://registry.npmjs.org/

1、背景&#xff1a; 在维护paas云平台过程中&#xff0c;有研发反馈paas云平台上的CI/CD的前端流水线执行异常。 2、问题描述&#xff1a; 流水线执行的是前端编译&#xff0c;使用的是node.js环境。报错内容如下&#xff1a; 2024-07-18T01:23:04.203585287Z npm ERR! code E…

【BUG】已解决:note: This is an issue with the package mentioned above,not pip.

已解决&#xff1a;note: This is an issue with the package mentioned above&#xff0c;not pip. 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医疗科技公司&#xff0c;热衷…