【Yarn】Yarn的基本执行流程(二)AM Container的启动

Yarn的基本执行流程之AM Container的启动

文章目录

  • Yarn的基本执行流程之AM Container的启动
    • AM Container(第一个Container)的启动
      • NM RM心跳交互触发调度Container的启动流程
      • RM中调度启动AM流程
      • AMLauncher启动流程
      • NM上容器的启动流程
        • 下载资源
        • AM Container 启动与运行
      • NM RM心跳交互触发调度更新Container的状态
    • AM启动之后怎么注册到RM上
    • AM怎么申请运行其他Container

AM Container(第一个Container)的启动

NM RM心跳交互触发调度Container的启动流程

NodeStatusUpdaterImpl ResourceTrackerService RMNodeImpl FairScheduler NM上的定时触发项RM进行心跳交互 1.NM向RM进行心跳交互 nodeHeartbeat(request) 2.触发RMNodeStatusEvent (RMNodeEventType.STATUS_UPDATE) StatusUpdateWhenHealthyTransition() 3.触发NodeUpdateSchedulerEvent (SchedulerEventType.NODE_UPDATE) nodeUpdate() NodeStatusUpdaterImpl ResourceTrackerService RMNodeImpl FairScheduler

当有NM节点向RM发送心跳请求时,RM内部最终会以事件的形式通知到调度器,调度器则选择合适的应用为其分配资源。

  1. NM上的节点NodeStatusUpdater服务的实现NodeStatusUpdaterImpl与ResourceTrackerService保持心跳联系,定时发送信息。
  2. ResourceTrackerService验证相关信息后,会向调度器发送RMNodeStatusEvent事件。
  3. RMNodeImpl向调度器发送NodeUpdateSchedulerEvent事件,由FairScheduler进行nodeUpdate处理,其中就包含了启动AM流程。

RM中调度启动AM流程

FairScheduler FSAppAttempt RMContainerImpl RMAppAttemptImpl SchedulerApplicationAttempt RMAppImpl RMStateStore ApplicationMasterLauncher 1.尝试为Container分配资源 assignContainer() 2.分配资源 allocate() 3.触发 RMContainerEvent (RMContainerEventType.START) ContainerStartedTransition() 4.触发 RMAppAttemptEvent (RMAppAttemptEventType.CONTAINER_ALLOCATED) AMContainerAllocatedTransition() 5. Acquire the AM container from the scheduler. allocate() 6.pullNewlyAllocatedContainers() 7.触发 RMContainerEvent (RMContainerEventType.ACQUIRED) AcquiredTransition() 8.触发 RMAppRunningOnNodeEvent (RMAppEventType.APP_RUNNING_ON_NODE) AppRunningOnNodeTransition() 9.异步存储attempt storeNewApplicationAttempt() 10.触发 RMStateStoreAppAttemptEvent (RMStateStoreEventType.STORE_APP_ATTEMPT) StoreAppAttemptTransition() 11.触发 RMAppAttemptEvent (RMAppAttemptEventType.ATTEMPT_NEW_SAVED) AttemptStoredTransition() 12.触发 AMLauncherEvent (AMLauncherEventType.LAUNCH) FairScheduler FSAppAttempt RMContainerImpl RMAppAttemptImpl SchedulerApplicationAttempt RMAppImpl RMStateStore ApplicationMasterLauncher
  1. FairSchduler在更新节点时会调用attemptScheduling方法,尝试为Container分配资源
  2. FSAppAttempt申请分配Container资源,实例化Container。
  3. 申请到了Container资源,触发RMContainerEventType.START事件。在完成ContainerStartedTransition方法后,RMContainerState.NEW将变为RMContainerState.ALLOCATED
  4. ContainerStartedTransition方法发送了RMAppAttemptEventType.CONTAINER_ALLOCATED事件,触发AMContainerAllocatedTransition方法,RMAppAttemptState.SCHEDULED将变为RMAppAttemptState.ALLOCATED_SAVING
  5. 从调度器获取启动 AM 的 Container。
  6. 把之前申请资源拿走。
  7. 处理RMContainerEventType.ACQUIRED事件,RMContainerState.ALLOCATED将变为RMContainerState.ACQUIRED
  8. 把当前Container所处的Node放入上下文,RMAppState.ACCEPTED保持不变
  9. 当第5步开始的链路结束后,回到RMAppAttemptImpl,执行异步存储Attempt信息。
  10. 处理RMStateStoreEventType.STORE_APP_ATTEMPT事件,RMStateStore.storeApplicationAttemptStateInternal持久化存储,是存ZK???
  11. 存储成功时候,发送RMAppAttemptEventType.ATTEMPT_NEW_SAVED事件,RMAppAttemptState.ALLOCATED_SAVING将变为RMAppAttemptState.ALLOCATED
  12. 执行registerClientToken()注册客户端token,向处理器发送AMLauncherEventType.LAUNCH事件。处理器是将事件交由ApplicationMasterLauncher继续处理AMLauncher启动流程。

AMLauncher启动流程

RMContainerImpl StartContainerRequest StartContainersRequest ApplicationMasterLauncher LauncherThread AMLauncher ContainerManagerImpl 1.创建AMLauncher实例 createRunnableLauncher() 2.masterEvents.add(launcher) 3.获取队列的事件元素 masterEvents.take() 4. 执行AMLauncher线程 launcherPool.execute(toLaunch) 5.与NM交互启动容器 launch() 与NM建立连接 connect() 构建AM容器,并设置相关参数 createAMContainerLaunchContext 使用AM容器构建StartContainerRequest请求 使用StartContainerRequest构建StartContainersRequest请求 启动容器 startContainers() 6.触发 RMAppAttemptEvent (RMAppAttemptEventType.LAUNCHED) AMLaunchedTransition() RMContainerImpl StartContainerRequest StartContainersRequest ApplicationMasterLauncher LauncherThread AMLauncher ContainerManagerImpl

ResourceManager启动的时候会将会创建ApplicationMasterLauncher服务,用来进行AM Container的启动与关闭。

  1. ApplicationMasterLauncher回去创建一个AMLauncher实例,用来启动AM Container。

  2. 将AMLauncher实例放入masterEvents队列。AMLauncher实例的处理是一种异步的处理方式。

  3. 在实例化ApplicationMasterLauncher时,会创建一个LauncherThread线程实例,用来调度处理masterEvents。

  4. LauncherThread从队列中获取AMLauncher调度执行。

  5. 执行launch()方法,这里面包含了与NM交互,具体启动NM上Container的部分。

  6. 向事件处理器发送RMAppAttemptEventType.LAUNCHED事件,调度执行RMAppAttemptImpl的AMLaunchedTransition(),此时认为AM container已经启动,等待AM container注册到RN上,将刚刚启动的 ApplicationMaster 注册到 AMLivelinessMonitor,启动心跳监控。RMAppAttemptState.ALLOCATED将变为 RMAppAttemptState.LAUNCHED

NM上容器的启动流程

由ContainerManagerImpl被调用到startContainers()方法展开。遍历StartContainerRequests,处理每个StartContainerRequest。具体操作是在startContainerInternal() 方法。

下载资源
ContainerManagerImpl ContainerImpl ApplicationImpl NMLeveldbStateStoreService LogAggregationService ResourceLocalizationService LocalResourcesTrackerImpl LocalizedResource LocalizerRunner PublicLocalizer ContainerScheduler 1. 创建容器实例 (填充信息) 2. 创建Application实例 (填充信息) 3. 存储Application信息 storeApplication() 4. 触发ApplicationInitEvent (ApplicationEventType.INIT_APPLICATION) AppInitTransition() 5. 触发LogHandlerAppStartedEvent (LogHandlerEventType.APPLICATION_STARTED) 6. 触发 ApplicationEvent (ApplicationEventType.APPLICATION_LOG_HANDLING_INITED) AppLogInitDoneTransition() 7. 触发 ApplicationLocalizationEvent (LocalizationEventType.INIT_APPLICATION_RESOURCES) 8. 触发 ApplicationInitedEvent (ApplicationEventType.APPLICATION_INITED) AppInitDoneTransition() 9. 触发 ContainerInitEvent (ContainerEventType.INIT_CONTAINER) RequestResourcesTransition() 10. 触发 ContainerLocalizationRequestEvent (LocalizationEventType.LOCALIZE_CONTAINER_RESOURCES) RequestResourcesTransition() 11. 为每个容器资源获取本地资源追踪器 12. 触发 ResourceRequestEvent (ResourceEventType.REQUEST) FetchResourceTransition() 13. 触发 LocalizerResourceRequestEvent (LocalizerEventType.REQUEST_RESOURCE_LOCALIZATION) FetchResourceTransition() 14. 为Application创建对应的LocalizerRunner实例,并启动该线程实例 15. 将公共资源下载交给PublicLocalizer下载 16. 触发ResourceLocalizedEvent (ResourceEventType.LOCALIZED) FetchSuccessTransition() 17. 触发ContainerResourceLocalizedEvent (ContainerEventType.RESOURCE_LOCALIZED) LocalizedTransition() 18. ContainerLocalizationEvent (LocalizationEventType..CONTAINER_RESOURCES_LOCALIZED) 19. 触发 ContainerSchedulerEvent (ContainerSchedulerEventType.SCHEDULE_CONTAINER) loop [ContainerResourceLocalizedEvent] loop [ResourceRequestEvent] loop [getLocalResourcesTracker] loop [ContainerInitEvent] loop [startContainerInternal synchronized] ContainerManagerImpl ContainerImpl ApplicationImpl NMLeveldbStateStoreService LogAggregationService ResourceLocalizationService LocalResourcesTrackerImpl LocalizedResource LocalizerRunner PublicLocalizer ContainerScheduler
  1. 创建一个ContainerImpl实例,初始化相关信息。
  2. 为新的appc创建一个Application实例,即app的AM Container来初始化。
  3. 获取日志聚合上下文,将Application信息,存储下来。
  4. 向调度器发送ApplicationInitEvent(ApplicationEventType.INIT_APPLICATION)事件,调用AppInitTransition()方法,执行成功后会将ApplicationState.INITING变成ApplicationState.RUNNING
  5. 发送LogHandlerAppStartedEvent(LogHandlerEventType.APPLICATION_STARTED)事件,由LogAggregationService来处理。会为APP创建一个AppLogAggregatorImpl实例,并由线程池调度它。
  6. 向调度器发送ApplicationEvent(ApplicationEventType.APPLICATION_LOG_HANDLING_INITED)事件,触发AppLogInitDoneTransition()方法。
  7. 向调度器发送ApplicationLocalizationEvent(LocalizationEventType.INIT_APPLICATION_RESOURCES)事件,由ResourceLocalizationService来处理。开始对app的创建应用程序资源跟踪。
  8. 向调度器发送ApplicationInitedEvent(ApplicationEventType.APPLICATION_INITED)事件,调用ApplicationImpl中的AppInitDoneTransition方法处理。
  9. 遍历此APP中的所有Container(需要建立的),向调度器发送ContainerInitEvent(ContainerEventType.INIT_CONTAINER)事件,由ContainerImpl的RequestResourcesTransition方法处理,ContainerState.LOCALIZING.NEW将变为ContainerState.LOCALIZING
  10. 会发送辅助服务的相关事件AuxServicesEvent(AuxServicesEventType.CONTAINER_INIT)AuxServicesEvent(AuxServicesEventType.APPLICATION_INIT)暂时展开,之后发送ContainerLocalizationRequestEvent事件,进行容器资源的本地化。
  11. 资源本地服务ResourceLocalizationService为每个资源请求构建LocalResourcesTracker(LocalResourcesTrackerImpl)。
  12. 由LocalResourcesTrackerImpl发送ResourceRequestEvent(ResourceEventType.REQUEST)事件,ResourceState.INIT将变为ResourceState.DOWNLOADING
  13. 转发LocalizerResourceRequestEvent<br>(LocalizerEventType.REQUEST_RESOURCE_LOCALIZATION)事件给ResourceLocalizationService
  14. 按照资源的分类交交由PublicLocalizer和LocalizerRunner两个线程进行处理,此时该容器应该是没有对应的LocalizerRunner的,所以先进行LocalizerRunner实例化之后再启动。将PRIVATE和APPLICATION资源交给LocalizerRunner。
  15. 请求公共资源下载交给PublicLocalizer。
  16. 发送ResourceLocalizedEvent(ResourceEventType.LOCALIZED)事件,交由LocalizedResource处理。
  17. 没当一个下载完成之后,发送ContainerEventType.RESOURCE_LOCALIZED事件,触发该容器的全部资源的检查,如果还有资源没下载,就保持ContainerState.LOCALIZING,等待下次事件触发。
  18. 如果全部资源下载完成,则发送ContainerLocalizationEvent(LocalizationEventType.CONTAINER_RESOURCES_LOCALIZED)事件给ResourceLocalizationService,去销毁该容器的LocalizerRunner线程,
  19. 发送ContainerSchedulerEvent<br>(ContainerSchedulerEventType.SCHEDULE_CONTAINER)事件给ContainerScheduler。

此时ContainerState.LOCALIZING变为ContainerState.SCHEDULED

AM Container 启动与运行
ContainerScheduler ContainerImpl ContainersLauncher ContainerLaunch ContainersMonitorImpl NMLeveldbStateStoreService DefaultContainerExecutor 1. sendLaunchEvent() 2. 触发ContainersLauncherEvent (ContainersLauncherEventType.LAUNCH_CONTAINER) 3. 创建ContainerLaunch实例 由线程池启动call() 4. 触发 ContainerEvent (ContainerEventType.CONTAINER_LAUNCHED) LaunchTransition() 5. 触发 ContainerStartMonitoringEvent (ContainersMonitorEventType.START_MONITORING_CONTAINER) 6. 存储ContainerLaunched信息 storeContainerLaunched() 7. 启动容器 launchContainer ContainerScheduler ContainerImpl ContainersLauncher ContainerLaunch ContainersMonitorImpl NMLeveldbStateStoreService DefaultContainerExecutor
  1. 尝试启动pending的容器们,在资源满足情况的前提下,遍历容器,按队列顺序向ContainerImpl发送启动事件,直到无法满足。

  2. 向容器启动器发送ContainersLauncherEvent<br>(ContainersLauncherEventType.LAUNCH_CONTAINER)事件

  3. 创建ContainerLaunch实例,并由线程池启动该实例线程

  4. 更新容器信息到对应的日志目录和工作目录,将待运行的 Container 所需的环境和运行命令写到 Shell 脚本中launch_container.sh 脚本中,并将启动该脚本的命令写入 default_container_executro.sh 中,然后通过该脚本启动 Container。在这里主要对执行的环境和内容进行相关配置。ContainerState.SCHEDULED将变为ContainerState.RUNNING

  5. 发送ContainerStartMonitoringEvent事件,开启容器监控。此刻以及认为容器以及启动了。

  6. 将容器的启动信息更新进持久化存储

  7. 发送启动命令给默认容器执行器(DefaultContainerExecutor),真正启动 Container。

    在DefaultContainerExecutor的launchContainer方法中会执行bash default_container_executor.sh命令,default_container_executor.sh脚本的包含部分内容有:,其中huatuo是队列名称,/data10/yarn是配置yarn.nodemanager.local-dirs的值。

    /bin/bash "/data10/yarn/usercache/huatuo/appcache/application_1723033197835_26906/container_e87_1723033197835_26906_01_000001/default_container_executor.sh"
    

    调用了default_container_executor_session.sh脚本

    #!/bin/bash
    ...
    exec /bin/bash "/data10/yarn/usercache/huatuo/appcache/appcache/application_1723033197835_26906/container_e87_1723033197835_26906_01_000001/launch_container.sh"
    

    最后调用了launch_container.sh脚本,内容如下:

    ...
    echo "Launching container"
    exec /bin/bash -c "$JAVA_HOME/bin/java -server -Djava.net.preferIPv6Addresses=false -XX:+IgnoreUnrecognizedVMOptions --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens=java.base/jdk.internal.ref=ALL-UNNAMED --add-opens=java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.base/sun.nio.cs=ALL-UNNAMED --add-opens=java.base/sun.security.action=ALL-UNNAMED --add-opens=java.base/sun.util.calendar=ALL-UNNAMED --add-opens=java.security.jgss/sun.security.krb5=ALL-UNNAMED -Djdk.reflect.useDirectMethodHandle=false -Xmx2048m -Djava.io.tmpdir=$PWD/tmp '-XX:MaxMetaspaceSize=512m' '-XX:+PrintGCDetails' '-XX:+PrintGCDateStamps' '-XX:+UseParNewGC' '-XX:+UseConcMarkSweepGC' '-XX:CMSInitiatingOccupancyFraction=70' '-XX:+UseCMSInitiatingOccupancyOnly' '-XX:+ExplicitGCInvokesConcurrent' '-XX:ParallelGCThreads=4' '-XX:ConcGCThreads=2' '-XX:GCTimeLimit=90' '-XX:GCHeapFreeLimit=10' '-XX:OnOutOfMemoryError=kill %p' '-Dfastjson.parser.safeMode=true' -Xloggc:/data10/logs/application_1723033197835_26906/container_e87_1723033197835_26906_01_000001/gclog -Dspark.yarn.app.container.log.dir=/data10/logs/application_1723033197835_26906/container_e87_1723033197835_26906_01_000001 org.apache.spark.deploy.yarn.ApplicationMaster --class 'com.suning.bigquery.worker.BigqueryWorker' --jar file:/home/bigquery/software/bigquery-3.0.2/lib/worker/bigquery-worker-3.0.2.jar --arg 'huatuo' --arg '0' --arg 'namenode1-sit.cnsuning.com:2015,namenode2-sit.cnsuning.com:2015,slave01-sit.cnsuning.com:2015' --properties-file $PWD/__spark_conf__/__spark_conf__.properties --dist-cache-conf $PWD/__spark_conf__/__spark_dist_cache__.properties 1> /data10/logs/application_1723033197835_26906/container_e87_1723033197835_26906_01_000001/stdout 2> /data10/logs/application_1723033197835_26906/container_e87_1723033197835_26906_01_000001/stderr"
    

    这个container是个Spark任务,所以这里调用的是org.apache.spark.deploy.yarn.ApplicationMaster,并将标准输出写到stdout中,将标准错误输出写到stderr中。这也就是container的log目录里有三个文件的原因。至此,AM Container启动完毕。

NM RM心跳交互触发调度更新Container的状态

NodeStatusUpdaterImpl ResourceTrackerService RMNodeImpl FairScheduler AbstractYarnScheduler containerLaunchedOnNode RMContainerImpl NM上的定时触发项RM进行心跳交互 1.NM向RM进行心跳交互 nodeHeartbeat(request) 2.触发RMNodeStatusEvent (RMNodeEventType.STATUS_UPDATE) StatusUpdateWhenHealthyTransition() 3.触发NodeUpdateSchedulerEvent (SchedulerEventType.NODE_UPDATE) nodeUpdate() 4. nodeUpdate() 5. containerLaunchedOnNode() 3. 触发 RMContainerEvent (RMContainerEventType.LAUNCHED) nodeUpdate() NodeStatusUpdaterImpl ResourceTrackerService RMNodeImpl FairScheduler AbstractYarnScheduler containerLaunchedOnNode RMContainerImpl

RMContainerState.ACQUIRED, RMContainerState.RUNNING

AM启动之后怎么注册到RM上

不同的任务类型在AM Container 启动的类不同,由这个l类管理进行AM注册到RM上

  • mapreduce任务的AM上启动类:org.apache.hadoop.mapreduce.v2.app.MRAppMaster

  • spark任务的AM上启动类:org.apache.spark.deploy.yarn.ApplicationMaster

  • flink任务的AM上启动类:org.apache.flink.yarn.entrypoint.YarnApplicationClusterEntryPoint

以MRAppMaster为例:

MRAppMaster RMContainerAllocator RMCommunicator ApplicationMasterService AMSProcessingChain DefaultAMSProcessor RMAppAttemptImpl RMAppImpl 1.创建实例 2.serviceInit() 3.serviceStart() 4.registerApplicationMaster() 与RM基于ApplicationMasterProtocol协议建立连接 5.registerApplicationMaster() 6.registerApplicationMaster() 7. 触发 RMAppAttemptRegistrationEvent (RMAppAttemptEventType.REGISTERED) AMRegisteredTransition() 8. 触发 RMAppEvent (RMAppEventType.ATTEMPT_REGISTERED) AMRegisteredTransition() MRAppMaster RMContainerAllocator RMCommunicator ApplicationMasterService AMSProcessingChain DefaultAMSProcessor RMAppAttemptImpl RMAppImpl
  1. Container启动的时候会去加载实例化MRAppMaster类,由MRAppMaster类中去创建RMContainerAllocator。
  2. 通过服务框架进行服务的初始化
  3. 通过服务框架进行服务的启动
  4. 与RM基于ApplicationMasterProtocol协议建立连接,调用执行ApplicationMasterService的registerApplicationMaster方法,
  5. 通过AMS处理链进行转发
  6. 获取节点上的需要更新的Container,即是获取nodeUpdateQueue队列中的元素,其中包含了新启动的Container。
  7. 触发 RMAppAttemptRegistrationEvent (RMAppAttemptEventType.REGISTERED) 事件,执行AMRegisteredTransition方法,RMAppAttemptState.ALLOCATED将变成RMAppAttemptState.RUNNING,
  8. 触发 RMAppEvent (RMAppEventType.ATTEMPT_REGISTERED) 事件,执行方法AMRegisteredTransition(),RMAppState.ACCEPTED将变成RMAppState.RUNNING

AM怎么申请运行其他Container

以MRAppMaster为例:

在MRAppMaster启动中会创建一个JobImpl,由JobImpl计算出需要的MapTasks和ReduceTasks的个数。在RMCommunicator中会独立有一个AllocatorRunnable线程,在注册AM之后,会启动该线程,通过心跳机制,请求与RM中ApplicationMasterService服务的allocate方法,进行资源申请的调度。

MRAppMaster RMContainerAllocator AllocatorRunnable RMContainerRequestor TaskAttemptImpl ContainerLauncherImpl RMCommunicator ApplicationMasterService ContainerManagerImpl 1.创建实例 2.serviceInit() 3.serviceStart() 与RM通信 4.registerApplicationMaster() 返回RegisterApplicationMasterResponse 5.startAllocatorThread() 6.heartbeat() 7.makeRemoteRequest() 与RM通信 8.allocate() 返回AllocateResponse 返回AllocateResponse 9. TaskAttemptContainerAssignedEvent TaskAttemptEventType.TA_ASSIGNED ContainerAssignedTransition() 10. createContainerLaunchContext 11. ContainerRemoteLaunchEvent ContainerLauncher.EventType.CONTAINER_REMOTE_LAUNCH launch() 与NM通信 12. startContainers() 返回 StartContainersResponse 13. executeHeartbeatCallbacks() MRAppMaster RMContainerAllocator AllocatorRunnable RMContainerRequestor TaskAttemptImpl ContainerLauncherImpl RMCommunicator ApplicationMasterService ContainerManagerImpl

1~4为AM注册到RM上流程(同上)

  1. 在注册AM的之后,会启动分配器线程
  2. AllocatorRunnable与RMContainerAllocator之前有心跳交互
  3. 开始触发向RM申请接下来任务需要容器的资源流程
  4. 请求与RM中ApplicationMasterService服务的allocate方法,获取分配结果,去开始对task进行分配和信息填充。
  5. 检查分配的Container信息情况
  6. 为task构建启动Context信息
  7. 触发ContainerRemoteLaunchEvent(ContainerLauncher.EventType.CONTAINER_REMOTE_LAUNCH)事件,准备向分配的目标NodeManager发送启动容器的请求
  8. 向分配的目标NodeManager发送启动容器请求
  9. 从之前一些注册的心跳回调方法的队列heartbeatCallbacks中获取Runnable并执行

NM上的APP相关的任务会通过心跳机制来进行交互,更新运行情况。

【Yarn】Yarn的基本执行流程(三) 应用运行结束流程

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

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

相关文章

告别PDF格式困扰,2024年PDF转换器推荐

PDF现在已经逐渐成为了文件传输的主流格式了&#xff0c;它有保存文件页面版式的优点&#xff0c;但是这个格式编辑对大部分人来说还是不那么方便&#xff0c;日常我们还是习惯将它们转换成我们常见的 文本格式来操作。今天我分享一下可以实现PDF格式转换的pdf转换器有哪些吧。…

SX_c语言字符串赋值 “multiple definition of .. first defined here”问题_21

字符串赋值问题&#xff1a; #include <stdio.h> #include <string.h>char* my_string_cat(int position, int slot, char* content){char* gnsst NULL;static char retvalue[50];memset(retvalue, \0, sizeof(retvalue));if(position 0){//头部if(slot 0){//卡…

探索微服务架构中的动态服务发现与调用:使用 Nacos 与 Spring Cloud OpenFeign 打造高效订单管理系统

1. 背景 在现代微服务架构中&#xff0c;服务之间的通信与协作是非常重要的。Spring Cloud Alibaba 提供了一套完整的微服务解决方案&#xff0c;其中包括 Nacos 用于服务注册与发现&#xff0c;OpenFeign 用于声明式服务调用&#xff0c;Spring Cloud LoadBalancer 用于负载均…

FAISS 索引

FAISS&#xff08;Facebook AI Similarity Search&#xff09;是一个由 Facebook 开发的开源库&#xff0c;用于高效的相似性搜索和密集向量的聚类。它非常适合处理大规模的向量搜索任务&#xff0c;例如推荐系统、图像搜索、自然语言处理中的嵌入搜索等。 FAISS 文件概述 FAI…

vite 实现包的拆分

Vite 和 Rollup 是现代前端开发中两个非常流行的工具&#xff0c;它们各自有独特的用途和特点&#xff0c;但它们之间也存在一定的联系。 Vite Vite 是一个由 Vue 团队成员开发的前端构建工具&#xff0c;它的核心特点是在开发环境下提供极快的服务器启动和热模块替换&#x…

【视频讲解】SMOTEBoost、RBBoost和RUSBoost不平衡数据集的集成分类酵母数据集、治癌候选药物|数据分享...

全文链接&#xff1a;https://tecdat.cn/?p37502 分析师&#xff1a;Zilin Wu 在当今的大数据时代&#xff0c;科研和实际应用中常常面临着海量数据的处理挑战。在本项目中&#xff0c;我们拥有上万条数据&#xff0c;这既是宝贵的资源&#xff0c;也带来了诸多难题。一方面&a…

【递归回溯之floodfill算法专题练习】

1. 图像渲染 class Solution {int dx[4] {0, 0, -1, 1};int dy[4] {1, -1, 0, 0};int m, n;int oldcolor; public:vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int color) {oldcolor image[sr][sc]; // 保存原…

MySQL数据库MVCC机制底层原理详解

mvcc机制即多版本并发控制 当在事务中使用了写操作&#xff08;增删改&#xff09;语句时会给当前事务生成一个事务id&#xff0c;事务id是递增的 同时&#xff0c;对于被修改的行的数据会创建一个数据版本 &#xff0c;这个数据版本除了包含原有的字段还会包含一个事务id和一…

Linux驱动开发—创建总线,创建属性文件

文章目录 1.什么是BUS&#xff1f;1.1总线的主要概念1.2总线的操作1.3总线的实现 2.创建总线关键结构体解析2.1注册总线到系统2.2 struct bus_type *bus 解析 3.实验结果分析1. devices 目录2. drivers 目录3. drivers_autoprobe 文件4. drivers_probe 文件5. uevent 文件 4.在…

【Rust光年纪】深度解读:Rust语言中各类消息队列客户端库详细对比

选择最佳 Rust 消息队列客户端库&#xff1a;全面对比与分析 前言 随着现代应用程序的复杂性不断增加&#xff0c;消息队列成为构建可靠、高性能系统的重要组件。本文将介绍一些用于Rust语言的消息队列客户端库&#xff0c;包括AMQP、Apache Kafka、NSQ、Apache Pulsar和Rock…

开发新系统时,数据库字符集怎么选择对中文的支持最好?

在新开发的系统时,如果你希望确保中文按拼音顺序正确排序,同时支持更多的特殊字符与符号,下面是对 utf8mb4_zh_cn_ci、utf8mb4_unicode_ci 和 utf8mb4_unicode_520_ci 这几种字符集和校对规则的分析以及推荐方案: 校对规则分析 utf8mb4_zh_cn_ci: 特点:这是专为简体中文…

goalng http client的MaxIdleConnsPerHost,MaxIdleConns,MaxConnsPerHost参数设置总结

MaxIdleConnsPerHost&#xff1a;优先设置这个&#xff0c;决定了对于单个Host需要维持的连接池大小。该值的合理确定&#xff0c;应该根据性能测试的结果调整。MaxIdleConns&#xff1a;客户端连接单个Host&#xff0c;不少于MaxIdleConnsPerHost大小&#xff0c;不然影响MaxI…

数据压缩(2)——变长编码

【定长编码】 变长和定长是很基本的概念&#xff0c;不光是在数据压缩&#xff0c;在其他很多地方都可以见到&#xff0c;这里就不多说了。 前文说过&#xff0c;在数据压缩时&#xff0c;我们需要用某些字符A替换或修改某些字符B&#xff0c;字符A占用的存储空间更小一些。 …

【力扣】划分为k个相等的子集

&#x1f525;博客主页&#xff1a; 我要成为C领域大神&#x1f3a5;系列专栏&#xff1a;【C核心编程】 【计算机网络】 【Linux编程】 【操作系统】 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 给定一个整数数组 …

超越基础:Visual Basic在科学计算与数据分析的革新应用

标题&#xff1a;超越基础&#xff1a;Visual Basic在科学计算与数据分析的革新应用 Visual Basic&#xff08;VB&#xff09;&#xff0c;最初以其易于学习和使用而闻名&#xff0c;常被视为入门级编程语言。然而&#xff0c;VB的潜力远不止于简单的应用程序开发。在科学计算…

WHAT - 综合书单推荐

拥有一个成功的人生&#xff0c;书籍确实是一个重要的知识来源。可以将书籍分为几个主要类别&#xff0c;每个类别对应不同的知识领域和成长方向。以下是一些建议的分类及每类书籍推荐&#xff1a; 1. 个人发展与心理学 《如何赢得朋友与影响他人》 - 戴尔卡耐基《思考&#…

【qt】锁

线程安全问题. 多线程程序太复杂了. 加锁 把多个线程要访问的公共资源&#xff0c;通过锁保护起来.>把并发执行变成串行执行. Linux mutex 互斥量. C11引入std::mutex Qt 同样也提供了对应的锁&#xff0c;来针对系统提供的锁进行封装.QMutex 多个线程进行加锁的对象&…

example-apisix-1 清空日志之后启动异常处理

异常信息 2024/08/27 11:34:33 [emerg] 1#1: bind() to unix:/usr/local/apisix/conf/config_listen.sock failed (98: Address already in use) nginx: [emerg] bind() to unix:/usr/local/apisix/conf/config_listen.sock failed (98: Address already in use) 2024/08/27 1…

【生日视频制作】室内告白表白祝福布置霓虹灯AE模板修改文字软件生成器教程特效素材【AE模板】

室内告白表白祝福布置霓虹灯生日视频制作教程AE模板改字生成器 怎么如何做的【生日视频制作】室内告白表白祝福布置霓虹灯AE模板修改文字软件生成器教程特效素材【AE模板】 生日视频制作步骤&#xff1a; 安装AE软件下载AE模板把AE模板导入AE软件修改图片或文字渲染出视频

【Go - 每日一小问: 对未初始化的的 chan 进行读写,会怎么样?为什么?】

对未初始化的 chan 进行读写会有不同的行为&#xff1a; 1. 对未初始化的 chan 进行读取 读取操作&#xff1a; 对未初始化的 chan 进行读取操作会导致永久阻塞&#xff08;deadlock&#xff09;&#xff0c;因为没有任何 goroutine 可以向这个 chan 发送数据。读取操作会一直…