[大厂实践] 重新发明后端子集

子集算法有助于优化服务间连接利用率,降低资源使用。但随机或轮询子集算法在动态拓扑环境中会造成较高的连接扰动。本文介绍了谷歌在解决连接扰动方面所做的思考和实践,并介绍了当前最新的Rocksteadier子集算法。原文: Reinventing Backend Subsetting at Google

近年来,由于有利于提高资源利用率,Autopilot系统在谷歌内部越来越受欢迎。Autopilot可以做很多事情:可以配置为执行水平扩展,调整服务正在运行的任务数量以满足需求;可以配置为执行垂直扩展,调整每个任务分配的CPU/内存资源。Autopilot在防止停机方面也很有效,相对人工运维来说,可以实现服务规模的更快扩容来响应不断增长的需求。

随着Autopilot的广泛使用,服务所有者发现了一个有趣的问题: 每当横向扩容的服务调整大小时,许多客户端连接(通常是长连接)都会短暂断开并重新连接,这种连接扰动会导致如下后果:

  • 增加了当前请求的错误或延迟
  • 增加了连接握手消耗的CPU/内存使用率
  • TCP慢启动建立新连接的过程降低了吞吐量
  • 增加了连接缓存的压力

这些影响的严重程度因服务而异,但在某些情况下,错误或延迟的增加会使服务水平目标面临风险,并阻碍Autopilot的采用。最终研究发现,这种连接扰动问题是由后端子集引起的。

后端子集(Backend subsetting)是一种将服务连接在一起时减少连接数量的技术,对于降低成本非常有用,甚至可能是在系统限制条件下进行运维所必需的。十多年来,Google使用确定性子集(deterministic subsetting)[1]作为默认后端子集算法,尽管该算法平衡了每个后端任务的连接数量,但会造成较高水平的连接扰动(connection churn)。

我们的目标是设计一种减少连接扰动的算法,用以取代确定性子集作为默认后端子集算法。该目标雄心勃勃,如海鲁姆定律(Hyrum's Law)所说,"系统所有可观察到的行为都将依赖于某个人。"我们需要了解确定性子集的所有行为,避免犯同样的错误。

Borg的后端子集

谷歌的服务运行在内部集群管理软件Borg上。服务所有者配置可以在多个Borg单元(cell) 中运行的作业(job) ,以实现地理分区。在计算单元中,作业由一个或多个任务组成,每个任务在数据中心的某些机器上运行,任务从0开始连续编号。

利用后端子集将作业连接在一起,如果由M个任务组成的前端作业连接到由N个任务组成的后端作业,则通常会有M×N个连接,当作业有数千个任务时,连接数可能会相当大。相反,如果每个前端任务都连接到k个后端任务,可以将连接数减少到M×k。为k选择合适的值取决于使用者,但通常比MN小得多。

要使用后端子集,必须服务必须是可重复的(replicated): 如果将相同请求发送给不同任务,它们应该执行相同的工作并返回相同的响应。

前端任务的负载均衡策略用于将请求定向到特定的后端任务,目标是在后端任务之间实现统一使用。每个后端任务分配相同资源,为了避免过载,需要为负载最多的后端任务预备资源。

以前的方法

后端子集算法选择的子集对生产有各种影响: 连接均衡、子集多样性、连接扰动和子集扩容。为了描述这些行为并解释新算法是如何开发的,我们从一个简单的算法开始,并对其进行迭代改进。

随机子集

最简单的可行算法之一是选择随机子集: 每个前端任务将后端任务列表(由任务编号0到N-1标识)打乱,并选择前k个任务。

不幸的是,这与许多负载均衡策略的交互效果很差。假设有一个CPU密集型服务,所有请求都消耗相同的成本,并且每个前端任务都用循环负载均衡来均匀的分发请求。因此,每个后端任务的负载将与其连接的数量直接相关。然而,随机子集的连接分布远非均匀,如图1所示。

alt

轮循是一种简单的负载均衡策略,但并不是唯一受连接分布影响的策略。考虑到谷歌服务的多样性及其不同的负载均衡需求,要求与连接无关的负载均衡策略是不切实际的。因此,子集算法应努力平衡连接分布。

属性: 连接平衡(Connection Balance)

假设负载均衡策略受连接分布影响,目标是度量子集算法造成的负载不均衡的数量。为此,假设每个前端任务在其子集中的每个后端任务上生成等量负载,这并不一定完全符合实际情况,但对于当前目标已经足够了。

利用率是衡量负载均衡的一个有用指标: 用总使用率除以总容量得到正在使用的资源比例。可以应用于连接分布: 总使用量将是连接总数(M×k),并且(因为我们为负载最多的后端任务预留资源)总容量将基于具有最多连接的后端任务( ,其中 是到第n个后端任务的连接数)。从而获得以下指标:

alt

然而,该度量并没有考虑到连接的离散性。如果M×k不能被N整除,理想的子集算法必须为每个后端任务分配 个连接,因此 并且Utilization < 1。在这种情况下,要实现Utilization = 1,必须调整度量以给出可实现的利用率:

alt

这个指标可以比较不同场景下子集算法的连接平衡性。注意,实现高利用率有两种简单的方法。首先,增加k自然会提高利用率,因为降低了子集对负载均衡的影响,将子集大小增加到N意味着完全禁用子集设置。其次,随着前端任务与后端任务比例的增加,每个后端任务的子集算法有更多选择,因此即使随机选择,连接平衡性也会自然改善。如图2所示,对于最多有256个任务的作业(k = 20, 1≤ M ≤ 256, k ≤ N ≤ 256, M × k > N),图中绘制了利用率与前后端任务的比率,虽然不完全是现实场景,但足以证明算法的行为。

alt
轮询子集

随机子集可以基于前端任务编号(0到M-1)引入协调来改进。轮询子集将后端任务连续分配给第一个前端任务子集,然后是第二个任务子集,依此类推,如表1所示。每个前端任务m可以通过后端任务号有效生成自己的子集。

alt

很容易看出,这样做可以尽可能统一的平衡连接,一旦后端任务n被分配了一个连接,在所有其他后端任务都被分配连接之前,不会被分配另一个连接。虽然该算法具有良好的连接平衡性,但其其他性能并不理想。

属性: 子集多样性(Subset Diversity)

想象一下,如果表1中有更多前端任务会发生什么。前端任务5将被分配给后续的4个后端任务,即{0,1,2,3},但这与前端任务0的子集相同。这10个后端任务的每个子集有4个任务,总共有10选4=210个可能子集,但该算法只能分配5个不同的子集。一般情况下,应该有 个子集。

这有什么问题?想象一下,一个前端任务正在执行某个更改,该更改会在其子集中的后端任务中触发不良行为(例如,高延迟或崩溃),而这将影响其他前端任务,这些任务应该能够在其他后端任务上重试请求。但是,如果其他前端任务所分配的子集和金丝雀前端任务完全相同,那它们将共享相同的命运,并且无法实现故障转移或者只能将故障转移到相同的后端任务,从而造成这些后端任务过载。

确定性子集(Deterministic subsetting)

可以通过引入随机性来增加子集多样性,但必须以保持连接平衡的方式进行。这就产生了这样一种解决方案: 打乱所有后端任务,将它们分配给前几个前端,然后重复这一步骤。

例如,对于表1中的场景,可以将后端任务排列为[9,1,3,0,8,6,5,7,2,4],并将子集{9,1,3,0}和{8,6,5,7}分配给前两个前端任务。然而,这带来了一个问题,因为后端任务2和4没有分配。然后到下一个前端任务子集,洗牌后的后端任务列表可能是[7,2,0,8,9,1,4,5,3,6],但不能将后端任务2分配给相同的前端任务。尝试跳过后端任务2(使用后端任务0)也有问题,因为这样就引入了一种依赖关系,在这种依赖关系中,前端任务需要计算之前每一组打乱的后端任务,而不仅只考虑分配了的后端任务。

该问题可以通过忽略多余的任务来解决,这样只会导致少量的连接不平衡。在这个例子中,前端任务2将使用子集{7,2,0,8}。

这是之前在《站点可靠性工程:谷歌如何运行生产系统》(第20章)中描述的算法,但可以通过平衡每个组中的剩余任务来进行改进,最简单的实现方法是(在洗牌之前)选择哪些任务在轮询过程中遗留下来。例如,第一组前端任务选择留下{0,1},然后对剩下的任务进行洗牌,得到子集{8,3,9,2}和{4,6,5,7},第二组前端任务选择留下{2,3},然后对剩下的任务进行洗牌,得到子集{9,7,1,6}和{0,5,4,8}。这种额外的平衡确保所有后端任务都被均匀的留下,从而产生更好的分布。

该算法提供了良好的连接平衡性和子集多样性,并在生产中取得了十多年的良好效果。在Autopilot更频繁的调整横向大小之前,其唯一的主要问题在于特别小的子集大小。

属性: 连接扰动(Connection Churn)

考虑一下当后端任务从10个增加到11个时,前端任务的子集会发生什么变化,如图3所示,其中的变化用红色突出显示。

alt

尽管集群大小变化不大,但子集发生了很多变化,前端任务3尤为不幸,其被分配了完全不同的子集。当后端大小发生变化时,每个前端任务将和不再属于其子集的后端断开连接,并连接到新添加的后端。重新建立连接需要多次网络交互,在此期间可能发生以下情况:

  • 后端过载,因为前端任务只能通过更少的已连接的后端任务来平衡负载,并且连接分布不均衡。
  • 如果没有既定后端任务可用于给定的前端任务,将发生更多错误和延迟。

这种连接扰动是由于改变后端大小引起的,因此称为后端扰动。子集算法也可能因为前端扰动(改变前端大小)和子集大小扰动(改变子集大小)而造成问题。

理想情况下,后端扰动数量应该与后端大小的变化成正比。例如,如果后端大小翻倍,则每个前端任务的子集更改一半是合理的。这种后端变动应该均匀分布在各个子集中: 每个前端子集中的一半后端发生变化是可接受的,但如果有一半前端子集中的所有后端都发生了变化,那就不行了。

到目前为止,所有算法都没有考虑前端扰动,这在子集算法中尤其不可取。假设某个前端作业过载,并且添加了额外任务来增加容量。前端扰动将导致现有前端任务重新连接到后端任务,在添加的任务能够开始服务之前容量将显著减小。

如果子集大小是动态调整的,比如基于前端大小、后端大小和/或流量级别,那么子集大小的变动就很重要。很容易看出,随机子集具有最小的扰动: 只有洗牌后列表的一部分被用作子集。另一方面,轮循和确定性子集都依赖于子集大小,从而导致较高的子集大小扰动。

属性: 子集分布(Subset Spread)

另一个需要考虑的有趣问题是如何将新版本软件部署到Borg作业中。作业通常通过从任务0开始进行滚动重启来完成更新,并限制正在运行的任务重启次数。除了重启缓慢的异常任务外,这意味着在更新期间,某个连续编号的任务组将不可用。

考虑对轮询子集的影响: 在表1中,第一个前端任务的子集{0,1,2,3}也是该过程将重新启动的前四个任务,如果正在运行的任务数量与子集大小相似,则大多数前端任务的子集在更新期间的某个时刻将完全不可用。随机子集和确定性子集的性能更好,因为任何单个子集都不太可能具有相对接近的任务数,但是如果有足够数量的前端任务,则很可能会遇到这一问题。

我们在实践中观察到这一问题,可以通过减少运行中的任务数量(减慢更新速度)或增加子集大小(增加成本)来缓解这种情况。理想情况下,子集算法将在每个子集中分散后端任务数,以便更新对前端任务具有一致且最小的影响。子集多样性和子集扩展之间存在矛盾: 前者需要许多不同的子集,但后者需要限制可接受的子集。

寻找新算法

这些是后端子集算法的期望属性:

  • 良好的连接平衡性
  • 较高的子集多样性
  • 没有前端扰动
  • 较低的后端扰动
  • 较低的子集大小扰动
  • 良好的子集分布

除了前端扰动,其他都不需要最优性能,只需要满足避免不良行为即可。

一致性子集(Consistent subsetting)

出发点基于一致性哈希: 每个前端和后端在单位环上随机分配一个位置,每个前端通过选择沿圆周顺时针移动找到的前k个后端来确定其子集。图4a显示了前端任务(蓝色方块)和后端任务(黄色圆圈)随机位置的一致性子集。前端任务0顺时针移动并选择看到的前两个后端,获得子集{3,2}。

alt

当任务被添加到环或从环中移除时,其他任务位置不受影响,从而极大减少了连接扰动。当添加后端任务时,每个前端任务的子集最多只有一个更改。

不幸的是,该算法在连接平衡性或子集多样性方面做得不太好。由于前端任务在选择其子集时没有协调,因此连接平衡性并不比随机子集更好。因为前端任务选择的第一个后端任务决定了子集的其余部分,所以最多可能有N个不同的子集,从而影响到了子集多样性。

稳定环子集(Ringsteady subsetting)

如何改善一致性子集的连接平衡性?后端任务的连接数与后端任务在环上的"空闲空间"成正比,因此连接平衡性取决于后端任务在环周围的均匀间隔程度。有了这种认识,就可以通过有利于均匀分布的位置序列来改进随机选择的位置,即构造低差异序列[2]

仅仅因为后端任务是连续编号的,所以低差异序列中的第n个元素可以与第n个后端任务相关联。

我们在谷歌选择的序列是二进制的van der Corput序列[3](将0作为第0个元素),它表示为0, 。这些分数决定了每个节点在圆上的位置,如图4b所示,第一个任务被放置在圆的顶部,第二个任务被放置在圆的中间,以此类推。

选择这个序列的原因之一是它在计算元素位置时很方便。例如,要获得第5个元素的位置(字长为8位),只需要将5的二进制00000101反转为10100000(十进制为160),然后将其作为位置的定点数,得到

到目前为止,本文只讨论了后端任务,但是前端任务的需求是一样的。如果后端任务比前端任务多得多,那么前端任务应该均匀分布,以便选择的子集尽可能均匀,避免重叠。对前端和后端任务使用相同的顺序会获得另一个方便的属性: 当M = N时,每个前端任务都有不同的子集(从相同编号的后端任务开始),并实现理想的连接平衡性。图4b显示了实际的算法,我们称之为稳定环子集(Ringsteady Subsetting)。

与随机和确定性子集(子集的分布取决于运气)不同,稳定环子集保证了良好的子集分布性,连续编号的后端任务在圆上彼此相距很远,因此圆周围连续任务的子集将具有均匀分布的任务编号。

图2c显示,算法在某些情况下的利用率低于确定性子集(见图2b),但明显优于随机子集(见图2a)。

前端和后端扩容

不幸的是,稳定环子集的连接平衡性有缺陷,如图2c右侧所示,前端任务数量超过后端任务,但利用率并没有向理想状态收敛,这与图2b中的确定性子集不同。低差异序列导致前端和后端任务的位置接近但并不完全均匀间隔。不过这种不平衡性只存在于有多余任务的场景中。

那为什么不让它们完全均匀间隔呢?这就需要稍微做一点移动了(比较图4b和图4c),而这会引入少量连接扰动,但应该能改善连接平衡性。当应用于前端任务时,我们称之为前端扩容,当应用于后端任务时,我们称之为后端扩容。

对于前后端扩容,算法将始终实现理想的连接平衡性。不幸的是,前端扩容使得前端任务的位置依赖于前端大小,这就引入了前端扰动,使得它不适合这个用例。

图2d显示了结果。与图2c相比,当M > N时,后端扩容达到了改善连接平衡性的目标,而当M < N时,仅出现了较小的退化。虽然在某些情况下,仍然比确定性子集(见图2b)的利用率低,但足够了。

Rocksteadier子集

支持后端扩容的稳定环子集几乎拥有我们想要的所有属性。它继承自一致性子集,所以在子集多样性上有缺陷,可能只有N个不同的子集。我们研究了Rendezvous Hashing作为增加子集多样性的替代方案,但除了随机性并不能改善连接平衡性。相反,我们设计了一种结合稳定环的算法来增加子集多样性,而且不会显著降低任何其他属性。

之前我们通过打乱后端任务来实现子集多样性,但这使得顺序依赖于后端大小,因此导致后端扰动。相反,通常前端大小M明显小于可能的子集数量。因此,并非每个后端都必须进行洗牌(即,产生所有可能的排列)以实现足够的子集多样性。

解决问题的方法是形成L个后端任务组(称为lot),并对任务进行洗牌。参数L必须是常量,如果其依赖于前端大小、后端大小或子集大小就会导致连接扰动。最后一个后端lot必须由L个任务组成,所以如果后端大小不是L的倍数,则添加填充任务(不是真正的后端任务,在选择子集时将被跳过)。此外还要构造L个前端任务组。在每个前端批次中,尝试将后端任务均匀分布在前端任务上,类似于轮循或确定性子集。

表2显示了这个过程的第一步: 基于L = 10将前端和后端任务分组。为了便于说明,这里显示了第二个前端lot(任务10-19)。由于后端大小不是L的倍数,填充任务55-59(用灰色文本表示)被添加到最后一个后端lot。

alt

表3显示了这个过程的第二步: 对每个后端批进行洗牌。该表显示了从左到右对每个后端lot进行洗牌后,前端任务13(红色)和19(蓝色)的潜在子集分配。

alt

这个过程的要求是:

  • 前端lot中的每个前端任务需要对后端任务使用相同的洗牌顺序。
  • 后端lot应该在不同的前端lot中进行不同的洗牌。
  • 添加新的后端lot不能影响先前洗牌后端lot的顺序。

这些需求可以通过使用前端lot号(对于前端任务m,是 )作为PRNG(伪随机数生成器,pseudorandom number generator)的种子,然后使用该PRNG按顺序对每个后端批号进行洗牌来实现。

我们仍然需要想出一种将子集分配给前端任务的方法。可以从考虑一些简单但不太好用的方法开始。第i个前端任务可以遍历第i行,并从每个lot中获取后端任务。如果到达该行的最后一个后端lot,绕行读取表中的下一行。例如,在表3中,前端任务13将选择以{4,14,21,39,46,52,7,18,…}开头的子集。此外还要跳过填充后端任务,并从最后一个后端lot绕到第一个lot,因此前端任务19将选择以{6,10,20,30,44,8,13,22,…}开头的子集。

这种分配子集的方法在两个方面造成了连接不平衡: 它无法在后端lot(即跨列)之间实现平衡,并且无法在后端lot(即多行)内保持平衡。

为了在后端lot之间进行平衡,请考虑表3中描述的场景,其中子集大小较小,例如k = 3。前端任务10-19的子集将只从前三列中选择后端任务,后端任务0-29每个都有一个连接。请注意,对于每个前端lot都是如此,虽然每个后端lot中的顺序因前端lot而异,但第一个后端lot始终包含任务0-9,第二个10-19,以此类推。

不同的前端lot需要以均匀分布的方式访问不同的后端lot,并且不会引入扰动。这部分问题可以通过将Rocksteadier算法中的前端/后端lot映射到Ringsteady中的前端/后端任务来解决。例如,在图4c中,前端任务1看到后端任务的顺序为[1,5,3,0,4,2],在表4中,列被重新排序,以便前端lot 1中的任务以相同顺序从选择后端任务。Rocksteadier前端任务1使用与Ringsteady前端任务1相对应的顺序。

alt

剩余的(相对较小的)平衡问题发生在最后一个前端lot不完整的时候。例如,考虑表4,如果只有前端任务10、11和12,那就存在一个相对较大的子集大小。因为子集都从连续行开始,之间会有一些重叠,从而导致某些后端任务(例如,第三行上的任务,5,45,26,…有多个连接,甚至可能有来自所有三个前端任务的连接),而位于较低行的后端任务将没有连接。这种不平衡可以通过调整前端任务到起始行的不同映射来缓解: 这是大小为L的固定排列,可以任意选择稳定环顺序[0,8,2,4,6,1,9,5,3,7]将连续的前端任务分散到各行中。表5显示了最终的子集分配过程,对前端任务进行了排列,并显示了前端任务10(红色)、11(蓝色)和12(绿色)的子集分配(k = 10)。

alt

较大的L值提高了子集多样性,但代价是连接不平衡。幸运的是,相对较小的值(例如10)能够为典型的Borg作业提供足够的子集多样性,而且不会增加连接不平衡。

测试及部署

我们在开发期间基于生产环境收集的前端、后端和子集大小的测试套件来比较不同算法的属性,表明Rocksteadier子集减少了连接扰动率,不过我们想要验证是否也能减少二阶效应。

为此,我们在非生产环境中的一个服务上运行实验。两个前端作业(一个使用确定性子集,另一个使用Rocksteadier子集)不断向后端作业发送请求,后端作业在实验期间逐渐调整大小(使用不同步长)。图5显示了结果,每次后端大小发生变化时,使用确定性子集的前端作业都会出现错误峰值,而使用Rocksteadier子集的前端作业则基本不受影响。

alt

我们在最受后端扰动影响的服务中试用了Rocksteadier子集,消除了这一服务采用Autopilot的障碍,大大节省了资源,降低了生产事故率。

经过几个月运行,没有发生任何重大事故,Rocksteadier子集作为新的默认后端子集算法在全公司推出并获得了成功,基本上没有引起服务所有者的注意。

结论

本文介绍了谷歌寻求的一种算法,能够提供良好的连接平衡性、较高的子集多样性、无前端扰动、较低的后端扰动、较低的子集大小扰动和良好的子集传播性。大多数子集算法能够提供其中的几个属性,但据我们所知,只有Rocksteadier子集能够提供所有这些属性。

最后,虽然这些折衷适用于谷歌的生产环境,但在其他环境中可能并不理想。无论如何,对这些属性的讨论和对设计过程的理解也有可能对其他环境有所帮助。


你好,我是俞凡,在Motorola做过研发,现在在Mavenir做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。为了方便大家以后能第一时间看到文章,请朋友们关注公众号"DeepNoMind",并设个星标吧,如果能一键三连(转发、点赞、在看),则能给我带来更多的支持和动力,激励我持续写下去,和大家共同成长进步!

参考资料

[1]

A subset selection algorithm deterministic subsetting: https://sre.google/sre-book/load-balancing-datacenter/#a-subset-selection-algorithm-deterministic-subsetting-eKsdcaUm

[2]

Low discrepancy sequence: https://en.wikipedia.org/wiki/Low-discrepancy_sequence

[3]

van der Corput sequence: https://en.wikipedia.org/wiki/Van_der_Corput_sequence

- END -

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/605152.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

面试题:怎么给详情页做性能优化的?

文章目录 一、背景二、接口优化方案总结1.批处理2.异步处理3.空间换时间4.预处理5.池化思想6.串行改并行7.索引8.避免大事务9.优化程序结构10.深分页问题11.SQL优化12.锁粒度避免过粗 三、最后 一、背景 针对老项目&#xff0c;去年做了许多降本增效的事情&#xff0c;其中发现…

03MyBatis完成CRUD

准备工作 ○ 创建module&#xff08;Maven的普通Java模块&#xff09;&#xff1a;mybatis-002-crud ○ pom.xml ■ 打包方式jar ■ 依赖&#xff1a; ● mybatis依赖 ● mysql驱动依赖 ● junit依赖 ● logback依赖 ○ mybatis-config.xml放在类的根路径下 ○ CarMapper.xml放…

Elasticsearch:Serarch tutorial - 使用 Python 进行搜索 (二)

这个是继上一篇文章 “Elasticsearch&#xff1a;Serarch tutorial - 使用 Python 进行搜索 &#xff08;一&#xff09;” 的续篇。在今天的文章中&#xff0c;我们接着来完成如何进行分页及过滤。 分页 - pagination 应用程序处理大量结果通常是不切实际的。 因此&#xff0…

【ros笔记】urdf文件

urdf文件属于xml文件&#xff0c;他的标签有&#xff1a; <robot name"robot_name"><!-- 看的见摸的着刚体用link --><link name"base_link"><!-- 可视化部分 --><visual><!-- 几何形状 --><geometry><!-- b…

vue-springboot 音乐推荐系统 带歌词的音乐播放器系统设计与实现 7902c

少数民族音乐网站在流畅性&#xff0c;续航能力&#xff0c;等方方面面都有着很大的优势。这就意味着少数民族音乐网站的设计可以比其他系统更为出色的能力&#xff0c;可以更高效的完成最新的音乐信息、音乐资讯、在线交流等功能。 此系统设计主要采用的是JAVA语言来进行开发&…

基于SpringBoot的教学辅助系统

文章目录 项目介绍主要功能截图&#xff1a;部分代码展示设计总结项目获取方式 &#x1f345; 作者主页&#xff1a;超级无敌暴龙战士塔塔开 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简历模板、学习资料、面试题库【关注我&#xff0c;都给你】 &…

实战Flink Java api消费kafka实时数据落盘HDFS

文章目录 1 需求分析2 实验过程2.1 启动服务程序2.2 启动kafka生产 3 Java API 开发3.1 依赖3.2 代码部分 4 实验验证STEP1STEP2STEP3 5 时间窗口 1 需求分析 在Java api中&#xff0c;使用flink本地模式&#xff0c;消费kafka主题&#xff0c;并直接将数据存入hdfs中。 flin…

java火车查询管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java Web火车查询管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql…

深度学习工具-Jupyter Notebook使用

在本地编辑和运行代码 运行命令jupyter notebook。如果浏览器未自动打开&#xff0c;请打开http://localhost:8888 你可以通过单击网页上显示的文件夹来访问notebook文件。它们通常有后缀“.ipynb”。为了简洁起见&#xff0c;我们创建了一个临时的“test.ipynb”文件。单击后…

计算机网络(超级详细笔记)

使用教材计算机网络&#xff08;第8版&#xff09;&#xff08;谢希仁&#xff09; 第一章&#xff1a;概述 第二章&#xff1a;物理层 第三章&#xff1a;数据链路层 第四章&#xff1a;网络层 第五章&#xff1a;运输层 第六章&#xff1a;应用层 目…

Linux学习第50天:Linux块设备驱动实验(二):Linux三大驱动之一

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 三、使用请求队列实验 1.实验程序编写 使用开发板上的一段RAM来模拟一段块设备&#xff0c;也就是ramdisk. 机械硬盘 34 #define RAMDISK_SIZE (2 * 1024 * 10…

使用即时设计绘制原型设计方便吗?和Axure RP相比怎么样?

对于原型设计&#xff0c;APP 和 Web 都是一样的&#xff0c;因为产品原型是用来确定需求的工具。我们使用这种工具的目的是为了快速迭代&#xff0c;从而深入挖掘和筛选产品的需求。 绘制原型&#xff0c;最重要的原则是&#xff1a;快速、清晰&#xff01; Axure 工具的优缺…

2023APMCM亚太数学建模C题 - 中国新能源汽车的发展趋势(3)

六、问题三的模型建立和求解 6.1问题分析 问题3.收集数据&#xff0c;建立数学模型分析新能源电动汽车对全球传统能源汽车行业的影响。 本题要求建立模型分析新能源电动汽车对全球传统能源汽车行业的影响。由于数据集可能略大&#xff0c;而在处理复杂问题、大量特征和大规模…

spatialRF

官网&#xff1a;Easy Spatial Modeling with Random Forest • spatialRF (blasbenito.github.io) spatialRF是一种在考虑空间自相关的前提下&#xff0c;利用随机森林对空间数据进行回归并解释的R包。 数据要求 参数命名 data&#xff1a;训练集&#xff0c;data frame。 …

基于SpringBoot的房屋租赁管理系统

文章目录 项目介绍主要功能截图&#xff1a;部分代码展示设计总结项目获取方式 &#x1f345; 作者主页&#xff1a;超级无敌暴龙战士塔塔开 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简历模板、学习资料、面试题库【关注我&#xff0c;都给你】 &…

WorkPlus Meet打造高质量的视频会议体验,助力实时远程协作

在全球化的商业环境中&#xff0c;远程协作和在线会议成为了企业高效工作的关键。作为一款高质量的视频会议软件&#xff0c;WorkPlus Meet以其卓越的性能和创新的功能&#xff0c;成为企业实时远程协作的首选。 WorkPlus Meet打造了高质量的视频会议体验&#xff0c;为企业提供…

书生·浦语大模型趣味 Demo笔记及作业

文章目录 笔记作业基础作业&#xff1a;进阶作业&#xff1a; 笔记 书生浦语大模型InternLM-Chat-7B 智能对话 Demo&#xff1a;https://blog.csdn.net/m0_49289284/article/details/135412067书生浦语大模型Lagent 智能体工具调用 Demo&#xff1a;https://blog.csdn.net/m0_…

雾天条件下 SLS 融合网络的三维目标检测

论文地址&#xff1a;3D Object Detection with SLS-Fusion Network in Foggy Weather Conditions 论文代码&#xff1a;https://github.com/maiminh1996/SLS-Fusion 论文摘要 摄像头或激光雷达&#xff08;光检测和测距&#xff09;等传感器的作用对于自动驾驶汽车的环境意识…

vue项目中的录屏插件recordrtc且带声音

vue项目中的录屏插件recordrtc且带声音 一、效果图二、安装插件三、直接上代码 一、效果图 其中窗口录屏不带声音&#xff0c;chrome标签和整个屏幕的录屏是带声音的 二、安装插件 npm i recordrtc 三、直接上代码 <template><div class"record-page">…

react-router-domV6.21.1版本结合ant design mobile的TabBar标签栏和Popup弹出层实现移动端路由配置

react-router-demo react-router-dom在V6版本之后更换了很多的API名称&#xff0c;在ant design mobile的TabBar配置中还是之前的旧版本&#xff0c;比如使用了switch组件等。我们在这里使用新版本的react-router-dom进行react移动端的配置 首先使用npm下载最新版的react-rout…