Unite Shanghai 2024 团结引擎专场 | 团结引擎 OpenHarmony 工程剖析
在 2024 年 7 月 24 日的 Unite Shanghai 2024 团结引擎专场演讲中,Unity中国 OpenHarmony 技术负责人刘伟贤对团结引擎导出的 OpenHarmony 工程进行了细节剖析,详细讲解 XComponent 如何与引擎结合,UI 线程和引擎线程的关联以及 ts/ets 的代码如何与引擎功能进行交互。帮助大家在接入 SDK 以及 OpenHarmony 系统能力调用方面有更深入的了解。
刘伟贤:大家下午好!今天在这里带来的分享是《团结引擎 OpenHarmony 工程剖析》。我是刘伟贤,目前是 Unity中国 OpenHarmony 平台和车机平台的技术负责人。今天的内容一共四个部分:基本概念介绍、引擎画布-XComponent、引擎线程模型、引擎跨语言交互。
OpenHarmony 是一个全新的操作系统,其次这个系统本身在快速发展过程中,中间胶水层代码也在频繁变化,而且很多开发者对这个胶水层代码很不熟悉。因为原来的 Android 和 iOS 是有一定历史的,但是对于 OpenHarmony 来讲是全新的。所以,今天希望能通过概念和核心部分的讲解,让大家对于胶水层代码有更深入了解,从而看到 OpenHarmony 技术平台的一些技术细节。
基本概念
首先大家打开一个工程,切换到 OpenHarmony 这个平台,当我们在 BuildSettings 里面勾选 Export Project,我们就能得到一个 Ability Project,是 OpenHarmony 平台的一个原生工程,然后使用 Deveco Studio 打开这个 Ability Project,我们就能进行调试、构建等常规的操作。同时,通过 Export Project 也能窥探到所有引擎适配 OpenHarmony 的胶水代码。
首先,我们从一个项目的目录结构来窥探 Ability Project 整体的目录结构是怎么样的。开发态包结构(Stage 模型)分成 AppScope 跟 entry 这两个比较重要的目录,AppScope 是一个应用的全局配置,核心是 app.json5,去配置包名信息、版本号等。Entry 是一个模块,类似于 Android 工程的 module,但是里面会存有资源、ets 代码、ArkTS 代码、模块配置、一些配置项,还有应用级的配置信息、签名信息会在 build-profile.json5。
上面是一般 OpenHarmony Ability Project 开发包结构,但是与引擎相关的目录只有上图这些,比如说引擎所有的 so,包括要接入的 SDK 都会放到 entry/libs 目录中,引擎中所有的胶水代码都在 entry/main/ets 中,而胶水代码中还有一个关键的入口 TuanjiePlayerAbility,相当于安卓的 activity。还有 UIAbility 对应的 page 文件 TuanjiePlayerAbilityIndex.ets。除了这些以外,其他plugins代码也会自动导到这个地方。对于包内的资源,会放在 resources/rawfile/Data 中,包括 StreamingAssets, boot.config 等。这就是引擎在适配的时候,我们怎么样把引擎中的资源放到原生的 Ability Project 里面去。
上面这个图展示了在 OpenHarmony 的工程由开发态视图经过编译以后的包结构视图。可以看出刚才提到的 entry 实际上是一个 module,里面有一些 resource 和代码。我们有一个全局的 AppScope,中间可以扩展很多不同的 module。但是这里面与 Android 有一个比较大的差异,在于它的 module 实际上会编译成一个一个的 HAP,就像分成一个一个的小安装包,最终由一个 .app 把这些全部包起来。
所以说,从刚才怎么把引擎的东西放到项目中可以看出,目前引擎所有的东西都放在 entry 的 module 里面,意味着目前在 OpenHarmony 很难做到像原来安卓工程那种 uaal (use as a library) 的形式。如果要达到,我们应该把它抽象成一个自己的 module,大家可以把 module 拷出放到别的 OpenHarmony 原生应用里去集成、开发。我们后续可能会计划改成一个独立的 library 或者 module,会在后面的版本迭代掉。
我们有一个非常重要的主入口 TuanjiePlayerAbility,它类似于 Android 的 Activity。UIAbility 底下还有一个 WindowStage,它们在我们的整个胶水代码里是捆在一起的,主要做一些生命周期管理。最后有一个有别于 Android 的地方,叫做 ArkUIPage,主要做一些布局以及简单代码的实现。所以 UIAbility 组件是一种包含 UI 的应用组件,主要用于和用户交互。
在 OpenHarmony 里面, UIAbility 组件是系统调度的基本单元,为应用提供绘制界面的窗口。一个应用可以包含一个或多个 UIAbility 组件。例如,在支付应用中,可以将入口功能和收付款功能分别配置为独立的 UIAbility。每一个 UIAbility 也可以包含不同的 page,所以整体在切换上面还是相对比较灵活的。
对于开发者而言,可以根据具体场景选择单个还是多个 UIAbility,如果开发者希望在任务视图中看到一个任务,则建议使用一个 UIAbility,多个页面的方式。如果开发者希望在任务视图中看到多个任务,或者需要同时开启多个窗口,则建议使用多个 UIAbility 开发不同的模块功能。
每个 UIAbility 实例都会与一个 WindowStage 类实例绑定,该类起到了应用进程内窗口管理器的作用。它包含一个主窗口。也就是说 UIAbility 实例通过 WindowStage 持有了一个主窗口,该主窗口为 ArkUI 提供了绘制区域。
在 TuanjiePlayerAbility.ts 中,它整个生命周期就是 UIAbility 和 WindowStage 绑定在一起,UIAbility 实例创建完成之后,在进入 Foreground 之前,系统会创建一个 WindowStage。WindowStage 创建完成后会进入 onWindowStageCreate() 回调,可以在该回调中设置 UI 加载、设置 WindowStage 的事件订阅。
适配时,在 OnCreate 的时候我们主要是获取了 AbilityContext,用来做跨语言调用时需要的上下文。其次我们初始化 TuanjieMainWorker 线程。WindowStage 里面的OnForeground/onBackground对应的就是前后台切换,所以不管是OnForeground/onBackground,包括 WindowStage 的 Shown/Hidden 都会执行到引擎的 onResume/onPause。在 WindowStage 中的 Active 和 InActive 就是对应引擎的焦点获取 Focus/LostFocus。
TuanjiePlayerAbility 对应 TuanjiePlayerAbilityIndex.ets,对应的是基于 ArkUI 的声明范式的一个文件,它是方舟开发框架下的一套开发极简、高性能、支持跨设备的 UI 开发框架,包含了 ArkTS(eTS) 、布局、组件、交互事件。从上图右侧的 TuanjiePlayer 可以看到整个简单、清晰的结构。
接下来我们详细剖析 TuanjiePlayerAbility 里面对应的 page 中的内容。首先,上面是装饰器,有自定义组件 TuanjiePlayer,有点类似 Android 里面也有一个 UnityPlayer.java 的 component。其次,在 TuanjiePlayer component 中包含了一些布局信息,内置了 Xcomponent,就是我们引擎最后用来绘制的画布,要从 Xcomponent 拿到 surface,引擎用于绘制。在 Xcomponent 里面还会扩展一些事件方法,然后对应一些 log 输出,包括属性设置、宽高。
下面还可以看到我们自己定义的 TuanjiePlayer component 整个层级结构是怎么样的:一个 Xcomponent,盖着 TuanjieWebview,再盖着 SlapshScreen,再盖着 VideoPlayer,这些都像 stack 一样一层一层叠加上面,通过状态控制显示还是隐藏。所以这里面就是我们自己定义的一些控件,底下是一些属性方法。从整体文件可以看出,它的 ArkUI 写法非常舒适,可以一目了然地看到整个页面的布局、事件、属性是怎么样的。
TuanjiePlayerAbility.ts/TuanjiePlayerAbilityIndex.ets,这里面有两个文件的后缀,大家要了解 ts 代表 TypeScript,ets 代表 extented TypeScript(ArkTS 语言)。ArkTS 是 OpenHarmony 的主力应用开发语言。ArkTS 围绕应用开发在 TypeScript 生态基础上做了进一步扩展,后缀为 ets,它保持了 TS 的基本风格,在 TypeScript 的基础上扩展了声明式 UI、状态管理等相应的能力。同时通过规范定义强化开发期静态检查和分析,提升程序执行稳定性和性能。TS 是 JavaScript(简称 JS)的超集,eTS 则是 TS 的超集。从 eTS 我们可以看一些特点,包括强制使用静态类型、禁止在运行时改变对象布局、限制运算符语义、不支持 Structural typing,去掉原本动态语言的一些特性,加了一些限制,能够达到更好的编译优化,从而把整个运行的性能提升上去。
引擎画布 - Xcomponent
Xcomponent 是 OpenHarmony 提供的一个非常重要的组件,主要用来进行 EGL/OpenGLES 和媒体数据写入,并将其显示在 XComponent 组件上。它有 surface/component/texture 类型,目前团结引擎使用的是 surface 类型。同时 XComponent 组件可以和其他组件一起进行布局和渲染。我们整个 TuanjiePlayer 中除了 Xomponent 之外还叠加了一些自定义组件在上面。开发者可将相关数据传入 XComponent 单独拥有 NativeWindow 来渲染画面。
Native XComponent 是 XComponent 组件提供在 Native 层的实例,可作为 JS 层和 Native 层 XComponent 绑定的桥梁。通过 XComponet 的 libraryname,指明 so 名字,这时候就会到 C++ 层,可以在 C++ 层通过 napi 去获取 OH_NativeXComponent,然后并且注册事件回调,得到最终用来渲染的 NativeWindow。
所以从整体渲染模型来讲,我们其实在 XComponent 回调获得 NativeWindow,使用 NativeWindow 来创建 EGL/OpenGLES 环境,也满足和安卓类似的生产者-消费者模型。从上图可以看出,引擎这一层如果是一个相对原生的 OpenHarmony 应用,原生组件会走到一个渲染服务中,经过 skia 最终进行 GLES/EGL 调用。如果是自绘制的应用,基本是经过 Xcomponent 直接调用到 OpenGLES 的这些绘制指令上面去。
引擎线程模型
从整个目录结构、怎么样把引擎所要的东西合进 Ability Project,到引擎需要拿到怎么样的画布进行渲染,下一步就是引擎在 OpenHarmony 上的线程模型是怎么样的。对于所有的应用来说,我们都不希望耗时操作会对我们的 UI 交互造成卡顿,在 OpenHarmony 上也一样,我们不会把引擎和 UI 放在同一条线程上面。
TuanjiePlayer Ability 起来的时候,它有一条 ArkUI 线程,即传统意义上的 UI 线程,我们通过 threadWorker 创建一条 TuanjieMain 线程,放到 C++ 那边去,走引擎的正式启动流程。这条 TuanjieMain 线程才会再去把渲染线程、JobWoker 线程,以及脚本中会调用的 C# 线程创建出来。
在这里面,ArkUI 线程可以说是 UI 线程,主要执行 UI 绘制,管理主线程的 ArkTS 引擎实例,使多个 UIAbility 组件能够运行在其之上。同时也可以管理其他线程的 ArkTS 引擎实例,例如启动和终止 Worker 线程,处理应用代码的回调,包括事件处理和生命周期管理。
对于 Worker 线程 - TuanjieMain,它是引擎的主线程,用于执行耗时操作,支持线程间通信,因为我们有一些 UI 操作要回到主线程 UI 线程执行。但是这里面有一个非常重要的点,Worker 的上下文对象和主线程的上下文对象是不同的,一定要小心,而且 Worker 线程不支持 UI 操作,意味着 TuanjieMain 线程不能进行任何 UI 操作,必须 post message 回到 UI 线程进行 UI 相关操作。
下面看一下整个引擎在 Worker 线程的初始化。
UIAbility.ts 在 OnCreate的时候,会传递 AbilityContext,并且初始化 TuanjieMainWorker。TuanjieMainWorker 的初始化调用到 TuanjieMainWorker.getInstance,它是一个单例,此时会调用到构造方法,会去创建一个 threadWorker。threadWorker 整个线程的运行环境就在 TuanjieMainWorkerHandler.ts。所以从这里看到,不管是 ArkUI 还是 Worker 线程,在 OpenHarmony 都挺特别的,都分成两个文件,没有合到一起去。
当我们 new 好 Worker thread 的时候,TuanjieMainWorkerHandler.ts 文件内所执行的代码已经是在 Worker 线程,这时候我们就会通过 tuanjie.nativeSetWorker() 调用 C++,从而注册 libuv 的回调,从而作为引擎 Loop,然后再循环。
关于 ArkUI 线程与 TuanjieMain 线程的交互,大家一定要注意 ArkUI 线程消息处理是在 threadWorker.onmessage;TuanjieMain 线程消息处理要去找到 workerPort.onmessage。如果从 ArkUI 线程发消息到 TuanjieMain 线程,需要 threadWorker.postMessage;反过来 TuanjieMain 线程到 ArkUI 线程是 workerPort.postMessage。线程之间的交互基本就是通过 postMessage 去处理,消息的接收也是通过 onMessage 的回调进行处理。
在 Worker 里面有比较多的注意事项:
-
Worker 创建后需要手动管理生命周期,且 TS 里面最多同时运行的 Worker 子线程数量为 8 个;
-
由于不同线程中上下文对象是不同的,因此 Worker 线程只能使用线程安全的库;
-
因为线程之间只能通过 postMessage 进行交互,序列化传输的数据量大小限制为 16MB;
-
使用 Worker 模块时,需要在主线程中注册 onerror 接口,否则当 worker 线程出现异常时会发生 jscrash 问题。
引擎跨语言交互
引擎跨语言交互部分,首先 OH 使用 Node-API 实现跨语言交互。在 ArkTs/JS 侧只需要 import 一个对应的 so 库后,即可调用 C++ 方法。我们只需要在 TS 代码中 import tuanjie from ‘libtuanjie.so'; 然后调用 tuanjie.nativeOnResume(),是让引擎从后台回前台的接口。nativeOnResume 就会 call 到 C,C 侧的实现则是通过 RegisterModule 把 napi 的 module 丢到 TS,并且 module name 叫 tuanjie。里面有一个 register function 叫 JSI_onLoad。
右侧展示所有的这些代码就是我们把 C++ 接口暴露到 TS 接口的 API,我们绝大多数接口都是用 Native 开头的。如果大家在操作 TS 代码的时候,想知道哪些会调用到 C++ 内层去,只需要知道 Native 开头的基本都是调到 C++ 里面去。其中可能会有一些特别的如 Tuanjie.SendMessage,是为了和原来的 Unity.SendMessage 保持一致,没有把 Native 放在前面。
C++ 与 TS 是通过 Node-API 进行交互的,接下来如果要使用 C# 怎么进行 TS 的交互呢?首先 C# 调用 TS 接口,我们提供了很多的 OpenHarmony 的 js object, js class 等等 C# 接口,这些接口的执行都是在 TuanjieMain 线程里面的。当我们在 C# 中调用我们提供的 OpenHarmony js object 的接口时,它是从 C# 的 API 到了 C++ 内层,就会经过 Node-API,再到 TS API。
如果从 TS 调用 C# 接口,我们通过 import tuanjie from ‘libtuanjie.so' 直接调用 tuanjie.TuanjieSendMessage()TS 把信息发送到 C# 端。实际上是在 C++ 里面导出了 tuanjie.TuanjieSendMessage 的接口到 TS 层,从 C++ 回到 scripting的API,再回到 C#。需要注意的一点是,目前 C# call TS 目前所有的执行都还在 TuanjieMain 线程里面,但是如果是 TS 调用 C# 接口可以在任意线程,因为 TuanjieSendMessage 是线程安全的,会把来自不同线程的消息先放在消息堆中,等引擎每一个 loop 在走的时候才会把消息拿出来进行处理。
以上是我对 OpenHarmony 工程的分析,希望大家从今天的分享中可以了解引擎整体目录是什么样的、整个线程之间是怎样的关系,特别是在做 C# 和 TS 交互的时候,大家一定要注意线程之间交互的区别。
今天的分享就到这里,谢谢大家!
相关文章:

Unite Shanghai 2024 团结引擎专场 | 团结引擎 OpenHarmony 工程剖析
在 2024 年 7 月 24 日的 Unite Shanghai 2024 团结引擎专场演讲中,Unity中国 OpenHarmony 技术负责人刘伟贤对团结引擎导出的 OpenHarmony 工程进行了细节剖析,详细讲解 XComponent 如何与引擎结合,UI 线程和引擎线程的关联以及 ts/ets 的代…...

计算机毕业设计 基于Hadoop的智慧校园数据共享平台的设计与实现 Python毕业设计 Python毕业设计选题 Spark 大数据【附源码+安装调试】
博主介绍:✌从事软件开发10年之余,专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ 🍅文末获取源码联系🍅 👇🏻 精…...

2022CCPC绵阳站VP题解报告(CGHMAE六题)
文章目录 2022CCPC绵阳站VP题解报告前言[Problem - C ](https://codeforces.com/gym/104065/problem/C) (签到思维)[H (codeforces.com)](https://codeforces.com/gym/104065/problem/H) (签到构造)[Problem - G ](https://codefo…...

代码随想录day23:贪心part1
455. 分发饼干 class Solution {public int findContentChildren(int[] g, int[] s) {Arrays.sort(g);Arrays.sort(s);int res 0;int index s.length - 1;for(int i g.length - 1; i > 0; i--){if(index > 0 && s[index] > g[i]){res;index--;}}return r…...

通过网页设置参数,submit还是json
在通过网页设置参数并发送到服务器时,选择使用submit(通常是通过HTML表单的提交)还是直接发送JSON数据(通常是通过AJAX请求,如使用fetch API)取决于几个因素,包括你的服务器端如何处理这些请求、…...

C语言 | Leetcode C语言题解之第463题岛屿的周长
题目: 题解: const int dx[4] {0, 1, 0, -1}; const int dy[4] {1, 0, -1, 0};int dfs(int x, int y, int** grid, int n, int m) {if (x < 0 || x > n || y < 0 || y > m || grid[x][y] 0) {return 1;}if (grid[x][y] 2) {return 0;}g…...

逼近理论及应用精解【12】
文章目录 卷积卷积层与滤波层定义数学原理与公式定理架构例子例题 卷积层和滤波层概念的详细解释卷积层滤波层 滤波层和卷积层在卷积神经网络(CNN)中区别滤波层卷积层总结卷积层的数学原理滤波层的数学原理 参考文献 卷积 卷积层与滤波层 定义 卷积层…...

LIN总线学习大全(基于CANoe和CAPL)
🍅 我是蚂蚁小兵,专注于车载诊断领域,尤其擅长于对CANoe工具的使用🍅 寻找组织 ,答疑解惑,摸鱼聊天,博客源码,点击加入👉【相亲相爱一家人】🍅 玩转CANoe&…...

国庆作业
day1 1.开发环境 Linux系统GCCFDBmakefilesqlite3 2.功能描述 项目功能: 服务器:处理客户端的请求,并将数据存入数据库中,客户端请求的数据从数据库进行获取,服务器转发给客户端。 用户客户端:实现账号的注册、登…...

Android OpenGLES2.0开发(四):矩阵变换和相机投影
事物的本质是事物本身所固有的、深藏于现象背后并决定或支配现象的方面。 还记得我们上一篇绘制的三角形吗,我们确实能够顺利用OpenGL ES绘制出图形了,这是一个好的开始,但这还远远不够。我们定义的坐标是正三角形,但是绘制出…...

快递查询软件:实现单号识别与批量物流查询的高效工具
随着网络购物的普及,快递物流行业迎来了前所未有的发展机遇,同时也面临着巨大的挑战。跟踪物流信息成为一个难题,因此,快递查询软件的核心功能之一便是单号识别。传统的快递单号输入方式繁琐且易出错在此背景下,快递查…...

nodejs与npm版本对应表
Node.js — Node.js 版本 (nodejs.org)...

Spring Boot 项目中如何使用异步任务
前置知识: 同步任务: 同步任务是在单线程中按顺序执行,每次只有一个任务在执行,不会引发线程安全和数据一致性等并发问题 同步任务需要等待任务执行完成后才能执行下一个任务,无法同时处理多个任务,响应慢…...

Scrum实战中遇到的问题与解决方法
在当今快速变化的技术环境中,IT企业面临着持续的市场压力和竞争,传统的瀑布式开发模式已经难以满足现代企业的需要。瀑布模型过于僵化,缺乏灵活性,导致项目经常延期,成本增加,最终可能无法达到预期效果。为…...

全面介绍 Windows 录屏工具:开启录制新篇章
高质量的录屏工具是我们录屏的得力助手。但是日常因为侧重点的不同,比如有的喜欢录制游戏画面、有的需要录制教学视频、演示操作也需要录屏工具。这次我们就来探讨一下windows录屏工具有哪些吧。 1.福晰录屏大师 链接:www.foxitsoftware.cn/REC/ 从这…...

Maven 和 NetBeans:集成与使用
Maven 和 NetBeans:集成与使用 Maven 和 NetBeans 是两款强大的工具,常用于Java开发。Maven是一个项目管理工具,它能够帮助管理项目的构建、报告和文档。NetBeans是一个集成开发环境(IDE),它为Java开发提供了丰富的功能和友好的用户界面。将Maven集成到NetBeans中,可以…...

【系统架构设计师】目录提纲
一、绪论(TODO) 二、计算机与网络基础知识(TODO) 三、信息系统基础知识(TODO) 四、系统开发基础知识(TODO) 五、软件架构设计(TODO) 六、UML建模与架构文…...

【微服务】—SpringBoot入门
⭐⭐⭐⭐⭐⭐ Github主页👉https://github.com/A-BigTree 笔记仓库👉https://github.com/A-BigTree/tree-learning-notes 个人主页👉https://www.abigtree.top ⭐⭐⭐⭐⭐⭐ 文章目录 1 SpringBoot快速入门1.1 SpringBoot简介1.1.1 简介1.1.2…...

Linux: debug: perf: report: --sort
文章目录 简介实例简介 接上回:https://mzhan017.blog.csdn.net/article/details/142689870。 这里介绍perf的这个参数,还是非常的有用,尤其是分析对整个系统做perf record的数据,而不是单个进程做perf record。-s, --sort= : Sort histogram entries by given key(s) - …...

like 模糊查询的底层算法
like 模糊查询的底层算法 全文搜索算法、模糊查询、n-gram分隔算法功能介绍 百度搜索,文心一言给出的结果: SQL模糊查询底层通常使用全文搜索算法,如LIKE操作符和全文索引通常使用的n-gram分割算法。 n-gram是一种将文本分割成固定大小的词…...

【Linux实践】实验九:Shell流程控制语句
文章目录 实验九:Shell流程控制语句实验目的:实验内容:操作步骤:1. 复制*.c文件并排序2. 计算1-10的平方 实验九:Shell流程控制语句 实验目的: 掌握条件判断语句,如if语句、case语句。掌握循环…...

YOLOv8实战TT100K中国交通标志检测【数据集+YOLOv8模型+源码+PyQt5界面】
YOLOv8实战TT100k交通标志识别 文章目录 研究背景资源获取1.前言1.1 YOLO 系列:中国交通标志检测领域的璀璨明星1.2 Transformer与注意力机制:为中国交通标志检测注入新活力1.3 中国交通标志检测技术:迎接挑战,砥砺前行1.4 YOLOv8…...

SQLite3
文章目录 SQLite3 C/CAPI介绍SQLite3 C/C API 使⽤ SQLite3 C/CAPI介绍 C/C API是SQLite3数据库的⼀个客⼾端,提供⼀种⽤C/C操作数据库的⽅法。 SQLite3 C/C API 使⽤ 下⾯我们将这⼏个接⼝封装成⼀个类,快速上⼿这⼏个接口 创建/打开数据库文件针对打开…...

我的创作纪念日一年
目录 机缘 收获 日常 成就 憧憬 机缘 我之所以开始写CSDN博客,源于一段特殊的时光。去年此时,我独自待在实验室,周围的世界仿佛与我无关。没有旅游,没有与朋友的欢聚,情感的挫折和学业的压力如潮水般袭来。在这样的…...

Docker基本操作命令(一)
Docker 是一个开源的应用容器引擎,允许开发者打包应用以及其依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。主要功能是为开发者提供一个简单…...

PGMP-02项目集管理绩效域
目录 1.概要 2.defintions定义 3.Program Management Performance Domain interactions 交互 4. Organizational Strategy, Portfolio Management, and Program Management Linkage 5. Portfolio and Program Distinctions 区别 6. Program and Project Distinctions区别 …...

CAN(Controller Area Network)总线的仲裁机制
CAN(Controller Area Network)总线的仲裁机制是其核心特性之一,它确保了在多节点环境中数据能够高效、公正地传输。以下是对CAN仲裁机制的详细解释和介绍: 一、仲裁机制概述 在CAN总线网络中,各个节点地位平等&#…...

计算机毕业设计 | SpringBoot 房屋租赁网 租房买房卖房平台(附源码)
1,绪论 1.1 背景调研 在房地产行业持续火热的当今环境下,房地产行业和互联网行业协同发展,互相促进融合已经成为一种趋势和潮流。本项目实现了在线房产平台的功能,多种技术的灵活运用使得项目具备很好的用户体验感。 这个项目的…...

OJ在线评测系统 微服务高级 Gateway网关接口路由和聚合文档 引入knife4j库集中查看管理并且调试网关项目
Gateway微服务网关接口路由 各个服务之间已经能相互调用了 为什么需要网关 因为我们的不同服务是放在不同的端口上面的 如果前端调用服务 需要不同的端口 8101 8102 8103 8104 我们最好提供一个唯一的 给前端去调用的路径 我们学习技术的时候必须要去思考 1.为什么要用&am…...

腾讯云上传pushdocker镜像到镜像仓库
文章目录 腾讯云上传docker镜像 腾讯云上传docker镜像 >docker login ccr.ccs.tencentyun.com --usernameXXXXXX用户名>sudo docker tag mynginx:1.0 ccr.ccs.tencentyun.com/crfkitty/mynginx:1.0>docker push ccr.ccs.tencentyun.com/crfkitty/mynginx:1.0 The pu…...