分类: 操作系统

通过WPeMatico自动添加.

  • 从一次经历谈 TIME_WAIT 的那些事

    从一次经历谈 TIME_WAIT 的那些事

    今天来讲一讲TCP 的 TIME_WAIT 的问题。这个问题尽人皆知,不过,这次遇到的是不太一样的场景,前两天也解决了,正好写篇文章,顺便把 TIME_WAIT 的那些事都说一说。对了,这个场景,跟我开源的探活小工具 EaseProbe 有关,我先说说这个场景里的问题,然后,顺着这个场景跟大家好好说一下这个事。

    问题背景

    先说一下背景,EaseProbe 是一个轻量独立的用来探活服务健康状况的小工具,支持http/tcp/shell/ssh/tls/host以及各种中间件的探活,然后,直接发送通知到主流的IM上,如:Slack/Telegram/Discrod/Email/Team,包括国内的企业微信/钉钉/飞书, 非常好用,用过的人都说好

    这个探活工具在每次探活的时候,必须要从头开始建立整个网络链接,也就是说,需要从头开始进行DNS查询,建立TCP链接,然后进行通信,再关闭链接。这里,我们不会设置 TCP 的 KeepAlive 重用链接,因为探活工具除了要探活所远端的服务,还要探活整个网络的情况,所以,每次探活都需要从新来过,这样才能捕捉得到整个链路的情况。

    但是,这样不断的新建链接和关闭链接,根据TCP的状态机,我们知道这会导致在探测端这边出现的 TIME_WAIT 的 TCP 链接,根据 TCP 协议的定义,这个 TIME_WAIT 需要等待 2倍的MSL 时间,TCP 链接都会被系统回收,在回收之前,这个链接会占用系统的资源,主要是两个资源,一个是文件描述符,这个还好,可以调整,另一个则是端口号,这个是没法调整的,因为作为发起请求的client来说,在对同一个IP上理论上你只有64K的端口号号可用(实际上系统默认只有近30K,从32,768 到 60,999 一共 60999+1-32768=28,232,你可以通过 sysctl net.ipv4.ip_local_port_range 查看  ),如果 TIME_WAIT 过多,会导致TCP无法建立链接,还会因为资源消耗太多导致整个程序甚至整个系统异常。

    试想,如果我们以 10秒为周期探测10K的结点,如果TIME_WAIT的超时时间是120秒,那么在第60秒后,等着超时的 TIME_WAIT 我们就有可能把某个IP的端口基本用完了,就算还行,系统也有些问题。(注意:我们不仅仅只是TCP,还有HTTP协议,所以,大家不要觉得TCP的四元组只要目标地址不一样就好了,一方面,我们探的是域名,需要访问DNS服务,所以,DNS服务一般是一台服务器,还有,因为HTTPS一般是探API,而且会有网关代理API,所以链接会到同一个网关上。另外就算还可以建出站连接,但是本地程序会因为端口耗尽无法bind了。所以,现实情况并不会像理论情况那样只要四元组不冲突,端口就不会耗尽)

    为什么要 TIME_WAIT

    那么,为什么TCP在 TIME_WAIT 上要等待一个2MSL的时间?

    以前写过篇比较宏观的《TCP的那些事》(上篇下篇),这个访问在“上篇”里讲过,这里再说一次,TCP 断链接的时候,会有下面这个来来回回的过程。

    我们来看主动断链接的最后一个状态 TIME_WAIT 后就不需要等待对端回 ack了,而是进入了超时状态。这主要是因为,在网络上,如果要知道我们发出的数据被对方收到了,那我们就需要对方发来一个确认的Ack信息,那问题来了,对方怎么知道自己发出去的ack,被收到了?难道还要再ack一下,这样ack来ack回的,那什么谁也不要玩了……是的,这就是比较著名的【两将军问题】——两个将军需要在一个不稳定的信道上达成对敌攻击时间的协商,A向B派出信鸽,我们明早8点进攻,A怎么知道B收到了信?那需要B向A派出信鸽,ack说我收到了,明早8点开干。但是,B怎么知道A会收到自己的确认信?是不是还要A再确认一下?这样无穷无尽的确认导致这个问题是没有完美解的(我们在《分布式事务》一文中说过这个问题,这里不再重述)

    所以,我们只能等一个我们认为最大小时来解决两件个问题:

    1) 为了 防止来自一个连接的延迟段被依赖于相同四元组(源地址、源端口、目标地址、目标端口)的稍后连接接受(被接受后,就会被马上断掉,TCP状态机紊乱)。虽然,可以通过指定 TCP 的 sequence number 一定范围内才能被接受。但这也只是让问题发生的概率低了一些,对于一个吞吐量大的的应用来说,依然能够出现问题,尤其是在具有大接收窗口的快速连接上。RFC 1337详细解释了当 TIME-WAIT状态不足时会发生什么。TIME-WAIT以下是如果不缩短状态可以避免的示例:

    duplicate segment
    由于缩短的 TIME-WAIT 状态,后续的 TCP 段已在不相关的连接中被接受(来源

     

    2)另一个目的是确保远端已经关闭了连接。当最后一个ACK​​ 丢失时,对端保持该LAST-ACK状态。在没有TIME-WAIT状态的情况下,可以重新打开连接,而远程端仍然认为先前的连接有效。当它收到一个SYN段(并且序列号匹配)时,它将以RST应答,因为它不期望这样的段。新连接将因错误而中止:

     

    last ack
    如果远端因为最后一个 ACK​​ 丢失而停留在 LAST-ACK 状态,则打开具有相同四元组的新连接将不起作用 (来源

    TIME_WAIT 的这个超时时间的值如下所示:

    • 在 macOS 上是15秒, sysctl net.inet.tcp | grep net.inet.tcp.msl
    • 在 Linux 上是 60秒 cat /proc/sys/net/ipv4/tcp_fin_timeout

    解决方案

    要解决这个问题,网上一般会有下面这些解法

    • 把这个超时间调小一些,这样就可以把TCP 的端口号回收的快一些。但是也不能太小,如果流量很大的话,TIME_WAIT一样会被耗尽。
    • 设置上 tcp_tw_reuse 。RFC 1323提出了一组 TCP 扩展来提高高带宽路径的性能。除其他外,它定义了一个新的 TCP 选项,带有两个四字节时间戳字段。第一个是发送选项的 TCP 时间戳的当前值,而第二个是从远程主机接收到的最新时间戳。如果新时间戳严格大于为前一个连接记录的最新时间戳。Linux 将重用该状态下的现有 TIME_WAIT 连接用于出站的链接。也就是说,这个参数对于入站连接是没有任何用图的。
    • 设置上 tcp_tw_recycle 。 这个参数同样依赖于时间戳选项,但会影响进站和出站链接。这个参数会影响NAT环境,也就是一个公司里的所有员工用一个IP地址访问外网的情况。在这种情况下,时间戳条件将禁止在这个公网IP后面的所有设备在一分钟内连接,因为它们不共享相同的时间戳时钟。毫无疑问,禁用此选项要好得多,因为它会导致 难以检测诊断问题。(注:从 Linux 4.10 (commit 95a22caee396 ) 开始,Linux 将为每个连接随机化时间戳偏移量,从而使该选项完全失效,无论有无NAT。它已从 Linux 4.12中完全删除)

    对于服务器来说,上述的三个访问都不能解决服务器的 TIME_WAIT 过多的问题,真正解决问题的就是——不作死就不会死,也就是说,服务器不要主动断链接,而设置上KeepAlive后,让客户端主动断链接,这样服务端只会有CLOSE_WAIT

    但是对于用于建立出站连接的探活的 EaseProbe来说,设置上 tcp_tw_reuse 就可以重用 TIME_WAIT 了,但是这依然无法解决 TIME_WAIT 过多的问题。

    然后,过了几天后,我忽然想起来以前在《UNIX 网络编程》上有看到过一个Socket的参数,叫 <code>SO_LINGER,我的编程生涯中从来没有使用过这个设置,这个参数主要是为了延尽关闭来用的,也就是说你应用调用 close()函数时,如果还有数据没有发送完成,则需要等一个延时时间来让数据发完,但是,如果你把延时设置为 0  时,Socket就丢弃数据,并向对方发送一个 RST 来终止连接,因为走的是 RST 包,所以就不会有 TIME_WAIT 了。

    这个东西在服务器端永远不要设置,不然,你的客户端就总是看到 TCP 链接错误 “connnection reset by peer”,但是这个参数对于 EaseProbe 的客户来说,简直是太完美了,当EaseProbe 探测完后,直接 reset connection, 即不会有功能上的问题,也不会影响服务器,更不会有烦人的 TIME_WAIT 问题。

    Go 实际操作

    在 Golang的标准库代码里,net.TCPConn 有个方法 SetLinger()可以完成这个事,使用起来也比较简单:

    conn, _ := net.DialTimeout("tcp", t.Host, t.Timeout())
    
    if tcpCon, ok := conn.(*net.TCPConn); ok {
        tcpCon.SetLinger(0)
    }

    你需要把一个 net.Conn  转型成 net.TCPConn,然后就可以调用方法了。

    但是对于Golang 的标准库中的 HTTP 对象来说,就有点麻烦了,Golang的 http 库把底层的这边连接对象全都包装成私有变量了,你在外面根本获取不到。这篇《How to Set Go net/http Socket Options – setsockopt() example 》中给出了下面的方法:

    dialer := &net.Dialer{
        Control: func(network, address string, conn syscall.RawConn) error {
            var operr error
            if err := conn.Control(func(fd uintptr) {
                operr = syscall.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.TCP_QUICKACK, 1)
            }); err != nil {
                return err
            }
            return operr
        },
    }
    
    client := &http.Client{
        Transport: &http.Transport{
            DialContext: dialer.DialContext,
        },
    }

    上面这个方法非常的低层,需要直接使用setsocketopt这样的系统调用,我其实,还是想使用 TCPConn.SetLinger(0) 来完成这个事,即然都被封装好了,最好还是别破坏封闭性碰底层的东西。

    经过Golang http包的源码阅读和摸索,我使用了下面的方法:

    client := &http.Client{
        Timeout: h.Timeout(),
        Transport: &http.Transport{
          TLSClientConfig:   tls,
          DisableKeepAlives: true,
          DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
            d := net.Dialer{Timeout: h.Timeout()}
            conn, err := d.DialContext(ctx, network, addr)
            if err != nil {
              return nil, err
            }
            tcpConn, ok := conn.(*net.TCPConn)
            if ok {
              tcpConn.SetLinger(0)
              return tcpConn, nil
            }
            return conn, nil
          },
        },
      }

    然后,我找来了全球 T0p 100W的域名,然后在AWS上开了一台服务器,用脚本生成了 TOP 10K 和 20K 的网站来以5s, 10s, 30s, 60s的间隔进行探活,搞到Cloudflare 的 1.1.1.1 DNS 时不时就把我拉黑,最后的测试结果也非常不错,根本 没有 TIME_WAIT 的链接,相关的测试方法、测试数据和测试报告可以参看:Benchmark Report

    总结

    下面是几点总结

    • TIME_WAIT 是一个TCP 协议完整性的手段,虽然会有一定的副作用,但是这个设计是非常关键的,最好不要妥协掉。
    • 永远不要使用  tcp_tw_recycle ,这个参数是个巨龙,破坏力极大。
    • 服务器端永远不要使用  SO_LINGER(0),而且使用 tcp_tw_reuse 对服务端意义不大,因为它只对出站流量有用。
    • 在服务端上最好不要主动断链接,设置好KeepAlive,重用链接,让客户端主动断链接。
    • 在客户端上可以使用 tcp_tw_reuse  和 SO_LINGER(0)

    最后强烈推荐阅读这篇文章 – Coping with the TCP TIME-WAIT state on busy Linux servers

    (全文完)

    (转载本站文章请注明作者和出处 酷 壳 – CoolShell ,请勿用于任何商业用途)

    The post 从一次经历谈 TIME_WAIT 的那些事 first appeared on 酷 壳 – CoolShell.

  • 40+硅谷大佬抢投1000万美元,打造全球首个销售人员的AI操作系统

    B2B 销售正深陷效率泥潭:销售人员仅 30% 时间用于真正销售,每年浪费超 4000 亿美元生产力。AnyTeam 以 AI 原生销售操作系统破局,通过本地运行的 Account Agent、Call Companion 与 Sales Studio 三大核心模块,将繁琐任务从数小时压缩至几分钟,重新定义销售角色与工作流。

    你有没有算过,销售团队每天到底有多少时间在真正卖东西?答案可能会让你震惊:只有 30%。剩下的 70% 时间,也就是每天 4-5 个小时,都消耗在准备会议、做客户调研、制作演示文稿和跟进邮件这些琐碎事务上。更糟糕的是,新入职的销售代表需要 7-11 个月才能完全上手,而每年有 30% 的销售人员会离职。对于上市的 B2B 公司来说,每个季度用在销售团队运营上的开支占总运营成本的 25%-60%,这意味着数亿美元的开销。这不仅仅是效率问题,这是整个 B2B 行业最昂贵的运营黑洞。

    当我看到 AnyTeam 刚刚完成 1000 万美元种子轮融资的消息时,我意识到这家公司正在做一件极具颠覆性的事情:他们打造了全球第一个 AI 原生的销售操作系统。这不是又一个销售工具,而是对销售这个职业的彻底重新定义。更让我感兴趣的是,这轮融资由 SignalFire 和 Crosslink Capital 共同领投,还吸引了超过 40 位来自 Salesforce、Elastic、Snyk、ClickHouse 等公司的资深天使投资人。这些投资者都深刻理解销售的痛苦,他们的参与本身就说明了 AnyTeam 正在解决的问题有多么关键。

    全球 350 万销售人员的共同困境

    我深入研究了 B2B 销售领域的现状后发现,这个行业的效率问题已经到了不可忽视的地步。全球有超过 350 万 B2B 销售代表,他们每个人每天要花 4-5 个小时做那些与销售没有直接关系的工作。如果把这些时间乘以全球所有销售人员的薪酬,你会得到一个惊人的数字:每年超过 4000 亿美元的生产力浪费。这还只是直接成本,如果算上因为效率低下导致的客户流失、销售周期延长和收入目标未达成,实际损失可能是这个数字的好几倍。

    更让我震惊的是这个恶性循环的程度。新销售代表需要近一年时间才能真正开始产出,但平均每三个销售中就有一个会在一年内离职。这意味着很多公司投入大量资源培训的销售人员,刚刚开始创造价值就离开了。而那些留下来的销售,也在日复一日的繁琐工作中消耗热情和创造力。我认识的一位销售主管曾经跟我抱怨说,他最优秀的销售代表每天早上 8 点到公司,但直到下午 1 点才能真正开始第一个销售电话,因为之前的所有时间都用来准备资料、更新 CRM、回复邮件和制作演示文稿了。

    这种低效率不仅让销售人员痛苦,也让公司的财务状况雪上加霜。上市 B2B 公司每个季度在销售和市场营销上的支出占总运营费用的 25%-60%,这对任何一家公司来说都是巨大的负担。当董事会要求用更少的人创造更多的收入时,销售团队面临的压力就更大了。购买周期越来越长,获客成本不断攀升,但销售人员的日常工作方式却几十年没有真正改变过。这就是为什么我认为 AnyTeam 瞄准的是一个真正值得解决的巨大问题。

    传统销售工具为什么失败了

    在深入了解 AnyTeam 之前,我一直在思考一个问题:市场上已经有那么多销售工具了,从 CRM 到销售自动化平台,从数据分析工具到销售培训系统,为什么销售效率问题还是没有得到解决?答案其实很简单:这些工具从一开始就没有为真正做销售的人设计。

    我发现,传统的 GTM(上市)软件都是为管理层和运营团队打造的。CRM 系统的主要目的是跟踪销售流程和预测收入,仪表盘是为了让管理者能看到团队表现,报告系统是为了生成各种分析报告。这些工具确实给管理层提供了很好的可见性,但对于实际执行销售任务的销售代表来说,它们只是增加了更多的工作量。每次打完客户电话,销售代表都要花 20-30 分钟更新 CRM,记录会议纪要,设置后续任务。这些工具不是在帮助销售人员卖东西,而是在要求他们为管理层提供数据。

    AnyTeam 的联合创始人兼首席增长官 Jeff Yoshimura 说得很直接:”我们在与数百位销售代表交谈后发现,今天的 GTM 工具是为管理层和运营团队构建的,而不是为真正做销售的人。”这句话点出了问题的核心。Jeff 不是随便说说,他是 Zuora 的第一号员工,也是 Salesforce 最早的几百名员工之一,经历过三次 IPO。他亲眼见证了销售如何成为公司最大的开支项目,高昂的获客成本、高流失率和让 CFO 头疼的销售与市场营销费用比率。

    传统工具还有另一个致命缺陷:它们都是事后系统。销售人员必须先完成所有工作,然后再把信息输入到这些系统中。这些工具不会在销售人员准备会议时主动提供客户洞察,不会在电话会议中实时给出建议,也不会在需要创建演示文稿时自动生成相关内容。它们只是被动地等待销售人员输入数据,然后生成报告。这就像是给一个正在跑马拉松的运动员身上绑了一个沉重的背包,还期望他跑得更快。

    AnyTeam 的革命性突破

    AnyTeam 的方法完全不同。他们没有创造另一个销售工具,而是重新定义了销售人员的工作方式。他们打造的是一个 AI 原生的销售操作系统,就像 Windows 或 macOS 是电脑的操作系统一样,AnyTeam 要成为销售专业人士的工作操作系统。这个操作系统始终在线,能感知上下文,并在每次客户互动的前、中、后主动提供指导。

    让我印象最深的是 AnyTeam 的技术架构选择。与那些基于云的传统 SaaS 应用不同,AnyTeam 选择在本地设备上运行 AI。这个决策看似简单,实际上意味深长。在销售场景中,速度至关重要。当客户在视频会议中提出一个异议时,你需要立即得到相关信息和应对建议,哪怕延迟几秒钟都可能错失关键时机。通过在本地运行 AI,AnyTeam 能够提供闪电般快速的响应,与实时对话的节奏完美匹配。这种速度优势在传统的云端 AI 应用中是不可能实现的。

    AnyTeam 的产品架构由三个核心支柱组成,每一个都针对销售流程中的关键痛点。第一个是 Account Agent(客户 Agent),它能为每个潜在客户和现有客户提供全面的洞察。过去销售人员需要花 3-4 个小时在各种网站、LinkedIn、新闻网站和 CRM 之间来回切换做客户调研,现在 Account Agent 能把这个过程压缩到 3-5 分钟。更重要的是,这个 Agent 会持续监控客户动态,当你的潜在客户公司宣布新一轮融资或高管变动时,你会立即知道。不需要手动追踪,信息会自动推送给你。

    第二个支柱是 Call Companion(通话伴侣),这个功能让我想起了科幻电影中的场景。想象一下,你正在与一个重要客户开视频会议,客户突然提出了一个棘手的问题或异议。传统情况下,你可能会有些慌乱,需要快速思考如何回应。但有了 Call Companion,就像是有一个经验丰富的销售教练在你耳边低语,实时提供应对建议、相关数据和谈话要点。它会自动完成会议准备工作,在会议中提供智能指导,会议结束后还会自动生成跟进内容。整个会议生命周期的管理从原来需要 1-2 小时缩短到 3-5 分钟。

    第三个支柱是 Sales Studio(销售工作室),这是一个按需创建定制销售材料的交互式环境。销售人员经常需要创建各种内容:竞争分析、针对特定利益相关者的谈话要点、定制化演示文稿等等。这些工作过去可能需要 1-2 小时,现在 Sales Studio 能在几分钟内完成。它连接到用户的数据源和 AnyTeam 的研究能力,能够自动处理会议中的行动项目,理解你的信息传递方式,并生成真正能推进交易的材料。

    这三个支柱不是孤立运作的,而是通过与日历、邮件、CRM、Slack 和其他内部工具的集成,形成了一个完整的工作流程。AnyTeam 就像是销售人员的智能副手,始终陪伴在侧,自动化日常任务,提供实时的情境化指导,并且不断学习以持续改进。AnyTeam 的 CEO Ajay Arora 说:”我们构建 AnyTeam 是为了’把工作从工作中拿走’,将每天的销售任务从几小时缩短到几分钟,并给销售代表提供实时支持,帮助他们建立真实的客户关系。”

    为什么这个团队能成功

    我一直相信,真正能定义一个新品类的公司,不仅需要解决一个巨大的问题和拥有出色的产品,更需要深刻理解这个问题并知道如何解决它的创始人。这就是为什么我对 AnyTeam 的团队如此看好。

    CEO Ajay Arora 是一位三次创业的连续创业者,有多次成功退出经验。他最近的一家公司 BluBracket 在 2023 年被 HashiCorp 收购。Ajay 不仅是产品和工程领域的深度专家,拥有七项专利,更重要的是他构建过企业级系统,知道如何创建销售人员真正信任的工具。作为创始人,他经历过产品市场契合度确定后,销售变成最昂贵也最难预测的职能的痛苦。当你的销售团队把 70% 的时间花在行政任务上时,你就是在烧钱并错失机会。

    首席增长官 Jeff Yoshimura 可能是企业软件领域最受尊敬的 GTM 领导者之一。他帮助 Salesforce、Zuora 和 Elastic 实现了 IPO,后来又推动 Snyk 在不到三年的时间内从 3500 万美元的年度经常性收入增长到 2.15 亿美元,将公司估值推到 74 亿美元。Jeff 的经验覆盖了从种子阶段初创公司到数十亿美元规模公司的各个阶段,他亲身经历了销售效率危机如何在每个阶段表现出来。

    这两位创始人的组合非常强大。Ajay 带来了产品和技术的深度,知道如何构建销售人员实际会使用的系统。Jeff 带来了 GTM 的实战经验,理解销售流程的每一个细节和痛点。他们不是从外部观察销售问题,而是在职业生涯中反复遭遇这个问题,现在决心要彻底解决它。这种”亲身经历过痛苦”的背景,往往是创业成功的关键因素。

    AI 原生时代的操作系统思维

    我一直在思考一个问题:为什么 AnyTeam 选择将自己定位为”操作系统”而不是”工具”?这个选择背后有着深刻的战略思考。我们正处在 AI 原生时代的早期阶段,在这个时代,新应用不再只是在 SaaS 产品上添加功能,而是围绕智能自动化进行根本性的重新架构。

    就像每台电脑都有操作系统一样,我相信每个专业人士很快都会有一个为其角色专门构建的 AI 原生操作系统。销售是这个转变的完美切入点。全球有 350 万 B2B 销售代表,这个市场足够大;销售工作流程定义明确且可重复,这让 AI 有用武之地;效率低下的问题显而易见,这创造了紧迫需求;而生产力提升带来的投资回报是立竿见影的,这让决策更容易。

    AnyTeam 的边缘计算架构也解决了我在很多纯云端 AI 应用中看到的关键限制:速度不够快。当你需要实时指导时,比如在客户提出异议的那一刻提供答案,延迟可能会毁掉交易。通过在本地运行 AI,AnyTeam 能够提供与实时对话节奏匹配的闪电般快速响应。这种架构选择不仅是技术决策,更是对销售工作本质的深刻理解。

    SignalFire 的合伙人 Wayne Hu 在谈到投资 AnyTeam 的原因时说:”Ajay 和 Jeff 不只是在构建另一个销售工具,他们正在创建将定义下一代 AI 原生工作场所应用的操作系统。”这句话准确地抓住了 AnyTeam 的愿景。这不是一个点状解决方案,而是一个平台,一个基础设施,未来可能会有更多的应用和功能在这个操作系统之上构建。

    从工具到超能力的转变

    在 AI 销售领域,有很多噪音。很多公司在谈论 AI SDR(销售开发代表)和替代销售人员的 AI 化身,但我认为这些想法都误解了销售的本质。客户不想从机器人那里买东西。销售是一个深度人际互动的过程,需要同理心、判断力和建立真实关系的能力。AI 不应该替代销售人员,而应该增强他们的能力。

    AnyTeam 采取的是完全相反的方法。他们的 AI 原生桌面应用是销售代表的 AI 副手,始终在线、感知上下文、主动提供帮助。它在用户的设备上运行,连接日历、邮件、CRM、Slack 和内部工具,创建一个单一的智能销售操作系统。这就像是销售人员的终极私人助理,把几小时的繁琐工作压缩到几分钟,让销售人员能够在每次会议中都表现得敏锐、信息充分并准备好赢得客户。

    我特别欣赏 AnyTeam 提出的”全栈 AE”概念。在软件工程领域,全栈工程师指的是能够处理从前端到后端所有技术栈的开发者。类似地,全栈销售代表指的是能够独立完成从客户研究、会议准备、实时销售到内容创建的所有销售流程的专业人士。过去,这种全栈能力只有最顶尖、经验最丰富的销售人员才具备。但 AnyTeam 的目标是让每个销售代表都能拥有这种超能力。

    这种转变的意义非常深远。当销售人员从繁琐的行政任务中解放出来,他们就有更多时间和精力专注于真正重要的事情:理解客户需求、建立信任关系、提供有价值的洞察。销售不再是一场信息不对称的游戏,而是成为真正的顾问式销售。销售人员能够在每次对话中都准备充分,提供个性化的价值,并快速响应客户的每一个关切。这种转变最终会提高成交率、缩短销售周期,并建立更牢固的客户关系。

    市场反应和投资者信心

    AnyTeam 的 1000 万美元种子轮融资规模本身就说明了很多问题。在当前的融资环境下,种子轮能拿到这么多钱并不容易。但更引人注目的是投资者阵容的质量。SignalFire 和 Crosslink Capital 共同领投,SignalFire 的合伙人 Wayne Hu 加入董事会,Crosslink 的合伙人 Phil Boyer 担任董事会观察员。

    更让我印象深刻的是那 40 多位天使投资人的名单。这些投资者来自 Salesforce、Elastic、Snyk、ClickHouse、MaintainX、HarveyAI 等公司的 CEO 和高管,还有私募股权和风险投资领域的领导者。这些人不是随便投资的。他们都深刻理解销售的痛苦,很多人自己就管理过大型销售团队或者需要依赖销售团队来推动增长。他们的参与表明,AnyTeam 解决的问题是真实存在的,而且解决方案是可行的。

    Wayne Hu 在解释投资决策时说:”我们投资 AnyTeam 是因为他们正在解决 B2B 中最昂贵的问题:销售效率低下。”这个问题的规模是惊人的。如果 AnyTeam 能够将销售人员的非销售时间从 70% 降低到 40%,那将释放出巨大的生产力。对于一家拥有 100 名销售人员的公司来说,这相当于突然多了 30 名全职销售人员,而不需要支付额外的薪酬、福利或办公空间成本。

    从商业角度看,AnyTeam 的价值主张非常清晰。它能够加速新销售人员的培训时间,提高现有销售人员的生产力,降低流失率,并最终提高收入。这些都是 CEO 和 CFO 关心的核心指标。而且,与传统 SaaS 产品不同,AnyTeam 的影响是立竿见影的。销售人员从第一天开始使用就能感受到时间节省和效率提升,不需要几个月的实施和培训周期。

    这对整个销售行业意味着什么

    我深信,AnyTeam 代表的不仅仅是一个产品或公司,而是销售工作方式的根本性转变。未来的销售人员将不再是信息的搬运工或流程的执行者,而是真正的战略顾问和关系建设者。他们的价值不在于记住产品细节或整理客户信息,而在于理解客户的业务挑战并提供创造性的解决方案。

    这种转变也会改变公司对销售人员的要求和评估方式。过去,优秀的销售人员需要有出色的组织能力、对细节的关注和处理多任务的能力。但在 AI 原生时代,这些能力将由系统提供。公司会更看重销售人员的同理心、战略思维和建立关系的能力。招聘标准会改变,培训重点会改变,甚至薪酬结构也可能会改变。

    从更宏观的角度看,我认为 AnyTeam 正在开创一个新的产品类别。就像 Salesforce 在 20 年前开创了云端 CRM 类别一样,AnyTeam 可能正在定义 AI 原生销售操作系统这个全新类别。其他公司肯定会跟进,市场会变得拥挤。但作为先行者,AnyTeam 有机会设定标准、建立品牌认知,并在竞争对手进入之前占据大量市场份额。

    我也在思考这种转变对软件生态系统的影响。如果 AnyTeam 真的成为销售人员的操作系统,那么它就会成为一个平台,其他工具和应用可能会在这个平台上构建。就像 iOS 和 Android 成为移动应用的平台一样,AnyTeam 可能会成为销售工具的平台。这将创造一个生态系统效应,随着越来越多的集成和功能添加,AnyTeam 的价值会呈指数级增长。

    挑战和未来展望

    虽然我对 AnyTeam 的前景非常乐观,但我也看到一些需要克服的挑战。首先是数据隐私和安全问题。销售人员处理的很多信息都是敏感的商业数据,包括客户信息、交易细节和公司战略。虽然 AnyTeam 在本地设备上运行 AI 有助于数据安全,但企业 IT 部门仍然会对任何新工具持谨慎态度。AnyTeam 需要建立强大的安全框架和合规认证,才能赢得大企业客户的信任。

    其次是集成挑战。AnyTeam 需要与各种 CRM、邮件系统、日历工具和内部应用集成才能发挥全部价值。虽然他们已经支持主流工具,但企业环境的复杂性意味着总会有定制系统和特殊要求。建立和维护这些集成将是一个持续的工程挑战。

    第三是用户采用和行为改变。销售人员已经习惯了现有的工作方式,即使这种方式效率低下。引入一个完全不同的工作模式需要培训、支持和时间。AnyTeam 需要确保产品的学习曲线足够平缓,让销售人员能够快速上手并立即看到价值。

    尽管有这些挑战,我仍然认为 AnyTeam 处在一个完美的位置来引领这场变革。他们有经验丰富的创始团队,充足的资金,强大的投资者网络,最重要的是,他们有一个清晰的愿景和能够实现这个愿景的产品。从私有发布开始,他们有机会与早期客户密切合作,完善产品,积累案例研究,然后在公开发布时引爆市场。

    我相信,五年后回头看,我们会认为 AnyTeam 是销售工作方式转变的标志性公司之一。就像我们现在很难想象没有云端 CRM 的销售工作一样,未来的销售人员也很难想象没有 AI 操作系统的工作方式。那个 4000 亿美元的生产力黑洞将会大幅缩小,销售人员将能够把更多时间花在真正重要的事情上:理解客户、建立关系、创造价值。这不仅会让销售人员的工作更有成就感,也会让整个 B2B 商业生态系统更加高效和健康。

    本文由人人都是产品经理作者【深思圈】,微信公众号:【深思圈】,原创/授权 发布于人人都是产品经理,未经许可,禁止转载。

    题图来自Unsplash,基于 CC0 协议。

  • eBPF 介绍

    eBPF 介绍

    很早前就想写一篇关于eBPF的文章,但是迟迟没有动手,这两天有点时间,所以就来写一篇,这文章主要还是简单的介绍eBPF 是用来干什么的,并通过几个示例来介绍是怎么玩的,这个技术非常非常之强,Linux 操作系统的观测性实在是太强大了,并在 BCC 加持下变得一览无余。这个技术不是一般的运维人员或是系统管理员可以驾驭的,这个还是要有底层系统知识并有一定开发能力的技术人员才能驾驭的了的。我在这篇文章的最后给了个彩蛋。

    介绍

    eBPF(extened Berkeley Packet Filter)是一种内核技术,它允许开发人员在不修改内核代码的情况下运行特定的功能。eBPF 的概念源自于 Berkeley Packet Filter(BPF),后者是由贝尔实验室开发的一种网络过滤器,可以捕获和过滤网络数据包。

    出于对更好的 Linux 跟踪工具的需求,eBPF 从 dtrace中汲取灵感,dtrace 是一种主要用于 Solaris 和 BSD 操作系统的动态跟踪工具。与 dtrace 不同,Linux 无法全面了解正在运行的系统,因为它仅限于系统调用、库调用和函数的特定框架。在Berkeley Packet Filter  (BPF)(一种使用内核 VM 编写打包过滤代码的工具)的基础上,一小群工程师开始扩展 BPF 后端以提供与 dtrace 类似的功能集。 eBPF 诞生了。2014 年随 Linux 3.18 首次限量发布,充分利用 eBPF 至少需要 Linux 4.4 以上版本

    eBPF 比起传统的 BPF 来说,传统的 BPF 只能用于网络过滤,而 eBPF 则可以用于更多的应用场景,包括网络监控、安全过滤和性能分析等。另外,eBPF 允许常规用户空间应用程序将要在 Linux 内核中执行的逻辑打包为字节码,当某些事件(称为挂钩)发生时,内核会调用 eBPF 程序。此类挂钩的示例包括系统调用、网络事件等。用于编写和调试 eBPF 程序的最流行的工具链称为 BPF 编译器集合 (BCC),它基于 LLVM 和 CLang。

    eBPF 有一些类似的工具。例如,SystemTap 是一种开源工具,可以帮助用户收集 Linux 内核的运行时数据。它通过动态加载内核模块来实现这一功能,类似于 eBPF。另外,DTrace 是一种动态跟踪和分析工具,可以用于收集系统的运行时数据,类似于 eBPF 和 SystemTap。[1]

    以下是一个简单的比较表格,可以帮助您更好地了解 eBPF、SystemTap 和 DTrace 这三种工具的不同之处:[1]

    工具 eBPF SystemTap DTrace
    定位 内核技术,可用于多种应用场景 内核模块 动态跟踪和分析工具
    工作原理 动态加载和执行无损编译过的代码 动态加载内核模块 动态插接分析器,通过 probe 获取数据并进行分析
    常见用途 网络监控、安全过滤、性能分析等 系统性能分析、故障诊断等 系统性能分析、故障诊断等
    优点 灵活、安全、可用于多种应用场景 功能强大、可视化界面 功能强大、高性能、支持多种编程语言
    缺点 学习曲线高,安全性依赖于编译器的正确性 学习曲线高,安全性依赖于内核模块的正确性 配置复杂,对系统性能影响较大

    对比表格[1]

    从上表可以看出,eBPF、SystemTap 和 DTrace 都是非常强大的工具,可以用于收集和分析系统的运行情况。[1]

    用途

    eBPF 是一种非常灵活和强大的内核技术,可以用于多种应用场景。下面是 eBPF 的一些常见用途:[1]

    • 网络监控:eBPF 可以用于捕获网络数据包,并执行特定的逻辑来分析网络流量。例如,可以使用 eBPF 程序来监控网络流量,并在发现异常流量时进行警报。[1]
    • 安全过滤:eBPF 可以用于对网络数据包进行安全过滤。例如,可以使用 eBPF 程序来阻止恶意流量的传播,或者在发现恶意流量时对其进行拦截。[1]
    • 性能分析:eBPF 可以用于对内核的性能进行分析。例如,可以使用 eBPF 程序来收集内核的性能指标,并通过特定的接口将其可视化。这样,可以更好地了解内核的性能瓶颈,并进行优化。[1]
    • 虚拟化:eBPF 可以用于虚拟化技术。例如,可以使用 eBPF 程序来收集虚拟机的性能指标,并进行负载均衡。这样,可以更好地利用虚拟化环境的资源,提高系统的性能和稳定性。[1]

    总之,eBPF 的常见用途非常广泛,可以用于网络监控、安全过滤、性能分析和虚拟化等多种应用场景。[1]

    工作原理

    eBPF 的工作原理主要分为三个步骤:加载、编译和执行。

    eBPF 需要在内核中运行。这通常是由用户态的应用程序完成的,它会通过系统调用来加载 eBPF 程序。在加载过程中,内核会将 eBPF 程序的代码复制到内核空间。

    eBPF 程序需要经过编译和执行。这通常是由Clang/LLVM的编译器完成,然后形成字节码后,将用户态的字节码装载进内核,Verifier会对要注入内核的程序进行一些内核安全机制的检查,这是为了确保 eBPF 程序不会破坏内核的稳定性和安全性。在检查过程中,内核会对 eBPF 程序的代码进行分析,以确保它不会进行恶意操作,如系统调用、内存访问等。如果 eBPF 程序通过了内核安全机制的检查,它就可以在内核中正常运行了,其会通过通过一个JIT编译步骤将程序的通用字节码转换为机器特定指令集,以优化程序的执行速度。

    下图是其架构图。

    (图片来自:https://www.infoq.com/articles/gentle-linux-ebpf-introduction/

    在内核中运行时,eBPF 程序通常会挂载到一个内核钩子(hook)上,以便在特定的事件发生时被执行。例如,

    • 系统调用——当用户空间函数将执行转移到内核时插入
    • 函数进入和退出——拦截对预先存在的函数的调用
    • 网络事件 – 在收到数据包时执行
    • Kprobes 和 uprobes – 附加到内核或用户函数的探测器

    最后 eBPF Maps,允许eBPF程序在调用之间保持状态,以便进行相关的数据统计,并与用户空间的应用程序共享数据。一个eBPF映射基本上是一个键值存储,其中的值通常被视为任意数据的二进制块。它们是通过带有BPF_MAP_CREATE参数的bpf_cmd系统调用来创建的,和Linux世界中的其他东西一样,它们是通过文件描述符来寻址。与地图的交互是通过查找/更新/删除系统调用进行的

    总之,eBPF 的工作原理是通过动态加载、执行和检查无损编译过的代码来实现的。[1]

    示例

    eBPF 可以用于对内核的性能进行分析。下面是一个基于 eBPF 的性能分析的 step-by-step 示例:

    第一步:准备工作:首先,需要确保内核已经支持 eBPF 功能。这通常需要在内核配置文件中启用 eBPF 相关的选项,并重新编译内核。检查是否支持 eBPF,你可以用这两个命令查看 ls /sys/fs/bpflsmod | grep bpf

    第二步:写 eBPF 程序:接下来,需要编写 eBPF 程序,用于收集内核的性能指标。eBPF 程序的语言可以选择 C 或者 Python,它需要通过特定的接口访问内核的数据结构,并将收集到的数据保存到指定的位置。

    下面是一个Python 示例(其实还是C语言,用python来加载一段C程序到Linux内核)

    #!/usr/bin/python3
    
    from bcc import BPF
    from time import sleep
    
    # 定义 eBPF 程序
    bpf_text = """
    #include <uapi/linux/ptrace.h>
    
    BPF_HASH(stats, u32);
    
    int count(struct pt_regs *ctx) {
        u32 key = 0;
        u64 *val, zero=0;
        val = stats.lookup_or_init(&key, &zero);
        (*val)++;
        return 0;
    }
    """
    
    # 编译 eBPF 程序
    b = BPF(text=bpf_text, cflags=["-Wno-macro-redefined"])
    
    # 加载 eBPF 程序
    b.attach_kprobe(event="tcp_sendmsg", fn_name="count")
    
    name = {
      0: "tcp_sendmsg"
    }
    # 输出统计结果
    while True:
        try:
            #print("Total packets: %d" % b["stats"][0].value)
            for k, v in b["stats"].items():
               print("{}: {}".format(name[k.value], v.value))
            sleep(1)
        except KeyboardInterrupt:
            exit()

    这个 eBPF 程序的功能是统计网络中传输的数据包数量。它通过定义一个 BPF_HASH 数据结构来保存统计结果(eBPF Maps),并通过捕获 tcp_sendmsg 事件来实现实时统计。最后,它通过每秒输出一次统计结果来展示数据。这个 eBPF 程序只是一个简单的示例,实际应用中可能需要进行更复杂的统计和分析。

    第三步:运行 eBPF 程序:接下来,需要使用 eBPF 编译器将 eBPF 程序编译成内核可执行的格式(这个在上面的Python程序里你可以看到——Python引入了一个bcc的包,然后用这个包,把那段 C语言的程序编译成字节码加载在内核中并把某个函数 attach 到某个事件上)。这个过程可以使用 BPF Compiler Collection(BCC)工具来完成。BCC 工具可以通过命令行的方式将 eBPF 程序编译成内核可执行的格式,并将其加载到内核中。

    下面是运行上面的 Python3 程序的步骤:

    sudo apt install python3-bpfcc

    注:在Python3下请不要使用 pip3 install bcc (参看:这里

    如果你是 Ubuntu 20.10 以上的版本,最好通过源码安装(否则程序会有编译问题),参看:这里

    apt purge bpfcc-tools libbpfcc python3-bpfcc
    wget https://github.com/iovisor/bcc/releases/download/v0.25.0/bcc-src-with-submodule.tar.gz
    tar xf bcc-src-with-submodule.tar.gz
    cd bcc/
    apt install -y python-is-python3
    apt install -y bison build-essential cmake flex git libedit-dev   libllvm11 llvm-11-dev libclang-11-dev zlib1g-dev libelf-dev libfl-dev python3-distutils
    apt install -y checkinstall
    mkdir build
    cd build/
    cmake -DCMAKE_INSTALL_PREFIX=/usr -DPYTHON_CMD=python3 ..
    make
    checkinstall

    接下来,需要将上面的 Python 程序保存到本地,例如保存到文件 netstat.py。运行程序:最后,可以通过执行以下命令来运行 Python 程序:

    $ chmod +x ./netstat.py
    $ sudo ./netstat.py
    tcp_sendmsg: 29
    tcp_sendmsg: 216
    tcp_sendmsg: 277
    tcp_sendmsg: 379
    tcp_sendmsg: 419
    tcp_sendmsg: 468
    tcp_sendmsg: 574
    tcp_sendmsg: 645
    tcp_sendmsg: 29
    

    程序开始运行后,会在控制台输出网络数据包的统计信息。可以通过按 Ctrl+C 组合键来结束程序的运行。

    下面我们再看一个比较复杂的示例,这个示例会计算TCP的发包时间(示例参考于Github上 这个issue里的程序):

    #!/usr/bin/python3
    
    from bcc import BPF
    import time
    
    # 定义 eBPF 程序
    bpf_text = """
    #include <uapi/linux/ptrace.h>
    #include <net/sock.h>
    #include <net/inet_sock.h>
    #include <bcc/proto.h>
    
    struct packet_t {
        u64 ts, size;
        u32 pid;
        u32 saddr, daddr;
        u16 sport, dport;
    };
    
    BPF_HASH(packets, u64, struct packet_t);
    
    int on_send(struct pt_regs *ctx, struct sock *sk, struct msghdr *msg, size_t size)
    {
        u64 id = bpf_get_current_pid_tgid();
        u32 pid = id;
    
        // 记录数据包的时间戳和信息
        struct packet_t pkt = {}; // 结构体一定要初始化,可以使用下面的方法
                                  //__builtin_memset(&pkt, 0, sizeof(pkt)); 
        pkt.ts = bpf_ktime_get_ns();
        pkt.size = size;
        pkt.pid = pid;
        pkt.saddr = sk->__sk_common.skc_rcv_saddr;
        pkt.daddr = sk->__sk_common.skc_daddr;
        struct inet_sock *sockp = (struct inet_sock *)sk;
        pkt.sport = sockp->inet_sport;
        pkt.dport = sk->__sk_common.skc_dport;
    
        packets.update(&id, &pkt);
        return 0;
    }
    
    int on_recv(struct pt_regs *ctx, struct sock *sk)
    {
        u64 id = bpf_get_current_pid_tgid();
        u32 pid = id;
    
        // 获取数据包的时间戳和编号
        struct packet_t *pkt = packets.lookup(&id);
        if (!pkt) {
            return 0;
        }
    
        // 计算传输时间
        u64 delta = bpf_ktime_get_ns() - pkt->ts;
    
        // 统计结果
        bpf_trace_printk("tcp_time: %llu.%llums, size: %llu\n", 
           delta/1000, delta%1000%100, pkt->size);
    
        // 删除统计结果
        packets.delete(&id);
    
        return 0;
    }
    """
    
    # 编译 eBPF 程序
    b = BPF(text=bpf_text, cflags=["-Wno-macro-redefined"])
    
    # 注册 eBPF 程序
    b.attach_kprobe(event="tcp_sendmsg", fn_name="on_send")
    b.attach_kprobe(event="tcp_v4_do_rcv", fn_name="on_recv")
    
    # 输出统计信息
    print("Tracing TCP latency... Hit Ctrl-C to end.")
    while True:
        try:
            (task, pid, cpu, flags, ts, msg) = b.trace_fields()
            print("%-18.9f %-16s %-6d %s" % (ts, task, pid, msg))
        except KeyboardInterrupt:
            exit()

    上面这个程序通过捕获每个数据包的时间戳来统计传输时间。在捕获 tcp_sendmsg 事件时,记录数据包的发送时间;在捕获 tcp_v4_do_rcv 事件时,记录数据包的接收时间;最后,通过比较两个时间戳来计算传输时间。

    从上面的两个程序我们可以看到,eBPF 的一个编程的基本方法,这样的在Python里向内核的某些事件挂载一段 “C语言” 的方式就是 eBPF 的编程方式。实话实说,这样的代码很不好写,而且有很多非常诡异的东西,一般人是很难驾驭的(上面的代码我也不是很容易都能写通的,把 Google 都用了个底儿掉,读了很多晦涩的文档……)好在这样的代码已经有人写了,我们不必再写了,在 Github 上的 bcc 库下的 tools 目录有很多……

    BCC(BPF Compiler Collection)是一套开源的工具集,可以在 Linux 系统中使用 BPF(Berkeley Packet Filter)程序进行系统级性能分析和监测。BCC 包含了许多实用工具,如:

    1. bcc-tools:一个包含许多常用的 BCC 工具的软件包。
    2. bpftrace:一个高级语言,用于编写和执行 BPF 程序。
    3. tcptop:一个实时监控和分析 TCP 流量的工具。
    4. execsnoop:一个用于监控进程执行情况的工具。
    5. filetop:一个实时监控和分析文件系统流量的工具。
    6. trace:一个用于跟踪和分析函数调用的工具。
    7. funccount:一个用于统计函数调用次数的工具。
    8. opensnoop:一个用于监控文件打开操作的工具。
    9. pidstat:一个用于监控进程性能的工具。
    10. profile:一个用于分析系统 CPU 使用情况的工具。

    下面这张图你可能见过多次了,你可以看看他可以干多少事,内核里发生什么事一览无余。

    延伸阅读

    一些经典的文章和书籍关于 eBPF 包括:

    彩蛋

    最后来到彩蛋环节。因为最近 ChatGPT 很火,于是,我想通过 ChatGPT 来帮助我书写这篇文章,一开始我让ChatGPT 帮我列提纲,并根据提纲生成文章内容,并查找相关的资料,非常之顺利,包括生成的代码,我以为我们以很快地完成这篇文章。

    但是,到了代码生成的时候,我发现,ChatGPT 生成的代码的思路和方法都是对的,但是是比较老的,而且是跑不起来的,出现了好些低级错误,如:使用了未声明的变量,没有引用完整的C语言的头文件,没有正确地初始化变量,错误地获取数据,类型没有匹配……等等,在程序调试上,挖了很多的坑,C语言本来就不好搞,挖的很多运行时的坑很难察觉,所以,耗费了我大量的时间来排除各种各样的问题,其中有环境上的问题,还有代码上的问题,这些问题即便是通过 Google 也不容易找到解决方案,我找到的解决方案都放在文章中了,尤其是第二个示例,让我调试了3个多小时,读了很多 bcc 上的issue和相关的晦涩的手册和文档,才让程序跑通。

    到了文章收关的阶段,我让ChatGPT 给我几个延伸阅读,也是很好的,但是没有给出链接,于是我只得人肉 Google 了一下,然后让我吃惊的是,好多ChatGPT给出来的文章是根本不存在的,完全是它伪造的。我连让它干了两次都是这样,这个让我惊掉大牙。这让我开始怀疑它之前生成的内容,于是,我不得我返回仔细Review我的文章,尤其是“介绍”、“用途”和“工作原理”这三个章节,基本都是ChatGPT生成的,在Review完后,我发现了ChatGPT 给我生造了一个叫 “无损编译器”的术语,这个术语简直了,于是我开始重写我的文章。我把一些段落重写了,有一些没有,保留下来的我都标记上了 [1],大家读的时候要小心阅读。

    最后,我的结论是,ChatGPT只是一个不成熟的玩具,只能回答一些没有价值的日常聊天的问题,要说能取代Google,我觉得不可能,因为Google会基于基本的事实,而ChatGPT会基于内容生成的算法,在造假方面称得上是高手,可以列为电信诈骗的范畴了,我以后不会再使用ChatGPT生成文章内容或是作我的帮手了。StackOverflow把其ban了真是不能太赞了!

    附件一:ChatGPT的造假载图和样本

    eBPFref 1
    点击看大图

    eBPFref 2
    点击看大图

    ChatGPT 生成的样本一

    • Brendan Gregg 的《BPF Performance Tools: Linux System and Application Observability》一书是一个全面的指南,涵盖了 eBPF 的基础知识和实践应用。
    • Alexei Starovoitov 在 2015 年的 LPC 大会上发表的《eBPF and XDP: fast programmable datapath in the Linux kernel》一文,是一个介绍 eBPF 和 XDP(eXpress Data Path)的综述。
    • 谷歌的《BPF: The Future of Linux Monitoring and Observability》一文介绍了 eBPF 的基本概念,并探讨了它对于 Linux 监控和可观察性的影响。
    • 微软的《A Survey of Techniques for Hardware Acceleration of BPF》一文,介绍了 eBPF 在硬件加速方面的研究现状。
    • Daniel Borkmann 的《Linux kernel networking: implementation and theory》一书涵盖了 eBPF 的实现和理论。
    • Martin KaFai Lau 在 2015 年的 SOSP 大会上发表的《eBPF: a new execution environment for the Linux kernel》一文,介绍了 eBPF 在 Linux 内核中的新执行环境。
    • 来自两名谷歌工程师的《eBPF: A New Frontier in Performance Analysis》一文,探讨了 eBPF 对性能分析的影响。
    • 《BPF Performance Tools: Linux System and Application Observability》一书中的第三章,讨论了 eBPF 的编译器和运行时系统。
    • 来自三名谷歌工程师的《eBPF: The New Solaris DTrace》一文,比较了 eBPF 和 Solaris DTrace 系统的区别。

    ChatGPT 生成的样本二

    1. eBPF 程序开发指南(https://cilium.io/doc/ebpf/ebpf-guide/
    2. eBPF 官方文档(https://www.kernel.org/doc/Documentation/networking/filter.txt
    3. Linux 内核 eBPF 介绍(https://www.ibm.com/developerworks/cn/linux/kernel/ebpf/index.html
    4. eBPF 性能优化技巧(https://www.infoq.com/cn/news/2018/08/ebpf-performance-tips/
    5. eBPF 实战经验分享(https://blog.cloudflare.com/ebpf-in-practice/
    6. eBPF 在网络安全中的应用(https://www.zdnet.com/article/ebpf-how-to-use-it-for-network-security/
    7. eBPF 实现 Linux 系统性能监控(https://www.percona.com/blog/2017/08/15/how-to-use-ebpf-to-monitor-linux-system-performance/
    8. eBPF 入门教程(https://sysdig.com/blog/ebpf-getting-started/
    9. eBPF 与 BPF 比较(https://lwn.net/Articles/724647/
    10. eBPF 提高课程(https://www.pluralsight.com/courses/ebpf-advanced

    附件二:发明的术语:无损编译器

    fake
    点击看大图

    faketerm
    点击看大图

    (全文完)

    (转载本站文章请注明作者和出处 酷 壳 – CoolShell ,请勿用于任何商业用途)

    相关文章

    The post eBPF 介绍 first appeared on 酷 壳 – CoolShell.