当前位置: 首页 > news >正文

TiDB 源码编译之 TiProxy 篇

作者: ShawnYan 原文来源: https://tidb.net/blog/3d57f54d

no-alt

TiProxy 简介

TiProxy 是一个基于 Apache 2.0 协议开源的、轻量级的 TiDB 数据库代理,基于 Go 语言编写,支持 MySQL 协议。 TiProxy 支持负载均衡,接收来自应用程序的请求,然后将其发送到 TiDB 集群。支持自动故障转移,当后端 TiDB Server 发生故障,可以自动将连接转移到其他节点,以提高应用程序的可用性。

no-alt

TiProxy 编译

TiProxy 是轻量级组件,编译步骤很简洁,编译环境同前 《TiDB 源码编译之 TiUP 篇》 。

编译步骤如下:

git clone https://github.com/shawn0915/tiproxy --depth=1
cd tiproxy
go mod download -x
go mod tidy -v
export VERSION='v0.1.1-ShawnYan'
make

日志输出:

$ make
go build -gcflags '' -ldflags ' -X github.com/pingcap/TiProxy/pkg/util/versioninfo.TiProxyVersion=v0.1.1-ShawnYan -X github.com/pingcap/TiProxy/pkg/util/versioninfo.TiProxyGitHash=b944a8fe77a56bd39a7de3bf17d7deb1da039494' -tags '' -o ./bin/tiproxy ./cmd/tiproxy
go build -gcflags '' -ldflags ' -X github.com/pingcap/TiProxy/pkg/util/versioninfo.TiProxyVersion=v0.1.1-ShawnYan -X github.com/pingcap/TiProxy/pkg/util/versioninfo.TiProxyGitHash=b944a8fe77a56bd39a7de3bf17d7deb1da039494' -tags '' -o ./bin/tiproxyctl ./cmd/tiproxyctl

检查版本号:

$ ./bin/tiproxy -v
./bin/tiproxy version v0.1.1-ShawnYan, commit 81f4897fcf859154255adc86f875eda3f7e5c8a0
$ ./bin/tiproxyctl -v
./bin/tiproxyctl version test, commit test commit

这里遇到第一个问题, tiproxyctl 不识别 VERSION 变量,原因是在代码中出现硬编码。( Hard code in tiproxyctl#340 )

修改后,版本号获取正常。

$ ./bin/tiproxy -v
./bin/tiproxy version v0.1.1-ShawnYan, commit b944a8fe77a56bd39a7de3bf17d7deb1da039494-dirty
$ ./bin/tiproxyctl -v
./bin/tiproxyctl version v0.1.1-ShawnYan, commit b944a8fe77a56bd39a7de3bf17d7deb1da039494-dirty

TiProxy 尝鲜

TiProxy 的日志格式支持 TiDB 原生格式、 json 格式和 console 格式。 下面启动 TiProxy 服务,日志采用 json 格式和 DEBUG 级别。

./bin/tiproxy --config ./conf/proxy.toml --log_encoder console --log_level debug

tiproxy 启动后尝试连接:

mysql --comments --host 127.0.0.1 --port 6000 -u root

值得注意的是,TiDB 服务端与客户端之间默认采用非加密连接 [1] ,TiDB 启动时默认也不会生成 TLS 证书 [2] ,但是 tiproxy 启动时默认启用 tls 认证,这里为了简化测试,选择修改默认配置项,不要求配置 tls。

vi conf/proxy.toml[proxy]
require-backend-tls = false

否则会连接失败,遇到报错:

$ mysql --comments --host 127.0.0.1 --port 6000 -u root
ERROR 1105 (HY000): Unknown error%!(EXTRA string=TiProxy fails to connect to TiDB, please check network)

以及控制台打印日志:

2023/08/23 12:00:27.645 +09:00  INFO    main.proxy      proxy/proxy.go:159      new connection  {"connID": 0, "client_addr": "127.0.0.1:42944"}
2023/08/23 12:00:27.645 +09:00  DEBUG   main.proxy.conn.be.authenticator        backend/authenticator.go:135    frontend send capabilities unsupported by proxy {"connID": 0, "client_addr": "127.0.0.1:42944", "common": "CLIENT_LONG_PASSWORD|CLIENT_LONG_FLAG|CLIENT_LOCAL_FILES|CLIENT_PROTOCOL_41|CLIENT_INTERACTIVE|CLIENT_TRANSACTIONS|CLIENT_SECURE_CONNECTION|CLIENT_MULTI_STATEMENTS|CLIENT_MULTI_RESULTS|CLIENT_PLUGIN_AUTH|CLIENT_CONNECT_ATTS|CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA|CLIENT_DEPRECATE_EOF", "frontend": "CLIENT_PS_MULTI_RESULTS|CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS|CLIENT_SESSION_TRACK|CLIENT_QUERY_ATTRIBUTES|MULTI_FACTOR_AUTHENTICATION", "proxy": "CLIENT_FOUND_ROWS|CLIENT_CONNECT_WITH_DB|CLIENT_ODBC|CLIENT_RESERVED"}
2023/08/23 12:00:27.646 +09:00  INFO    main.proxy.conn.be      backend/backend_conn_mgr.go:218 connected to backend    {"connID": 0, "client_addr": "127.0.0.1:42944", "ns": "default", "backend_addr": "127.0.0.1:4000"}
2023/08/23 12:00:27.646 +09:00  DEBUG   main.proxy.conn.be.authenticator        backend/authenticator.go:200    backend does not support capabilities from proxy        {"connID": 0, "client_addr": "127.0.0.1:42944", "common": "CLIENT_LONG_PASSWORD|CLIENT_FOUND_ROWS|CLIENT_LONG_FLAG|CLIENT_CONNECT_WITH_DB|CLIENT_LOCAL_FILES|CLIENT_PROTOCOL_41|CLIENT_INTERACTIVE|CLIENT_TRANSACTIONS|CLIENT_SECURE_CONNECTION|CLIENT_MULTI_STATEMENTS|CLIENT_MULTI_RESULTS|CLIENT_PLUGIN_AUTH|CLIENT_CONNECT_ATTS|CLIENT_DEPRECATE_EOF", "proxy": "CLIENT_ODBC|CLIENT_RESERVED|CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA", "backend": "CLIENT_SSL"}
2023/08/23 12:00:27.646 +09:00  INFO    main.proxy.conn client/client_conn.go:61        new connection failed   {"connID": 0, "client_addr": "127.0.0.1:42944", "proxy-protocol": false, "backend_addr": "127.0.0.1:4000", "quit source": "proxy error", "error": "require TLS config on TiProxy when require-backend-tls=true"}

使用 TiUP 启动 TiProxy

TiUP 下个版本应该就会包含这个功能,感谢 @xhebox 大佬的贡献,得以让我们使用 tiup 来调用 tiproxy 组件,这里先抢先体验一下如何使用 tiup playground 启动 tidb 和 tiproxy,当然 tiup cluster 也是支持的。

由于含有该功能代码的 tiup 还没发布,所以需要自行编译 tiup,编译步骤可参考 《TiDB 源码编译之 TiUP 篇》 。

编译后的 tiup 版本信息如下:

$ tiup --version
1.12.5 tiup
Go Version: go1.21.0
Git Ref: master
GitHash: a9580bd

tiproxy 组件尚未发布到官方的镜像库,所以要想使用 tiup 调度 tiproxy 组件,需要先将 tiproxy 包上传至当前使用的 tiup 镜像库,这里使用的是本地镜像库,使用如下命令进行上传:

tiup mirror publish tiproxy v0.1.1 ./tiproxy.tar.gz tiproxy --desc tiproxy
tiup mirror publish tiproxy nightly ./tiproxy.tar.gz tiproxy --desc tiproxy

具体操作步骤可参考 《TiUP:TiDBAer 必备利器》 ,提示,需要同时提交 nightly 版本,否则会提示错误信息。

Error: Playground bootstrapping failed: component tiproxy doesn't have nightly version on platform linux/amd64

上述步骤完成后,可以看到 tiup-playground 已经增加了 tiproxy 相关选项。

$ ./tiup-playground --version
tiup version 1.12.5 tiup
Go Version: go1.21.0
Git Ref: master
GitHash: a9580bd$ ./tiup-playground --help | grep tiproxy
--tiproxy int                      TiProxy instance number
--tiproxy.binpath string           TiProxy instance binary path
--tiproxy.config string            TiProxy instance configuration file
--tiproxy.host host                Playground TiProxy host. If not provided, TiProxy will still use host flag as its host
--tiproxy.port int                 Playground TiProxy port. If not provided, TiProxy will use 6000 as its port
--tiproxy.timeout int              TiProxy max wait time in seconds for starting, 0 means no limit (default 60)

启动演示如下:

tiup playground 7.0 --tag 7.0 --without-monitor --tiflash 0 --tiproxy 1

no-alt

通过端口 6000 连接 tiproxy:

no-alt

到此,tiproxy 已经启动成功,并成功通过 tiproxy 连接到后端 tidb 集群。由于篇幅有限,tiproxy 的功能演示、测试内容另行成文。

期许

1. 源码 repo 命名小写

目前的 repo 名为 [pingcap/TiProxy],建议改为小写 pingcap/tiproxy ,统一命名方式。 毕竟是 pingcap/tidb 而非 [pingcap/TiDB],是 tikv/tikv 而非 [tikv/TiKV],是 tikv/pd 而非 [tikv/PD]。

2. tiproxy 端口非 4000

我相信大家已经达成共识,端口 4000 就是 TiDB Server 的默认端口,所以真的不建议在 tiproxy 和 tidb server 同时启动时,将 tidb server 的端口改成其他端口,而将 tiproxy 的端口改成 4000。AskTUG 论坛中有相关贴子: 闲聊贴 | 数据库端口的问题

3. tiproxy 可以独立启动

对 TiDB 深入了解的同学都知道,TiDB 的三大核心组件 TiDB Server / TiKV / PD 都可以独立启动。希望 TiProxy 也可以做到这点,不依赖 PD 也可以独立启动,而不是找不到 PD 就原地“躺平”,无时间限制不断重试连接 PD。

[2023/08/22 11:47:46.122 +09:00] [WARN] [main.infosync.etcdcli] [v3@v3.5.6/retry_interceptor.go:62] [retrying of unary invoker failed]  [target=etcd-endpoints://0xc000802380/127.0.0.1:2379] [attempt=0] [error="rpc error: code = DeadlineExceeded desc = latest balancer error: last connection error: connection error: desc = \"transport: Error while dialing dial tcp 127.0.0.1:2379: connect: connection refused\""]
[2023/08/22 11:47:46.122 +09:00] [INFO] [main.infosync.etcdcli] [v3@v3.5.6/client.go:210] [Auto sync endpoints failed.]  [error="context deadline exceeded"]

tiproxy 连接 pd 异常时,通过客户端连接 6000 端口会报错:

$ mysql -uroot -hlocalhost -P6000
ERROR 1105 (HY000): Unknown error%!(EXTRA string=No available TiDB instances, please check TiDB cluster)

4. 包版本升级

建议升级包的版本,比如 【 go 1.19 】 升级到 【go 1.21】,跟核心组件对齐,参考帖子:【 Announcing upgrade to Go 1.21 】。

还有其他包,比如:

github.com/go-mysql-org/go-mysql v1.6.0
github.com/pingcap/tidb v1.1.0-beta.0.20230103132820-3ccff46aa3bc
github.com/pingcap/tidb/parser v0.0.0-20230103132820-3ccff46aa3bc

相关 Issue 如, upgrade go-sql-driver/mysql version to v1.7.1#2246 。

5. 监控面板

TiProxy 已经提供了一些 API 来对其进行管理,但还是期望可以有一个极简的 Web 页面来达到可视化的目的。 毕竟 HAProxy 有 http://localhost:9999/haproxy-status , ProxySQL 也有 http://localhost:6080 。 甚至,TiDB Lightning 都有 http://localhost:8289 ,参见文档: TiDB Lightning Web 界面 。

6. 操作系统支持

由于 tiproxy 尚未上载到 tiup mirror,所以想要测试 tiproxy 只能从 github repo asset 下载,或者自行编译。测试 github 上的包时发现,在 CentOS 7 上无法运行,相关讨论帖参见: tiproxy 无法使用 。 这只是一个点,tiproxy 兼容性测试也要加油啊。

no-alt

7. 编译参数

建议加上 make clean 选项,或者 make file 可以再完善一下,如果能做到像 tiup 那样一个 make 命令搞定就很棒了。( support make clean option#343 )

另外,希望将环境变量 GO111MODULE="on" 也写进 make file。

8. 错误日志

error code 建议细化一下,不然使用者真的容易 UNKNOWN

ERROR 1105 (HY000): Unknown error%!(EXTRA string=TiProxy fails to connect to TiDB, please check network)

有些日志的告警级别希望调整一下,比如查询错误现在是 DEBUG ,可以改为 WARN ,或者单独输出到一个日志文件。

2023/08/22 23:51:33.138 +08:00    DEBUG    main.proxy.conn.be    backend/backend_conn_mgr.go:283    got a mysql error    {"connID": 0, "client_addr": "127.0.0.1:41942", "ns": "default", "error": "ERROR 1105 (HY000): conflict hypo index name hypo_a", "cmd": "Query"}2023/08/22 23:59:08.745 +08:00    DEBUG    main.proxy.conn.be    backend/backend_conn_mgr.go:283    got a mysql error    {"connID": 0, "client_addr": "127.0.0.1:41942", "ns": "default", "error": "ERROR 8108 (HY000): Unsupported type *ast.DropProcedureStmt", "cmd": "Query"}

此外,开启 DEBUG 日志后,有大量的 main.infosync.etcdcli 日志输出,每 3s 打印一次,建议优化掉。

2023/08/22 23:59:02.799 +08:00    DEBUG    main.infosync.etcdcli    v3@v3.5.6/retry_interceptor.go:53    retrying of unary invoker  {"target": "etcd-endpoints://0xc000980000/127.0.0.1:2379", "attempt": 0}

总结

据说 TiProxy 的云化版本已经用在了 TiDB Cloud 中,期待 TiProxy 早日 GA,并且最终可以到达能够替换 HAProxy 或 ProxySQL 的水准。

附:

no-alt

End.

相关文章:

TiDB 源码编译之 TiProxy 篇

作者: ShawnYan 原文来源: https://tidb.net/blog/3d57f54d TiProxy 简介 TiProxy 是一个基于 Apache 2.0 协议开源的、轻量级的 TiDB 数据库代理,基于 Go 语言编写,支持 MySQL 协议。 TiProxy 支持负载均衡,接收来…...

利用驱动漏洞

sbyt3/IObitUnlocker.Wrapper (github.com)...

开始MySQL之路——MySQL约束概述详解

MySQL约束 create table [if not exists] 表名(字段名1 类型[(宽度)] [约束条件] [comment 字段说明],字段名2 类型[(宽度)] [约束条件] [comment 字段说明],字段名3 类型[(宽度)] [约束条件] [comment 字段说明] )[表的一些设置]; 概念 约束英文:constraint 约束实…...

CMake基础和命令介绍

CMake是一个跨平台的构建工具,它可以生成各种不同平台上的构建文件,例如Makefile或Visual Studio项目文件。以下是一些常用的CMake命令: 1. cmake_minimum_required:指定需要的最小CMake版本。 2. project:定义项目名…...

【matlab利用shp文件制作mask白化文件】

matlab白化文件 mask文件的作用matlab制作mask文件mask结果 mask文件的作用 地理信息绘图中的 “mask” 通常指的是遮罩或掩膜,用于在地图或图像上隐藏、高亮或标记特定区域。 数据可视化: 地理信息绘图 mask 可以用于突出显示特定地理区域,使…...

【LLM】解析pdf文档生成摘要

文章目录 一、整体思路二、代码三、小结Reference 一、整体思路 非常简单的一个v1版本 利用langchain和pdfminer切分pdf文档为k块,设置overlap等参数先利用prompt1对每个chunk文本块进行摘要生成,然后利用prompt2对多个摘要进行连贯组合/增删模型可以使…...

方案:AI边缘计算智慧工地解决方案

一、方案背景 在工程项目管理中,工程施工现场涉及面广,多种元素交叉,状况较为复杂,如人员出入、机械运行、物料运输等。特别是传统的现场管理模式依赖于管理人员的现场巡查。当发现安全风险时,需要提前报告&#xff0…...

【Python】【数据结构和算法】查找最大或最小的N个元素

除了直接排序,还可以利用heaq模块的nlargest()和nsmallest()方法,例如: >>> nums [3, 5, 2, 4, 1] >>> smallest heapq.nsmallest(3, nums) >>> print(smallest) [1, 2, 3] >>> largest heapq.nlarg…...

C++day1(笔记整理)

一、Xmind整理&#xff1a; 二、上课笔记整理&#xff1a; 1.第一个c程序&#xff1a;hello world #include <iostream> //#:预处理标识符 //<iostream>:输入输出流类所在的头文件 //istream:输入流类 //ostream:输出流类using namespace std; //std&#x…...

关于chromedriver.exe一系列问题的解决办法

最新 chromedriver.exe下载地址&#xff1a;https://googlechromelabs.github.io/chrome-for-testing/#stable 下载最新版本的 chromedriver.exe 将其解压在 python.exe 同目录下&#xff0c;以及Chrome 的路径下 例如&#xff1a; C:\Program Files\Google\Chrome\Applicati…...

css-选择器、常见样式、标签分类

CSS CSS简介 层叠样式表(英文全称&#xff1a;Cascading Style Sheets)是一种用来表现HTML&#xff08;标准通用标记语言的一个应用&#xff09;或XML&#xff08;标准通用标记语言的一个子集&#xff09;等文件样式的计算机语言。CSS不仅可以静态地修饰网页&#xff0c;还可…...

三星申请新商标:未来将应用于智能戒指,作为XR头显延伸设备

三星最近向英国知识产权局提交了名为“Samsung Curio”的新商标&#xff0c;这预示着三星正积极扩展可穿戴设备生态。该商标被分类为“Class 9”&#xff0c;这表明它有可能被用于未来的智能戒指。 据报道&#xff0c;三星计划将智能戒指作为XR头显设备的延伸&#xff0c;与苹果…...

0201hdfs集群部署-hadoop-大数据学习

文章目录 1 前言2 集群规划3 hadoop安装包上传与安装3.1 上传解压 4 hadoop配置5 从节点同步和环境变量配置6 创建用户7 集群启动8 问题集8.1 Invalid URI for NameNode address (check fs.defaultFS): file:/// has no authority. 结语 1 前言 下面我们配置下单namenode节点h…...

DevOps中的持续测试优势和工具

持续测试 DevOps中的持续测试是一种软件测试类型&#xff0c;它涉及在软件开发生命周期的每个阶段测试软件。持续测试的目标是通过早期测试和经常测试来评估持续交付过程的每一步的软件质量。 DevOps中的持续测试流程涉及开发人员、DevOps、QA和操作系统等利益相关者。 持续…...

函数-C语言(初阶)

目录 一、什么是函数 二、函数的分类 2.1 库函数 2.2 自定义函数 三、函数的参数 3.1 实际参数&#xff08;实参&#xff09; 3.2 形式参数&#xff08;形参&#xff09; 四、函数的调用 4.1 传值调用 4.2 传址调用 五、函数的嵌套调用和链式访问 5.1 嵌套调用 5.2 链式访问…...

elementuiplus设置scroll-to-error之后 提示被遮挡的解决方案

项目场景&#xff1a; 普通的头部固定&#xff0c;中间滑动的布局&#xff0c;中间内容有表单&#xff0c;提交校验不通过时滚动到第一个错误项 问题描述 elementuiplus的scroll-to-error设置之后是局部滚动 当头部内容层级高于中间表单的时候&#xff0c;错误会被遮挡。 ---…...

vue中将新添加的div标签自动定位到可视区域内

可以结合使用Vue的ref和scrollIntoView()方法来实现 <template><div><button click"addDiv">添加新的<div>标签</button><div ref"container" class"container"><div v-for"&#xff08;item,inde…...

Vue3笔记——(尚硅谷张天禹Vue笔记)

Vue3 Vue3简介 1.Vue3简介 .2020年9月18日&#xff0c;Vue.js发布3.0版本&#xff0c;代号: One Piece(海贼王)。耗时2年多、2600次提交、30个RFC、600次PR、99位贡献者 . github上的tags地址: https://github.com/vuejs/vue-next/releases/tag/v3.0.0 2.Vue3带来了什么 .性能…...

正则表达式一小时学完

闯关式学习Regex 正则表达式&#xff0c;我感觉挺不错的&#xff0c;记录一下。 遇到不会的题&#xff0c;可以评论交流。 真的很不错 链接 Regex Learn - Step by step, from zero to advanced....

上门服务系统|上门服务小程序如何提升生活质量?

上门服务其实就是本地生活服务的升级&#xff0c;上门服务包含很多行业可以做的。例如&#xff1a;厨师上门、上门家电维修、跑腿等等。如今各类本地化生活服务越来越受大家的喜爱。基于此市场愿景&#xff0c;我们来谈谈上门服务系统功能。 一、上门服务系统功能 1、预约服务…...

系统报错msvcp120.dll丢失的解决方法,常见的三种解决方法

今天为大家讲述关于系统报错msvcp120.dll丢失的解决方法。在这个信息爆炸的时代&#xff0c;我们每个人都可能遇到各种各样的问题&#xff0c;而这些问题往往需要我们去探索、去解决。今天&#xff0c;我将带领大家走进这个神秘的世界&#xff0c;一起寻找解决msvcp120.dll丢失…...

数据库备份工具有哪些

本文主要介绍下数据库备份工具。 数据库备份工具有很多种&#xff0c;以下是一些常见的数据库备份工具&#xff1a; mysqldump&#xff1a;MySQL官方提供的命令行备份工具&#xff0c;适用于MySQL和MariaDB数据库。它可以将数据库导出为SQL文件&#xff0c;方便进行备份和恢复…...

Sentinel流量控制与熔断降级

&#x1f4dd; 学技术、更要掌握学习的方法&#xff0c;一起学习&#xff0c;让进步发生 &#x1f469;&#x1f3fb; 作者&#xff1a;一只IT攻城狮 &#xff0c;关注我&#xff0c;不迷路 。 &#x1f490;学习建议&#xff1a;1、养成习惯&#xff0c;学习java的任何一个技术…...

The Connector 周刊#10:你真的知道什么是DevOps文化吗?

AI 探索 用 LLM 构建企业专属的用户助手&#xff1a;很好的 LLM 应用工程实践&#xff0c;主要介绍了 PingCAP 如何使用大型语言模型&#xff08;Large Language Model&#xff0c;LLM&#xff09;构建一个搭载企业专属知识库的智能客服机器人。除了采用行业内通行的基于知识库…...

leetcode438. 找到字符串中所有字母异位词(java)

滑动窗口 找到字符串中所有字母异位词滑动窗口数组优化 上期经典 找到字符串中所有字母异位词 难度 - 中等 Leetcode 438 - 找到字符串中所有字母异位词 给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出…...

【锐捷】OSPF 多区域配置

【实验名称】 配置 OSPF 多区域。 【实验目的】 配置 OSPF 多区域&#xff0c;理解 OSPF 层次型网络的特点。 【背景描述】 本实验拓扑图中有 3 台路由器&#xff0c;路由器在区域 0 和区域 1 中&#xff0c;路由器 B 在区域 0 和区域 30&#xff0c; 路由器 C 在区域 30。 【需…...

Linux常用命令_权限管理命令

文章目录 1. 权限管理命令: chmod2. 其他权限管理命令2.1 权限管理命令: chown2.2 权限管理命令: chgrp2.3 权限管理命令: umask 1. 权限管理命令: chmod {ugoa}中分别为&#xff1a;u-user、g-group、a-all&#xff1b;谁创建文件&#xff0c;谁是所有者&#xff1b;所属组为所…...

【黑马头条之热点文章kafkaStream】

本笔记内容为黑马头条项目的热点文章-实时计算部分 目录 一、实时流式计算 1、概念 2、应用场景 3、技术方案选型 二、Kafka Stream 1、概述 2、Kafka Streams的关键概念 3、KStream 4、Kafka Stream入门案例编写 5、SpringBoot集成Kafka Stream 三、app端热点文章…...

【SpringSecurity】三、访问授权

文章目录 1、配置用户权限2、针对URL授权3、针对方法的授权 1、配置用户权限 继续上一章&#xff0c;给在内存中创建两个用户配置权限。配置权限有两种方式&#xff1a; 配置roles配置authorities //哪个写在后面哪个起作用 //角色变成权限后会加一个ROLE_前缀&#xff0c;比…...

你对SPA单页面的理解,它的优缺点分别是什么?如何实现SPA应用呢?

一、什么是SPA SPA&#xff08;single-page application&#xff09;&#xff0c;翻译过来就是单页应用SPA是一种网络应用程序或网站的模型&#xff0c;它通过动态重写当前页面来与用户交互&#xff0c;这种方法避免了页面之间切换打断用户体验在单页应用中&#xff0c;所有必…...

哪个网站做漂流瓶任务/个人网站设计方案

3dsmax是一款很重要的3d场景绘制软件&#xff0c;可以做3d游戏&#xff0c;3d场景建模&#xff0c;3d动画等&#xff0c;但是软件比较大&#xff0c;安装也比较难&#xff0c;这就直接导致很多人心有余而力不足&#xff0c;想学&#xff0c;却找不到抓手&#xff0c;所以&#…...

get attached file wordpress/重庆seo网络推广优化

获取元素DOM对象有很多种方法&#xff0c;以前一直在用getElementById和getElementsByTagName等&#xff0c;现在对这些方法和querySelector做一个总结&#xff0e; 常见的获取元素的方法有3种&#xff0c;分别是通过元素ID、通过标签名字和通过类名字来获取。 DOM提供了一个名…...

河北网站开发多少钱/如何免费推广一个网站

文章目录流程循环数组简单案例先看看效果图 流程 使用数组的slice() 方法通过条件判断截取原数组相应内容组成新数组 循环数组 let currentPage 0 // arr:原数组 newLen:新数组需要的长度 currentPage:现在的页码// 方法一&#xff1a; function loopData(arr, newLen) {…...

国内做性视频网站有哪些/百度开户返点

AMD公司今日发布AMD EPYC™(霄龙)7000系列高性能数据中心处理器&#xff0c;与全球服器生态系统的合作伙伴共同开启数据中心发展的新时代。AMD与众多客户和合作伙伴共同启动了全球发布会&#xff0c;带来了一系列系统和性能演示&#xff0c;以及客户的背书。AMD EPYC采用创记录…...

网站建设需要什么教材/千锋教育官方网

预加载图片是提高用户体验的一个很好方法。图片预先加载到浏览器中&#xff0c;访问者便可顺利地在你的网站上冲浪&#xff0c;并享受到极快的加载速度。这对图片画廊及图片占据很大比例的网站来说十分有利&#xff0c;它保证了图片快速、无缝地发布&#xff0c;也可帮助用户在…...

建站费用明细/网络营销师证书有用吗

当L0文件达到12个, 而compaction来不及的时候, 写入完全阻塞, 这个阻塞时间可能长达10s.LevelDB实现上是L0达到4个时开始触发compaction, 8个时开始减慢写入, 12个时完全停止写入. 具体配置是写死的, 不过可以在编译时修改:// Level-0 compaction is started when we hit this …...