深入理解 Flink(五)Flink Standalone 集群启动源码剖析
前言
Flink 集群的逻辑概念:
JobManager(StandaloneSessionClusterEntrypoint) + TaskManager(TaskManagerRunner)
Flink 集群的物理概念:
ResourceManager(管理集群所有资源,管理集群所有从节点) + TaskExecutor(管理从节点资源,接收 Task 部署执行)
在 Flink 不同的部署模式下(Standalone、YARN、K8S 等)只是最外层的封装略有区别,实际运行的内核并无差异。因此本文以 Standalone 集群为例,剖析 Flink 集群的启动源码。
Flink 集群启动脚本分析
Flink 集群的启动脚本位于 flink-dist 子项目中,flink-bin 下的 bin 目录:
start-cluster.sh
根据具体组件的不同,脚本会按照以下流程执行:
Flink 主节点 StandaloneSessionClusterEntrypoint 启动源码分析
JobManager 是 Flink 集群的主节点,它包含三大重要的组件:
1、ResourceManager
Flink 的集群资源管理器,只有一个,关于 slot 的管理和申请等工作,都由它负责
2、DispatcherRunner
负责接收用户提交的 JobGragh, 然后启动一个 JobMaster, JobMaster 类似于 YARN 集群中的 AppMaster 角色,类似于 Spark Job 中的 Driver 角色。内部有一个持久服务:JobGraghStore,用来存储提交到 JobManager 中的 Job 的信息,也可以用作主节点宕机之后做 job 恢复之用。
3、WebMonitorEndpoint
里面维护了很多很多的 Handler,也还会启动一个 Netty 服务端,用来接收外部的 rest 请求。如果客户端通过 flink run 的方式来提交一个 job 到 flink 集群,最终是由 WebMonitorEndpoint 来接收处理,经过路由解析处理之后决定使用哪一个 Handler 来执行处理。Router 路由器 绑定了一大堆 Handler,例如:submitJob ===> JobSubmitHandler。
这里简单说明一下 Flink 的资源管理架构,后续章节会展开详述:
ResourceManager: 全局资源管理者 => SlotManager
JobMaster: 资源使用者 => SlotPool
TaskExecutor:资源提供者 => TaskSlotTable
以上三者的内部,都有一个专门用来做 slot 管理的一个组件。对应的要启动这三个组件,都有一个对应的 Factory,也就说,如果需要创建这些组件实例,那么都是通过这些 Factory 来创建。而这三个 Facotry 最终都会被封装在一个 ComponentFactory 中。
StandaloneSessionClusterEntrypoint main 方法
// 入口,解析命令行参数 和 配置文件 flink-conf.yaml
StandaloneSessionClusterEntrypoint.main(){ClusterEntrypoint.runClusterEntrypoint(entrypoint){// 启动插件组件,配置文件系统实例等clusterEntrypoint.startCluster(){runCluster(configuration, pluginManager){// 第一步:初始化各种服务(8个基础服务)// 比较重要的:HAService,BlobServer, RpcServices, HeatbeatServices,....initializeServices(configuration, pluginManager);// 第二步:创建 DispatcherResourceManagerComponentFactory, 初始化各种组件的工厂实例// 其实内部包含了三个重要的成员变量:// 创建 ResourceManager 的工厂实例// 创建 DispatcherRunner 的工厂实例// 创建 WebMonitorEndpoint 的工厂实例createDispatcherResourceManagerComponentFactory(configuration);// 第三步:创建 集群运行需要的一些组件:WebMonitorEndpoint,DispatcherRunner, ResourceManager 等// 创建和启动 ResourceManager// 创建和启动 DispatcherRunner// 创建和启动 WebMonitorEndpointclusterComponent = dispatcherResourceManagerComponentFactory.create(...);}}}
}
基础服务组件初始化
initializeServices(){// 初始化和启动 AkkaRpcService,内部其实包装了一个 ActorSystemcommonRpcService = AkkaRpcServiceUtils.createRemoteRpcService(...);// 启动一个 JMXService,用于客户端链接 JobManager JVM 进行监控JMXService.startInstance(configuration.getString(JMXServerOptions.JMX_SERVER_PORT));// 初始化一个负责 IO 的线程池, Flink 大量使用了 异步编程。// 这个线程池的线程的数量,默认是:cpu core 个数 * 4ioExecutor = Executors.newFixedThreadPool(...);// 初始化 HA 服务组件,负责 HA 服务的是:ZooKeeperHaServiceshaServices = createHaServices(configuration, ioExecutor);// 初始化 BlobServer 服务端blobServer = new BlobServer(configuration, haServices.createBlobStore());blobServer.start();// 初始化心跳服务组件, heartbeatServices = HeartbeatServicesheartbeatServices = createHeartbeatServices(configuration);// 启动 metrics(性能监控) 相关的服务,内部也是启动一个 ActorSystemMetricUtils.startRemoteMetricsRpcService(configuration, commonRpcService.getAddress());// 初始化一个用来存储 ExecutionGraph 的 Store, 实现是:FileArchivedExecutionGraphStorearchivedExecutionGraphStore = createSerializableExecutionGraphStore(...);
}
重要组件工厂实例初始化
DispatcherRunnerFactory,默认实现:DefaultDispatcherRunnerFactory,生产 DefaultDispatcherRunner
ResourceManagerFactory,默认实现:StandaloneResourceManagerFactory,生产 StandaloneResourceManager
RestEndpointFactory,默认实现:SessionRestEndpointFactory,生产 DispatcherRestEndpoint
三大重要组件初始化
Flink 源码中,三大重要组件初始化按照一下流程进行:
三大重要组件初始化源码解析
WebMonitorEndpoint 启动和初始化源码剖析
核心入口:
DispatcherResourceManagerComponentFactory.create(...)
启动流程:
- 初始化一大堆 Handler 和 一个 Router,并且进行排序去重,之后,再把每个 Handler 注册 到 Router 当中。
- 启动一个 Netty 的服务端。
- 启动内部服务:执行竞选。WebMonitorEndpoint 本身就是一个 LeaderContender 角色。如果竞选成功,则回调 isLeader() 方法。
- 竞选成功,其实就只是把 WebMontiroEndpoint 的 address 以及跟 zookeeper 的 sessionID 写入到 znode 中。
- 启动一个关于 ExecutionGraph 的 Cache 的定时清理任务。
ResourceManager 启动和初始化源码剖析
核心入口:
DispatcherResourceManagerComponentFactory.create(...)
启动流程:
1、ResourceManager 是 RpcEndpoint 的子类,所以在构建 ResourceManager 对象完成之后,肯定会调用 start() 方法来启动这个 RpcEndpoint,然后就跳转到它的 onStart() 方法执行。
2、ResourceManager 是 LeaderContender 的子类,会通过 LeaderElectionService 参加竞选,如果竞选成功,则会回调 isLeader() 方法。
3、启动 ResourceManager 需要的一些服务:两个心跳服务ResourceManager 和 TaskExecutor 之间的心跳ResourceManager 和 JobMaster 之间的心跳两个定时服务checkTaskManagerTimeoutsAndRedundancy() 检查 TaskExecutor 的超时checkSlotRequestTimeouts() 检查 SlotRequest 超时
DispatcherRunner 启动和初始化源码剖析
核心入口:
DispatcherResourceManagerComponentFactory.create(...)
启动流程:
1、启动 JobGraphStore 服务
2、从 JobGraphStrore 恢复执行 Job, 要启动 Dispatcher
从节点 TaskManagerRunner 启动源码分析
TaskManager 是 Flink 的 worker 节点,负责 Flink 中本机 slot 资源的管理以及具体 task 的执行。
TaskManager 上的基本资源单位是 slot,一个作业的 task 最终会部署在一个 TaskManager 的 slot 上运行,TaskManager 会负责维护本地的 slot 资源列表,并与 Flink Master 和 JobMaster 通信。
// 核心启动入口
TaskManagerRunner.main(args){runTaskManagerSecurely(args, ResourceID.generate()){// 加载配置:解析 args 和 flink-conf.yaml 得到配置信息Configuration configuration = loadConfiguration(args);// 启动 TaskManager// 在Flink 当中,所有的组件(跟资源有关)都有一个 ResourceID// 后续还会见到很多的类似的ID的概念:AllocationIDrunTaskManagerSecurely(configuration, resourceID){// 启动 TaskManager// 这个具体实现是:首先初始化 TaskManagerRunner, TaskManager 启动中,要初始化的一些服务,都是在这个构造方法里面!// 最后,再调用 TaskManagerRunner.start() 来启动,然后跳转到 TaskExecutor 的 onStart() 开启注册。runTaskManager(configuration, resourceID, pluginManager){// 第一步:构建 TaskManagerRunner 实例// 具体实现中也做了两件事:// 第一件事: 初始化了一个 TaskManagerServices 对象! 其实这个动作就类似于 JobManager 启动的时候的第一件大事(启动8个服务)// 第二件是: 初始化 TaskExecutor(Standalone 集群中提供资源的角色,ResourceManager 其实就是管理集群中的从节点的管理角色)// TaskExecutor 它是一个 RpcEndpoint,意味着,当 TaskExecutor 实例构造完毕之后,启动 RPC 服务就会跳转到 onStart() 方法taskManagerRunner = new TaskManagerRunner(...){// 初始化一个线程池 ScheduledThreadPoolExecutor 用于处理回调this.executor = Executors.newScheduledThreadPool(....)// 获取高可用模式:ZooKeeperHaServiceshighAvailabilityServices = HighAvailabilityServicesUtils.createHighAvailabilityServices(...)// 初始化 JMXServer 服务JMXService.startInstance(configuration.getString(JMXServerOptions.JMX_SERVER_PORT));// 创建 RPC 服务rpcService = createRpcService(configuration, highAvailabilityServices);// 创建心跳服务heartbeatServices = HeartbeatServices.fromConfiguration(conf);// 创建 BlobCacheService,内部会启动两个定时任务:PermanentBlobCleanupTask 和 TransientBlobCleanupTaskblobCacheService = new BlobCacheService(....);// 创建 TaskExecutorService,内部其实就是创建 TaskExecutor 并且启动,详细内容如下一部分阐述。taskExecutorService = taskExecutorServiceFactory.createTaskExecutor(....){// 创建 TaskExecutorToServiceAdapter,内部封装 TaskExecutor,它是 TaskManagerRunner 的成员变量TaskManagerRunner::createTaskExecutorService;}}// 第二步:启动 TaskManagerRunner,然后跳转到 TaskExecutor 中的 onStart() 方法taskManagerRunner.start(){taskExecutor.start();}}}}
}
TaskManager/TaskExecutor 注册
TaskManager 是一个逻辑抽象,代表一台服务器,这台服务器的启动,必然会包含一些服务,另外再包含一个 TaskExecutor,存在于 TaskManager 的内部,真实的帮助 TaskManager 完成各种核心操作,比如:
1、部署和执行 StreamTask
2、管理和分配 slot
监听和获取 ResourceManager 的地址
核心入口为:resourceManagerLeaderRetriever 的 start() 方法,具体实现方式见前面章节:
https://blog.csdn.net/weixin_44512041/article/details/135493920
在注册监听之后,如果发生了对应的事件,则会收到一个响应,然后回调:
ResourceManagerLeaderListener.notifyLeaderAddress();
内部详细实现:
// 关闭原有的 ResouceManager 的链接
closeResourceManagerConnection(cause);
// 开启注册超时的延时调度任务
startRegistrationTimeout();
// 当前 TaskExecutor 完成和 ResourceManager 的链接
tryConnectToResourceManager();
最重要的是第三步,TaskExecutor 和 ResourceManager 建立连接,会进行注册,心跳,Slot 汇报 三件大事。
TaskExecutor 开始注册
核心入口:
TaskExecutorToResourceManagerConnection.start();
TaskExecutor 注册失败
核心入口:
TaskExecutorToResourceManagerConnection.onRegistrationFailure(failure);
TaskExecutor 注册成功
核心入口:
TaskExecutorToResourceManagerConnection.onRegistrationSuccess(result.f1);
TaskExecutor 进行 Slot 汇报
当注册成功,ResourceManager 会返回 TaskExecutorRegistrationSuccess 对象。然后回调下面的方法,进入到 slot 汇报的过程。
TaskExecutorToResourceManagerConnection.onRegistrationSuccess(TaskExecutorRegistrationSuccess success);// 继续回调ResourceManagerRegistrationListener.onRegistrationSuccess(this, success);// 封装链接对象establishResourceManagerConnection(resourceManagerGateway, resourceManagerId, taskExecutorRegistrationId, ....);// 内部实现resourceManagerGateway.sendSlotReport(getResourceID(),taskExecutorRegistrationId,taskSlotTable.createSlotReport(getResourceID()), taskManagerConfiguration.getTimeout());
TaskExecutor 和 ResourceManager 心跳
Flink 中 ResourceManager、JobMaster、TaskExecutor 三者之间存在相互检测的心跳机制,ResourceManager 会主动发送请求探测 JobMaster、TaskExecutor 是否存活,JobMaster 也会主动发送请求探测 TaskExecutor 是否存活,以便进行任务重启或者失败处理。
假定心跳系统中有两种节点:sender 和 receiver。心跳机制是 sender 和 receivers 彼此相互检测。但是检测动作是 Sender 主动发起,即 Sender 主动发送请求探测 receiver 是否存活,因为 Sender 已经发送过来了探测心跳请求,所以这样 receiver 同时也知道 Sender 是存活的,然后 Reciver 给 Sender 回应一个心跳表示自己也是活着的。具体表现:
- Flink Sender 主动发送 Request 请求给 Receiver,要求 Receiver 回应一个心跳;
- Flink Receiver 收到 Request 之后,通过 Receive 函数回应一个心跳请求给 Sender;
ResourceManager 端心跳服务启动
ResourceManager 在初始化的最后,执行了:
ResourceManager.startHeartbeatServices();
启动了两个心跳服务:
// 维持 TaskExecutor 和 ResourceManager 之间的心跳
taskManagerHeartbeatManager = heartbeatServices.createHeartbeatManagerSender(resourceId, new TaskManagerHeartbeatListener(),
getMainThreadExecutor(), log);
// 维持 JobMaster 和 ResourceManager 之间的心跳
jobManagerHeartbeatManager = heartbeatServices.createHeartbeatManagerSender(resourceId, new JobManagerHeartbeatListener(),
getMainThreadExecutor(), log);
具体是构造了一个 HeartbeatManagerSenderImpl 实例对象,并且调用了:
mainThreadExecutor.schedule(this, 0L, TimeUnit.MILLISECONDS);
heartbeatMonitor 内部封装了一个 heartbeatTarget,对于 ResourceManager 来说,每个注册成功的 TaskExecutor 都会被构建成一个 HeartbeatTarget ,然后构建成一个 heartbeatMonitor。这个可以在 ResourceManager 端完成 TaskExecutor 注册的时候进行验证。
当 ResourceManager 端完成一个 TaskExecutor 的注册的时候,马上调用:
// 维持心跳
taskManagerHeartbeatManager.monitorTarget(taskExecutorResourceId, new HeartbeatTarget<Void>() {@Overridepublic void receiveHeartbeat(ResourceID resourceID, Void payload) {}@Overridepublic void requestHeartbeat(ResourceID resourceID, Void payload) {// 给 TaskExecutor 发送心跳请求taskExecutorGateway.heartbeatFromResourceManager(resourceID);}
});
这样子,刚才注册的 TaskExecutor 就先被封装成一个 HeartbeatTarget, 然后被加入到 taskManagerHeartbeatManager 进行管理的时候,变成了 HeartbeatMonitor。当这句代码完成执行的时候,当前 ResourceManager 的心跳目标对象,就多了一个 TaskExecutor,然后当执行:
taskExecutorGateway.heartbeatFromResourceManager(resourceID);
就给 TaskExecutor 发送了一个心跳请求。
TaskExecutor 端心跳处理
当 TaskExecutor 接收到 ResourceManager 的心跳请求之后,进入内部实现:
TaskExecutor.heartbeatFromResourceManager(ResourceID resourceID);// 内部实现resourceManagerHeartbeatManager.requestHeartbeat(resourceID, null);// 内部实现reportHeartbeat(requestOrigin);// 第一件事:进行心跳报告heartbeatMonitor.reportHeartbeat();// 记录最后一次的心跳时间lastHeartbeat = System.currentTimeMillis();// 重设心跳超时相关的 时间 和 延迟调度任务resetHeartbeatTimeout(heartbeatTimeoutIntervalMs);// 先取消cancelTimeout();// 再重新调度futureTimeout = scheduledExecutor.schedule(this, heartbeatTimeout, TimeUnit.MILLISECONDS);// TaskExecutor 进行负载汇报heartbeatTarget.receiveHeartbeat(.....);// 给 ResourceManager 回复 TaskExecutor 的负载。resourceManagerGateway.heartbeatFromTaskManager(resourceID, heartbeatPayload);
如果连续 5 次心跳请求没有收到,也就是说,如果 50s 内都没有收到心跳请求,则执行心跳超时处理。
heartbeatListener.notifyHeartbeatTimeout(resourceID);
超时处理也非常的暴力有效,Flink 认为: 如果 TaskExecutor 收不到 ResourceManager 的心跳请求了,则认为当前 ResourceManager 死掉了。但是 Flink 集群肯定会有一个 active 的 ResourceManager 节点的。而且之前也注册过监听,如果 Flink HA 集群的 Active 节点发生迁移,则 TaskExecutor 也一定已经收到过通知了,然后现在需要做的,只是重新链接到新的 active ResourceManager 即可。
reconnectToResourceManager(new TaskManagerException(String.format("The heartbeat of ResourceManager with id %s timed out.", resourceId))
);
TaskExecutor 向 ResourceManager 汇报负载
核心入口:HeartBeatManagerImpl 的 requestHeartbeat() 方法的最后一句代码:
heartbeatTarget.receiveHeartbeat(getOwnResourceID(), heartbeatListener.retrievePayload(requestOrigin));
相关文章:

深入理解 Flink(五)Flink Standalone 集群启动源码剖析
前言 Flink 集群的逻辑概念: JobManager(StandaloneSessionClusterEntrypoint) TaskManager(TaskManagerRunner) Flink 集群的物理概念: ResourceManager(管理集群所有资源,管理集群所有从节点) TaskExecutor(管理从节点资源,接…...

SpringCloud Aliba-Nacos-从入门到学废【2】
🥚今日鸡汤🥚 比起不做而后悔,不如做了再后悔。 ——空白《游戏人生》 目录 🧈1.Nacos集群架构说明 🧂2.三种部署模式 🍿3.切换到mysql 1.在nacos-server-2.0.3\nacos\conf里找到nacos-mysql.sql 2.查…...

web前端算法简介之字典与哈希表
回顾 栈、队列 : 进、出 栈(Stack): 栈的操作主要包括: 队列(Queue): 队列的操作主要包括: 链表、数组 : 多个元素存储组成的 简述链表:数组&…...

【uview2.0】Keyboard 键盘 与 CodeInput 验证码输入 结合使用 uview
https://www.uviewui.com/components/codeInput.html (CodeInput 验证码输入) https://www.uviewui.com/components/keyboard.html (Keyboard 键盘) <u-keyboard mode"number" :dotDisabled"true" :show&q…...
解决chromebook kabylake安装linux没有声音问题
chromebook kabylake安装arch没有声音,好长时间没有解决,一直用的蓝牙耳机。 今天搜搜帖子解决了, 分享供参考 git clone https://github.com/eupnea-project/chromebook-linux-audiocd chromebook-linux-audio ./setup-audio提示 I Underst…...

Spring Boot - Application Events 的发布顺序_ApplicationContextInitializedEvent
文章目录 Pre概述Code源码分析 Pre Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEvent Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEvent 概述 Spring Boot 的广播机制是基于观察者模式实现的,…...
由jar包冲突导致的logback日志不输出
最近接手一个厂商移交的项目,发现后管子系统不打印日志。 项目使用的logback 本地断点调试发现logback-classic jar冲突导致 打出的war中没有 相关的jar 解决方法: 去除pom 文件中多余的 logback-classic 应用,只保留最新版本的。 重新打…...
app开发——安卓native开发思路记录
我们知道app开发目前有三种方式,第一种是webapp,第二种是hybird app,第三种是native app。 而native-app就是安卓原生app,这里记录一下安卓原生开发的基本思路。 首先,安卓原生开发虽然在当今时代不是那么常见了&…...

黑马程序员JavaWeb开发|案例:tlias智能学习辅助系统(1)准备工作、部门管理
一、准备工作 1.明确需求 根据产品经理绘制的页面原型,对部门和员工进行相应的增删改查操作。 2.环境搭建 将使用相同配置的不同项目作为Module放入同一Project,以提高相同配置的复用性。 准备数据库表(dept, emp) 资料中包含…...

C# .NET SQL sugar中 IsAny进行根据条件判断数据是否存在 IsAny的使用
SQL sugar 中控制器直接判断数据是否存在 首先确保你的Service层继承的表名 控制器中使用IsAny进行根据条件判断数据是否存在...

《Git学习笔记:Git入门 常用命令》
1. Git概述 1.1 什么是Git? Git是一个分布式版本控制工具,主要用于管理开发过程中的源代码文件(Java类、xml文件、html页面等),在软件开发过程中被广泛使用。 其它的版本控制工具 SVNCVSVSS 1.2 学完Git之后能做…...
小程序跳转安卓会跳转两次 iOS不会的解决方案
原因:元素点击事件在子元素上有绑定,父元素上也有绑定会形成冒泡事件; 原生小程序: bind:tap:会冒泡; <view bind:tap"gotoDetail"><image :src"{{ item2.img }}" mode&qu…...
vue3+ts 中实现压缩图片、blob 转 base64
压缩图片 1.npm 安装 image-compressor.js 2.引入 import ImageCompressor from image-compressor.js 3.使用 const compressImage async (file: any) > {var imageCompressor new ImageCompressor()return new Promise((resolve, reject) > {imageCompressor.comp…...
(框架设计-基础库建设) boost 库
“框架”这个词所有的开发都听过,但是有多少人能理解框架的作用?为什么要花那么大精力去弄一个框架?大家应该都听过各个大厂稍微大点的项目都会有一个“框架组”/“架构组”等。 费这么大人力组建一个组来 做框架/架构 到底值不值呢ÿ…...
将ResultSet转实体类
将ResultSet转实体类 sqlExecutor.executeQuery的执行结果的返回值是ResultSet:package java.sql; 一般在程序中我们需要把查询结果转为实体类返回给前端,此处可以使用的方法: ResultSet转实体类方法1 2 1:resultSet.getXXX(columnIndex)…...

Web后端开发
一、Maven 1.1 简介 1.2 作用 1.3 流程 通过各种插件实现项目的标准化构建。 1.4 安装 1.5 配置环境 1.5.1 当前工程环境 1.5.2 全局环境 1.6 创建 Maven项目 1.7 导入项目 1.8 依赖管理 1.8.1 依赖配置 1.8.2 依赖传递 pom.xml——右键——Diagrams——show dependen…...

CAN201 计网概念收集
Lecture 1 the theoretical basis for networking Network edge and core 地理覆盖范围:广WAN,城MAN,局LAN,个PAN 交换方式,电路,报文,分组 电路交换vs报文vs分组 Network performance pr…...

【占用网络】FlashOcc:快速、易部署的占用预测模型
前言 FlashOcc是一个它只需2D卷积就能实现“占用预测模型”,具有快速、节约内存、易部署的特点。 它首先采用2D卷积提取图形信息,生成BEV特征。然后通过通道到高度变换,将BEV特征提升到3D空间特征。 对于常规的占用预测模型,将…...
239.【2023年华为OD机试真题(C卷)】求幸存者之和(模拟跳数-JavaPythonC++JS实现)
🚀点击这里可直接跳转到本专栏,可查阅顶置最新的华为OD机试宝典~ 本专栏所有题目均包含优质解题思路,高质量解题代码(Java&Python&C++&JS分别实现),详细代码讲解,助你深入学习,深度掌握! 文章目录 一. 题目-求幸存数之和二.解题思路三.题解代码Python题解…...
Pytorch中的标准维度顺序
在PyTorch中,如果一个张量包括通道数(C)、宽度(W)、高度(H)和批量大小(N),那么它的标准维度顺序是 [N, C, H, W],即: 第一个维度 N 是…...

Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...

黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门 函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...

python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
Xen Server服务器释放磁盘空间
disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...