Service Mesh架构新技能之eBPF入门与实践

在分享这篇文章之前,先简单和大家说下背景。在之前的文章中作者分享了一些关于service mesh微服务架构的文章,在service mesh架构中需要通过sidecar代理的方式对应用容器流量进行劫持,并以此实现微服务治理相关的各种能力。但这种sidecar方式在微服务数量过多时会造成系统性能的降低,因为sidecar本质上来说,也是通过用户代码实现的网络代理来进行流量管控的。而ebpf则是一种替代sidecar的新式解决方案,它存在于操作系统的内核层级,在性能上表现更优。因此目前关于service mesh微服务架构的技术方案开始逐步趋向于使用ebpf来替代原先的像envoy这样的sidecar代理。本文的内容将详细介绍ebpf的前世今生,具体如下:

1

技术背景

eBPF 源于 BPF,本质上是处于内核中的一个高效与灵活的虚类虚拟机组件,以一种安全的方式在许多内核 hook 点执行字节码。BPF 最初的目的是用于高效网络报文过滤,经过重新设计,eBPF 不再局限于网络协议栈,已经成为内核顶级的子系统,演进为一个通用执行引擎。

开发者可基于 eBPF 开发性能分析工具、软件定义网络、安全等诸多场景。本文将介绍 eBPF 的前世今生,并构建一个 eBPF 环境进行开发实践,文中所有的代码可以在我的 GitHub[1] 中找到。

发展历史

BPF,是类 Unix 系统上数据链路层的一种原始接口,提供原始链路层封包的收发。1992 年,Steven McCanne 和 Van Jacobson 写了一篇名为《The BSD Packet Filter: A New Architecture for User-level Packet Capture[2]》的论文。在文中,作者描述了他们如何在 Unix 内核实现网络数据包过滤,这种新的技术比当时最先进的数据包过滤技术快 20 倍。

Service Mesh架构新技能之eBPF入门与实践

BPF 在数据包过滤上引入了两大革新:

一个新的虚拟机 (VM) 设计,可以有效地工作在基于寄存器结构的 CPU 之上应用程序使用缓存只复制与过滤数据包相关的数据,不会复制数据包的所有信息,这样可以最大程度地减少BPF 处理的数据

由于这些巨大的改进,所有的 Unix 系统都选择采用 BPF 作为网络数据包过滤技术,直到今天,许多 Unix 内核的派生系统中(包括 Linux 内核)仍使用该实现。tcpdump 的底层采用 BPF 作为底层包过滤技术,我们可以在命令后面增加 -d 来查看 tcpdump 过滤条件的底层汇编指令。

代码语言:javascript代码运行次数:0运行复制

$ tcpdump -d 'ip and tcp port 8080'(000) ldh      [12](001) jeq      #0x800           jt 2 jf 12(002) ldb      [23](003) jeq      #0x6             jt 4 jf 12(004) ldh      [20](005) jset     #0x1fff          jt 12 jf 6(006) ldxb     4*([14]&0xf)(007) ldh      [x + 14](008) jeq      #0x1f90          jt 11 jf 9(009) ldh      [x + 16](010) jeq      #0x1f90          jt 11 jf 12(011) ret      #262144(012) ret      #0

2014 年初,Alexei Starovoitov 实现了 eBPF(extended Berkeley Packet Filter)。经过重新设计,eBPF 演进为一个通用执行引擎,可基于此开发性能分析工具、软件定义网络等诸多场景。

eBPF 最早出现在 3.18 内核中,此后原来的 BPF 就被称为经典 BPF,缩写 cBPF(classic BPF),cBPF 现在已经基本废弃。现在,Linux 内核只运行 eBPF,内核会将加载的 cBPF 字节码透明地转换成 eBPF 再执行。

eBPF 与 cBPF

eBPF 新的设计针对现代硬件进行了优化,所以 eBPF 生成的指令集比旧的 BPF 解释器生成的机器码执行得更快。扩展版本也增加了虚拟机中的寄存器数量,将原有的 2 个 32 位寄存器增加到 10 个 64 位寄存器。

由于寄存器数量和宽度的增加,开发人员可以使用函数参数自由交换更多的信息,编写更复杂的程序。总之,这些改进使 eBPF 版本的速度比原来的 BPF 提高了 4 倍。

维度

cBPF

eBPF

内核版本

Linux 2.1.75(1997 年)

Linux 3.18(2014 年)[4.x for kprobe/uprobe/tracepoint/perf-event]

寄存器数目

2 个:A,X

10个:R0–R9,另外 R10 是一个只读的帧指针R0:eBPF 中内核函数的返回值和退出值R1 – R5:eBF 程序在内核中的参数值R6 – R9:内核函数将保存的被调用者callee保存的寄存器R10:一个只读的堆栈帧指针

寄存器宽度

32 位

64 位

存储

16 个内存位: M[0–15]

512 字节堆栈,无限制大小的 map 存储

限制的内核调用

非常有限,仅限于 JIT 特定

有限,通过 bpf_call 指令调用

目标事件

数据包、 seccomp-BPF

数据包、内核函数、用户函数、跟踪点 PMCs 等

R0:eBPF 中内核函数的返回值和退出值R1 – R5:eBF 程序在内核中的参数值R6 – R9:内核函数将保存的被调用者callee保存的寄存器R10:一个只读的堆栈帧指针

寄存器宽度32 位64 位存储16 个内存位: M[0–15]512 字节堆栈,无限制大小的 map 存储限制的内核调用非常有限,仅限于 JIT 特定有限,通过 bpf_call 指令调用目标事件数据包、 seccomp-BPF数据包、内核函数、用户函数、跟踪点 PMCs 等

2014 年 6 月,eBPF 扩展到用户空间,这也成为了 BPF 技术的转折点。正如 Alexei 在提交补丁的注释中写到:「这个补丁展示了 eBPF 的潜力」。当前,eBPF 不再局限于网络栈,已经成为内核顶级的子系统。

eBPF 与内核模块

对比 Web 的发展,eBPF 与内核的关系有点类似于 JavaScript 与浏览器内核的关系,eBPF 相比于直接修改内核和编写内核模块提供了一种新的内核可编程的选项。eBPF 程序架构强调安全性和稳定性,看上去更像内核模块,但与内核模块不同,eBPF 程序不需要重新编译内核,并且可以确保 eBPF 程序运行完成,而不会造成系统的崩溃。

维度

Linux 内核模块

eBPF

kprobes/tracepoints

支持

支持

安全性

可能引入安全漏洞或导致内核 Panic

通过验证器进行检查,可以保障内核安全

内核函数

可以调用内核函数

只能通过 BPF Helper 函数调用

编译性

需要编译内核

不需要编译内核,引入头文件即可

运行

基于相同内核运行

基于稳定 ABI 的 BPF 程序可以编译一次,各处运行

与应用程序交互

打印日志或文件

通过 perf_event 或 map 结构

数据结构

丰富性

一般丰富

入门门槛

升级

需要卸载和加载,可能导致处理流程中断

原子替换升级,不会造成处理流程中断

内核内置

视情况而定

内核内置支持

eBPF 架构

eBPF 分为用户空间程序和内核程序两部分:

用户空间程序负责加载 BPF 字节码至内核,如需要也会负责读取内核回传的统计信息或者事件详情内核中的 BPF 字节码负责在内核中执行特定事件,如需要也会将执行的结果通过 maps 或者 perf-event 事件发送至用户空间其中用户空间程序与内核 BPF 字节码程序可以使用 map 结构实现双向通信,这为内核中运行的 BPF 字节码程序提供了更加灵活的控制

eBPF 整体结构图如下:

Service Mesh架构新技能之eBPF入门与实践

用户空间程序与内核中的 BPF 字节码交互的流程主要如下:

1、使用 LLVM 或者 GCC 工具将编写的 BPF 代码程序编译成 BPF 字节码

2、使用加载程序 Loader 将字节码加载至内核

3、内核使用验证器(Verfier) 组件保证执行字节码的安全性,以避免对内核造成灾难,在确认字节码安全后将其加载对应的内核模块执行

4、内核中运行的 BPF 字节码程序可以使用两种方式将数据回传至用户空间:

maps 方式可用于将内核中实现的统计摘要信息(比如测量延迟、堆栈信息)等回传至用户空间;perf-event 用于将内核采集的事件实时发送至用户空间,用户空间程序实时读取分析。

eBPF 限制

eBPF 技术虽然强大,但是为了保证内核的处理安全和及时响应,内核中的 eBPF 技术也给予了诸多限制,当然随着技术的发展和演进,限制也在逐步放宽或者提供了对应的解决方案。

eBPF 程序不能调用任意的内核参数,只限于内核模块中列出的 BPF Helper 函数,函数支持列表也随着内核的演进在不断增加。

eBPF 程序不允许包含无法到达的指令,防止加载无效代码,延迟程序的终止。

eBPF 程序中循环次数限制且必须在有限时间内结束,这主要是用来防止在 kprobes 中插入任意的循环,导致锁住整个系统;解决办法包括展开循环,并为需要循环的常见用途添加辅助函数。Linux 5.3 在 BPF 中包含了对有界循环的支持,它有一个可验证的运行时间上限。

eBPF 堆栈大小被限制在 MAX_BPF_STACK,截止到内核 Linux 5.8 版本,被设置为 512;参见 include/linux/filter.h[3],这个限制特别是在栈上存储多个字符串缓冲区时:一个char[256]缓冲区会消耗这个栈的一半。目前没有计划增加这个限制,解决方法是改用 bpf 映射存储,它实际上是无限的。

代码语言:javascript代码运行次数:0运行复制

/* BPF program can access up to 512 bytes of stack space. */#define MAX_BPF_STACK 512

eBPF 字节码大小最初被限制为 4096 条指令,截止到内核 Linux 5.8 版本, 当前已将放宽至 100 万指令( BPF_COMPLEXITY_LIMIT_INSNS),参见:include/linux/bpf.h[4],对于无权限的BPF程序,仍然保留4096条限制 ( BPF_MAXINSNS );新版本的 eBPF 也支持了多个 eBPF 程序级联调用,虽然传递信息存在某些限制,但是可以通过组合实现更加强大的功能。

代码语言:javascript代码运行次数:0运行复制

#define BPF_COMPLEXITY_LIMIT_INSNS      1000000 /* yes. 1M insns */

2

eBPF 实战

在深入介绍 eBPF 特性之前,让我们 Get Hands Dirty,切切实实的感受 eBPF 程序到底是什么,我们该如何开发 eBPF 程序。随着 eBPF 生态的演进,现在已经有越来越多的工具链用于开发 eBPF 程序,在后文也会详细介绍:

基于 bcc 开发:bcc 提供了对 eBPF 开发,前段提供 Python API,后端 eBPF 程序通过 C 实现。特点是简单易用,但是性能较差。基于 libebpf-bootstrap 开发:libebpf-bootstrap 提供了一个方便的脚手架。基于内核源码开发:内核源码开发门槛较高,但是也更加切合 eBPF 底层原理,所以这里以这个方法作为示例。

内核源码编译

系统环境如下,采用PHP中文网 CVM,Ubuntu 20.04,内核版本 5.4.0。

代码语言:javascript代码运行次数:0运行复制

$ uname -aLinux VM-1-3-ubuntu 5.4.0-42-generic #46-Ubuntu SMP Fri Jul 10 00:24:02 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

首先安装必要依赖:

代码语言:javascript代码运行次数:0运行复制

sudo apt install -y bison build-essential cmake flex git libedit-dev pkg-config libmnl-dev    python zlib1g-dev libssl-dev libelf-dev libcap-dev libfl-dev llvm clang pkg-config    gcc-multilib luajit libluajit-5.1-dev libncurses5-dev libclang-dev clang-tools

一般情况下推荐采用 apt 方式的安装源码,安装简单而且只安装当前内核的源码,源码的大小在 200M 左右。

代码语言:javascript代码运行次数:0运行复制

# apt-cache search linux-source# apt install linux-source-5.4.0

源码安装至 /usr/src/ 目录下。

代码语言:javascript代码运行次数:0运行复制

$ ls -hltotal 4.0Kdrwxr-xr-x 4 root root 4.0K Nov  9 13:22 linux-source-5.4.0lrwxrwxrwx 1 root root   45 Oct 15 10:28 linux-source-5.4.0.tar.bz2 -> linux-source-5.4.0/linux-source-5.4.0.tar.bz2$ tar -jxvf linux-source-5.4.0.tar.bz2$ cd linux-source-5.4.0$ cp -v /boot/config-$(uname -r) .config # make defconfig 或者 make menuconfig$ make headers_install$ make modules_prepare$ make scripts     # 可选$ make M=samples/bpf  # 如果配置出错,可以使用 make oldconfig && make prepare 修复

编译成功后,可以在 samples/bpf 目录下看到一系列的目标文件和二进制文件。

Hello World

前面说到 eBPF 通常由内核空间程序和用户空间程序两部分组成,现在 samples/bpf 目录下有很多这种程序,内核空间程序以 _kern.c 结尾,用户空间程序以 _user.c 结尾。先不看这些复杂的程序,我们手动写一个 eBPF 程序的 Hello World。

内核中的程序 hello_kern.c:

代码语言:javascript代码运行次数:0运行复制

#include #include "bpf_helpers.h"#define SEC(NAME) __attribute__((section(NAME), used))SEC("tracepoint/syscalls/sys_enter_execve")int bpf_prog(void *ctx){    char msg[] = "Hello BPF from houmin!n";    bpf_trace_printk(msg, sizeof(msg));    return 0;}char _license[] SEC("license") = "GPL";

函数入口:

上述代码和普通的C语言编程有一些区别。

程序的入口通过编译器的 pragama __section(“tracepoint/syscalls/sys_enter_execve”) 指定的。入口的参数不再是 argc, argv, 它根据不同的 prog type 而有所差别。我们的例子中,prog type 是 BPF_PROG_TYPE_TRACEPOINT, 它的入口参数就是 void *ctx。

头文件:

代码语言:javascript代码运行次数:0运行复制

#include 

这个头文件的来源是kernel source header file 。它安装在 /usr/include/linux/bpf.h中。

它提供了bpf 编程需要的很多symbol。例如:

enum bpf_func_id 定义了所有的kerne helper function 的idenum bpf_prog_type 定义了内核支持的所有的prog 的类型。struct __sk_buff 是bpf 代码中访问内核struct sk_buff的接口。

等等

代码语言:javascript代码运行次数:0运行复制

#include “bpf_helpers.h”

来自libbpf ,需要自行安装。我们引用这个头文件是因为调用了bpf_printk()。这是一个kernel helper function。

程序解释:

这里我们简单解读下内核态的 ebpf 程序,非常简单:

bpf_trace_printk 是一个 eBPF helper 函数,用于打印信息到 trace_pipe (/sys/kernel/debug/tracing/trace_pipe),详见这里[5]代码声明了 SEC 宏,并且定义了 GPL 的 License,这是因为加载进内核的 eBPF 程序需要有 License 检查,类似于内核模块

加载 BPF 代码:

用户态程序 hello_user.c:

代码语言:javascript代码运行次数:0运行复制

#include #include "bpf_load.h"int main(int argc, char **argv){    if(load_bpf_file("hello_kern.o") != 0)    {        printf("The kernel didn't load BPF programn");        return -1;    }    read_trace_pipe();    return 0;}

在用户态 ebpf 程序中,解读如下:

通过 load_bpf_file 将编译出的内核态 ebpf 目标文件加载到内核通过 read_trace_pipe 从 trace_pipe 读取 trace 信息,打印到控制台中

修改 samples/bpf 目录下的 Makefile 文件,在对应的位置添加以下三行:

代码语言:javascript代码运行次数:0运行复制

hostprogs-y += hellohello-objs := bpf_load.o hello_user.oalways += hello_kern.o

重新编译,可以看到编译成功的文件:

代码语言:javascript代码运行次数:0运行复制

$ make M=samples/bpf$ ls -hl samples/bpf/hello*-rwxrwxr-x 1 ubuntu ubuntu 404K Mar 30 17:48 samples/bpf/hello-rw-rw-r-- 1 ubuntu ubuntu  317 Mar 30 17:47 samples/bpf/hello_kern.c-rw-rw-r-- 1 ubuntu ubuntu 3.8K Mar 30 17:48 samples/bpf/hello_kern.o-rw-rw-r-- 1 ubuntu ubuntu  246 Mar 30 17:47 samples/bpf/hello_user.c-rw-rw-r-- 1 ubuntu ubuntu 2.2K Mar 30 17:48 samples/bpf/hello_user.o

进入到对应的目录运行 hello 程序,可以看到输出结果如下:

代码语言:javascript代码运行次数:0运行复制

$ sudo ./hello           -102735 [001] ....  6733.481740: 0: Hello BPF from houmin!           -102736 [000] ....  6733.482884: 0: Hello BPF from houmin!           -102737 [002] ....  6733.483074: 0: Hello BPF from houmin!

代码解读

前面提到 load_bpf_file 函数将 LLVM 编译出来的 eBPF 字节码加载进内核,这到底是如何实现的呢?

经过搜查,可以看到 load_bpf_file 也是在 samples/bpf 目录下实现的,具体的参见 bpf_load.c[6]。

阅读 load_bpf_file 代码可以看到,它主要是解析 ELF 格式的 eBPF 字节码,然后调用 load_and_attach[7] 函数。

在 load_and_attach 函数中,我们可以看到其调用了 bpf_load_program 函数,这是 libbpf 提供的函数。

调用的 bpf_load_program 中的 license、kern_version 等参数来自于解析 eBPF ELF 文件,prog_type 来自于 bpf 代码里面 SEC 字段指定的类型。

代码语言:javascript代码运行次数:0运行复制

static int load_and_attach(const char *event, struct bpf_insn *prog, int size){  bool is_socket = strncmp(event, "socket", 6) == 0; bool is_kprobe = strncmp(event, "kprobe/", 7) == 0; bool is_kretprobe = strncmp(event, "kretprobe/", 10) == 0; bool is_tracepoint = strncmp(event, "tracepoint/", 11) == 0; bool is_raw_tracepoint = strncmp(event, "raw_tracepoint/", 15) == 0; bool is_xdp = strncmp(event, "xdp", 3) == 0; bool is_perf_event = strncmp(event, "perf_event", 10) == 0; bool is_cgroup_skb = strncmp(event, "cgroup/skb", 10) == 0; bool is_cgroup_sk = strncmp(event, "cgroup/sock", 11) == 0; bool is_sockops = strncmp(event, "sockops", 7) == 0; bool is_sk_skb = strncmp(event, "sk_skb", 6) == 0; bool is_sk_msg = strncmp(event, "sk_msg", 6) == 0;    //...   fd = bpf_load_program(prog_type, prog, insns_cnt, license, kern_version,         bpf_log_buf, BPF_LOG_BUF_SIZE); if (fd < 0) {  printf("bpf_load_program() err=%dn%s", errno, bpf_log_buf);  return -1; }  //...}

3

eBPF 特性

Hook Overview

eBPF 程序都是事件驱动的,它们会在内核或者应用程序经过某个确定的 Hook 点的时候运行,这些 Hook 点都是提前定义的,包括系统调用、函数进入/退出、内核 tracepoints、网络事件等。

Service Mesh架构新技能之eBPF入门与实践

如果针对某个特定需求的 Hook 点不存在,可以通过 kprobe 或者 uprobe 来在内核或者用户程序的几乎所有地方挂载 eBPF 程序。

Service Mesh架构新技能之eBPF入门与实践

Verification

With great power there must also come great responsibility.

每一个 eBPF 程序加载到内核都要经过 Verification,用来保证 eBPF 程序的安全性,主要包括:

要保证加载 eBPF 程序的进程有必要的特权级,除非节点开启了 unpriviledged 特性,只有特权级的程序才能够加载 eBPF 程序。

1、内核提供了一个配置项 /proc/sys/kernel/unprivileged_bpf_disabled 来禁止非特权用户使用 bpf(2) 系统调用,可以通过 sysctl 命令修改

2、比较特殊的一点是,这个配置项特意设计为一次性开关(one-time kill switch), 这意味着一旦将它设为 1,就没有办法再改为 0 了,除非重启内核

3、一旦设置为 1 之后,只有初始命名空间中有 CAP_SYS_ADMIN 特权的进程才可以调用 bpf(2) 系统调用 。Cilium 启动后也会将这个配置项设为 1:

代码语言:javascript代码运行次数:0运行复制

$ echo 1 > /proc/sys/kernel/unprivileged_bpf_disabled

要保证 eBPF 程序不会崩溃或者使得系统出故障。

要保证 eBPF 程序不能陷入死循环,能够 runs to completion。

要保证 eBPF 程序必须满足系统要求的大小,过大的 eBPF 程序不允许被加载进内核。

要保证 eBPF 程序的复杂度有限,Verifier 将会评估 eBPF 程序所有可能的执行路径,必须能够在有限时间内完成 eBPF 程序复杂度分析。

JIT Compilation

Just-In-Time(JIT)编译用来将通用的 eBPF 字节码翻译成与机器相关的指令集,从而极大加速 BPF 程序的执行:

与解释器相比,它们可以降低每个指令的开销。通常,指令可以 1:1 映射到底层架构的原生指令这也会减少生成的可执行镜像的大小,因此对 CPU 的指令缓存更友好特别地,对于 CISC 指令集(例如 x86),JIT 做了很多特殊优化,目的是为给定的指令产生可能的最短操作码,以降低程序翻译过程所需的空间

64 位的 x86_64、arm64、ppc64、s390x、mips64、sparc64 和 32 位的 arm 、x86_32 架构都内置了 in-kernel eBPF JIT 编译器,它们的功能都是一样的,可以用如下方式打开:

代码语言:javascript代码运行次数:0运行复制

$ echo 1 > /proc/sys/net/core/bpf_jit_enable

32 位的 mips、ppc 和 sparc 架构目前内置的是一个 cBPF JIT 编译器。这些只有 cBPF JIT 编译器的架构,以及那些甚至完全没有 BPF JIT 编译器的架构,需要通过内核中的解释器(in-kernel interpreter)执行 eBPF 程序。

要判断哪些平台支持 eBPF JIT,可以在内核源文件中 grep HAVE_EBPF_JIT:

代码语言:javascript代码运行次数:0运行复制

$ git grep HAVE_EBPF_JIT arch/arch/arm/Kconfig:       select HAVE_EBPF_JIT   if !CPU_ENDIAN_BE32arch/arm64/Kconfig:     select HAVE_EBPF_JITarch/powerpc/Kconfig:   select HAVE_EBPF_JIT   if PPC64arch/mips/Kconfig:      select HAVE_EBPF_JIT   if (64BIT && !CPU_MICROMIPS)arch/s390/Kconfig:      select HAVE_EBPF_JIT   if PACK_STACK && HAVE_MARCH_Z196_FEATURESarch/sparc/Kconfig:     select HAVE_EBPF_JIT   if SPARC64arch/x86/Kconfig:       select HAVE_EBPF_JIT   if X86_64
Service Mesh架构新技能之eBPF入门与实践

Maps

BPF Map 是驻留在内核空间中的高效 Key/Value store,包含多种类型的 Map,由内核实现其功能,具体实现可以参考我的这篇博文[8]。

Service Mesh架构新技能之eBPF入门与实践

BPF Map 的交互场景有以下几种:

BPF 程序和用户态程序的交互:BPF 程序运行完,得到的结果存储到 map 中,供用户态程序通过文件描述符访问BPF 程序和内核态程序的交互:和 BPF 程序以外的内核程序交互,也可以使用 map 作为中介BPF 程序间交互:如果 BPF 程序内部需要用全局变量来交互,但是由于安全原因 BPF 程序不允许访问全局变量,可以使用 map 来充当全局变量BPF Tail call:Tail call 是一个BPF程序跳转到另一BPF程序,BPF程序首先通过 BPF_MAP_TYPE_PROG_ARRAY 类型的 map 来知道另一个BPF程序的指针,然后调用 tail_call() 的 helper function 来执行Tail call

共享 map 的 BPF 程序不要求是相同的程序类型,例如 tracing 程序可以和网络程序共享 map,单个 BPF 程序目前最多可直接访问 64 个不同 map。

Service Mesh架构新技能之eBPF入门与实践

当前可用的通用 map 有:

BPF_MAP_TYPE_HASHBPF_MAP_TYPE_ARRAYBPF_MAP_TYPE_PERCPU_HASHBPF_MAP_TYPE_PERCPU_ARRAYBPF_MAP_TYPE_LRU_HASHBPF_MAP_TYPE_LRU_PERCPU_HASHBPF_MAP_TYPE_LPM_TRIE

以上就是Service Mesh架构新技能之eBPF入门与实践的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/33452.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年11月4日 10:36:02
下一篇 2025年11月4日 10:40:15

相关推荐

  • 比特币最近的新历史高度高于100,000美元的新兴速度受到了大量机构投资的推动

    这种进展不仅体现在价格方面,还伴随着强大的机构推动力和有利的宏观经济环境。 比特币的价格似乎并未显现出减速的迹象,继续在历史高位不断攀升,业内专家预计到2025年第四季度,潜在的上涨目标或将达到16万美元。 比特币突破了11万美元关口,为刷新历史高点创造了条件。 比特币目前的交易价格约为109,45…

    2025年12月8日
    000
  • Ruvi AI是新的Shiba INU:到2025年的100倍增长潜力

    加密货币市场正处于快速扩张阶段,并非所有项目都能跟上步伐。曾被视为模因币领军者的柴犬币(shiba inu)似乎正逐渐褪去昔日光环。 加密货币市场发展迅猛,众多项目难以同步跟进。柴犬币(Shiba Inu),作为模因币中的明星,因投资者转而青睐具备实际应用场景及长远发展潜力的项目,目前似乎正逐步失去…

    2025年12月8日
    000
  • 随着传统银行为加密付款的传统银行,Stripe Eyes Stablecoin集成

    付款巨头(giant stripe)正着手研究如何将stablecoins纳入其核心金融服务,这预示着全球支付领域正在经历一场深刻变革。 Payments Giant Stripe计划将Stablecoins与其核心金融服务相整合,这一举措象征着全球支付系统的重要进步。 据彭博社报道,Stripe的…

    2025年12月8日
    000
  • AIOZ网络宣布与NEO区块链进行战略合作

    通过此次合作,aioz成为depin解决方案供应商。 AIOZ网络已宣布与NEO区块链建立战略合作伙伴关系,将去中心化基础设施与NEO的EVM兼容Sidechain(Chain X)整合在一起。通过这一联盟,Aioz担当Depin解决方案供应商的角色。 这种结合让Aioz的去中心化服务(分割视频流、…

    2025年12月8日
    000
  • 比特币鲸在不到一周的时间内积累了20,000 BTC,增加了对BTC的赌注

    根据加密货币分析师及交易员阿里·马丁内斯(ali martinez)撰写的文章,比特币巨鲸在短短几天内购入超过20,000枚btc。 加密货币分析师兼商人阿里·马丁内斯指出,比特币巨鲸正在积极增持更多BTC,进一步增加其对全球顶级加密货币的投资。 依据分析师发布的内容,Santiment提供的数据显…

    2025年12月8日
    000
  • 哪些加密货币在2025年可以看到重大收益?

    随着加密货币市场的再度崛起,人们正积极寻找2025年最具潜力的加密货币,尤其是那些具备实用场景并拥有强劲增长前景的项目。 加密货币市场的热度持续上升,众多投资者开始关注2025年最具潜力的加密货币。这些项目通常能提供实际的应用价值,并展现出在牛市后期的强大增长潜力。 比特币突破111,000美元大关…

    2025年12月8日
    000
  • Cantor Fitzgerald通过基于黄金的树篱推出了比特币基金

    cantor fitzgerald asset management(cfam)宣布,计划推出名为cantor fitzgerald gold precogen fund,lp的投资平台,该工具将为投资者提供接触比特币的机会。 Cantor Fitzgerald Asset Management(C…

    2025年12月8日
    000
  • 在Ozak AI翻转剧本之前,Doge可以打1美元吗?

    长期以来,dogecoin(狗狗币)一直是加密货币领域备受欢迎的模因币之一,凭借其可爱的柴犬形象以及埃隆·马斯克等知名人士的支持而广受关注。 埃隆·马斯克偏爱的这种加密货币再次成为焦点,因为一些投机者预计其价格可能升至1美元。与此同时,一个相对低调的项目——Ozak AI——在预售阶段以0.003美…

    2025年12月8日
    000
  • Web3 AI的10,000x预测使其成为加密市场中的下一个大事!蒙罗(Monero

    $777,000的奖励能否与10,000倍的回报机会抗衡?4月份,shiba inu(shib)创造了超过100位新百万富翁! Shiba Inu(Shib)迅速成为加密货币爱好者热议的话题,特别是由于其创造百万富翁的巨大潜力。近期的报道指出,Shib在4月份的价格上涨帮助产生了109位新的百万富翁…

    2025年12月8日
    000
  • 波纹:XRP在SEC ETF延误和法律战斗

    xrp的交易价格低于$ 2.2,比中层布林带低约30美分。若要再次尝试回到2025年初的水平,价格需回升至高于$ 2.5。 瑞波币:XRP受SEC ETF延期及法律纠纷影响 当前,XRP的价格低于0.22美元,较之中期布林带低大约30美分。布林带是一种常用的技术工具,用于判断价格走势及支撑与阻力位。…

    2025年12月8日
    000
  • 惩罚者硬币可能很快竞争雪崩(Avax)和Chainlink(链接)

    随着加密货币市场的继续成熟,敏锐的投资者总是在寻找最有前途的加密货币,不仅提供短期的资产 随着加密货币市场的继续成熟,敏锐的投资者总是在寻找最有前途的加密货币,不仅可以提供短期增长的资产,而且还提供长期可持续性,强大的社区支持和现实世界中的实用性。 尽管诸如Avalanche(Avax)和Chain…

    2025年12月8日
    000
  • Unilabs(Unil)在初始硬币产品中粉碎了100万美元的里程碑

    在过去的几周里,以太坊(eth)和solana的价格都出现了显著的上涨。这两种加密货币的涨幅均达到了两位数。 受比特币价格激增11万美元的影响,这些加密货币的价格均有显著提升。市场专家卡莱奥和亨利等人也纷纷看好以太坊和Solana的未来走势,激励了许多交易者。 与此同时,一种新型加密货币——Unil…

    2025年12月8日
    000
  • 什么是山寨币季节指数?山寨币季节指数如何运作?山寨币季节指数全面介绍

    目录 什么是山寨币?什么是山寨币季节?什么是山寨币季节指数?山寨币季节指数如何运作山寨币季节应遵循的策略使用 Bitget Altcoin 季节指数进行更智能的交易结论 加密货币市场呈现周期性波动。虽然比特币通常是市场中的明星,但有时规模较小的数字资产(称为山寨币)的增长速度会超过比特币。这个激动人…

    2025年12月8日
    000
  • 灰度推出全新人工智能加密货币板块,涵盖20种山寨币

    知名资产管理公司灰度投资(grayscale investments)近日宣布推出一个全新的人工智能加密货币板块,专注于与ai相关的加密项目。该板块包括20种精选的山寨币,这些项目被认为在人工智能与区块链融合领域具有重要潜力。灰度此举旨在为投资者提供一个结构化的方式,以参与这一快速发展的技术交汇点。…

    2025年12月8日 好文分享
    000
  • 据Coingecko称

    加密货币市场持续迅猛发展,新项目与老牌巨头共同吸引了市场的目光。 加密货币市场热度持续攀升,伴随新项目的转型以及投资者的关注点转移。Coingecko在其最新发布的涵盖5月24日至30日当周的报告中,列出了前20个趋势硬币,展现了新兴生态系统与主流区块链平台之间引人注目的结合。 超级流动性(HYPE…

    2025年12月8日
    000
  • 渲染(RNDR)价格预测2025显示出强大的增长潜力

    rndr当前的交易价格为4.40美元,过去24小时内跌幅达2.19%。交易量显著减少,仅剩1.3086亿美元,较之前下降了31.70%。 渲染代币(RNDR)在最近一天内下跌了2.19%,现价为4.40美元。过去一周,该代币累计下跌11.55%,显示出短期内的明显下行趋势。此外,其成交量已降至20日…

    2025年12月8日
    000
  • crypto.com和for spot cro cro etf的加那利资本档案

    5月30日,crypto.com与canary capital共同向美国sec提交了史上首个现货cro etf的注册声明。 Crypto.com与Canary Capital携手创立了Canary CRO Trust,这是一款立足于美国的投资产品。 该信托旨在让机构投资者通过符合美国财务规定的商品接…

    2025年12月8日
    000
  • 币圈必备App盘点 虚拟币交易APP前十盘点

    随着加密货币市场的持续发展和壮大,投资者们需要高效且可靠的工具来管理他们的投资组合。币圈必备App为投资者提供了便捷的交易和管理平台。本文将盘点虚拟币交易APP前十名,详细介绍它们的功能和特点,帮助你更好地选择适合自己的交易工具。 Binance – 币安   币安(Binance)是全…

    2025年12月8日 好文分享
    000
  • 安币binance交易所v2.100.4官网最新版安卓版入口

    安币Binance交易所作为全球领先的数字资产交易平台,其不断更新的版本始终致力于为用户提供最优质的交易体验。最近推出的V2.100.4版本特别针对安卓用户进行了优化,使其在操作流畅度、安全性和功能丰富度上都有了显著提升。本文将详细介绍如何通过官方网站获取安币Binance交易所V2.100.4安卓…

    2025年12月8日
    000
  • Puffverse(PFVS)价格预测2025年-2030:未来能达到 1 美元吗?

    随着元宇宙和游戏市场吸引越来越多的投资者关注,puffverse (pfvs) 有望成为 gamefi 和娱乐平台的参与者。2025 年,pfvs 价格有望维持在 0.07 美元左右,潜在的上涨动力取决于接受度、游戏内经济状况以及整体市场情绪。随着平台参与度和 nft 集成度的提升,价格支撑位有望在…

    2025年12月8日
    000

发表回复

登录后才能评论
关注微信