haproxy七层代理详解之-完整安装部署流程及负载均衡实现-及热更新方法
一.负载均衡
1.1负载均衡时什么
- 负载均衡:Load Balance,简称LB,是一种服务或基于硬件设备等实现的高可用反向代理技术,负载均网络流量等)分担给指定的一个或多个后端特定的服务器或设备,从而提高了衡将特定的业务(web服务、公司业务的并发处理能力、保证了业务的高可用性、方便了业务后期的水平动态扩展
1.1.1四层负载均衡
1.1.1.1介绍
1.四层负载均衡是基于ip+port的负载均衡。
2.四层是基于三层负载均衡,发布三层的ip地址(虚拟ip),再加上四层的端口号,从而决定哪些流量需要做负载均衡。
3.四层负载均衡器也称为四层交换机,分析IP层及TCP/UDP层,但是无法解析应用层协议。
1.1.1.2原理
1.通过ip+port决定负载均衡的去向。
2.对流量请求进行NAT处理,转发至后台服务器
3.记录tcp、udp流量分别是由哪台服务器处理,后续该请求连接的流量都通过该服务器处理。
1.1.1.3支持4层代理的软件
1.F5:硬件负载均衡器,成本较高。
2.Nginx:轻量级四层负载均衡器,可缓存。(nginx四层是通过upstream模块)
3.Haproxy:模拟四层转发。
4.lvs:重量级四层负载均衡器。
1.1.2七层负载均衡
1.1.2.1介绍
1.七层负载均衡器是基于虚拟的url或主机ip的负载均衡。
2.七层负载均衡在于内容的交换,即应用层报文内容的交换解析。
3.七层负载均衡器也称为七层交换机,支持四层负载均衡器的功能,且可分析应用层信息,如HTTP协议、URI、Cookie等信息
1.1.2.2原理
1.通过虚拟url或主机ip进行流量识别,根据应用层信息进行解析,决定是否需要进行负载均衡。
2.代理后台服务器与客户端建立连接,如nginx可代理前后端,与前端客户端tcp连接,与后端服务器建立tcp连接,
1.1.2.3支持7层代理的软件
-
Nginx:基于http协议(nginx七层是通过proxy_pass)
-
Haproxy:七层代理,会话保持、标记、路径转移等
1.2.3四层和七层的区别
1.分层位置:四层负载均衡在传输层及以下,七层负载均衡在应用层及以下
2.性能:四层负载均衡架构无需解析报文消息内容,在网络吞吐量与处理能力上较高:七层可支持解析应用层报文消息内容,识别URL、Cookie、HTTP header等信息。
3.原理 :四层负载均衡是基于ip+port;七层是基于虚拟的URL或主机IP等。
4.功能类比:四层负载均衡类似于路由器;七层类似于代理服务器。
5.安全性:四层负载均衡无法识别DDoS攻击;七层可防御SYN Cookie/Flood攻击
三.haproxy简介
- HAProxy是法国开发者 威利塔罗(Willy Tarreau)在2000年使用C语言开发的一个开源软件是一款具备高并发(万级以上)、高性能的TCP和HTTP负载均衡器支持基于cookie的持久性,自动故障切换,支持正则表达式及web状态统计
haproxy安装(负载均衡软件)
实验环境
功能 | ip |
haproxy | eth0:172.25.254.100 |
RS | eth0:172.25.254.10 |
RS | eth0:172.25.254.20 |
3.1三台主机部署
webserver1
[root@webserver1 ~]# dnf install nginx -y[root@webserver1 ~]# echo webserver1 - 172.25.254.10 > /usr/share/nginx/html/index.html[root@webserver1 ~]# systemctl enable --now nginx.service
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
webserver2
[root@webserver22 ~]# dnf install nginx -y[root@webserver2 ~]# echo webserver2 - 172.25.254.20 > /usr/share/nginx/html/index.html[root@webserver2 ~]# systemctl enable --now nginx.service
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
安装haproxy并编辑配置文件
# 安装
[root@haproxy ~]# dnf install haproxy -y[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webcluster # 设置前端bind *:80 # 监听端口mode http # 七层use_backend webcluster-host # 使用的后端backend webcluster-host # 定义后端名称balance roundrobin # 调度规则(使用的算法)server web1 172.25.254.10:80 # 后端server的ipserver web2 172.25.254.20:80# 第二种写法
# listen webcluster
# bind *:80
# mode http
# balance roundrobin
# server web1 172.25.254.10:80
# server web2 172.25.254.20:80[root@haproxy ~]# systemctl enable haproxy.service
[root@haproxy ~]# systemctl restart haproxy.service
测试
后端检测
[root@webserver1 ~]# systemctl stop nginx.service
四.haproxy的基本配置信息
4.1global配置
globallog 127.0.0.1 local2 # 日志级别为2 记录在本机chroot /var/lib/haproxy # 设定haproxy运行目录pidfile /var/run/haproxy.pid # PID文件maxconn 100000 # 最大链接数user haproxy # 运行的用户group haproxy # 运行的组daemon # 运行在后台# turn on stats unix socketstats socket /var/lib/haproxy/stats # 状态接口# utilize system-wide crypto-policiesssl-default-bind-ciphers PROFILE=SYSTEM # 支持ssl的加密认证ssl-default-server-ciphers PROFILE=SYSTEM
4.1.1多进程和线程
启用查询多进程
# 默认为单进程
[root@haproxy ~]# pstree -p | grep haproxy|-haproxy(1925)---haproxy(1927)---{haproxy}(1928)[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg global
###省略### nbproc 2 # 启用多线程 cpu-map 1 0 # 进程和cpu核心绑定防止cpu抖动从而减少系统资源消耗cpu-map 2 1 # 2 表示第二个进程,1表示第二个cpu核心[root@haproxy ~]# systemctl restart haproxy.service [root@haproxy ~]# pstree -p | grep haproxy|-haproxy(2042)-+-haproxy(2045)| `-haproxy(2046)# 查看多进程
[root@haproxy ~]# pstree -p | grep haproxy|-haproxy(2030)-+-haproxy(2032)| `-haproxy(2033)
多线程对比
[root@haproxy ~]# cat /proc/2045/status | grep -i thread
Threads: 1 # 未开启多线程
Speculation_Store_Bypass: thread vulnerable[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg global
###省略###nbthread 2 # 开启多线程[root@haproxy ~]# systemctl restart haproxy.service [root@haproxy ~]# pstree -p | grep haproxy|-haproxy(2066)---haproxy(2068)---{haproxy}(2069)[root@haproxy ~]# cat /proc/2068/status | grep -i thread
Threads: 2
Speculation_Store_Bypass: thread vulnerable
4.2proxies配置
4.2.1proxies参数说明
参数 | 类型 | 作用 |
---|---|---|
defaults[] | proxies | 默认配置项,针对以下的frontend、backend和listen生效,可以多个name也可以没有name |
frontend | proxies | 前端servername,类似于Nginx的一个虚拟主机 server和LVS服务集群。 |
backend | proxies | 后端服务器组,等于nginx的upstream和LVS中的RS服务器 |
listen | proxies | 将frontend和backend合并在一起配置,相对于frontend和backend配置更简洁,生产常用 |
4.2.1.1defaults
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg defaultsmode http # 使用七层log global # 日志 根据global的设定option httplog # 记录http的日志option dontlognull # 空链接的日志不记录option http-server-close # 等待客户端完整HTTP请求的时间,此处为等待10soption forwardfor except 127.0.0.0/8 # 透传客户端真实IP至后端web服务器# 在apache配置文件中加入:<br>%{x-Forwarded-For}i# 后在webserer中看日志即可看到地址透传信息option redispatch # #当server ID对应的服务器挂掉后,强制定向到其他健康的服务器,重新派发retries 3 # 连接后端服务器失败次数timeout http-request 10s # 等待客户端请求完全被接收和处理的最长时问timeout queue 1m # 设置删除连接和客户端收到503或服务不可用等提示信息前的等待时问timeout connect 10s # 设置等待服务器连接成功的时间timeout client 1m # 设置允许客户端处于非活动状态,即既不发送数据也不接收数据的时间timeout server 1m # 设置服务器超时时间,即允许服务器处于既不接收也不发送数据的非活动时间timeout http-keep-alive 10s # session会话保持超时时间,此时问段内会转发到相同的后服务器timeout check 10s # 对后端服务器的默认检测超时时间maxconn 3000 # 最大能够承受的并发链接
backup使用案例
web1
[root@webserver1 ~]# systemctl stop nginx.service web2
[root@webserver2 ~]# systemctl stop nginx.service
### backup 示例
[root@haproxy ~]# dnf install httpd -y[root@haproxy ~]# vim /etc/httpd/conf/httpd.conf
# 定位47行,修改端口号46 #Listen 12.34.56.78:8047 Listen 8080[root@haproxy ~]# systemctl enable --now httpd
Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service.[root@haproxy ~]# echo sorry 下班了 > /var/www/html/index.html[root@haproxy ~]# vim /etc/haproxy/haproxy.cfglisten webclusterbind *:80mode httpbalance roundrobinserver web1 172.25.254.10:80 check inter 2 fall 3 rise 5 weight 2server web2 172.25.254.20:80 check inter 2 fall 3 rise 5 weight 1server web_s 172.25.254.100:8080 backup
# web1和web2没有被调用的时候,调用web_s[root@haproxy ~]# systemctl restart haproxy.service
[root@haproxy ~]# curl 172.25.254.100
sorry 下班了
[root@haproxy ~]# curl 172.25.254.100
sorry 下班了
# 开启其中一台
[root@webserver2 ~]# systemctl start nginx.service # 检测
[root@haproxy ~]# curl 172.25.254.100
webserver2 - 172.25.254.20
[root@haproxy ~]# curl 172.25.254.100
webserver2 - 172.25.254.20
[root@haproxy ~]# curl 172.25.254.100
webserver2 - 172.25.254.20
server配置
# 针对一个server配置
check #对指定rea1进行健康状态检査,如果不加此设置,默认不开启检査,只有check后面没有其它配置也可以启用检查功能# 默认对相应的后端服务器IP和端口,利用TCP连接进行周期性健康性检查,注意必须指定端口才能实现健康性检查
addr <IP> # 可指定的健康状态监测IP,可以是专门的数据网段,减少业务网络的流量
port <num> # 指定的健康状态监测端口
inter <num> # 健康状态检查间隔时间,默认2000ms
fa11 <num> # 后端服务器从线上转为线下的检查的连续失效次数,默认为3
rise <num> # 后端服务器从下线恢复上线的检查的连续有效次数,默认为2
weight <weight> # 默认为1,最大值为256,0(状态为蓝色)表示不参与负载均衡,但仍接受持久连
接
backup # 将后端服务器标记为备份状态,只在所有非备份主机down机时提供服务,类似Sorry
Server
disabled # 将后端服务器标记为不可用状态,即维护状态,除了持久模式,将不再接受连接,状态为深黄色,优雅下线,不再接受新用户的请求redirect prefix http://www.baidu.com/ # 将请求临时(302)重定向至其它URL,只适用于http模式
redir http://www.baidu.com # 将请求临时(302)重定向至其它URL,只适用于http模式maxconn <maxconn> # 当前后端server的最大并发连接数
4.3socat工具
- 对服务器动态权重和其它状态可以利用 socat工具进行调整,Socat 是 Linux 下的一个多功能的网络工具,名字来由是Socket CAT,相当于netCAT的增强版.Socat 的主要特点就是在两个数据流之间建立双向通道,且支持众多协议和链接方式。如IP、TCP、UDP、IPv6、Socket文件等
利用工具socat 对服务器动态权重调整
# 动态调整haproxy里面的参数
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg # turn on stats unix socketstats socket /var/lib/haproxy/stats mode 600 level admin
# mode 600:stats文件权限是600
# level admin 表示管理员权限,通过stats文件来控制haproxy文件的配置,不加admin只能看不能写[root@haproxy ~]# systemctl restart haproxy.service [root@haproxy ~]# ll /var/lib/haproxy/stats
srw------- 1 root root 0 8月 9 11:55 /var/lib/haproxy/stats# 安装socat动态调整haproxy的参数
[root@haproxy ~]# dnf install socat -y# 查看当前集群的权重
[root@haproxy ~]# echo get weight webcluster/web1 | socat stdio /var/lib/haproxy/stats
2 (initial 2)# 设置权重
[root@haproxy ~]# echo "set weight webcluster/web1 1 "| socat stdio /var/lib/haproxy/stats # 查看修改成功
[root@haproxy ~]# echo get weight webcluster/web1 | socat stdio /var/lib/haproxy/stats
1 (initial 2)
[root@haproxy ~]# for i in {1..10}
> do
> curl 172.25.254.100
> done
webserver2 - 172.25.254.20
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
webserver1 - 172.25.254.10# 设置一台主机下线
[root@haproxy ~]# echo "disable server webcluster/web1" | socat stdio /var/lib/haproxy/stats [root@haproxy ~]# for i in {1..10}; do curl 172.25.254.100; done
webserver2 - 172.25.254.20
webserver2 - 172.25.254.20
webserver2 - 172.25.254.20
webserver2 - 172.25.254.20
webserver2 - 172.25.254.20
webserver2 - 172.25.254.20
webserver2 - 172.25.254.20
webserver2 - 172.25.254.20
webserver2 - 172.25.254.20
webserver2 - 172.25.254.20# 重新启用
[root@haproxy ~]# echo "enable server webcluster/web1" | socat stdio /var/lib/haproxy/stats [root@haproxy ~]# for i in {1..10}; do curl 172.25.254.100; done
webserver2 - 172.25.254.20
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
webserver1 - 172.25.254.10
针对多进程处理方法
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg global
###省略#### turn on stats unix socketstats socket /var/lib/haproxy/stats1 mode 600 level admin process 1 # haproxy多进程热处理stats socket /var/lib/haproxy/stats2 mode 600 level admin process 2# utilize system-wide crypto-policiesssl-default-bind-ciphers PROFILE=SYSTEMssl-default-server-ciphers PROFILE=SYSTEMnbproc 2 # 多进程cpu-map 1 0cpu-map 2 1[root@haproxy ~]# systemctl restart haproxy.service [root@haproxy ~]# ll /var/lib/haproxy
总用量 0
srw------- 1 root root 0 8月 11 19:22 stats
srw------- 1 root root 0 8月 11 19:25 stats1
srw------- 1 root root 0 8月 11 19:25 stats2
相关文章:

haproxy七层代理详解之-完整安装部署流程及负载均衡实现-及热更新方法
一.负载均衡 1.1负载均衡时什么 负载均衡:Load Balance,简称LB,是一种服务或基于硬件设备等实现的高可用反向代理技术,负载均网络流量等)分担给指定的一个或多个后端特定的服务器或设备,从而提高了衡将特定的业务(web服务、公司…...
C++11 bind
bind bind 用来将可调用对象和参数一起进行绑定。可调用对象包括普通函数、全局函 数、静态函数、类静态函数甚至是类成员函数,参数包括普通参数和类成员。绑定后的 结果,可以使用 std::function 进行保存,并延迟调用到我们需要的时候。 绑…...
LeetCode199 二叉树的右视图
前言 题目: 199. 二叉树的右视图 文档: 代码随想录——二叉树的右视图 编程语言: C 解题状态: 成功解决! 思路 二叉树层序遍历问题的变种,右视图即意味着二叉树每层的最后一个节点。 代码 /*** Definiti…...
数据赋能(172)——开发:数据挖掘——影响因素、直接作用、主要特征
影响因素 主要影响因素如下: 数据类型与属性: 数据类型和对象的不同属性会使用不同的数据类型来描述,如年龄可能是整数类型,而生日则是日期类型。数据挖掘时需要对不同的数据类型进行不同的处理,这直接影响到挖掘算法…...

Vue:Vue3-TypeScript-Pinia-Vite-pnpm / 基础项目 / 20240807
一、项目技术栈 / 依赖 序号技术栈版本解释1node20.14.02vue 3.4.31 3vite 5.3.4 4TypeScript 5.2.2 5 types/node 22.0.2 解决TypeScript项目中缺少对应模块的类型定义文件的问题6 element-plus 2.7.8 ui组建7 types/js-cookie js-cookie 3.0.6 3.0.5 8 sass 1.77.8 9 hu…...
windows Qt 录屏 录音
启动录屏录音: connect(&m_Process, &QProcess::readyReadStandardOutput, [&]() {qDebug() << "Standard output:" << QString::fromLocal8Bit(m_Process.readAllStandardOutput()); });connect(&m_Process, &QProcess…...

AAC中的ADTS格式分析
😎 作者介绍:欢迎来到我的主页👈,我是程序员行者孙,一个热爱分享技术的制能工人。计算机本硕,人工制能研究生。公众号:AI Sun(领取大厂面经等资料),欢迎加我的…...

iOS内存管理---MRC vs ARC
系列文章目录 iOS基础—Block iOS基础—Protocol iOS基础—KVC vs KVO iOS网络—AFNetworking iOS网络—NSURLSession iOS内存管理—MRC vs ARC iOS基础—Category vs Extension iOS基础—多线程:GCD、NSThread、NSOperation iOS基础—常用三方库:Mason…...

【数学分析笔记】第1章第1节:集合(2)
这节我自己补了一些内容,要不然听不太懂陈纪修老师讲的 1. 集合与映射 1.3 子集与真子集 假如有 S \textbf{S} S和 T \textbf{T} T两个集合,其中, S \textbf{S} S的所有元素都属于 T \textbf{T} T,则称 S \textbf{S} S是 T \te…...

大话设计模式:七大设计原则
目录 一、单一职责原则(Single Responsibility Principle, SRP) 二、开放封闭原则(Open-Closed Principle, OCP) 三、依赖倒置原则(Dependency Inversion Principle, DIP) 四、里氏替换原则&am…...

利用多商家AI智能名片小程序提升消费者参与度与个性化体验:重塑零售行业的忠诚策略
摘要:在数字化浪潮席卷全球的今天,零售行业正经历着前所未有的变革。消费者对于购物体验的需求日益多样化、个性化,而零售商则面临着如何将一次性购物者转化为品牌忠诚者的巨大挑战。多商家AI智能名片小程序作为一种新兴的数字营销工具&#…...
Scala 闭包
Scala 闭包 Scala 闭包是一个非常重要的概念,它允许我们创建可以在稍后某个时间点执行的功能片段。闭包是一个函数,它捕获了封闭范围内的变量,即使在函数外部,这些变量也可以在函数内部使用。这使得闭包成为处理异步操作、回调和…...
前端JS总结(中)
目录 前言 正文 对象: 分类: 自定义对象: 内置对象: 重点: 常用内置对象: 字符串对象:String 获取字符串长度: 大小写转换: 获取某个字符: 截取字…...

elasticsearch的match_phrase匹配及其可能导致的查询问题
目录 1.match_phrase使用介绍 2.规避可能产生的查询问题 解决方式 一.查询和索引分词器一致,即都使用max_word或者都使用smart 二.使用slop增加匹配的容忍度 3.参考文档 1.match_phrase使用介绍 elasticsearch的match_phrase查询是全文查询,主要用…...

C++快速理解之继承
一、继承和派生 1.是什么? C 中的继承是类与类之间的关系,与现实世界中的继承类似 例如:儿子继承父亲的财产 继承(Inheritance)可以理解为一个类从另一个类获取成员变量和成员函数的过程 例如: 类B继承…...

Node.JS - 基础(Express)
目录 A. 简介 B. 下载,安装 C. 启动服务,查看文件结构 A. 简介 Express 是一个基于 Node.js 平台的极简、灵活的 Web 应用开发框架,它提供了一系列强大的功能来构建 Web 应用程序和 API。 一、Express 的基本特点 简洁的路由系统: Express 的路由系…...

I/O复用
I/O复用使得程序能够同时监听多个文件描述符,这对提高程序的性能至关重要。 举个例子: 就好比你天天玩手机,你妈为了监控你,在你房间安装了一个监控,这个监控可以实时监控你的一举一动,并上传到你妈手机上…...

【验证可用】解决安装SQL Server数据库时,报错“启用 windows 功能 NetFx3 时出错,错误代码:-2146498298......“的问题
目录 背景一. 报错信息1.1 报错的图片信息1.2 报错的文字信息 二. 解决报错2.1 下载 NetFx3.cab 文件2.2 执行命令 三. SQL Server 修复安装 背景 一次在阿里云服务器安装 SQL Server 2012时,系统报错了,导致安装进行不下去…通过在网上查找了多种解决方…...

STM32的SDIO接口详解
目录 1. 定义与兼容性 2. SDIO时钟 3. SDIO命令与响应 4. SDIO块数据传输 5. SDIO控制器的硬件结构 6.代码实现 1.SD初始化 2.测试SD卡的读取 3.测试SD卡的写入 STM32的SDIO(Secure Digital Input/Output,安全数字输入输出)接口是一…...

docker容器常用指令,dockerfile
docker:容器,主要是解决环境迁移的问题,将环境放入docker中,打包成镜像。 docker的基本组成:镜像(image),容器(container),仓库(repository)。镜像相当于类,容器相当于类的实例对象…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...

如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...