2024-10-10 14:32
109 次阅读|
0 个评论
01 概述 物联网开发场景中,大多数情况下是一台服务器对应很多台设备。大量的设备定时和服务器进行通信,会产生高并发,服务器处理不及时,可能会产生丢包等问题。因此,需要有一种机制,让设备分散上报,减轻服务器的压力。 本组件适合TCP等传统的通信方式。MQTT等服务器端如果做了消息队列这种处理,设备端可以不用考虑高并发。 02 高并发 高并发是指系统或应用程序在同一时间段内接收到大量并发请求的能力。具体来说,高并发环境下系统需要能够同时处理大量的请求,而不会出现性能问题或响应延迟。 大量请求: 高并发场景下,系统需要同时处理大量的请求,这些请求可能来自于不同的用户或客户端。 同时访问: 这些请求几乎同时到达系统,需要在短时间内进行处理和响应。 资源竞争: 由于大量请求同时到达,系统的资源(如CPU、内存、网络带宽等)可能会面临竞争和争夺。 响应时间要求高: 高并发场景通常对系统的响应速度有较高的要求,用户期望能够快速获取响应结果。 03 应对策略 1 服务器端 负载均衡 负载均衡是指将多台服务器组成一个集群,通过某种策略将访问请求均匀地分发到各个服务器上,使每个服务器的负载均衡。负载均衡可以提高系统的可用性和性能。 缓存 缓存是将数据存储在高速缓存中,以便在需要时快速访问。缓存可以减少数据库的读写操作,从而提高系统的性能。可以使用内存缓存、分布式缓存等方式实现缓存功能。 数据库优化 数据库是高并发系统的瓶颈之一,因此对数据库进行优化是解决高并发问题的重要方法。可以通过分库分表、索引优化、SQL优化等方式来提高数据库的性能。 异步处理 异步处理是将处理请求放入消息队列中,由后台进程或线程异步处理,从而避免了同步处理带来的性能瓶颈。异步处理可以使用消息队列、定时任务等方式实现。 分布式架构 分布式架构是将系统拆分成多个独立的子系统,每个子系统都可以独立运行,从而提高系统的可扩展性和可用性。分布式架构可以使用微服务、分布式缓存等方式实现。 高并发是互联网应用面临的一个重要问题,需要采取一系列措施来解决。负载均衡、缓存、数据库优化、异步处理和分布式架构是解决高并发问题的主要方法。 在实际应用中,需要根据具体情况选择不同的方法来解决高并发问题。在高并发情况下,使用负载均衡是解决问题的一种常见方法。 负载均衡可以通过将请求分配到多个服务器上,从而减少单个服务器的负载。这可以通过硬件设备或软件实现。在选择负载均衡器时,需要考虑多种因素,包括负载均衡算法、可靠性、安全性、性能和成本等。负载均衡算法是负载均衡器的关键组成部分之一。 负载均衡算法的选择会影响到服务器的响应时间、可用性和负载均衡的效率等因素。 常见的负载均衡算法包括轮询、加权轮询、最少连接、IP散列和URL散列等。每种算法都有其优缺点,需要根据具体的业务场景进行选择。 在高并发情况下,缓存也是提高性能的有效方法之一。 缓存可以将常用的数据存储在内存中,从而避免每次都去查询数据库,从而提高响应速度和并发能力。 常见的缓存方案包括本地缓存和分布式缓存。本地缓存是指将数据存储在应用服务器的内存中,而分布式缓存则是将数据存储在多个服务器上,从而实现更高的可靠性和可扩展性。 此外,在高并发情况下,需要优化数据库的性能,以避免成为瓶颈。数据库优化的方法包括使用索引、合理设计数据库表结构、优化SQL查询语句、使用分库分表等。这些方法可以提高数据库的响应速度和并发能力,从而保证系统的稳定性和可靠性。 针对不同的业务场景,还可以采用其他的技术方案来解决高并发问题。例如,使用消息队列解耦系统各个组件之间的依赖关系,从而提高系统的可扩展性;使用异步处理机制将耗时的操作放在后台进行,从而提高系统的响应速度等。 在高并发的环境下,需要综合考虑多种技术手段来解决问题。从负载均衡、缓存、数据库优化到消息队列等方面入手,才能实现系统的高性能和高可用性。 高并发情况下的系统性能瓶颈分析可以采用性能分析工具,例如 JProfiler、VisualVM 等,这些工具可以帮助开发者定位代码中的性能问题,分析线程和内存使用情况,从而优化系统性能。 此外,还可以采用分布式系统架构来解决高并发问题。分布式系统是将系统中的不同模块分离出来,分别部署在不同的服务器上,通过网络协议进行通信,以此提高系统的并发处理能力。在分布式架构中,可以采用负载均衡技术,将请求均匀地分发到不同的服务器上,从而避免单一服务器出现瓶颈。 针对高并发场景下的数据访问问题,可以采用缓存技术,将热点数据缓存在内存中,从而加速数据的访问速度。常用的缓存技术有 Redis、Memcached 等,它们能够有效地减轻数据库的负担,提高系统的并发处理能力。 针对高并发场景下的安全问题,需要采用一些安全防护措施,例如限流、熔断、防火墙等,防止系统受到恶意攻击或者大量无效请求的干扰。同时,需要对系统进行定期的安全评估和漏洞扫描,及时修补安全漏洞,确保系统的稳定和安全。 综上所述,高并发场景下的系统性能优化需要综合考虑多个方面,包括代码优化、分布式系统架构、缓存技术、安全防护措施等。只有在各个方面都得到充分的考虑和优化,才能够构建出稳定、高效、安全的高并发系统。 当然,在进行高并发优化时,也需要注意安全性问题。例如,防止恶意攻击、防止SQL注入、防止DDoS攻击等等。因此,在进行高并发优化时,也需要考虑安全性问题,并采取相应的安全措施。 高并发优化是一个复杂的过程,需要从多个方面入手。从架构层面优化,例如采用分布式架构、缓存技术等等;从代码层面优化,例如采用异步编程、使用多线程技术等等;从数据库层面优化,例如采用数据库分库分表、使用读写分离等等。当然,在进行高并发优化时,也需要注意安全性问题,并采取相应的安全措施。 2 设备端 对于定时定点上报的场景,设备尽可能在定时的时刻左右偏移一些时间上报,减轻服务器压力,本文描述的就是设备端偏移时间随机产生的方法。 04 设备随机上报组件的使用 1 Gitee链接地址 Demo位于amaziot_bloom_os_sdk\sample\libraries\8.6_random Gitee源码地址:https://gitee.com/ning./hongdou Github源码地址:https://github.com/ayumid/hongdou 编译指令:.\build.bat -l .\amaziot_bloom_os_sdk\sample\libraries8.6_random 2 组件功能介绍 随机上报组件,利用系统ticks和时间戳进行整出取余运算,余数作为一个随机数,随机数可以通过调用函数中的形参传递来确定范围。 随机数可以用来设置定时器定时时间,或者作为其它用途。 3 代码讲解 1 lib_random_systick_get 功能:该函数用于,通过系统ticks取余来获取一个随机数。 参数: 参数 释义 residual 除数,ticks除以这个数后的余数,返回给调用函数 例如61 % 60 = 1, 随机数就是1 156 % 120 = 36 随机数就是36 返回值:无 示例: lib_random_systick_get(121); 2 lib_random_timestamp_get 功能:该函数用于,通过系统时间戳取余来获取一个随机数。 参数: 参数 释义 residual 除数,ticks除以这个数后的余数,返回给调用函数 例如1724741112 % 60 = 12, 随机数就是1 1724741153 % 120 = 113 随机数就是113 返回值:0 示例: air_sw_log_write_data(1111.1111) 3 lib_random_timer_callback 功能:该函数用于,定时器回调函数,产生事件,给调用文件中的任务使用。 参数:无 返回值:无 示例: OSATimerStart(lib_random_timer_ref, random_num * 200, 0, lib_random_timer_callback, 0); //随机时间 一个系统ticks是50ms,200个就是1s 4 lib_random_event_flg_init 功能:该函数用于,事件标志位初始化。 参数:无 返回值:无 示例: lib_random_event_flg_init(); 5 lib_random_timer_init 功能:该函数用于,上报定时器初始化。 参数:无 返回值:文件指针 示例: lib_random_timer_init(); 6 lib_random_timer_start_random_systick 功能:该函数用于,开始上报定时器,使用系统ticks定时。 参数:无 返回值:无 示例: lib_random_timer_start_random_systick(60); 7 lib_random_timer_start_random_timestamp 功能:该函数用于,开始上报定时器,使用系统时间戳定时。 参数:无 返回值:无 示例: lib_random_timer_start_random_timestamp(60); 4 Demo实战 4.1 创建一个Demo 复制5.1_socket示例工程,到同一个文件夹下,修改文件名为8.6_random,如图: 4.2 修改makefile 增加文件组件所在目录头文件路径,和源文件路径,如图: 4.3 增加头文件 使用代码编辑器,将新建的工程文件加入代码编辑器中,打开main.c,修改main.c,加入am.h等头文件,如图: 4.4 修改代码 在Phase2Inits_exit 创建一个任务,如图: 4.5 宏定义介绍 sample_random_uart_printf 输出日志到DEBUG 串口,日志比较少,可以输出到这个串口,如果日志比较多,需要输出到usb口,以免不必要的问题出现 sample_random_catstudio_printf 输出日志到USB 串口,使用catstudio查看,catstudio查看日志需要更新对应版本mdb.txt文件,软件打开filtter过滤日志,只查看用户输出的日志 SAMPLE_RANDOM_TASK_STACK_SIZE 栈空间宏定义 4.6 全局变量介绍 sample_random_task_stack 任务栈空间,本例使用数组实现,用户在做项目时,可以预先估算下当先任务需要的大致栈空间,OS没有提供可以查看栈空间使用情况的API sample_random_task_ref 任务指针 4.7 函数介绍 Phase1Inits_enter 底层初始化,本例空 Phase1Inits_exit 底层初始化,本例空 Phase2Inits_enter 底层初始化,本例空 Phase2Inits_exit 创建主任务,初始化消息队列,定时器,任务等。 代码片段: int ret; //事件初始化 lib_random_event_flg_init(); //初始化上报定时器 lib_random_timer_init(); ret = OSATaskCreate(&sample_random_task_ref, sample_random_task_stack, SAMPLE_RANDOM_TASK_STACK_SIZE, 200, "test-task", sample_random_task, NULL); ASSERT(ret == OS_SUCCESS); //打开定时器,定时时间使用系统ticks,获取一个随机数 lib_random_timer_start_random_systick(60); sample_random_socket socket业务函数,连接服务器后随机时间发送“amaziot”字符串 代码片段: ai_protocol); if (sock ai_addrlen); if (ret < 0) { sample_random_uart_printf("sample_random_task: connect error"); close(sock); sock = -1; continue; } else { break; } } freeaddrinfo(result); if (sock < 0) { sample_random_uart_printf("sample_random_task: connect error"); return; } ret = send(sock, "amaziot", 7, 0); if (ret != 7) { sample_random_uart_printf("sample_random_task: send error"); close(sock); return; } close(sock); sample_random_task 接收组件发来的事件,触发一次,连接服务器并进行数据通信 代码片段: 150) { PM812_SW_RESET(); } } }while(0); while(1) { status = OSAFlagWait(lib_random_flag_ref, flag_mask, OSA_FLAG_OR_CLEAR, &flag_value, OSA_SUSPEND); ASSERT(status == OS_SUCCESS); sample_random_uart_printf("flag_value: %d", flag_value); if (flag_value & SAMPLE_RANDOM_TASK_TIMER_CHANGE_FLAG_BIT) { sample_random_socket(); //打开定时器,定时时间使用系统时间戳,获取一个随机数 lib_random_timer_start_random_timestamp(120); } } 4.8 编译 在SDK根目录打开命令行,输入命令.\build.bat -l .\amaziot_bloom_os_sdk\sample\libraries\8.6_random\ 1.270(MB)| |------------------------------------------------------------------------------------| cp_1606L.axf cp_1606L.bin cp_1606L.map gnumake: Leaving directory `F:/3.asr-b/cat.1-asr1606/1.software/BLOOM_OS_1606_OPENCPU_1191_A09_WIHT_NEWRF/amaziot_bloom_os_sdk/sample/libraries/8.6_random' "copy NEZHAC_CP_CNR_MIFI_TX.bin to ./ " 已复制 1 个文件。 4.9 生成固件 参考入门中开发工具,生成工具。 4.10 测试 测试步骤: 参考编译教程,和文档开头的编译指令,进行编译 按照编译教程选择对应的选项 烧录 4.11 固件 上电后,系统会随机时间上报,日志如下,日志中的时间为定时器定时随机时间; 本文章源自奇迹物联开源的物联网应用知识库Cellular IoT Wiki,更多技术干货欢迎关注收藏Wiki: Cellular IoT Wiki 知识库(https://rckrv97mzx.feishu.cn/wiki/wikcnBvAC9WOkEYG5CLqGwm6PHf) 注:本文部分内容来源于网络,如有侵权,请及时联系我们。