深入解析B站androidApp接口:从bilibili.api.ticket.v1.Ticket/GetTicket到SendMsg的技术分析
前言
最近一段时间,我对B站的App接口进行了深入分析,特别是关注了认证机制和私信功能的实现。通过逆向工程和网络抓包,发现了B站移动端API的底层工作原理,包括设备标识生成机制、认证流程和消息传输协议。本文将分享这些研究成果,希望能对API安全设计和防护提供一些思考。
B站接口的基本架构
B站的移动端API采用了gRPC作为主要通信协议,这与普通的REST API有较大区别。gRPC使用Protocol Buffers(protobuf)进行数据序列化,具有更高的效率和更严格的类型检查。
gRPC请求结构
B站的API请求通常包含以下几个关键部分:
[压缩标志(1字节)][消息长度(4字节)][Protobuf消息体]
- 压缩标志:通常是0(不压缩)或1(gzip压缩)
- 消息长度:大端序的4字节整数,表示消息体的长度
- 消息体:使用protobuf编码的实际数据
例如,一个典型的请求可能是:
00 00 00 00 52 0A 2A 08 88 F3 EC 8A 01 10 01 18 E4 C7 A0 85 01 20 E9 8D FF E7 07 28 01 32 0F 7B 22 63 6F 6E 74 65 6E 74 22 3A 22 32 22 7D 80 01 01 2A 24 65 65 62 35 35 63 38 37 2D 66 32 36 34 2D 34 39 64 33 2D 61 61 39 62 2D 63 37 36 34 39 66 36 31 39 34 33 38
其中:
00- 不使用压缩00 00 00 52- 消息长度为82字节- 剩余部分 - protobuf编码的消息体
设备标识机制深度解析
BUVID生成机制
BUVID (Bilibili Unique Video ID) 是B站用来唯一标识设备的关键值,其生成过程如下:
def generate_buvid(device_id, buvid_type):"""生成BUVID (B站设备唯一标识)参数:device_id: 设备ID (根据buvid_type的不同可以是AndroidID、MAC等)buvid_type: BUVID类型 (XX代表Android ID, XY代表MAC地址)"""# 预处理device_idif buvid_type == BUVIDType.MAC:device_id = device_id.replace(":", "")# 计算device_id的MD5值并转为大写id_md5 = hashlib.md5(device_id.encode('utf-8')).hexdigest().upper()# ..............(敏感信息脱敏处理)# 最终BUVID: 类型前缀 + ID_E + MD5buvid = buvid_type + id_e + id_md5return buvid
BUVID的格式为:XX/XY + 3位特征码 + 32位MD5,共37位字符。
设备指纹(fp_local)生成与BUVID的关系
设备指纹(fp_local)与BUVID密切相关,通常用于二次验证设备身份。fp_local的生成依赖于BUVID,同时也考虑了设备型号和无线电版本信息:
def generate_fp(buvid, device_model, device_radio):"""根据BUVID生成设备指纹"""# 1. 构建基础字符串并计算MD5base_str = buvid + device_model + device_radiomd5_hex = hashlib.md5(base_str.encode('utf-8')).hexdigest()# 2. 添加时间戳time_str = datetime.now().strftime("%Y%m%d%H%M%S")# 3. 添加随机字符串(16位十六进制)random_hex = ''.join(random.choice('0123456789abcdef') for _ in range(16))# 4. 合并所有部分fp_base = md5_hex + time_str + random_hex# 5. 计算校验和,这里是关键部分。所以随机生成并不能通过验证calculate_checksum就不公布了checksum = calculate_checksum(fp_base)# 6. 返回完整指纹return fp_base + checksum
关键点:
- fp_local的首32位是由BUVID、设备型号和无线电版本共同决定的MD5值
- 接下来14位是生成时的时间戳
- 再加上16位随机数据
- 最后2位是校验和
BUVID与fp_local的关系验证:
def verify_fp(buvid, fp, device_model, device_radio):"""验证FP是否与BUVID匹配"""# 1. 提取FP中的MD5部分(前32个字符)fp_md5 = fp[:32]# 2. 计算预期的MD5base_str = buvid + device_model + device_radioexpected_md5 = hashlib.md5(base_str.encode('utf-8')).hexdigest()# 3. 验证MD5部分是否匹配if fp_md5 != expected_md5:return False# 4. 验证校验和fp_base = fp[:-2]expected_checksum = calculate_checksum(fp_base)actual_checksum = fp[-2:]# 5. 返回校验和是否匹配return expected_checksum == actual_checksum
这种设计确保了:
- 设备更换后无法保持相同的指纹
- 服务器可以验证设备指纹的真实性
- 可以检测设备信息的篡改
Ticket认证机制分析
JWT格式的Ticket结构
Ticket采用JWT(JSON Web Token)格式,由三部分组成:Header、Payload和Signature。
典型的B站Ticket如下:
eyJhbGciOiJIUzI1NiIsImtpZCI6InMwMyIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NDQ2NTYxNjcsImlhdCI6MTc0NDYyNzA2NywiYnV2aWQiOiJYVUY4MjRFRkQ3NjUyNTE5NzhCOEIyNzlEMDYyODNFQkQ1OTZFIn0.flJFBus6TltpIlD_byS2bM0kzXyQe0o-5ndOnrtuTOc
解析后:
- Header:
{"alg":"HS256","kid":"s03","typ":"JWT"} - Payload:
{"exp":1744656167,"iat":1744627067,"buvid":"XUF824EFD765251978B8B279D06283EBD596E"} - Signature: HMAC-SHA256签名
Ticket获取请求的构造
获取Ticket的请求较为复杂,涉及多层嵌套的protobuf消息和签名计算:
def create_ticket_request(self, device_bin):"""创建Ticket请求数据"""# 创建请求数据request_data = bytearray()# 创建x-fingerprint的值fingerprint_value = self.create_fingerprint_value()# 添加字段1: context (x-fingerprint)# 添加字段1: context (x-exbadbasket)# 将两个context条目添加到请求中# 添加字段2: key_id = "ec01"# 添加字段3: sign# 压缩数据compressed_data = gzip.compress(bytes(request_data))# 构造gRPC消息# ----------- 此处省略return bytes(grpc_message)
签名计算的安全性
签名计算是认证系统的核心安全机制:
def calculate_app_sign(self, device_bin, fingerprint_value, exbadbasket_value=b''):"""计算应用签名"""# 签名密钥key = b'E2lc5tgtl' # 注:此处为示例密钥,非真实值# 将base64编码的device_bin解码device_bin_data = base64.b64decode(device_bin)# 创建HMAC对象h = hmac.new(key, digestmod=hashlib.sha256)# 按特定顺序更新数据# 此处脱敏处理,省略# 获取十六进制摘要return h.hexdigest()
Protobuf消息的构造与解析
protobuf字段类型
protobuf编码中,每个字段都由标签和值组成:
- 标签:
(field_number << 3) | wire_type - 值:根据wire_type决定编码方式
常见的wire_type:
- 0: Varint (int32, int64, bool等)
- 1: 64-bit (fixed64, double等)
- 2: Length-delimited (string, bytes, embedded messages等)
- 5: 32-bit (fixed32, float等)
手动构造protobuf消息
没有.proto定义文件时,我们需要手动构造protobuf消息,当然你也可以用现成的库去处理:
def append_tag(self, buf, field_number, wire_type):"""添加字段标签"""tag = (field_number << 3) | wire_typeself.append_varint(buf, tag)def append_varint(self, buf, value):"""添加varint类型的值"""while value >= 0x80:buf.append((value & 0x7f) | 0x80)value >>= 7buf.append(value & 0x7f)def append_string(self, buf, value):"""添加字符串类型字段"""encoded = value.encode('utf-8')self.append_varint(buf, len(encoded)) # 长度前缀buf.extend(encoded) # 字符串内容
解析protobuf消息
从二进制数据解析protobuf消息也很关键:
def parse_protobuf(data):"""解析protobuf格式数据"""result = {}try:offset = 0while offset < len(data):# 获取字段编号和类型field_and_type = data[offset]field_num = field_and_type >> 3wire_type = field_and_type & 0x07offset += 1# 基于wire_type处理不同类型的数据if wire_type == 0: # Varintvalue = 0shift = 0while True:b = data[offset]offset += 1value |= ((b & 0x7f) << shift)if not (b & 0x80):breakshift += 7result[str(field_num)] = valueelif wire_type == 2: # Length-delimitedlength = 0shift = 0while True:b = data[offset]offset += 1length |= ((b & 0x7f) << shift)if not (b & 0x80):breakshift += 7# 尝试解析为字符串、JSON或嵌套消息try:string_value = data[offset:offset+length].decode('utf-8')if string_value.startswith('{') and string_value.endswith('}'):try:json_value = json.loads(string_value)result[str(field_num)] = string_valueexcept:result[str(field_num)] = string_valueelse:result[str(field_num)] = string_valueexcept:# 嵌套消息或二进制数据nested_result = parse_protobuf(data[offset:offset+length])if nested_result:result[str(field_num)] = nested_resultelse:result[str(field_num)] = data[offset:offset+length].hex()offset += length# 处理其他wire_type...except Exception as e:print(f"Protobuf解析错误: {e}")return result
私信发送功能详解
私信消息的protobuf结构
私信消息的protobuf结构如下:
消息 {field1: { // 内部消息field1: 接收者UID (VarInt)field2: 消息类型 (VarInt)field3: 序列号 (VarInt)field4: 设备标识 (VarInt)field5: 标志位 (VarInt)field6: 消息内容JSON (String)field16: 标志位 (VarInt)}field5: 消息ID (String)
}
构造和发送私信
def create_and_send_message(self, content, receiver_uid, message_id=None):"""构造并发送B站私信消息"""# 生成消息IDif message_id is None:message_id = str(uuid.uuid4())# 创建消息数据message_data = bytearray()# 添加内部消息inner_msg = bytearray()# 添加接收者UID# 添加消息类型# 添加序列号# 添加设备标识# 添加标志位# 添加消息内容(JSON格式)# 添加标志位self.append_tag(inner_msg, 16, 0)self.append_varint(inner_msg, 1)# 将内部消息添加到外层消息self.append_tag(message_data, 1, 2)self.append_varint(message_data, len(inner_msg))message_data.extend(inner_msg)# 添加消息IDself.append_tag(message_data, 5, 2)self.append_string(message_data, message_id)# 创建gRPC消息# 准备请求头headers = {"APP-KEY": "android64","Content-Type": "application/grpc","User-Agent": "...","buvid": self.buvid,"x-bili-device-bin": self.device_bin(),"x-bili-fawkes-req-bin": self.fawkes_req_bin(),"x-bili-locale-bin": "...","x-bili-metadata-bin": self.generate_bili_metadata(),"authorization": f"identify_v1 {self.access_key}","x-bili-ticket": self.ticket# 其他必要的头信息...}# 发送请求url = "https://app.bilibili.com/bilibili.im.interface.v1.ImInterface/SendMsg"response = requests.post(url, headers=headers, data=bytes(grpc_message))return response
解析Base64编码的错误消息
B站的错误响应常常是Base64编码的protobuf消息:
def parse_base64_protobuf(base64_str):"""解析Base64编码的protobuf数据"""try:# 补全paddingpadding = len(base64_str) % 4if padding:base64_str += '=' * (4 - padding)# 解码Base64decoded_data = base64.b64decode(base64_str)# 解析protobufreturn resultexcept Exception as e:print(f"解析Base64 protobuf数据失败: {e}")return None
例如,错误消息CAISBTIxMDI2GlAKJ3R5cGUuZ29vZ2xlYXBpcy5jb20vYmlsaWJpbGkucnBjLlN0YXR1cxIlCKKkARIf5LiN6IO957uZ6Ieq5bex5Y+R6YCB5raI5oGv5ZOmfg解析后可能包含"不允许给自己发送消息"的提示。
技术要点分析
1. 多层认证机制
B站采用了多层认证策略:
- BUVID:设备唯一标识
- fp_local:基于BUVID的设备指纹
- Ticket:JWT格式的临时凭证
- access_key:长期授权令牌
这种多层机制增加了伪造身份的难度。
2. 签名验证
请求过程中,多处使用了HMAC签名来确保数据完整性和来源可靠性。例如:
- Ticket请求中对device_bin和fingerprint_value进行签名
- JWT格式的Ticket本身也包含签名
3. 设备指纹算法
设备指纹(fp_local)的生成算法具有以下特点:
- 基于设备特征(BUVID、型号、无线电版本)
- 包含时间戳,允许追踪指纹生成时间
- 添加校验和,验证数据完整性
- 部分随机化,防止完全预测
4. protobuf格式的优势利用
B站充分利用了protobuf的优势:
- 高效的序列化/反序列化
- 严格的类型检查
- 二进制格式难以直接分析和修改
- 版本兼容性好
5. 协议头中各个值的算法
Ascii 类
user-agent 客户端 UA, 必需.
device_model 设备 Model
device_build 设备 Build
app_ver APP 版本号
mobi_app APP 包类型
app_build APP 版本号
app_build_inner APP 版本号(内部)
x-bili-gaia-vtoken 暂时留空.
x-bili-aurora-eid 未登录留空. 必需.
x-bili-mid 用户 UID, 未登录默认为 0. 必需.
x-bili-aurora-zone 留空. 必需.
x-bili-trace-id 如 16e903399574695df75be114ff63ac64:f75be114ff63ac64:0:0. 需要算法处理. 必需.
authorization 鉴权, 登录时设定为 identify_v1 {access_key}, 未登录时无需此项.
buvid 设备唯一标识, 有自己的一套算法.
bili-http-engine cronet
te trailers
Binary 类
x-bili-fawkes-req-bin 设备 Fawkes 信息,加密信息,必须
x-bili-metadata-bin 使用 Metadata 生成. 加密信息,必须
x-bili-device-bin 设备信息, 加密信息,必须
x-bili-network-bin 设备网络信息, 加密信息,必须
x-bili-restriction-bin 限制信息, 加密信息,必须
x-bili-locale-bin 设备区域信息,加密信息,必须
x-bili-exps-bin 加密信息,必须
安全漏洞与防范建议
通过分析,我发现了几个潜在的安全问题及其防范措施:
1. 设备模拟防范
问题:通过分析可以伪造设备信息,包括BUVID和指纹。
防范措施:
- 增加设备特征采集,如硬件序列号、系统指纹等
- 引入设备行为特征分析,识别异常行为模式
- 实施设备绑定策略,限制账号可用设备数量
- 定期更新设备指纹算法,增加逆向难度
2. 签名密钥保护
问题:客户端存储的签名密钥可能被提取。
防范措施:
- 使用白盒加密技术保护客户端密钥
- 实施密钥分散存储和动态派生
- 定期轮换密钥
- 服务端增加额外验证,不完全依赖客户端签名
3. Protobuf结构保护
问题:通过逆向工程可以分析出protobuf结构。
防范措施:
- 混淆字段名和字段编号
- 定期更新协议结构
- 添加冗余或诱饵字段
- 对关键字段进行额外加密
4. JWT安全加固
问题:JWT可能面临重放攻击或篡改。
防范措施:
- 缩短Token有效期
- 实施Token绑定(将Token与特定会话或设备绑定)
- 使用更强的签名算法(如ES256而非HS256)
- 服务端维护已吊销Token列表
5. 请求频率限制
问题:可能出现API滥用。
防范措施:
- 实施基于账号和设备的请求频率限制
- 为敏感操作增加验证码或其他人机验证
- 监控异常请求模式并实施自动封禁
- 对同一设备的多账号操作进行关联分析
实践经验与优化方向
代码优化
在研究过程中,我发现以下编码实践更有效:
# 更清晰的protobuf构造
def create_message(receiver_id, content):msg = bytearray()# 使用辅助函数增加可读性add_varint_field(msg, 1, receiver_id)add_string_field(msg, 6, json.dumps({"content": content}))return msg
调试技巧
分析和调试protobuf消息:
def debug_protobuf(hex_data):"""将十六进制数据解析为人类可读的形式"""data = binascii.unhexlify(hex_data.replace(" ", ""))result = parse_protobuf(data)# 美化输出return json.dumps(result, indent=2, ensure_ascii=False)
结语
通过对B站App接口的深入分析,我们不仅理解了其身份验证和消息发送机制,也掌握了protobuf消息的构造和解析技术。这些知识不仅适用于B站,也可以应用到其他使用类似技术栈的应用分析中。
对于API开发者,本文揭示了现代移动应用API安全设计的多层次防护策略,以及可能的改进方向。对于研究者,则提供了一个深入理解gRPC和protobuf在实际应用中如何使用的案例。
希望本文对你了解现代移动应用的API实现有所帮助。记住,技术研究应当遵守伦理和法律边界,尊重平台和用户的权益。

本文内容仅供学习和研究使用,请勿用于任何非法或违反相关服务条款的目的。使用本文中的技术进行未授权访问或攻击行为可能违反《网络安全法》等相关法律法规,责任自负,如有需要联系作者可通过 dGcgQGludm9rZXlvdQ== (base64decode后查看联系方式) 联系我。
相关文章:
深入解析B站androidApp接口:从bilibili.api.ticket.v1.Ticket/GetTicket到SendMsg的技术分析
前言 最近一段时间,我对B站的App接口进行了深入分析,特别是关注了认证机制和私信功能的实现。通过逆向工程和网络抓包,发现了B站移动端API的底层工作原理,包括设备标识生成机制、认证流程和消息传输协议。本文将分享这些研究成果…...
#去除知乎中“盐选”付费故事
添加油猴脚本,去除知乎中“盐选”付费故事 // UserScript // name 盐选内容隐藏脚本 // namespace http://tampermonkey.net/ // version 0.2 // description 自动隐藏含有“盐选专栏”或“盐选”文字的回答卡片 // author YourName // mat…...
MATLAB脚本实现了一个转子系统的参数扫描和分岔分析
% 参数扫描范围 clc; clear; close all;S_values 500:200:20000; % 转速范围% 定义系统参数 N 5; % 质量点数量 num_nodes N; % 节点数 num_dofs_per_node 4; % 每个节点的自由度数 num_elements num_nodes-1; % 单元数 total_dofs num_nodes * num_dofs_per_node; % 总自…...
UWP发展历程
通用Windows平台(UWP)发展历程 引言 通用Windows平台(Universal Windows Platform, UWP)是微软为实现"一次编写,处处运行"的愿景而打造的现代应用程序平台。作为微软统一Windows生态系统的核心战略组成部分,UWP代表了从传统Win32应用向现代应…...
数据库相关概念,关系型数据库的核心要素,MySQL(特点,安装,环境变量配置,启动,停止,客户端连接),数据模型
目录 数据库相关概念 MySQL(特点,安装,环境变量配置,启动和停止,客户端连接) MySQL数据库的特点 Windows下安装MySQL MySQL 8.0.36(安装版) MySQL安装 配置Path环境变量 MySQ…...
Facebook隐私保护:从技术到伦理的探索
在这个数字化时代,隐私保护已成为公众关注的焦点。Facebook,作为全球最大的社交媒体平台之一,其用户隐私保护问题更是引起了广泛的讨论。本文将从技术层面和伦理层面探讨 Facebook 在隐私保护方面的努力和挑战。 技术层面的隐私保护 在技术…...
三维点拟合平面ransac c++
理论 平面的一般定义 在三维空间中,一个平面可以由两个要素唯一确定: 法向量 n(a,b,c):垂直于平面的方向 平面上一点 平面上任意一点 p(x,y,z) 满足: ( p − p 0 ) ∗ n 0 (p - p0) * n 0 (p−p0)∗n0 即 a ( x − x 0 ) …...
香港服务器CPU对比:Intel E3与E5系列核心区别与使用场景
香港服务器的 CPU 配置(核心数与主频)直接决定了其并发处理能力和数据运算效率,例如高频多核处理器可显著提升多线程任务响应速度。在实际业务场景中,不同负载需求对 CPU 架构的要求存在显著差异——以 Intel E3 和 E5 系列为例,由于两者在性…...
ChatGPT-o3辅助学术大纲效果如何?
目录 1 引言 2 背景综述 2.1 自动驾驶雷达感知 2.2 生成模型演进:从 GAN 到 Diffusion 3 相关工作 3.1 雷达点云增强与超分辨率 3.2 扩散模型在数据增广中的应用 4 方法论 4.1 问题定义与总览 4.2 数据预处理与雷达→体素表示 4.3 潜在体素扩散网络&…...
AI大模型API文档的核心内容概述,以通用框架和典型实现为例
以下是AI大模型API文档的核心内容概述,以通用框架和典型实现为例: 一、API基础架构 1. 基础信息 API类型:RESTful API或gRPC(如阿里云通义千问支持HTTPS接口)请求方式:通常为POST方法基础URL:…...
使用pnpm第一次运行项目报错 ERR_PNPM_NO_PKG_MANIFEST No package.json found in E:\
开始用unibestpnpm写一个小程序 运行pnpm init报错 如标题所示没有package.json这个文件 博主犯了一个很愚蠢的错误。。 准备方案手动创建一个json文件 此时才发现没到根目录下,创建了一个项目之后就没有切入文件夹里。 切入根目录再下载就成功啦...
单线服务器有什么优点
单线服务器是一个普遍存在的术语,它是指一种服务器连接互联网时只使用一个物理线路的服务器。简单来说,就是使用一条网络线路的服务器,上传和下载的数据都通过一个通道实现。在当今数字化的时代,服务器的选择至关重要。今天&#…...
手持式三维扫描设备赋能智能汽车制造
随着电动化与智能化趋势的加速,传统逆向工程手段已难以满足复杂零部件的建模需求。 3D逆向建模技术,为汽车制造企业提供高效、精准的数字化解决方案。 传统汽车零部件的尺寸检测与建模依赖三坐标测量机(CMM)或人工测绘&#…...
FA-YOLO:基于FMDS与AGMF的高效目标检测算法解析
本文《FA-YOLO: Research On Efficient Feature Selection YOLO Improved Algorithm Based On FMDS and AGMF Modules》针对YOLO系列在特征融合与动态调整上的不足,提出两种创新模块:FMDS(细粒度多尺度动态选择模块)和AGMF(自适应门控多分支聚焦融合模块)。论文结构…...
Hutool之DateUtil:让Java日期处理变得更加简单
前言 在Java开发中,日期和时间的处理是一个常见问题。为了简化这个过程,许多开发者会使用第三方工具包,如Hutool。Hutool是一个Java工具包,提供了许多实用的功能,其中之一就是日期处理。日期时间工具类是Hutool的核心包…...
Ambari 中移除/重装 yarn 集群中的 NodeManager 节点
文章目录 背景分析解决分析:现有 NodeManager 情况移除:240 服务器上的 NodeManager重新安装:240 服务器上的安装 NodeManager疑问为什么直接添加就可以运行?参考背景 项目中有Spark应用,主要在 yarn 集群中部署。 现在发现 yarn 集群中的节点资源过剩,需要将部分节点移…...
小程序在 skyline 下如何开启多行省略
参考:https://developers.weixin.qq.com/community/develop/doc/000a648baacca06e83f1034d66c000 前言 小程序在 skyline 下不支持 line-clamp,想要开启多行省略使用 text 组件的 max-lines 结合 overflow 属性。 解决办法:skyline 下不支…...
uni.createInnerAudioContext踩坑duration在真机环境一直为0
解决 uni.createInnerAudioContext 的 duration 在真机环境一直为 0 的问题 在使用 uni.createInnerAudioContext 播放音频时,开发者可能会遇到以下问题: duration 在真机环境中一直为 0:即使音频文件是正常的,duration 属性也无法正确获取音频的时长。音频实例未放到全局…...
《MySQL:MySQL数据类型分类》
数据类型分类 数值类 tinyint类型 数值越界测试。 在MySQL中,整型可以指定是有符号的和无符号的,默认是有符号的。 可以通过UNSIGNED来说明某个字段是无符号的。 无符号整型数值越界测试。 如果我们向mysql特定的类型中插入不合法的数据,my…...
Kubernetes》》k8s》》Namespace
Namespace 概述 Namespace(命名空间) 是 Kubernetes 中用于逻辑隔离集群资源的机制,可将同一集群划分为多个虚拟环境,适用于多团队、多项目或多环境(如开发、测试、生产)的场景。 核心作用: 资…...
ZYNQ笔记(八):UART 串口中断
版本:Vivado2020.2(Vitis) 任务:UART串口中断实验,实现串口中断数据回环(接收数据并发送出去) 目录 一、介绍 二、硬件设计 三、软件设计 四、效果 一、介绍 ZYNQ 的 UART(Unive…...
vue3 nprogress 使用
nprogress 介绍与作用 1.nprogress 是一个轻量级的进度条组件,主要用于在页面加载或路由切换时显示一个进度条,提升用户体验。它的原理是通过在页面顶部创建一个 div,并使用 fixed 定位来实现进度条的效果 2.在 Vite Vue 3 项目中…...
相比其他缓存/内存数据库(如 Memcached, Ehcache 等),Redis 在微服务环境中的优势和劣势是什么?
我们来比较一下 Redis 与 Memcached、Hazelcast、Ehcache 等在微服务环境下的优势和劣势。 Redis 的优势 : 丰富的数据结构 (Rich Data Structures): 优势: 这是 Redis 最显著的优势之一。除了简单的 Key-Value (字符串) 外,Redis 还原生支持 Lists, Sets, Sorted …...
生态篇|多总线融合与网关设计
引言 1. 车内多总线概览 2. 主流车载总线技术对比 3. 网关设计原则与架构 4. 协议转换与映射策略 5. 安全与诊断功能集成...
Node做BFF中间层架构优化前端开发体验并提升系统整体性能。
文章目录 1. BFF 层的定位2. 技术选型3. 架构设计3.1 分层设计3.2 示例架构 4. 核心功能实现4.1 数据聚合4.2 权限校验4.3 缓存优化 5、实战示例1. 场景说明2. ECharts 数据格式要求3. BFF 层实现步骤3.1 接收前端参数3.2 调用后端服务获取数据 4. 前端使用 总结 在使用 Node.j…...
基于autoware1.14的实车部署激光雷达循迹,从建图、定位、录制轨迹巡航点、到实车运行。
1.首先安装autoware ,大家可以以下一下博客进行安装,如果缺少库什么的直接问ai安装对应的库就行。ubuntu18.04安装Autoware1.14---GPU版 最全环境配置说明_autoware1.14安装教程-CSDN博客 安装成功后运行: source install/setup.bash roslau…...
数据类型相关问题导致的索引失效 | OceanBase SQL 优化实践
背景 针对在OceanBase 论坛中遇到的一些典型SQL调优问题,进行记录与总结,分享给大家。本文介绍的事3个场景:数据类型不匹配、字符集相关属性不匹配,和过滤/联接条件上包含系统函数。 场景一:数据类型不匹配 类型不匹…...
云计算(Cloud Computing)概述——从AWS开始
李升伟 编译 无需正式介绍亚马逊网络服务(Amazon Web Services,简称AWS)。作为行业领先的云服务提供商,AWS为全球开发者提供了超过170项随时可用的服务。 例如,Adobe能够独立于IT团队开发和更新软件。通过AWS的服务&…...
UE学习记录part18
225 animation blueprint templates: generic animation blueprints 在Animation Blueprint中选择template生成动画蓝图模板 在function中选择blurprintthreadsafeupdateanimation,用于做数据的更新 先创建变量,再将变量再blueprintinitializeanimation…...
刀片服务器的散热构造方式
刀片服务器的散热构造是其高密度、高性能设计的核心挑战之一。其散热系统需在有限空间内高效处理多个刀片模块产生的集中热量,同时兼顾能耗、噪音和可靠性。以下从模块化架构、核心散热技术、典型方案对比、厂商差异及未来趋势等方面展开分析: 一、模块化散热架构 刀片服务器…...
