C++负载均衡远程调用学习之负载均衡算法与实现
目录
01 lars 系统架构回顾
02 lars-lbAgentV0.4-route_lb处理report业务流程
03 lars-lbAgentV0.4-负责均衡判断参数配置
04 lars-lbAgentV0.4-负载均衡idle节点的失败率判断
05 lars-lbAgentV0.4-负载均衡overload节点的成功率判断
06 lars-lbAgentV0.4-负载均衡上报提交模块
07 lars-lbAgentV0.4-数据问题修改-上报业务测试
08 lars-lbAgentV0.4-模拟器测试工具
09 lars-lbAgentV0.5-idle连续成功-overload连续失败的定期窗口重置机制
10 lars-lbAgentV0.6-loadbalance主动更新主机信息功能
11 昨日回顾
12 Lars-LbAgentV0.7-GetRouteAPI实现
13 Lars-LbAgentV0.7-Udp-server-获取路由服务业务注册
14 Lars-LbAgentV0.7-Udp-server-API和udpserver的测试
01 lars 系统架构回顾
**启动 Lars Reporter**
```bash
$ ./run_lars reporter
▄▄
██
██ ▄█████▄ ██▄████ ▄▄█████▄
██ ▀ ▄▄▄██ ██▀ ██▄▄▄▄ ▀
██ ▄██▀▀▀██ ██ ▀▀▀▀██▄
██▄▄▄▄▄▄ ██▄▄▄███ ██ █▄▄▄▄▄██
▀▀▀▀▀▀▀▀ ▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀▀▀
Load balance And Remote service schedule System
_____ _
| __ \ | |
| |__) |___ _ __ ___ _ __| |_ ___ _ __
| _ // _ \ '_ \ / _ \| '__| __/ _ \ '__|
| | \ \ __/ |_) | (_) | | | || __/ |
|_| \_\___| .__/ \___/|_| \__\___|_|
| |
|_|
ITCAST(https://www.itcast.cn)
------------------------------------
create 0 thread
create 1 thread
create 2 thread
create 3 thread
create 4 thread
add msg cb msgid = 3
```
**启动 Lars dns**
```bash
$ ./run_lars dns
▄▄
██
██ ▄█████▄ ██▄████ ▄▄█████▄
██ ▀ ▄▄▄██ ██▀ ██▄▄▄▄ ▀
██ ▄██▀▀▀██ ██ ▀▀▀▀██▄
██▄▄▄▄▄▄ ██▄▄▄███ ██ █▄▄▄▄▄██
▀▀▀▀▀▀▀▀ ▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀▀▀
Load balance And Remote service schedule System
_____
| __ \
| | | |_ __ ___
| | | | '_ \/ __|
| |__| | | | \__ \
|_____/|_| |_|___/
ITCAST(https://www.itcast.cn)
------------------------------------
create 0 thread
create 1 thread
create 2 thread
create 3 thread
create 4 thread
add msg cb msgid = 1
lars dns service ....
now route version is 1574674421
```
**启动 Lars Lb Agent**
```c
$ ./run_lars lbagent
▄▄
██
██ ▄█████▄ ██▄████ ▄▄█████▄
██ ▀ ▄▄▄██ ██▀ ██▄▄▄▄ ▀
██ ▄██▀▀▀██ ██ ▀▀▀▀██▄
██▄▄▄▄▄▄ ██▄▄▄███ ██ █▄▄▄▄▄██
▀▀▀▀▀▀▀▀ ▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀▀▀
Load balance And Remote service schedule System
_ _ _
| | | | /\ | |
| | | |__ / \ __ _ ___ _ __ | |_
| | | '_ \ / /\ \ / _` |/ _ \ '_ \| __|
| |____| |_) | / ____ \ (_| | __/ | | | |_
|______|_.__/ /_/ \_\__, |\___|_| |_|\__|
__/ |
|___/
ITCAST(https://www.itcast.cn)
------------------------------------
```
02 lars-lbAgentV0.4-route_lb处理report业务流程

LB Agent拥有5个线程,一个LB算法:
- UDP Server服务,并运行LB算法,对业务提供节点获取和节点调用结果上报服务;为了增大系统吞吐量,使用3个UDP Server服务互相独立运行LB算法:`modid+cmdid % 3 = i`的那些模块的服务与调度,由第`i+1`个UDP Server线程负责
- Dns Service Client:是dnsserver的客户端线程,负责根据需要,向dnsserver获取一个模块的节点集合(或称为获取路由);UDP Server会按需向此线程的MQ写入获取路由请求,DSS Client将MQ到来的请求转发到dnsserver,之后将dnsserver返回的路由信息更新到对应的UDP Server线程维护的路由信息中
- Report Service Client:是reporter的客户端线程,负责将每个模块下所有节点在一段时间内的调用结果、过载情况上报到reporter Service端,便于观察情况、做报警;本身消费MQ数据,UDP Server会按需向MQ写入上报状态请求
03 lars-lbAgentV0.4-负责均衡判断参数配置
## 2) 构建Lars-Agent项目
### 2.1 构建目录结构
依次创建如下目录:
> Lars/lars_loadbalance_agent
```bash
lars_loadbalance_agent/
├── bin/
├── conf/
│ └── lars_lb_agent.conf
├── include/
├── Makefile
└── src/
```
其中Makefile如下:
```makefile
TARGET= bin/lars_lb_agent
CXX=g++
CFLAGS=-g -O2 -Wall -Wno-deprecated
BASE=../base
BASE_H=$(BASE)/include
PROTO = $(BASE)/proto
PROTO_H = $(BASE)/proto
LARS_REACTOR=../lars_reactor
LARS_REACTOR_H =$(LARS_REACTOR)/include
LARS_REACTOR_LIB=$(LARS_REACTOR)/lib -llreactor
MYSQL=$(BASE)/mysql-connector-c
MYSQL_H=$(MYSQL)/include
MYSQL_LIB=$(MYSQL)/lib/libmysqlclient.a
OTHER_LIB = -lpthread -ldl -lprotobuf
SRC= ./src
INC= -I./include -I$(BASE_H) -I$(LARS_REACTOR_H) -I$(MYSQL_H) -I$(PROTO_H)
LIB= $(MYSQL_LIB) -L$(LARS_REACTOR_LIB) $(OTHER_LIB)
OBJS = $(addsuffix .o, $(basename $(wildcard $(SRC)/*.cpp)))
OBJS += $(PROTO)/lars.pb.o
$(TARGET): $(OBJS)
mkdir -p bin
$(CXX) $(CFLAGS) -o $(TARGET) $(OBJS) $(INC) $(LIB)
%.o: %.cpp
$(CXX) $(CFLAGS) -c -o $@ $< $(INC)
.PHONY: clean
clean:
-rm -f src/*.o $(PROTO)/lars.pb.o $(TARGET)
```
实际上reporter、dns相似。
> conf/lars_lb_agent.conf
```ini
[reporter]
ip = 127.0.0.1
port = 7779
[dnsserver]
ip = 127.0.0.1
port = 7778
```
目前的基本配置文件,因为loadbalance_agent是充当reporter和dnsserver的客户端,所以需要知道对应的reporter和dnsserver的ip和port信息。
04 lars-lbAgentV0.4-负载均衡idle节点的失败率判断
### 2.2 主模块业务搭建

首先我们要在主线程中,启动3个UDP Server线程,这个是提供业务层/API层的服务。然后分别启动report_client线程,用来和reporter Service进行通信,将请求上报信息发送给Reporter Service。 然后再启动dns_client线程,用来和dns service通信。
> lars_loadbalance_agent/include/main_server.h
```c
#pragma once
#include "lars_reactor.h"
#include "lars.pb.h"
//与report_client通信的thread_queue消息队列
extern thread_queue<lars::ReportStatusRequest>* report_queue;
//与dns_client通信的thread_queue消息队列
extern thread_queue<lars::GetRouteRequest>* dns_queue;
// 启动udp server服务,用来接收业务层(调用者/使用者)的消息
void start_UDP_servers(void);
// 启动lars_reporter client 线程
void start_report_client(void);
// 启动lars_dns client 线程
void start_dns_client(void);
```
05 lars-lbAgentV0.4-负载均衡overload节点的成功率判断
> lars_loadbalance_agent/src/main_server.cpp
```c
#include "main_server.h"
#include "lars.pb.h"
//与report_client通信的thread_queue消息队列
thread_queue<lars::ReportStatusRequest>* report_queue = NULL;
//与dns_client通信的thread_queue消息队列
thread_queue<lars::GetRouteRequest>* dns_queue = NULL;
int main(int argc, char **argv)
{
//1 加载配置文件
//2 启动udp server服务,用来接收业务层(调用者/使用者)的消息
start_UDP_servers();
//3 启动lars_reporter client 线程
report_queue = new thread_queue<lars::ReportStatusRequest>();
if (report_queue == NULL) {
fprintf(stderr, "create report queue error!\n");
exit(1);
}
start_report_client();
//4 启动lars_dns client 线程
dns_queue = new thread_queue<lars::GetRouteRequest>();
if (dns_queue == NULL) {
fprintf(stderr, "create dns queue error!\n");
exit(1);
}
start_dns_client();
std::cout <<"done!" <<std::endl;
while (1) {
sleep(10);
}
return 0;
}
```
06 lars-lbAgentV0.4-负载均衡上报提交模块
这里我们分别在main()中 ,开启以上线程。
其中`report_client`线程需要携带`thread_queue<lars::ReportStatusRequest>`消息队列通道。`agent`负责将上报请求消息`lars::ReportStatusRequest`通过thread_queue发送给reporter service。
其中`dns_client`线程需要携带`thread_queue<lars::GetRouteRequest>`。`agent`负责将请求modid/cmdid的route消息`lars::GetRouteRequest`通过thread_queue发送给dns service。
3个udp server的线程开辟实现如下:
> lars_loadbalance_agent/src/agent_udp_server.cpp
```c
#include "lars_reactor.h"
#include "main_server.h"
void * agent_server_main(void * args)
{
int *index = (int*)args;
short port = *index + 8888;
event_loop loop;
udp_server server(&loop, "0.0.0.0", port);
//TODO 给server注册消息分发路由业务
printf("agent UDP server :port %d is started...\n", port);
loop.event_process();
return NULL;
}
07 lars-lbAgentV0.4-数据问题修改-上报业务测试
void start_UDP_servers(void)
{
for (int i = 0; i < 3; i ++) {
pthread_t tid;
int ret = pthread_create(&tid, NULL, agent_server_main, &i);
if (ret == -1) {
perror("pthread_create");
exit(1);
}
pthread_detach(tid);
}
}
```
reporter thread创建实现如下:
> lars_loadbalance_agent/src/reporter_client.cpp
```c
#include "lars_reactor.h"
#include "main_server.h"
#include <pthread.h>
void *report_client_thread(void* args)
{
printf("report client thread start\n");
#if 0
event_loop loop;
//1 加载配置文件得到repoter ip + port
std::string ip = config_file::instance()->GetString("reporter", "ip", "");
short port = config_file::instance()->GetNumber("reporter", "port", 0);
//2 创建客户端
tcp_client client(&loop, ip.c_str(), port, "reporter client");
//3 将 thread_queue消息回调事件,绑定到loop中
report_queue->set_loop(&loop);
report_queue->set_callback()
//4 启动事件监听
loop.event_process();
#endif
return NULL;
}
08 lars-lbAgentV0.4-模拟器测试工具
void start_report_client()
{
//开辟一个线程
pthread_t tid;
//启动线程业务函数
int ret = pthread_create(&tid, NULL, report_client_thread, NULL);
if (ret == -1) {
perror("pthread_create");
exit(1);
}
//设置分离模式
pthread_detach(tid);
}
```
dns thread创建实现如下:
> lars_loadbalance_agent/src/dns_client.cpp
```c
#include "lars_reactor.h"
#include "main_server.h"
#include <pthread.h>
void *dns_client_thread(void* args)
{
printf("dns client thread start\n");
return NULL;
}
void start_dns_client()
{
//开辟一个线程
pthread_t tid;
//启动线程业务函数
int ret = pthread_create(&tid, NULL, dns_client_thread, NULL);
if (ret == -1) {
perror("pthread_create");
exit(1);
}
//设置分离模式
pthread_detach(tid);
}
```
09 lars-lbAgentV0.5-idle连续成功-overload连续失败的定期窗
口重置机制
### 2.3 测试lb_agentV0.1开发
编译,然后我们简单启动一下`./bin/lars_lb_agent`
```bash
$ ./bin/lars_lb_agent
dns client thread start
report client thread start
done!
msg_router init...
server on 0.0.0.0:8888 is running...
agent UDP server :port 8888 is started...
msg_router init...
server on 0.0.0.0:8888 is running...
agent UDP server :port 8888 is started...
msg_router init...
server on 0.0.0.0:8888 is running...
agent UDP server :port 8888 is started...
...
```
10 lars-lbAgentV0.6-loadbalance主动更新主机信息功能
## 3) Report Client设计与实现
report client主要是实现thread_queue的回调业务,udp server会定期的上传上报数据到reporter,那么请求对于report client就是透传给reporter serivce即可。
> lars_loadbalance_agent/src/reporter_client.cpp
```c
#include "lars_reactor.h"
#include "main_server.h"
#include <string>
#include <pthread.h>
//typedef void io_callback(event_loop *loop, int fd, void *args);
//只要thread_queue有数据,loop就会触发此回调函数来处理业务
void new_report_request(event_loop *loop, int fd, void *args)
{
tcp_client *client = (tcp_client*)args;
//1. 将请求数据从thread_queue中取出,
std::queue<lars::ReportStatusRequest> msgs;
//2. 将数据放在queue队列中
report_queue->recv(msgs);
//3. 遍历队列,通过client依次将每个msg发送给reporter service
while (!msgs.empty()) {
lars::ReportStatusRequest req = msgs.front();
msgs.pop();
std::string requestString;
req.SerializeToString(&requestString);
//client 发送数据
client->send_message(requestString.c_str(), requestString.size(), lars::ID_ReportStatusRequest);
}
}
11 昨日回顾
void *report_client_thread(void* args)
{
printf("report client thread start\n");
event_loop loop;
//1 加载配置文件得到repoter ip + port
std::string ip = config_file::instance()->GetString("reporter", "ip", "");
short port = config_file::instance()->GetNumber("reporter", "port", 0);
//2 创建客户端
tcp_client client(&loop, ip.c_str(), port, "reporter client");
//3 将 thread_queue消息回调事件,绑定到loop中
report_queue->set_loop(&loop);
report_queue->set_callback(new_report_request, &client);
//4 启动事件监听
loop.event_process();
return NULL;
}
12 Lars-LbAgentV0.7-GetRouteAPI实现
void start_report_client()
{
//开辟一个线程
pthread_t tid;
//启动线程业务函数
int ret = pthread_create(&tid, NULL, report_client_thread, NULL);
if (ret == -1) {
perror("pthread_create");
exit(1);
}
//设置分离模式
pthread_detach(tid);
}
```
## 4) Dns Client设计与实现
dns client 和report client的业务十分相似,只是针对的协议不同了。dns client的thread_queue 回调业务主要是透传`lars::GetRouteRequest`数据包。
> lars_loadbalance_agent/src/dns_client.cpp
```c
#include "lars_reactor.h"
#include "main_server.h"
#include <pthread.h>
//typedef void io_callback(event_loop *loop, int fd, void *args);
//只要thread_queue有数据,loop就会触发此回调函数来处理业务
void new_dns_request(event_loop *loop, int fd, void *args)
{
tcp_client *client = (tcp_client*)args;
//1. 将请求数据从thread_queue中取出,
std::queue<lars::GetRouteRequest> msgs;
//2. 将数据放在queue队列中
dns_queue->recv(msgs);
//3. 遍历队列,通过client依次将每个msg发送给reporter service
while (!msgs.empty()) {
lars::GetRouteRequest req = msgs.front();
msgs.pop();
std::string requestString;
req.SerializeToString(&requestString);
//client 发送数据
client->send_message(requestString.c_str(), requestString.size(), lars::ID_GetRouteRequest);
}
}
13 Lars-LbAgentV0.7-Udp-server-获取路由服务业务注册
void *dns_client_thread(void* args)
{
printf("dns client thread start\n");
event_loop loop;
//1 加载配置文件得到dns service ip + port
std::string ip = config_file::instance()->GetString("dnsserver", "ip", "");
short port = config_file::instance()->GetNumber("dnsserver", "port", 0);
//2 创建客户端
tcp_client client(&loop, ip.c_str(), port, "dns client");
//3 将thread_queue消息回调事件,绑定到loop中
dns_queue->set_loop(&loop);
dns_queue->set_callback(new_dns_request, &client);
//4 启动事件监听
loop.event_process();
return NULL;
}
void start_dns_client()
{
//开辟一个线程
pthread_t tid;
//启动线程业务函数
int ret = pthread_create(&tid, NULL, dns_client_thread, NULL);
if (ret == -1) {
perror("pthread_create");
exit(1);
}
//设置分离模式
pthread_detach(tid);
}
```
14 Lars-LbAgentV0.7-Udp-server-API和udpserver的测试
## 5) 负载均衡模块基础设计(V0.2)
### 5.1 基础
每个模块`modid/cmdid`下有若干节点,节点的集合称为此模块的路由; 对于每个节点,有两种状态:
- `idle`:此节点可用,可作为API**(相当于Agent的客户端)**请求的节点使用;
- `overload`:此节点过载,暂时不可作为API请求的节点使用
在请求节点时,有几个关键属性:
- 虚拟成功次数`vsucc`,API汇报节点调用结果是成功时,该值+1
- 虚拟失败次数`verr`,API汇报节点调用结果是失败时,该值+1
- 连续成功次数`contin_succ`,连续请求成功的次数
- 连续失败次数`contin_err`,连续请求失败的次数
这4个字段,在节点状态改变时(idle<—>overload),会被重置。
相关文章:
C++负载均衡远程调用学习之负载均衡算法与实现
目录 01 lars 系统架构回顾 02 lars-lbAgentV0.4-route_lb处理report业务流程 03 lars-lbAgentV0.4-负责均衡判断参数配置 04 lars-lbAgentV0.4-负载均衡idle节点的失败率判断 05 lars-lbAgentV0.4-负载均衡overload节点的成功率判断 06 lars-lbAgentV0.4-负载均衡上报提交…...

缓存(1):三级缓存
三级缓存是指什么 我们常说的三级缓存如下: CPU三级缓存Spring三级缓存应用架构(JVM、分布式缓存、db)三级缓存 CPU 基本概念 CPU 的访问速度每 18 个月就会翻 倍,相当于每年增⻓ 60% 左右,内存的速度当然也会不断…...

Cursor —— AI编辑器 使用详解
Cursor - The AI Code Editor 一、Cursor 是什么? Cursor 是一款优秀的AI代码编辑器,它内置了 Deepseek-R1、GPT-4、Claude等 AI 模型。 简单说,就是:Cursor VS Code 编辑器 AI 大模型 Cursor 功能特性(代码补全、…...

Pytorch-CUDA版本环境配置
Pytorch-CUDA版本环境配置 电脑如果是Windows平台下的Nvidia GPU的用户,需配置Pytorch的CUDA版本,分为三步: 1. 安装或更新NVIDA显卡驱动 官方驱动下载地址: https://www.nvidia.cn/Download/index.aspx?langcn 2. 安装CUDA Too…...
一个完整的神经网络训练流程详解(附 PyTorch 示例)
🧠 一个完整的神经网络训练流程详解(附 PyTorch 示例) 📌 第一部分:神经网络训练流程概览(总) 在深度学习中,构建和训练一个神经网络模型并不是简单的“输入数据、得到结果”这么简…...

OpenCV 图形API(77)图像与通道拼接函数-----对图像进行几何变换函数remap()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 对图像应用一个通用的几何变换。 函数 remap 使用指定的映射对源图像进行变换: dst ( x , y ) src ( m a p x ( x , y ) , m a p y…...
windows通过wsl安装ubuntu20.04
1 *.bat文件安装hyper-v pushd "%~dp0" dir /b %SystemRoot%\servicing\Packages\*Hyper-V*.mum >hyper-v.txt for /f %%i in (findstr /i . hyper-v.txt 2^>nul) do dism /online /norestart /add-package:"%SystemRoot%\servicing\Packages\%%i"…...

Spring AI 入门(持续更新)
介绍 Spring AI 是 Spring 项目中一个面向 AI 应用的模块,旨在通过集成开源框架、提供标准化的工具和便捷的开发体验,加速 AI 应用程序的构建和部署。 依赖 <!-- 基于 WebFlux 的响应式 SSE 传输 --> <dependency><groupId>org.spr…...

QUIC协议优化:HTTP_3环境下的超高速异步抓取方案
摘要 随着 QUIC 和 HTTP/3 的普及,基于 UDP 的连接复用与内置加密带来了远超 HTTP/2 的性能提升,可显著降低连接握手与拥塞恢复的开销。本文以爬取知乎热榜数据为目标,提出一种基于 HTTPX aioquic 的异步抓取方案,并结合代理 IP设…...

uni-app实现完成任务解锁拼图功能
界面如下 代码如下 <template><view class"puzzle-container"><view class"puzzle-title">任务进度 {{completedCount}}/{{totalPieces}}</view><view class"puzzle-grid"><viewv-for"(piece, index) in…...
Vue3 中当组件嵌套层级较深导致 ref 无法直接获取子组件实例时,可以通过 provide/inject + 回调函数的方式实现子组件方法传递到父组件
需求:vue3中使用defineExposeref调用子组件方法报错不是一个function 思路:由于组件嵌套层级太深导致ref失效,通过provide/inject 回调函数来实现多层穿透 1. 父组件提供「方法注册函数」 父组件通过 provide 提供一个用于接收子组件方法…...
关于 js:3. 闭包、作用域、内存模型
一、闭包的本质:函数 其词法作用域环境 闭包(Closure)的本质可以概括为: 闭包是一个函数,以及它定义时捕获的词法作用域中的变量集合。 这意味着:即使外部函数已经返回或作用域结束,只要有内…...

数据链路层(MAC 地址)
目录 一、前言: 二、以太网: 三、MAC 地址的作用: 四、ARP协议: 一、前言: 数据链路层主要负责相邻两个节点之间的数据传输,其中,最常见数据链路层的协议有 以太网(通过光纤 / 网…...

基于DQN的自动驾驶小车绕圈任务
1.任务介绍 任务来源: DQN: Deep Q Learning |自动驾驶入门(?) |算法与实现 任务原始代码: self-driving car 最终效果: 以下所有内容,都是对上面DQN代码的改进&#…...
terraform resource创建了5台阿里云ecs,如要使用terraform删除其中一台主机,如何删除?
在 Terraform 中删除阿里云 5 台 ECS 实例中的某一台,具体操作取决于你创建资源时使用的 多实例管理方式(count 或 for_each)。以下是详细解决方案: 方法一:使用 for_each(推荐) 如果创建时使…...

【Linux】Linux工具(1)
3.Linux工具(1) 文章目录 3.Linux工具(1)Linux 软件包管理器 yum什么是软件包关于 rzsz查看软件包——yum list命令如何安装软件如何卸载软件补充——yum如何找到要安装软件的下载地址 Linux开发工具Linux编辑器-vim使用1.vim的基…...
探索大语言模型(LLM):词袋法(Bag of Words)原理与实现
文章目录 引言一、词袋法原理1.1 核心思想1.2 实现步骤 二、数学公式2.1 词频表示2.2 TF-IDF加权(可选) 三、示例表格3.1 构建词汇表3.2 文本向量化(词频) 四、Python代码实现4.1 基础实现(手动计算)4.2 输…...
vue引入物理引擎matter.js
vue引入物理引擎matter.js 在 Vue 项目中集成 Matter.js 物理引擎的步骤如下: 1. 安装 Matter.js npm install matter-js # 或 yarn add matter-js2. 创建 Vue 组件 <template><div ref="physicsContainer" class="physics-container"><…...

基于 Spring Boot 瑞吉外卖系统开发(十一)
基于 Spring Boot 瑞吉外卖系统开发(十一) 菜品启售和停售 “批量启售”、“批量停售”、操作列的售卖状态绑定单击事件,触发单击事件时,最终携带需要修改售卖状态的菜品id以post请求方式向“/dish/status/{params.status}”发送…...
支持鸿蒙next的uts插件
*本文共四个功能函数,相当于四个插件。作者为了偷懒写成了一个插件,调对应的函数即可。 1、chooseImageHarmony函数:拉起相册选择图片并转为Base64 2、takePhotoAndConvertToBase64函数:拉起相机拍照并转为Base64 3、openBrows…...

深入理解负载均衡:传输层与应用层的原理与实战
目录 前言1. 传输层(Layer 4)负载均衡1.1 工作层级与核心机制1.2 实现方式详解1.3 优缺点分析1.4 典型实现工具 2. 应用层(Layer 7)负载均衡2.1 工作层级与核心机制2.2 实现方式解析2.3 优缺点分析2.4 常用实现工具 3. Layer 4 与…...

WPF之Slider控件详解
文章目录 1. 概述2. 基本属性2.1 值范围属性2.2 滑动步长属性2.3 刻度显示属性2.4 方向属性2.5 选择范围属性 3. 事件处理3.1 值变化事件3.2 滑块拖动事件 4. 样式和模板自定义4.1 基本样式设置4.2 控件模板自定义 5. 数据绑定5.1 绑定到ViewModel5.2 同步多个控件 6. 实际应用…...
极狐GitLab 如何将项目共享给群组?
极狐GitLab 是 GitLab 在中国的发行版,关于中文参考文档和资料有: 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 共享项目和群组 (BASIC ALL) 在极狐GitLab 16.10 中,更改为在成员页面的成员选项卡上显示被邀请群组成员…...

企业微信自建消息推送应用
企业微信自建应用来推送消息 前言 最近有个给特定部门推送消息的需求,所以配置一个应用专门用来推送消息。实现过程大致为:服务器生成每天的报告,通过调用API来发送消息。以前一直都是发邮件,整个邮箱里全是报告文件,…...
【React】Hooks useReducer 详解,让状态管理更可预测、更高效
1.背景 useReducer是React提供的一个高级Hook,没有它我们也可以正常开发,但是useReducer可以使我们的代码具有更好的可读性,可维护性。 useReducer 跟 useState 一样的都是帮我们管理组件的状态的,但是呢与useState不同的是 useReducer 是集…...

日志之ClickHouse部署及替换ELK中的Elasticsearch
文章目录 1 ELK替换1.1 Elasticsearch vs ClickHouse1.2 环境部署1.2.1 zookeeper 集群部署1.2.2 Kafka 集群部署1.2.3 FileBeat 部署1.2.4 clickhouse 部署1.2.4.1 准备步骤1.2.4.2 添加官方存储库1.2.4.3 部署&启动&连接1.2.4.5 基本配置服务1.2.4.6 测试创建数据库和…...
亚远景-ASPICE vs ISO 21434:汽车软件开发标准的深度对比
ASPICE(Automotive SPICE)和ISO 21434是汽车软件开发领域的两大核心标准,分别聚焦于过程质量与网络安全。以下从核心目标、覆盖范围、实施重点、协同关系及行业价值五个维度进行深度对比分析: 一、核心目标对比 ASPICE࿱…...
51单片机快速成长路径
作为在嵌入式领域深耕18年的工程师,分享一条经过工业验证的51单片机快速成长路径,全程干货无注水: 一、突破认知误区(新手必看) 不要纠结于「汇编还是C」:现代开发90%场景用C,掌握指针和内存管…...
使用 NGINX 实现 HTTP Basic 认证ngx_http_auth_basic_module 模块
一、前言 在 Web 应用中,对部分资源进行访问控制是十分常见的需求。除了基于 IP 限制、JWT 验证、子请求校验等方式外,最经典也最简单的一种方式便是 HTTP Basic Authentication。NGINX 提供的 ngx_http_auth_basic_module 模块支持基于用户名和密码的基…...

解构与重构:自动化测试框架的进阶认知之旅
目录 一、自动化测试的介绍 (一)自动化测试的起源与发展 (二)自动化测试的定义与目标 (三)自动化测试的适用场景 二、什么是自动化测试框架 (一)自动化测试框架的定义 &#x…...