浅尝Apache Mesos

news2024/11/23 23:17:11

文章目录

    • 1. Mesos是什么
    • 2. 共享集群
    • 3. Apache Mesos
      • 3.1 Mesos主节点
      • 3.2 Mesos代理
      • 3.3 Mesos框架
    • 4. 资源管理
      • 4.1 资源提供
      • 4.2 资源角色
      • 4.3 资源预留
      • 4.4 资源权重与配额
    • 5. 实现框架
      • 5.1 框架主类
      • 5.3 实现执行器
    • 6. 小结
    • 参考

1. Mesos是什么

Mesos是什么,Mesos是一个分布式的系统内核。

Mesos的构建原理与Linux内核相同,只是抽象级别不同。Mesos的内核在每台机器上运行并为应用程序(例如Hadoop、Spark、Kafka、ElasticSearch)提供API跨整个数据中心和云环境的资源管理和调度。

Mesos主要有以下特性:

  1. 线性可扩展
    1. 经过业界验证,可以轻松扩展到数万个节点
  2. 高可用性
    1. 使用Zookeeper实现主服务器和代理服务器容错副本,无中断升级
  3. 容器化
    1. 原生支持使用Docker和AppC镜像启动容器
  4. 可插拔隔离
    1. 对CPU、内存、磁盘、端口、GPU和自定义资源隔离模块的一流隔离支持
  5. 两级调度
    1. 支持使用可插入的调度策略在同一集群中运行云原生和遗留应用程序
  6. 接口
    1. 用于开发新的分布式应用程序、操作集群和监控的HTTP API
  7. Web UI
    1. 内置Web UI,用于查看集群状态和容器沙箱导航
  8. 跨平台
    1. 可在Linux、OSX和Windows上运行,与云服务商无关

我们通常会将各种应用程序部署在同一台机器集群上。而Apache Mesos是一个允许此类程序之间共享资源的平台。

2. 共享集群

许多应用程序需要共享集群,总的来说有两种常见的方法:

  1. 对集群静态分区并在每个分区上运行一个应用程序
  2. 为应用程序分配一组机器

上述方法虽然允许应用程序彼此独立运行,但并不能实现较高的资源利用率:比如某个应用程序只运行了一小段时间,之后处于非活动状态,由于我们为该应用程序分配了静态机器或分区,因此在非活动状态期间,存在未使用的资源。

我们可以通过将非活动状态期间的共享资源重新分配给其他应用程序来优化资源利用率,而Apache Mesos则可以帮助应用程序之间的资源动态分配。

3. Apache Mesos

基于我们上面讨论的两种共享集群的方法,应用程序只知道他们正在运行的特定分区或机器的资源,然而Apache Mesos为应用程序提供了集群中所有资源的抽象视图。

Mesos会充当机器与应用程序之间的接口,为应用程序提供集群中所有机器上的可使用资源,它会经常更新此信息从而获取完成状态的应用程序释放的资源。它允许应用程序做出关于哪台机器上执行哪个任务的最佳决定。

为了理解Mesos的工作原理,我们来看下它的架构:

Mesos架构

上图展示了Mesos的主要组件,Mesos由一个管理运行在每个集群节点上的代理守护进程和主守护进程以及在这些代理上运行任务的Mesos框架组成。

主节点通过提供资源实现跨框架的细粒度资源共享(CPU、RAM等)。每个提供的资源包含一个列表<agent ID, resource1: amount1, resource2: amount2, ...>,主节点根据给定的组织策略(例如公平共享和严格优先级)决定向每个框架提供多少资源。为了支持多样化的策略集,主节点才用模块化架构,可通过插件机制来轻松添加新的分配模块。

在Mesos上运行的框架由两个组件组成:

  1. 向主节点注册以获取资源的调度程序
  2. 在代理节点上启动以运行框架任务的执行程序进程

主节点确定向每个框架提供多少资源,而框架的调度程序则选择使用提供资源中的哪些资源。当框架接受提供的资源时,它会将要在这些资源上运行的任务的描述传递给Mesos,反过来,Mesos会在相应的代理上启动任务。

3.1 Mesos主节点

Master是Mesos中的核心组件,用于存储集群中资源的当前状态,此外,它还通过传递有关资源和任务等信息,从而充当代理和应用程序之间的协调器。

由于主服务器发生任何故障都会导致资源和任务状态丢失,因此我们将其部署在高可用性配置中。如上图所示,Mesos部署了主服务器守护进程和一个Master,这些守护进程依靠Zookeeper在发生故障时恢复状态。

3.2 Mesos代理

Mesos集群必须在每台机器上运行代理,这些代理定期向主节点报告其资源,并依次接收应用程序已经安排运行的任务。在计划任务完成或者丢失后,次循环将重复。

3.3 Mesos框架

Mesos允许应用程序实现一个抽象组件,该组件与Master交互以接收集群中的可用资源,并根据这些资源做出调度决策,这些组件成为框架。

Mesos的框架由两个子组件组成:

  • 调度程序:使应用程序能够根据所有代理上的可用资源来调度任务
  • 执行器:在所有代理上运行,并包含该代理上执行任务计划任务所需的所有信息

框架安排任务运行的示例图:

Mesos框架安排任务运行示意

  1. 代理1向主服务器报告其有4个CPU和4GB的可用内存,主服务器随后调度分配策略模块,告知其应该为框架1提供所有可用资源。
  2. 主服务器向框架1发送资源邀约,描述代理1有哪些可用资源
  3. 框架的调度程序向主服务器回复在代理上运行的两个任务的信息,第一个任务使用<2CPU,1GB RAM>,第二个任务使用<1CPU,2GB RAM>
  4. 最后主服务器将任务发送给代理,代理将适当的额资源分配给框架的执行器,执行器则启动这两个任务(图中虚线所示),由于仍然存在1CPU和1GB RAM未分配,因此分配模块现在可以将它提供给框架2.

此外,当任务完成且新资源变为空闲时,此资源提供过程会重复。

Mesos允许应用程序使用各种编程语言实现自定义调度程序和执行程序。按照Mesos-go中的Scheduler接口的定义如下,具体可参考:Mesos Scheduler interface

// Scheduler a type with callback attributes to be provided by frameworks
// schedulers.
//
// Each callback includes a reference to the scheduler driver that was
// used to run this scheduler. The pointer will not change for the
// duration of a scheduler (i.e., from the point you do
// SchedulerDriver.Start() to the point that SchedulerDriver.Stop()
// returns). This is intended for convenience so that a scheduler
// doesn't need to store a reference to the driver itself.
type Scheduler interface {

	Registered(SchedulerDriver, *mesos.FrameworkID, *mesos.MasterInfo)

	Reregistered(SchedulerDriver, *mesos.MasterInfo)

	Disconnected(SchedulerDriver)

	ResourceOffers(SchedulerDriver, []*mesos.Offer)

	OfferRescinded(SchedulerDriver, *mesos.OfferID)

	StatusUpdate(SchedulerDriver, *mesos.TaskStatus)

	FrameworkMessage(SchedulerDriver, *mesos.ExecutorID, *mesos.SlaveID, string)

	SlaveLost(SchedulerDriver, *mesos.SlaveID)

	ExecutorLost(SchedulerDriver, *mesos.ExecutorID, *mesos.SlaveID, int)

	Error(SchedulerDriver, string)
}

从上述接口的定义可以看出,它主要由各种回调方法组成,主要用于与主机通信。

同样,执行器的实现也需要实现Executor接口,具体可参考:Mesos Executor interface

/**
 * Executor callback interface to be implemented by frameworks' executors. Note
 * that only one callback will be invoked at a time, so it is not
 * recommended that you block within a callback because it may cause a
 * deadlock.
 *
 * Each callback includes an instance to the executor driver that was
 * used to run this executor. The driver will not change for the
 * duration of an executor (i.e., from the point you do
 * ExecutorDriver.Start() to the point that ExecutorDriver.Join()
 * returns). This is intended for convenience so that an executor
 * doesn't need to store a pointer to the driver itself.
 */
type Executor interface {

	Registered(ExecutorDriver, *mesosproto.ExecutorInfo, *mesosproto.FrameworkInfo, *mesosproto.SlaveInfo)

	Reregistered(ExecutorDriver, *mesosproto.SlaveInfo)

	Disconnected(ExecutorDriver)

	LaunchTask(ExecutorDriver, *mesosproto.TaskInfo)

	KillTask(ExecutorDriver, *mesosproto.TaskID)

	FrameworkMessage(ExecutorDriver, string)

	Shutdown(ExecutorDriver)

	Error(ExecutorDriver, string)
}

4. 资源管理

4.1 资源提供

上面说到代理节点会将其资源信息发布给主服务器,反过来主服务器将这些资源提供给集群中运行的框架,此过程成为资源提供。

资源信息一般由两部分组成:

  1. 资源
    1. 资源用于发布代理机器的硬件信息,例如CPU、内存、磁盘等
  2. 属性

每个代理有五种预定义资源:

  • 中央处理器
  • 图形处理器
  • 内存
  • 磁盘
  • 端口

这些资源的值可以用以下三种类型之一来定义:

  • 标量:用浮点数来表示数值信息,以允许小数值,例如1.5G内存
  • 范围:用于表示标量值的范围,例如端口号范围
  • 集合:用于表示多个文本值

默认情况下,Mesos代理会尝试从机器检测这些资源。但在某些情况下我们可以在代理上配置自定义资源,此类自定义资源的值,也应为上述任何一种类型。

例如,我们可以使用以下这些资源启动我们的代理:

--resources='cpus:24;gpus:2;mem:2048;disk:40960;ports:[21000-24000];bugs(debug_role):{a,b,c}'

上面我们为代理配置了一些预定义资源和一个名为bugs集合类型的自定义资源。

除了资源之外,代理还可以向主服务器发布键值属性,这些属性充当代理的附加元数据,并帮助框架进行调度决策。

一个有用的例子是将带来添加到不同的机架或者区域,然后在同一个机架或者区域上安排各种任务以实现数据本地化

--attributes='rack:abc;zone:sg;os:centos5;level:10;keys:[1000-1500]'

与资源类似,属性的值可以是标量、范围或者文本类型。

4.2 资源角色

现代操作系统许多都支持多用户,同样,Mesos也支持同一个集群中的多个用户,这些用户被称为角色。我们可以将每个决策视为集群中的资源消费者。

由此,Mesos代理可以基于不同的分配策略对不同角色下的资源进行划分,而框架可以在集群内订阅这些角色,从而实现对不同角色下的资源进行细粒度的控制。

例如,假设有一个集群托管应用程序,为组织中不同用户提供服务,因此,通过将资源划分成角色,每个应用程序都可以彼此独立地工作。

此外,框架可以使用这些角色来实现数据局部性。

例如,假设集群中有两个应用程序,分别为生产者和消费者,其中生产者将数据写入持久卷,消费者随后可以读取该卷,我们可以通过生产者共享该卷来优化消费者应用程序。

由于Mesos允许多个应用程序订阅同一角色,我们可以将持久卷与资源角色关联起来,此外,生产者和消费者的框架都将订阅相同的资源角色,因此消费者应用程序现在可以在与生产者应用程序相同的卷上启动数据读取任务。

4.3 资源预留

Mesos如何将集群资源分配给不同的角色,Mesos通过预留来实现资源分配。

预留类型有两种:

  • 静态预留
  • 动态预留

静态预留则是在代理启动时的资源分配:

–resources=“cpus:4;mem:2048;cpus(test_abc):8;mem(test_abc):4096”

与静态预留不同,动态预留允许我们重新调整角色内的资源,Mesos允许框架和集群操作员通过框架消息(作为对资源提供的响应)或者通过HTTP API调用动态更改资源分配。

Mesos将所有不具有任何角色的资源分配给名为(*)的默认角色,Master主服务器向所有框架提供此类资源,无论它们是否订阅了该资源。

4.4 资源权重与配额

Mesos主节点一般使用公平策略来提供资源,它使用加权主导资源公平性来识别缺少资源的角色,然后主服务器向已订阅这些角色的框架提供更多资源。

尽管在应用程序之间公平共享资源是Mesos的一个重要特性,但这并非是必要的。假设一个集群托管着资源占用低的应用程序和资源需求高的应用程序。在样的部署中,我们希望根据应用程序的性质分配资源。

Mesos允许框架通过订阅角色并为该角色添加更高的权重来请求更多资源。因此,如果有两个角色,一个权重为1,另一个为2,则Mesos会为第二个角色分配两倍的公平份额资源。

另外,我们还可以通过HTTP接口调用来配置权重,可参考:Mesos Weights Set by HTTP API

除了确保为具有权重的角色公平分配资源之外,Mesos还确保为角色分配最少的资源。

Mesos允许我们为资源角色添加配额,配额可以指定角色保证接收到的最小资源量。

5. 实现框架

Mesos允许应用程序选择任意语言提供框架实现,即实现Scheduler和Executor的接口从而实现框架。

5.1 框架主类

在实现调度程序和执行程序之前,需要先实现框架的入口点:

  • 向master注册
  • 向代理执行器提供运行时信息
  • 启动调度程序

下面程序来自Mesos官方提供的示例,具体可参考:Mesos Framework Python test examples

import os
import sys
import time

import mesos.interface
from mesos.interface import mesos_pb2
from mesos.scheduler import MesosSchedulerDriver

TOTAL_TASKS = 5

TASK_CPUS = 1
TASK_MEM = 128

class TestScheduler(mesos.interface.Scheduler):
    def __init__(self, implicitAcknowledgements, executor, framework):
        self.implicitAcknowledgements = implicitAcknowledgements
        self.executor = executor
        self.framework = framework
        self.taskData = {}
        self.tasksLaunched = 0
        self.tasksFinished = 0
        self.messagesSent = 0
        self.messagesReceived = 0
		# 注册
    def registered(self, driver, frameworkId, masterInfo):
        print "Registered with framework ID %s" % frameworkId.value
        self.framework.id.CopyFrom(frameworkId)
        driver.updateFramework(framework, [])

    def resourceOffers(self, driver, offers):# 资源申请
        for offer in offers:
            tasks = []
            offerCpus = 0
            offerMem = 0
            for resource in offer.resources:
                if resource.name == "cpus":
                    offerCpus += resource.scalar.value
                elif resource.name == "mem":
                    offerMem += resource.scalar.value

            print "Received offer %s with cpus: %s and mem: %s" \
                  % (offer.id.value, offerCpus, offerMem)

            remainingCpus = offerCpus
            remainingMem = offerMem

            while self.tasksLaunched < TOTAL_TASKS and \
                  remainingCpus >= TASK_CPUS and \
                  remainingMem >= TASK_MEM:
                tid = self.tasksLaunched
                self.tasksLaunched += 1

                print "Launching task %d using offer %s" \
                      % (tid, offer.id.value)

                task = mesos_pb2.TaskInfo()
                task.task_id.value = str(tid)
                task.slave_id.value = offer.slave_id.value
                task.name = "task %d" % tid
                task.executor.MergeFrom(self.executor)

                cpus = task.resources.add()
                cpus.name = "cpus"
                cpus.type = mesos_pb2.Value.SCALAR
                cpus.scalar.value = TASK_CPUS # CPU资源

                mem = task.resources.add()
                mem.name = "mem"
                mem.type = mesos_pb2.Value.SCALAR
                mem.scalar.value = TASK_MEM # 内存资源

                tasks.append(task)
                self.taskData[task.task_id.value] = (
                    offer.slave_id, task.executor.executor_id)

                remainingCpus -= TASK_CPUS
                remainingMem -= TASK_MEM

            operation = mesos_pb2.Offer.Operation()
            operation.type = mesos_pb2.Offer.Operation.LAUNCH
            operation.launch.task_infos.extend(tasks)

            driver.acceptOffers([offer.id], [operation])

    def statusUpdate(self, driver, update):# 状态更新
        print "Task %s is in state %s" % \
            (update.task_id.value, mesos_pb2.TaskState.Name(update.state))

        # Ensure the binary data came through.
        if update.data != "data with a \0 byte":
            print "The update data did not match!"
            print "  Expected: 'data with a \\x00 byte'"
            print "  Actual:  ", repr(str(update.data))
            sys.exit(1)

        if update.state == mesos_pb2.TASK_FINISHED:
            self.tasksFinished += 1
            if self.tasksFinished == TOTAL_TASKS:
                print "All tasks done, waiting for final framework message"

            slave_id, executor_id = self.taskData[update.task_id.value]

            self.messagesSent += 1
            driver.sendFrameworkMessage(
                executor_id,
                slave_id,
                'data with a \0 byte')

        if update.state == mesos_pb2.TASK_LOST or \
           update.state == mesos_pb2.TASK_KILLED or \
           update.state == mesos_pb2.TASK_FAILED:
            print "Aborting because task %s is in unexpected state %s with message '%s'" \
                % (update.task_id.value, mesos_pb2.TaskState.Name(update.state), update.message)
            driver.abort()

        # Explicitly acknowledge the update if implicit acknowledgements
        # are not being used.
        if not self.implicitAcknowledgements:
            driver.acknowledgeStatusUpdate(update)
		# 框架消息处理
    def frameworkMessage(self, driver, executorId, slaveId, message):
        self.messagesReceived += 1

        # The message bounced back as expected.
        if message != "data with a \0 byte":
            print "The returned message data did not match!"
            print "  Expected: 'data with a \\x00 byte'"
            print "  Actual:  ", repr(str(message))
            sys.exit(1)
        print "Received message:", repr(str(message))

        if self.messagesReceived == TOTAL_TASKS:
            if self.messagesReceived != self.messagesSent:
                print "Sent", self.messagesSent,
                print "but received", self.messagesReceived
                sys.exit(1)
            print "All tasks done, and all messages received, exiting"
            driver.stop()

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print "Usage: %s master" % sys.argv[0]
        sys.exit(1)

    executor = mesos_pb2.ExecutorInfo()
    executor.executor_id.value = "default"
    executor.command.value = os.path.abspath("./test-executor")
    executor.name = "Test Executor (Python)"
    executor.source = "python_test"

    framework = mesos_pb2.FrameworkInfo()
    framework.user = "" # Have Mesos fill in the current user.
    framework.name = "Test Framework (Python)"
    framework.checkpoint = True
    framework.role = "*"

    implicitAcknowledgements = 1
    if os.getenv("MESOS_EXPLICIT_ACKNOWLEDGEMENTS"):
        print "Enabling explicit status update acknowledgements"
        implicitAcknowledgements = 0

    if os.getenv("MESOS_EXAMPLE_AUTHENTICATE"):
        print "Enabling authentication for the framework"

        if not os.getenv("MESOS_EXAMPLE_PRINCIPAL"):
            print "Expecting authentication principal in the environment"
            sys.exit(1);

        credential = mesos_pb2.Credential()
        credential.principal = os.getenv("MESOS_EXAMPLE_PRINCIPAL")

        if os.getenv("MESOS_EXAMPLE_SECRET"):
            credential.secret = os.getenv("MESOS_EXAMPLE_SECRET")

        framework.principal = os.getenv("MESOS_EXAMPLE_PRINCIPAL")

    else:
        framework.principal = "test-framework-python"
        credential = None

    # Subscribe with all roles suppressed to test updateFramework() method
    driver = MesosSchedulerDriver(
        TestScheduler(implicitAcknowledgements, executor, framework),
        framework,
        sys.argv[1],
        implicitAcknowledgements,
        credential,
        [framework.role])

    status = 0 if driver.run() == mesos_pb2.DRIVER_STOPPED else 1

    # Ensure that the driver process terminates.
    driver.stop();

    sys.exit(status)

调度程序可能会由于缺乏资源而无法再代理上启动任务,则会被拒绝,就是上面的DRIVER_STOPPED。

5.3 实现执行器

框架的执行器组件负责在Mesos代理上执行应用程序服务。

import sys
import threading
import time

import mesos.interface
from mesos.interface import mesos_pb2
from mesos.executor import MesosExecutorDriver

class MyExecutor(mesos.interface.Executor):
    def launchTask(self, driver, task):
        # Create a thread to run the task. Tasks should always be run in new
        # threads or processes, rather than inside launchTask itself.
        def run_task():
            print "Running task %s" % task.task_id.value
            update = mesos_pb2.TaskStatus()
            update.task_id.value = task.task_id.value
            update.state = mesos_pb2.TASK_RUNNING
            update.data = 'data with a \0 byte'
            driver.sendStatusUpdate(update)

            # This is where one would perform the requested task.

            print "Sending status update..."
            update = mesos_pb2.TaskStatus()
            update.task_id.value = task.task_id.value
            update.state = mesos_pb2.TASK_FINISHED
            update.data = 'data with a \0 byte'
            driver.sendStatusUpdate(update)
            print "Sent status update"

        thread = threading.Thread(target=run_task)
        thread.start()

    def frameworkMessage(self, driver, message):
        # Send it back to the scheduler.
        driver.sendFrameworkMessage(message)

if __name__ == "__main__":
    print "Starting executor"
    driver = MesosExecutorDriver(MyExecutor())
    sys.exit(0 if driver.run() == mesos_pb2.DRIVER_STOPPED else 1)

执行器的代码比较简单,主要是定义了task执行的逻辑以及对应将数据发回调度器的逻辑。

6. 小结

因为在工作中看到有对应的Mesos字眼,虽然自己不会去直接接触这个东西(大多都是通过包装好的组件间接使用),但了解一下运行原理对自己理解一些组件会有一些帮助。

主要是学习了一下Mesos的基本原理和统一集群中运行的应用程序之间的资源共享,以及Mesos是如何通过集群资源(CPU和内存等)帮助应用程序实现资源最大利用。

里面还有涉及到关于Mesos的资源的公平分配策略以及订阅角色的应用程序之间的资源动态分配,Mesos允许应用程序根据集群中的Mesos代理提供的资源做出调度决策,同时Mesos提供了大量HTTP API可用于接口调用进行资源的权重和配额修改。

另外关于Mesos的具体实践还需要继续学习,这次只是在虚拟机大致跑了一下测试用例,并没有采用手动编写程序的方式来进行具体实践。

参考

  • Mesos Architecture
  • mesos-go
  • Apache Mesos

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

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

相关文章

昇思25天学习打卡营第14天|Pix2Pix实现图像转换

Pix2Pix是基于条件生成对抗网络&#xff08;cGAN, Condition Generative Adversarial Networks &#xff09;实现的一种深度学习图像转换模型&#xff0c;该模型是由Phillip Isola等作者在2017年CVPR上提出的&#xff0c;可以实现语义/标签到真实图片、灰度图到彩色图、航空图到…

【js基础巩固】深入理解作用域与作用域链

作用域链 先看一段代码&#xff0c;下面代码输出的结果是什么&#xff1f; function bar() {console.log(myName) } function foo() {var myName "极客邦"bar() } var myName "极客时间" foo()当执行到 console.log(myName) 这句代码的时候&#xff0c…

acwing 291.蒙德里安的梦想

解法&#xff1a; 核心&#xff1a;先放横着的&#xff0c;再放竖着的。 总方案数&#xff0c;等于只放横着的小方块的合法方案数。 如何判断当前方案是否合法&#xff1f;所有剩余位置&#xff0c;能否填充满竖着的小方块。 即按列来看&#xff0c;每一列内部所有连续的空着的…

第六十八回 东平府误陷九纹龙 宋公明义释双枪将-文心大模型ernie-speed免费使用方法

宋江和卢俊义抓阄儿&#xff0c;宋江打东平府&#xff0c;卢俊义打东昌府&#xff0c;谁先打下谁做梁山泊主。宋江带领林冲、花荣、刘唐等二十八人&#xff0c;卢俊义带领吴用、公孙胜、关胜等二十八人。 宋江等人到了东平府外安山镇&#xff0c;郁保四和王定六自告奋勇去下战…

搭建NEMU与QEMU的DiffTest环境(动态库方式)

搭建NEMU与QEMU的DiffTest环境&#xff08;动态库方式&#xff09; 1 DiffTest原理简述2 编译NEMU3 编译qemu-dl-difftest3.1 修改NEMU/scripts/isa.mk3.2 修改NEMU/tools/qemu-dl-diff/src/diff-test.c3.3 修改NEMU/scripts/build.mk3.4 让qemu-dl-difftest带调试信息3.5 编译…

昇思12天

FCN图像语义分割 1. 主题和背景 FCN是由UC Berkeley的Jonathan Long等人于2015年提出的&#xff0c;用于实现图像的像素级预测。 2. 语义分割的定义和重要性 语义分割是图像处理和机器视觉中的关键技术&#xff0c;旨在对图像中的每个像素进行分类。它在很多领域有重要应用…

【问题解决】 pyocd 报错 No USB backend found 的解决方法

pyocd 报错 No USB backend found 的解决方法 本文记录了我在Windows 10系统上遇到的pyocd命令执行报错——No USB backend found 的分析过程和解决方法。遇到类似问题的朋友可以直接参考最后的解决方法&#xff0c;向了解问题发送原因的可以查看原因分析部分。 文章目录 pyoc…

ChatGPT-4o大语言模型优化、本地私有化部署、从0-1搭建、智能体构建等高级进阶

目录 第一章 ChatGPT-4o使用进阶 第二章 大语言模型原理详解 第三章 大语言模型优化 第四章 开源大语言模型及本地部署 第五章 从0到1搭建第一个大语言模型 第六章 智能体&#xff08;Agent&#xff09;构建 第七章 大语言模型发展趋势 第八章 总结与答疑讨论 更多应用…

端口被占用,使用小黑框查杀

netstat -ano &#xff08;查看目前所有被占的端口&#xff09; netstat -ano|findstr " 8080" 查一下目前被占用的端口号 &#xff0c;目前我要查的端口号是&#xff1a;8080&#xff0c;注意 后面打8080的时候&#xff0c;要有空格&#xff0c;要不然报错 **task…

无人机便携式侦测干扰设备(定全向)技术详解

无人机便携式侦测干扰设备&#xff08;定全向&#xff09;是一种专门针对无人机进行侦测和干扰的设备。它具备定向和全向两种工作模式&#xff0c;能够覆盖较宽的频率范围&#xff0c;有效侦测并干扰无人机与遥控器之间的通信信号&#xff0c;从而达到控制或驱离无人机的目的。…

CRT工具

CRT工具 传输位置设置 打开SFTP alt p 命令 ls&#xff1a;远程机器当前目录内容 lls&#xff1a;传输位置文件的目录内容 pwd&#xff1a;远程机器的当前位置 lpwd&#xff1a;传输位置的位置 get 文件&#xff1a;ftp传输文件 get -r 文件夹&#xff1a;ftp传输文件…

AI中药处方模型构建与案例

在中医领域,人工智能(AI)可以生成各种指令来辅助诊断、治疗和研究。 1. 诊断辅助指令: 根据患者的症状和体征,自动分析并生成可能的中医证候诊断建议。利用中医望闻问切四诊信息,智能识别关键症状,提供对应的中医辨证思路。2. 治疗建议指令: 根据辨证结果,自动推荐相应…

2024吉他手的超级助手Guitar Pro8中文版本发布啦!

亲爱的音乐爱好者们&#xff0c;今天我要来和你们分享一款让我彻底沉迷的软件—Guitar Pro。如果你是一名热爱吉他的朋友&#xff0c;那么接下来的内容你可要瞪大眼睛仔细看哦&#xff01;&#x1f440;&#x1f3b6; Guitar Pro免费绿色永久安装包下载&#xff1a;&#xff0…

90元搭建渗透/攻防利器盒子!【硬件篇】

前言 以下内容请自行思考后进行实践。 使用场景 在某些情况下开软件进行IP代理很麻烦&#xff0c;并不能实现真正全局&#xff0c;而且还老容易忘记&#xff0c;那么为了在实景工作中&#xff0c;防止蓝队猴子封IP&#xff0c;此文正现。 正文 先说一下实验效果&#xff1…

鸿蒙开发管理:【@ohos.account.distributedAccount (分布式帐号管理)】

分布式帐号管理 本模块提供管理分布式帐号的一些基础功能&#xff0c;主要包括查询和更新帐号登录状态。 说明&#xff1a; 本模块首批接口从API version 7开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。开发前请熟悉鸿蒙开发指导文档&#xff…

axios取消请求功能CancelToken原理解析

今天在论坛看到一个取消axios请求的功能&#xff0c;具体场景是这样的&#xff1a;前端接口以较短时间间隔请求后端接口刷新状态&#xff0c;接口返回“成功”状态之后还有处于pending状态的请求在排队&#xff0c;如果请求不取消就会导致前端最后获取到的状态出错&#xff0c;…

C语言实现计算器混合运算(含括号,加减乘除)

功能描述&#xff1a; 实现计算器混合运算基本功能&#xff0c;包括&#xff1a;( )、、-、*、/。 功能很简单&#xff0c;但实现起来还是有一定逻辑难度&#xff0c;因为&#xff0c;混合运算需要考虑优先级。 优先级最高的为&#xff1a;&#xff08;&#xff09; 其次&a…

LabVIEW干涉仪测向系统

开发了一套基于LabVIEW的软件系统&#xff0c;结合硬件设备&#xff0c;构建一个干涉仪测向实验教学平台。该平台应用于信号处理课程&#xff0c;帮助学生将理论知识与实际应用相结合&#xff0c;深化对信号处理核心概念的理解和应用。 项目背景&#xff1a; 当前信号处理教学…

基于Wireshark和TiWsPC(Wireshark Packet Converter)的Zigbee抓包

前言 介绍几种Zigbee抓包方式&#xff1a; 1. Ubiqua 使用教程网上非常多也非常清晰&#xff1b; 但是Ubiqua是收费软件&#xff0c;较贵&#xff1b; 我安装过了&#xff0c;费好多事&#xff0c;没安装成功。 2. Killerbee套件 https://github.com/riverloopsec/killerbe…

TB作品】51单片机 Proteus仿真 51单片机SPI显示OLED字符驱动

// GND 电源地 // VCC 接5V或3.3v电源 // D0 P1^4&#xff08;SCL&#xff09; // D1 P1^3&#xff08;SDA&#xff09; // RES 接P12 // DC 接P11 // CS 接P10 OLED显示接口与控制实验报告 背景 OLED&#xff08;有机发光二极管&#xff09;显示器由于其高对比度、低功耗和…