乐闻世界logo
搜索文章和话题

服务端面试题手册

什么是 DeFi?详解去中心化金融的核心协议和流动性挖矿机制

DeFi(Decentralized Finance,去中心化金融) 是建立在区块链上的金融服务生态系统,通过智能合约实现无需中介的借贷、交易、理财等金融服务。DeFi 与传统金融对比传统金融(CeFi) DeFi(去中心化金融)┌──────────────┐ ┌──────────────┐│ 银行 │ │ 智能合约 ││ 交易所 │ → │ 自动执行 ││ 券商 │ │ 无需许可 │└──────────────┘ └──────────────┘ ↓ ↓ 需要信任机构 信任代码 门槛高、审查 开放、透明| 特性 | 传统金融 | DeFi || -------- | ---------- | ---------- || 准入门槛 | 需要身份认证 | 无需许可,有钱包即可 || 运营时间 | 工作日 9-17 点 | 7×24 小时 || 透明度 | 不透明 | 链上完全透明 || 控制权 | 机构控制 | 用户自持资产 || 收益率 | 较低(0.5-3%) | 较高(5-20%+) || 风险 | 机构信用风险 | 智能合约风险 |DeFi 核心协议类型DeFi 生态系统├── DEX(去中心化交易所)│ ├── AMM(自动做市商)│ └── 订单簿模式├── 借贷协议│ ├── 超额抵押借贷│ └── 闪电贷├── 稳定币│ ├── 抵押型(DAI)│ └── 算法型(UST)├── 衍生品│ ├── 永续合约│ └── 期权└── 收益聚合器 └── 流动性挖矿1. DEX(去中心化交易所)AMM(自动做市商)机制传统订单簿 vs AMM:订单簿模式: AMM 模式:买单 卖单 流动性池┌──────┐ ┌──────┐ ┌─────────────┐│ 100 │ │ 102 │ │ ETH │ USDC ││ 99 │ │ 103 │ │ 100 │ 200K ││ 98 │ │ 104 │ └─────────────┘└──────┘ └──────┘ ↑ 需要对手方 与池子交易恒定乘积公式(Uniswap):x × y = k其中:x = 代币 A 数量y = 代币 B 数量k = 常数(流动性不变时)示例:池子:100 ETH + 200,000 USDCk = 100 × 200,000 = 20,000,000用 1 ETH 能换多少 USDC?(100 + 1) × (200,000 - Δy) = 20,000,000Δy ≈ 1,980 USDC无常损失(Impermanent Loss)流动性提供者面临的风险:初始:存入 1 ETH + 2000 USDC(ETH 价格 $2000)情况1:ETH 涨到 $4000- 如果不提供流动性:1 ETH × $4000 + 2000 USDC = $6000- 提供流动性后:池子自动平衡 √k = √(0.707 × 2828) ≈ $5656- 无常损失:$6000 - $5656 = $344 (5.7%)2. 借贷协议超额抵押借贷Aave/Compound 机制:存款流程: 借款流程:┌─────────┐ ┌─────────┐│ 存入 ETH │ │ 抵押 ETH ││ 获得 aETH │ │ 借款 USDC││ 赚取利息 │ │ │└─────────┘ │ 清算线:75%│ │ │ │ 利率模型:│ │ • 利用率↑ │ │ • 利率↑ │ └─────────┘关键参数:抵押因子(Collateral Factor):75%(最多借出抵押品价值的 75%)清算阈值(Liquidation Threshold):80%健康因子(Health Factor):\< 1 时触发清算闪电贷(Flash Loan)原理:在一个区块内借入和归还,无需抵押。闪电贷流程:1. 借入 1000 ETH(无抵押) ↓2. 在 DEX A 用 ETH 买代币(价格低估) ↓3. 在 DEX B 卖出代币(价格高估) ↓4. 归还 1000 ETH + 0.09% 手续费 ↓5. 套利利润留在合约中⚠️ 所有操作必须在一个原子交易中完成应用场景:套利抵押品互换自我清算3. 稳定币类型对比| 类型 | 机制 | 代表 | 优点 | 缺点 || -------- | -------- | --------- | ----- | ------ || 法币抵押 | 1:1 美元储备 | USDT、USDC | 价格稳定 | 中心化 || 加密抵押 | 超额加密资产抵押 | DAI | 去中心化 | 资本效率低 || 算法稳定 | 算法调节供需 | UST(已崩盘) | 资本效率高 | 死亡螺旋风险 |DAI 机制DAI 生成流程:1. 存入 150 ETH(价值 $300,000) ↓2. 铸造 100,000 DAI(抵押率 150%) ↓3. 使用 DAI 进行交易/投资 ↓4. 归还 100,000 DAI + 稳定费 ↓5. 取回抵押的 ETH清算机制:- 抵押率 < 150%:触发清算- Keeper 拍卖抵押品- 偿还 DAI 债务4. 流动性挖矿(Yield Farming)原理通过提供流动性获得代币奖励。流动性挖矿流程:1. 提供流动性 ETH + USDC → Uniswap 池 ↓2. 获得 LP Token ↓3. 质押 LP Token 到 Farm 合约 ↓4. 获得奖励 • 交易手续费(0.3%) • 平台代币(UNI、SUSHI)收益率计算APY(年化收益率)计算:基础公式:APY = (1 + r/n)^n - 1其中:r = 周期收益率n = 复利次数/年示例:日收益率 0.1%,复利计算APY = (1 + 0.001)^365 - 1 ≈ 44%⚠️ 注意:APY 会随价格波动,非保证收益风险无常损失:价格波动导致 LP 损失智能合约风险:合约漏洞被攻击无常损失 + 挖矿奖励 \:币价暴跌Rug Pull:项目方卷款跑路5. DeFi 组合性(Composability)乐高积木效应:收益最大化策略示例:1. 在 Aave 存入 ETH 获得 aETH ↓2. 将 aETH 作为抵押在 Compound 借款 USDC ↓3. 用 USDC 在 Curve 提供流动性获得 CRV ↓4. 质押 CRV 获得 veCRV 治理权 ↓5. 投票决定池子奖励分配风险:组合越多,风险越大(风险传染)面试要点理解 AMM 恒定乘积公式掌握无常损失的计算和影响了解超额抵押借贷的清算机制理解闪电贷的原理和应用场景熟悉不同类型稳定币的优缺点掌握流动性挖矿的收益率计算了解 DeFi 组合性的风险能够分析 DeFi 协议的经济模型
阅读 0·3月7日 19:41

cURL 的 -X 参数有什么作用?PUT、DELETE、PATCH 请求如何使用?

在 cURL 中,-X 或 --request 参数用于指定 HTTP 请求方法。虽然 cURL 会根据其他参数自动推断方法,但显式指定方法可以让请求更加明确和可控。-X 参数基础# 基本语法curl -X METHOD URL# 常见用法curl -X GET https://api.example.com/userscurl -X POST https://api.example.com/userscurl -X PUT https://api.example.com/users/1curl -X DELETE https://api.example.com/users/1curl -X PATCH https://api.example.com/users/1HTTP 方法详解GET 请求# GET 请求(默认,通常不需要 -X GET)curl https://api.example.com/users# 显式指定 GETcurl -X GET https://api.example.com/users# 带查询参数的 GETcurl -X GET "https://api.example.com/users?page=1&limit=10"# 带请求头的 GETcurl -X GET \ -H "Authorization: Bearer token123" \ https://api.example.com/usersPOST 请求# POST 请求(使用 -d 时自动使用 POST)curl -X POST \ -H "Content-Type: application/json" \ -d '{"name":"张三"}' \ https://api.example.com/users# 表单数据 POSTcurl -X POST \ -d "username=admin&password=123456" \ https://api.example.com/login# 文件上传 POSTcurl -X POST \ -F "file=@document.pdf" \ https://api.example.com/uploadPUT 请求PUT 用于完整更新资源,通常需要提供资源的全部字段。# 基本 PUT 请求curl -X PUT \ -H "Content-Type: application/json" \ -H "Authorization: Bearer token123" \ -d '{"id":1,"name":"张三","email":"zhangsan@example.com","age":25}' \ https://api.example.com/users/1# PUT 更新文件内容curl -X PUT \ -H "Content-Type: application/octet-stream" \ --data-binary @updated-file.txt \ https://api.example.com/files/document.txt# PUT 上传文件(REST API 风格)curl -X PUT \ -T local-file.pdf \ https://api.example.com/documents/123DELETE 请求DELETE 用于删除资源。# 基本 DELETE 请求curl -X DELETE \ -H "Authorization: Bearer token123" \ https://api.example.com/users/1# DELETE 带请求体(某些 API 需要)curl -X DELETE \ -H "Content-Type: application/json" \ -H "Authorization: Bearer token123" \ -d '{"reason":"inactive user"}' \ https://api.example.com/users/1# 批量删除curl -X DELETE \ -H "Content-Type: application/json" \ -d '{"ids":[1,2,3]}' \ https://api.example.com/users/batchPATCH 请求PATCH 用于部分更新资源,只需提供要修改的字段。# 基本 PATCH 请求curl -X PATCH \ -H "Content-Type: application/json" \ -H "Authorization: Bearer token123" \ -d '{"email":"newemail@example.com"}' \ https://api.example.com/users/1# JSON Patch 格式 (RFC 6902)curl -X PATCH \ -H "Content-Type: application/json-patch+json" \ -d '[{"op":"replace","path":"/email","value":"new@example.com"}]' \ https://api.example.com/users/1# Merge Patch 格式 (RFC 7386)curl -X PATCH \ -H "Content-Type: application/merge-patch+json" \ -d '{"email":"new@example.com","settings":{"theme":"dark"}}' \ https://api.example.com/users/1HTTP 方法对比| 方法 | 用途 | 幂等性 | 安全性 | 典型场景 || ------- | ------- | --- | --- | ------- || GET | 获取资源 | ✅ | ✅ | 查询数据 || POST | 创建资源 | ❌ | ❌ | 提交表单、创建 || PUT | 完整更新 | ✅ | ❌ | 替换资源 || PATCH | 部分更新 | ❌ | ❌ | 修改部分字段 || DELETE | 删除资源 | ✅ | ❌ | 删除操作 || HEAD | 获取元数据 | ✅ | ✅ | 检查资源存在 || OPTIONS | 获取支持的方法 | ✅ | ✅ | CORS 预检 |其他 HTTP 方法# HEAD 请求(仅获取响应头)curl -X HEAD https://api.example.com/users/1# 或使用 -Icurl -I https://api.example.com/users/1# OPTIONS 请求(CORS 预检)curl -X OPTIONS \ -H "Origin: https://example.com" \ -H "Access-Control-Request-Method: POST" \ https://api.example.com/users# TRACE 请求(调试,通常被禁用)curl -X TRACE https://api.example.com/debug# CONNECT 请求(建立隧道)curl -X CONNECT http://proxy.example.com:8080RESTful API 完整示例#!/bin/bash# RESTful API 完整操作示例API_BASE="https://api.example.com/v1"TOKEN="your_bearer_token"# 1. 创建资源 (POST)echo "Creating user..."CREATE_RESPONSE=$(curl -s -X POST \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $TOKEN" \ -d '{"name":"张三","email":"zhangsan@example.com"}' \ "$API_BASE/users")USER_ID=$(echo $CREATE_RESPONSE | jq -r '.id')echo "Created user ID: $USER_ID"# 2. 获取资源 (GET)echo "Getting user..."curl -s -X GET \ -H "Authorization: Bearer $TOKEN" \ "$API_BASE/users/$USER_ID" | jq# 3. 完整更新 (PUT)echo "Updating user (PUT)..."curl -s -X PUT \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $TOKEN" \ -d "{\"id\":$USER_ID,\"name\":\"张三\",\"email\":\"updated@example.com\",\"age\":26}" \ "$API_BASE/users/$USER_ID" | jq# 4. 部分更新 (PATCH)echo "Updating user (PATCH)..."curl -s -X PATCH \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $TOKEN" \ -d '{"age":27}' \ "$API_BASE/users/$USER_ID" | jq# 5. 删除资源 (DELETE)echo "Deleting user..."curl -s -X DELETE \ -H "Authorization: Bearer $TOKEN" \ "$API_BASE/users/$USER_ID"echo "User deleted"注意事项自动推断方法:使用 -d 时,cURL 默认使用 POST使用 -T 时,cURL 默认使用 PUT显式使用 -X 可以覆盖默认行为幂等性考虑:GET、PUT、DELETE 应该是幂等的POST、PATCH 通常不是幂等的Content-Type:发送数据时必须设置正确的 Content-TypeJSON: application/json表单: application/x-www-form-urlencoded文件: multipart/form-data安全性:GET 不应该有副作用DELETE 操作应该谨慎敏感操作需要认证
阅读 0·3月7日 19:41

如何使用 cURL 发送 GET 和 POST 请求?

在 cURL 中,GET 和 POST 请求是最常用的两种 HTTP 方法,它们的使用场景和参数配置有所不同。GET 请求GET 请求用于获取数据,参数通常附加在 URL 中。# 基础 GET 请求curl https://api.example.com/users# 带查询参数curl "https://api.example.com/users?page=1&limit=10"# 带请求头curl -H "Authorization: Bearer token123" \ -H "Accept: application/json" \ https://api.example.com/users# 显示响应头信息curl -i https://api.example.com/users# 仅显示响应头curl -I https://api.example.com/usersPOST 请求POST 请求用于提交数据,需要使用 -X POST 指定方法,-d 传递数据。# 发送 JSON 数据curl -X POST https://api.example.com/users \ -H "Content-Type: application/json" \ -d '{"name":"张三","email":"zhangsan@example.com"}'# 发送表单数据curl -X POST https://api.example.com/login \ -d "username=admin&password=123456"# 从文件读取数据curl -X POST https://api.example.com/upload \ -H "Content-Type: application/json" \ -d @data.json# 上传文件curl -X POST https://api.example.com/upload \ -F "file=@/path/to/file.pdf"关键区别| 特性 | GET | POST || ---- | ---------- | ---- || 数据位置 | URL 参数 | 请求体 || 数据大小 | 受 URL 长度限制 | 无限制 || 安全性 | 参数可见 | 相对安全 || 缓存 | 可被缓存 | 不缓存 || 幂等性 | 幂等 | 非幂等 |常用参数说明-X 或 --request:指定 HTTP 方法-H 或 --header:添加请求头-d 或 --data:发送数据-F 或 --form:上传表单/文件-i:显示响应头和内容-I:仅显示响应头
阅读 0·3月7日 19:41

cURL 如何处理 HTTP 认证(Basic Auth、Bearer Token、OAuth)?

在 cURL 中,认证(Authentication) 是访问受保护资源的关键步骤。cURL 支持多种认证方式,包括 Basic Auth、Bearer Token、OAuth 等。Basic AuthenticationBasic Auth 是最简单的认证方式,将用户名和密码进行 Base64 编码后发送。# 方式一:使用 -u 参数curl -u "username:password" https://api.example.com/protected# 方式二:手动编码(不推荐)curl -H "Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=" \ https://api.example.com/protected# 仅提供用户名,cURL 会提示输入密码curl -u "username" https://api.example.com/protected# 从环境变量读取密码curl -u "username:$PASSWORD" https://api.example.com/protectedBearer Token 认证Bearer Token 是现代 API 最常用的认证方式。# 使用 Bearer Tokencurl -H "Authorization: Bearer your_access_token_here" \ https://api.example.com/protected# 结合其他参数curl -X POST \ -H "Authorization: Bearer token123" \ -H "Content-Type: application/json" \ -d '{"name":"test"}' \ https://api.example.com/resource# 从文件读取 TokenTOKEN=$(cat token.txt)curl -H "Authorization: Bearer $TOKEN" \ https://api.example.com/protectedAPI Key 认证API Key 通常通过查询参数或请求头传递。# 查询参数方式curl "https://api.example.com/data?api_key=your_api_key_here"# 请求头方式curl -H "X-API-Key: your_api_key_here" \ https://api.example.com/data# 自定义请求头名称curl -H "ApiKey: your_api_key_here" \ https://api.example.com/dataOAuth 2.0 认证OAuth 2.0 是复杂的认证流程,通常包含多个步骤。# 步骤 1:获取 Access Tokencurl -X POST https://auth.example.com/oauth/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=client_credentials" \ -d "client_id=your_client_id" \ -d "client_secret=your_client_secret"# 步骤 2:使用 Access Token 访问资源curl -H "Authorization: Bearer access_token_from_step1" \ https://api.example.com/protected# OAuth 密码模式curl -X POST https://auth.example.com/oauth/token \ -d "grant_type=password" \ -d "username=user@example.com" \ -d "password=user_password" \ -d "client_id=your_client_id"Digest 认证Digest 认证比 Basic Auth 更安全。# 使用 --digest 参数curl --digest -u "username:password" \ https://api.example.com/protected认证方式对比| 认证方式 | 安全性 | 使用场景 | cURL 参数 || ------------ | ---------- | ------ | ---------------------------- || Basic Auth | 低(需 HTTPS) | 简单场景 | -u || Bearer Token | 中 | API 调用 | -H "Authorization: Bearer" || API Key | 中 | 开放 API | -H "X-API-Key" 或查询参数 || OAuth 2.0 | 高 | 第三方授权 | 多步骤流程 || Digest | 高 | 内部系统 | --digest |实战示例# GitHub API 认证curl -H "Authorization: Bearer ghp_xxxx" \ https://api.github.com/user# AWS API(需要签名)curl -X GET "https://s3.amazonaws.com/bucket/file" \ -H "Authorization: AWS4-HMAC-SHA256 ..."# 带认证的完整 API 调用curl -X POST https://api.example.com/orders \ -H "Authorization: Bearer token123" \ -H "Content-Type: application/json" \ -H "X-Request-ID: $(uuidgen)" \ -d '{"product_id": 123, "quantity": 2}'安全最佳实践使用环境变量:不要在命令行中硬编码密码HTTPS 必须:认证信息必须通过加密通道传输Token 过期:定期刷新 Access Token权限最小化:只申请必要的权限范围日志安全:避免在日志中记录敏感信息
阅读 0·3月7日 19:39

iframe 如何实现跨域通信?postMessage API 的使用方法和安全注意事项是什么?

postMessage 是 HTML5 提供的跨文档消息传递 API,它允许不同源的窗口之间安全地进行通信,包括 iframe 与父页面之间的通信。基本语法// 发送消息otherWindow.postMessage(message, targetOrigin, [transfer]);// 接收消息window.addEventListener('message', (event) => { // 处理消息});参数说明message: 要发送的数据,可以是任何可序列化的对象targetOrigin: 目标窗口的源,可以是具体的 URL、"*"(所有源)或 "/"(同源)transfer: 可选,用于转移所有权的一组可转移对象安全最佳实践1. 始终验证消息来源window.addEventListener('message', (event) => { // 验证消息来源 if (event.origin !== 'https://trusted-domain.com') { return; } // 处理消息 const data = event.data;});2. 使用具体的 targetOrigin// 不推荐:允许所有源iframe.postMessage(data, '*');// 推荐:指定具体源iframe.postMessage(data, 'https://trusted-domain.com');3. 验证消息数据格式window.addEventListener('message', (event) => { if (event.origin !== 'https://trusted-domain.com') { return; } // 验证数据结构 if (!event.data || typeof event.data.type !== 'string') { return; } switch (event.data.type) { case 'resize': handleResize(event.data); break; case 'close': handleClose(); break; }});iframe 与父页面通信示例父页面发送消息到 iframeconst iframe = document.getElementById('myIframe');// 等待 iframe 加载完成iframe.onload = () => { iframe.postMessage({ type: 'init', data: { userId: 123, token: 'abc123' } }, 'https://child-domain.com');};iframe 发送消息到父页面// iframe 内部代码window.parent.postMessage({ type: 'resize', data: { width: 800, height: 600 }}, 'https://parent-domain.com');父页面接收 iframe 消息window.addEventListener('message', (event) => { if (event.origin !== 'https://child-domain.com') { return; } if (event.data.type === 'resize') { const iframe = document.getElementById('myIframe'); iframe.style.width = event.data.data.width + 'px'; iframe.style.height = event.data.data.height + 'px'; }});常见应用场景跨域通信: 不同域名下的页面之间进行数据交换第三方集成: 嵌入第三方服务(如支付、登录)时的状态同步响应式调整: iframe 内容根据自身尺寸通知父页面调整单点登录: 在不同域之间传递认证信息实时数据更新: 子页面向父页面推送实时数据注意事项同源策略限制: postMessage 不受同源策略限制,但需要正确设置 targetOrigin消息序列化: 发送的数据会被结构化克隆,某些对象(如函数、DOM 节点)无法发送性能考虑: 频繁的消息传递可能影响性能,建议批量处理或使用防抖错误处理: 添加适当的错误处理机制,防止恶意消息导致安全问题
阅读 0·3月7日 19:39

Babel 中 preset 和 plugin 的区别是什么?如何配置?

Preset 和 Plugin 的区别Plugin(插件)粒度更细:每个插件只负责单一的转换功能功能单一:例如 @babel/plugin-transform-arrow-functions 只转换箭头函数按需使用:可以精确控制需要哪些转换Preset(预设)插件集合:是一组插件的集合,用于简化配置批量处理:一次配置,包含多个相关插件常见预设:@babel/preset-env:根据目标环境自动选择转换@babel/preset-react:React/JSX 转换@babel/preset-typescript:TypeScript 转换配置方式1. 使用 Plugin// babel.config.jsmodule.exports = { plugins: [ '@babel/plugin-transform-arrow-functions', '@babel/plugin-transform-classes', // 带参数的插件 ['@babel/plugin-transform-runtime', { corejs: 3 }] ]};2. 使用 Preset// babel.config.jsmodule.exports = { presets: [ ['@babel/preset-env', { targets: { browsers: ['> 1%', 'last 2 versions'] }, useBuiltIns: 'usage', corejs: 3 }], '@babel/preset-react' ]};3. Plugin 和 Preset 的执行顺序重要规则:Plugin 先于 Preset 执行Plugin 从前往后执行Preset 从后往前执行module.exports = { plugins: [ 'plugin-a', // 第1个执行 'plugin-b' // 第2个执行 ], presets: [ 'preset-b', // 第4个执行(preset 逆序) 'preset-a' // 第3个执行 ]};最佳实践1. 优先使用 @babel/preset-envmodule.exports = { presets: [ ['@babel/preset-env', { targets: '> 0.25%, not dead' }] ]};2. 开发自定义 Plugin// 简单的 Babel 插件示例module.exports = function(babel) { const { types: t } = babel; return { name: 'my-custom-plugin', visitor: { Identifier(path) { // 转换逻辑 } } };};3. 开发自定义 Preset// 自定义 presetmodule.exports = function() { return { plugins: [ 'plugin-a', 'plugin-b' ] };};常见面试追问为什么 preset 是逆序执行?为了符合大多数用户的直觉,通常将更具体的 preset 放在后面如何查看 Babel 实际使用了哪些插件?使用 DEBUG=* babel src 查看调试信息plugin 和 preset 可以混用吗?可以,且非常常见,preset 处理大部分转换,plugin 处理特殊需求
阅读 0·3月7日 19:38

WebGL 渲染管线的工作流程是什么?

WebGL 渲染管线(Rendering Pipeline)是一系列将 3D 顶点数据转换为 2D 屏幕像素的处理阶段。理解渲染管线对于优化 WebGL 应用性能至关重要。渲染管线的各个阶段1. 顶点处理阶段(Vertex Processing)顶点着色器(Vertex Shader)输入:顶点位置、颜色、纹理坐标、法线等属性处理:坐标变换(模型矩阵、视图矩阵、投影矩阵)顶点光照计算纹理坐标变换输出:裁剪空间坐标(Clip Space Coordinates)// 顶点着色器示例attribute vec3 a_position;attribute vec2 a_texCoord;uniform mat4 u_modelViewProjectionMatrix;varying vec2 v_texCoord;void main() { gl_Position = u_modelViewProjectionMatrix * vec4(a_position, 1.0); v_texCoord = a_texCoord;}2. 图元装配阶段(Primitive Assembly)将顶点组装成图元(点、线、三角形)执行裁剪(Clipping):移除视锥体外的图元执行透视除法(Perspective Division):将裁剪坐标转换为标准化设备坐标(NDC)3. 光栅化阶段(Rasterization)将图元转换为片段(Fragments)片段是潜在的像素,包含颜色、深度等信息确定哪些像素被图元覆盖进行插值计算:颜色、纹理坐标、法线等属性在片段间的插值4. 片段处理阶段(Fragment Processing)片段着色器(Fragment Shader)输入:插值后的顶点属性处理:纹理采样光照计算颜色混合输出:最终像素颜色// 片段着色器示例precision mediump float;varying vec2 v_texCoord;uniform sampler2D u_texture;void main() { gl_FragColor = texture2D(u_texture, v_texCoord);}5. 逐片段操作阶段(Per-Fragment Operations)深度测试(Depth Testing)比较片段深度值与深度缓冲区决定是否丢弃片段模板测试(Stencil Testing)使用模板缓冲区进行掩码操作混合(Blending)将片段颜色与帧缓冲区已有颜色混合实现透明效果抖动(Dithering)减少颜色量化带来的色带WebGL 渲染流程图顶点数据 → 顶点着色器 → 图元装配 → 裁剪 → 透视除法 → 视口变换 ↓帧缓冲区 ← 逐片段操作 ← 片段着色器 ← 光栅化/插值 ← 屏幕映射性能优化要点减少绘制调用:合并网格,使用实例化渲染优化顶点着色器:避免复杂计算减少片段着色器复杂度:特别是移动端合理使用深度测试:从前到后绘制不透明物体避免过度绘制:使用遮挡查询WebGL 1.0 vs WebGL 2.0 管线差异| 特性 | WebGL 1.0 | WebGL 2.0 || ------ | --------- | --------- || 变换反馈 | 不支持 | 支持 || 多重渲染目标 | 需要扩展 | 原生支持 || 3D 纹理 | 需要扩展 | 原生支持 || 实例化渲染 | 需要扩展 | 原生支持 |​
阅读 0·3月7日 19:38

cURL 性能优化和最佳实践有哪些?

性能优化和最佳实践能显著提升 cURL 的使用效率和可靠性。掌握这些技巧对于生产环境至关重要。超时设置# 连接超时(秒)curl --connect-timeout 10 https://api.example.com# 最大传输时间(秒)curl --max-time 30 https://api.example.com# 组合使用curl --connect-timeout 5 --max-time 30 https://api.example.com# 毫秒级超时(7.68.0+)curl --connect-timeout 3.5 --max-time 10.5 https://api.example.com重试机制# 自动重试curl --retry 3 https://api.example.com# 重试延迟(秒)curl --retry 3 --retry-delay 2 https://api.example.com# 指数退避重试curl --retry 3 --retry-delay 1 --retry-max-time 10 https://api.example.com# 特定错误码重试curl --retry 5 --retry-connrefused https://api.example.com连接复用# 保持连接(HTTP Keep-Alive)curl --keepalive-time 60 https://api.example.com# 限制连接数curl --limit-rate 100K https://api.example.com# 并发请求(使用 xargs)cat urls.txt | xargs -P 5 -I {} curl -s {} -o /dev/null压缩传输# 请求压缩响应curl --compressed https://api.example.com# 手动指定压缩curl -H "Accept-Encoding: gzip, deflate" https://api.example.com性能分析# 详细性能指标curl -w "DNS: %{time_namelookup}s\nConnect: %{time_connect}s\nSSL: %{time_appconnect}s\nTTFB: %{time_starttransfer}s\nTotal: %{time_total}s\nSize: %{size_download}B\nSpeed: %{speed_download}B/s\n" \ -o /dev/null -s https://api.example.com# 保存性能报告curl -w "@perf-format.txt" -o /dev/null -s https://api.example.com > perf.log批量处理优化# 批量下载(并行)#!/bin/bashurls=( "https://api.example.com/users" "https://api.example.com/products" "https://api.example.com/orders")for url in "${urls[@]}"; do curl -s "$url" -o "$(basename $url).json" &donewait# 使用 GNU Parallelcat urls.txt | parallel -j 4 curl -s {} -o {/}.json# 连接池复用curl -K - <<EOFurl = "https://api.example.com/users"output = "users.json"url = "https://api.example.com/products"output = "products.json"EOF内存和资源优化# 限制下载速度curl --limit-rate 1M https://example.com/large-file.zip -O# 分块下载curl -r 0-1024000 https://example.com/large-file.zip -o part1.zipcurl -r 1024001-2048000 https://example.com/large-file.zip -o part2.zip# 断点续传curl -C - -O https://example.com/large-file.zip# 流式处理(不保存到内存)curl -s https://api.example.com/stream | jq '.[] | .name'最佳实践清单1. 安全性# 始终验证 SSL 证书curl https://api.example.com# 使用最新 TLS 版本curl --tlsv1.2 --tls-max tls1.3 https://api.example.com# 不在命令行暴露密码curl -u "username" https://api.example.com# 让 cURL 提示输入密码# 使用环境变量curl -H "Authorization: Bearer $API_TOKEN" https://api.example.com2. 可靠性# 设置合理的超时curl --connect-timeout 10 --max-time 60 https://api.example.com# 启用重试机制curl --retry 3 --retry-delay 2 --retry-max-time 30 https://api.example.com# 错误处理curl -f https://api.example.com || echo "Request failed"# 检查退出码curl -s https://api.example.comif [ $? -ne 0 ]; then echo "Error occurred"fi3. 可维护性# 使用配置文件# ~/.curlrcverboseconnect-timeout = 10max-time = 60retry = 3# 使用变量和函数#!/bin/bashAPI_BASE="https://api.example.com/v1"TOKEN="your_token"api_call() { curl -s -H "Authorization: Bearer $TOKEN" "$API_BASE/$1"}api_call "users"api_call "products"4. 日志和监控# 记录请求日志curl -v https://api.example.com 2>&1 | tee request.log# 结构化日志curl -w "$(date '+%Y-%m-%d %H:%M:%S') | URL: %{url_effective} | Status: %{http_code} | Time: %{time_total}s\n" \ -o /dev/null -s https://api.example.com >> api.log# 监控脚本#!/bin/bashwhile true; do STATUS=$(curl -w "%{http_code}" -o /dev/null -s https://api.example.com/health) echo "$(date): $STATUS" [ "$STATUS" != "200" ] && echo "Alert: API unhealthy!" | mail -s "API Alert" admin@example.com sleep 60done性能对比表| 优化项 | 优化前 | 优化后 | 提升 || ------ | ------ | ---------- | ------ || 连接复用 | 每次新建连接 | Keep-Alive | 30-50% || 压缩传输 | 原始大小 | Gzip 压缩 | 60-80% || 并发请求 | 串行执行 | 并行处理 | 3-5倍 || DNS 缓存 | 每次解析 | 缓存结果 | 10-20% || 断点续传 | 重新下载 | 续传 | 节省带宽 |完整优化示例#!/bin/bash# 生产级 API 调用脚本# 配置API_URL="https://api.example.com/v1/data"TOKEN="${API_TOKEN:-$(cat ~/.api_token)}"TIMEOUT=30RETRY=3# 调用函数optimized_call() { curl -s -S \ --connect-timeout 10 \ --max-time "$TIMEOUT" \ --retry "$RETRY" \ --retry-delay 2 \ --compressed \ --tlsv1.2 \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -H "User-Agent: MyApp/1.0" \ -w "\n{\"status\":${http_code},\"time\":${time_total},\"size\":${size_download}}\n" \ "$@"}# 执行response=$(optimized_call "$API_URL")# 处理响应if [ $? -eq 0 ]; then echo "Success: $response" | jq '.'else echo "Error: Request failed" exit 1fi​
阅读 0·3月7日 19:38

cURL 如何实现文件上传功能?

文件上传是 cURL 的重要功能,支持多种上传方式,包括表单上传、二进制上传、多文件上传等。基本文件上传使用 -F 或 --form 参数进行表单方式上传:# 上传单个文件curl -X POST https://api.example.com/upload \ -F "file=@/path/to/file.pdf"# 指定 MIME 类型curl -X POST https://api.example.com/upload \ -F "file=@/path/to/image.png;type=image/png"# 指定服务器接收的文件名curl -X POST https://api.example.com/upload \ -F "file=@/path/to/local.txt;filename=uploaded.txt"多文件上传# 上传多个文件curl -X POST https://api.example.com/upload \ -F "file1=@/path/to/file1.pdf" \ -F "file2=@/path/to/file2.jpg" \ -F "file3=@/path/to/file3.txt"# 使用数组形式上传多个文件curl -X POST https://api.example.com/upload \ -F "files[]=@/path/to/file1.pdf" \ -F "files[]=@/path/to/file2.jpg"# 混合文件和表单数据curl -X POST https://api.example.com/submit \ -F "name=张三" \ -F "email=zhangsan@example.com" \ -F "avatar=@/path/to/avatar.jpg" \ -F "resume=@/path/to/resume.pdf"二进制文件上传# 使用 --data-binary 上传原始二进制数据curl -X POST https://api.example.com/upload \ -H "Content-Type: application/octet-stream" \ --data-binary @/path/to/file.bin# 从标准输入读取cat file.bin | curl -X POST https://api.example.com/upload \ -H "Content-Type: application/octet-stream" \ --data-binary @-# 上传并显示进度curl -X POST https://api.example.com/upload \ -F "file=@/path/to/large.zip" \ --progress-barBase64 编码上传# 将文件编码为 Base64 后上传curl -X POST https://api.example.com/upload \ -H "Content-Type: application/json" \ -d "{\"file\":\"$(base64 -w 0 /path/to/file.pdf)\",\"filename\":\"document.pdf\"}"分块上传(大文件)# 上传大文件并显示进度curl -X POST https://api.example.com/upload \ -F "file=@/path/to/large_file.zip" \ -H "Authorization: Bearer token123" \ --progress-bar | tee upload.log# 断点续传(需要服务器支持)curl -C - -X POST https://api.example.com/upload \ -F "file=@/path/to/large_file.zip"上传到云存储# AWS S3 上传curl -X PUT "https://bucket.s3.amazonaws.com/file.pdf" \ -H "Content-Type: application/pdf" \ -H "Authorization: AWS4-HMAC-SHA256 ..." \ --data-binary @/path/to/file.pdf# 使用预签名 URL 上传curl -X PUT "https://presigned-url-here" \ -H "Content-Type: application/pdf" \ --data-binary @/path/to/file.pdf关键参数说明| 参数 | 作用 | 示例 || --------------- | ---------- | ------------------------------------- || -F 或 --form | 表单上传 | -F "file=@path" || @ | 读取文件 | @/path/to/file || ;type= | 指定 MIME 类型 | file=@img.png;type=image/png || ;filename= | 指定文件名 | file=@local.txt;filename=remote.txt || --data-binary | 二进制上传 | --data-binary @file.bin || -C - | 断点续传 | -C - |完整上传示例# 带认证和元数据的完整上传curl -X POST https://api.example.com/v1/files/upload \ -H "Authorization: Bearer your_token" \ -H "X-Upload-Category: documents" \ -F "file=@/path/to/document.pdf" \ -F "metadata={\"title\":\"合同文档\",\"tags\":[\"legal\",\"contract\"]};type=application/json" \ --progress-bar \ -o response.json# 查看上传结果cat response.json | jq常见问题解决# 问题 1:文件路径错误# 解决:使用绝对路径或确认相对路径正确# 问题 2:权限不足# 解决:检查文件读取权限ls -l /path/to/file# 问题 3:上传大小限制# 解决:分块上传或联系服务器管理员# 问题 4:超时# 解决:增加超时时间curl --max-time 600 -F "file=@large.zip" https://api.example.com/upload​
阅读 0·3月7日 19:37

如何使用 cURL 进行 API 调试和排错?

调试和排错是 cURL 的重要应用场景。掌握调试技巧能快速定位网络请求问题、API 故障和性能瓶颈。基本调试参数# 显示详细信息(最常用)curl -v https://api.example.com# 仅显示响应头curl -I https://api.example.com# 显示响应头和内容curl -i https://api.example.com# 静默模式(不显示进度)curl -s https://api.example.com# 显示错误信息curl -S https://api.example.com详细输出模式# -v 显示完整的请求和响应过程curl -v https://api.example.com/users# 输出说明:# > 表示发送的请求行和请求头# < 表示接收的响应头# * 表示连接和 SSL 握手信息# 更详细的调试信息curl --trace-ascii debug.log https://api.example.com# 十六进制格式输出curl --trace debug.hex https://api.example.com响应时间分析# 显示传输统计信息curl -w "DNS: %{time_namelookup}s\nConnect: %{time_connect}s\nTTFB: %{time_starttransfer}s\nTotal: %{time_total}s\n" \ -o /dev/null -s https://api.example.com# 完整的性能分析curl -w "DNS解析: %{time_namelookup}s\nTCP连接: %{time_connect}s\nSSL握手: %{time_appconnect}s\n首字节: %{time_starttransfer}s\n总时间: %{time_total}s\n下载大小: %{size_download}bytes\n下载速度: %{speed_download}bytes/s\n" \ -o /dev/null -s https://api.example.com# 输出到文件curl -w "@curl-format.txt" -o /dev/null -s https://api.example.com常用调试变量| 变量 | 说明 || -------------------- | ------------ || time_namelookup | DNS 解析时间 || time_connect | TCP 连接时间 || time_appconnect | SSL/SSH 握手时间 || time_starttransfer | 首字节时间(TTFB) || time_total | 总时间 || size_download | 下载大小 || speed_download | 下载速度 || http_code | HTTP 状态码 |错误排查技巧# 1. 检查 HTTP 状态码curl -w "\nHTTP Status: %{http_code}\n" -o /dev/null -s https://api.example.com# 2. 检查重定向链curl -L -v https://example.com 2>&1 | grep -E "(< HTTP|< Location)"# 3. 检查 SSL 证书curl -v https://api.example.com 2>&1 | grep -A 10 "SSL connection"# 4. 忽略 SSL 证书验证(仅测试用)curl -k https://self-signed.badssl.com# 5. 设置超时时间curl --connect-timeout 5 --max-time 10 https://api.example.com# 6. 重试机制curl --retry 3 --retry-delay 2 https://api.example.com网络问题诊断# 测试连接性curl -v telnet://example.com:80# 检查代理设置curl -v --proxy http://proxy.example.com:8080 https://api.example.com# 指定 DNS 服务器curl --dns-servers 8.8.8.8 https://api.example.com# 强制使用 IPv4curl -4 https://api.example.com# 强制使用 IPv6curl -6 https://api.example.com# 查看路由追踪curl -v --trace-time https://api.example.com完整调试脚本#!/bin/bash# API 调试脚本URL="https://api.example.com/users"TOKEN="your_token_here"echo "========== 请求信息 =========="echo "URL: $URL"echo "Time: $(date)"echo ""echo "========== 详细请求过程 =========="curl -v -X GET "$URL" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ 2>&1echo ""echo "========== 性能指标 =========="curl -w "DNS解析: %{time_namelookup}s\nTCP连接: %{time_connect}s\nSSL握手: %{time_appconnect}s\n首字节: %{time_starttransfer}s\n总时间: %{time_total}s\nHTTP状态: %{http_code}\n" \ -o /dev/null -s "$URL" \ -H "Authorization: Bearer $TOKEN"echo ""echo "========== 响应内容 =========="curl -s "$URL" -H "Authorization: Bearer $TOKEN" | jq '.'常见问题排查清单# 1. 连接超时curl --connect-timeout 10 https://api.example.com# 2. 读取超时curl --max-time 30 https://api.example.com# 3. DNS 解析问题curl --resolve example.com:443:192.168.1.100 https://example.com# 4. 证书问题curl --cacert /path/to/ca.crt https://api.example.com# 5. 编码问题curl -H "Accept-Charset: UTF-8" https://api.example.com# 6. 压缩传输curl --compressed https://api.example.com日志记录# 保存完整调试日志curl -v https://api.example.com > response.txt 2>&1# 分别保存请求和响应curl -v https://api.example.com \ --trace-ascii request-trace.txt \ -o response-body.txt# 时间戳日志curl --trace-time -v https://api.example.com 2>&1 | tee debug.log​
阅读 0·3月7日 19:37