最佳实践 | 如何基于GitHub Actions创建 DolphinScheduler Python API的CI/CD?

news2024/12/23 6:43:16

 点亮 ⭐️ Star · 照亮开源之路

https://github.com/apache/dolphinscheduler

19bd9cf8b03490aef18107b5726bb50e.png

01.

305f14925896e5bace20cbd90779694b.png

DolphinScheduler 和 Python API 介绍

Apache DolphinScheduler 是一个分布式、可扩展的工作流调度器平台,具有强大的 DAG 可视化界面。它可以帮助用户更轻松地构建和维护任何规模的工作流。

aecc518f1160b5c7ead1ea2d252d60df.png

为了满足同一团队中有不同偏好的所有用户,DolphinScheduler 提供了多种创建工作流的方式。最受欢迎的方式是通过 Web UI,非工程师出身也能经过简单的拖放创建工作流。如果您是一名工程师,并且更喜欢以编程的方式定义工作流,那么可以考虑使用其 Python API 或 YAML 文件定义来创建工作流。

PyDolphinScheduler 是 Apache DolphinScheduler 的 Python API,它让用户可以通过 Python 代码定义工作流,也就是 workflow-as-codes。就像使用其他 Python 库一样,你可以在任何你喜欢的编辑器中编写 Python代码,创建 DolphinScheduler 的用户、环境、项目和工作流。有关更多实操示例,可以参考:

DolphinScheduler 能用 Python 脚本编排工作流了!PyDolphinScheduler 简介与使用演示

02.

512219c1aa09ba40d601c3a698336493.png

一个简单的 Python API 示例

我们做了一个名为教程(tutorial)的示例来介绍 Python API 这个开箱即用的工具,其中包括基本概念,以及用最少的代码创建和运行我们第一个工作流的方法,可以在 https://github.com/apache/dolphinscheduler-sdk-python/blob/main/src/pydolphinscheduler/examples/tutorial.py 中查看更详细的代码。DolphinScheduler 及其 Python API 的核心概念是 DAG,在 Python API 中调用工作流。

下图可以更形象地说明这个概念。每个 DAG 包含多个节点和节点之间的连接,如名为 A、B、C 等的节点,以及它们之间的链接。在 Python API 中,任务代表 DAG 的节点,以及节点之间连接的依赖。

de2d8893c0746891a98c3a6ae1ffb8fa.png

03.

79ea31d32bbb1b580cb79cbd5cfa4987.png

如何触发 Python API 工作流程

01

单个工作流

当我们已经了解了 Python API 的基本概念,且看过了它的示例,那么我们如何触发并运行它来完成我们的工作呢?为了让它更 pythonic,你可以像其他 Python 脚本一样运行它,在终端输入一个简单的命令:

python tutorial.py


强大的 PyDolphinScheduler 可以帮你搞定所有设置并创建一个新的工作流,之后你可以在 DolphinScheduler web UI 中看到这个新的工作流。

02

多个工作流

如果我有多个包含多个工作流程的文件,该如何触发它们?是的,你可能已经想到了,你可以一个一个触发,就像我们触发单条一样。我们可以这样完成:

python workflow1.py
python workflow2.py
python workflow3.py
...
python workflowN.py


我们可以将上述所有命令添加到一个 bash 脚本中,之后,我们只需要执行 bash 脚本

bash <bash-script-contain-all>


它虽然很有用,但是当一些工作流添加或删除时,我们也必须更改 bash 脚本,这意味着我们必须考虑同步更改代码。否则,bash 脚本会失败,或者我们的一些新工作流将触发失败。

修复的方法很简单,我们可以动态检测特定目录下的 Python 脚本,然后将已有的脚本传递给 Python 解释器,我们可以这样修改我们的脚本

for file in $(find . -name "*.py"); do
    python "$file"
done

也就是说,这是我们触发任何规模的所有 DolphinScheduler Python API 工作流的最终脚本。但实际上会有点不同,因为通过手动触发来部署生产工作流的情况几乎不存在。所以,下一步我们将讨论如何在 CI 中触发我们的工作流。

04

1d1cd8f50fd542ce6d8a3e529b439c4e.png

在 GitHub Action中触发

在本节中,我们将通过 CI 触发我们的工作流程,以 GitHub Action 为例,其他 CI 工具也差不多。

01

什么是 GitHub Action

GitHub Actions 让我们可以轻松实现所有软件工作流程的自动化,现在是用全球流行的 CI/CD。直接从 GitHub 构建、测试和部署代码。按照你的需求进行代码审查、分支管理和问题分类。随着 GitHub 的流行和开源项目的发展,GitHub Action 目前非常流行。你可以在 GitHub 操作文档[https://github.com/features/actions]中查看更多详细信息。这是 GitHub Action 的 hello world

name: GitHub Actions Demo
on:
  push:
    branches:
      - main
jobs:
  hello-world:
    runs-on: ubuntu-latest
    steps:
      - name: Run my very first GitHub Actions
        run: echo "🎉 Hello World."

你可以将其保存为 YAML 文件,并放在你的项目中,路径为 .github/workflows/hello.yaml,让 GitHub 知道你是想要干什么。之后,每次提交并将其推送到名为 main 的分支时,名为 `hello.yaml` 的配置文件将被触发,它只会执行一个操作,执行 bash 命令并回显“🎉 Hello World. “ 到 GitHub 操作控制台。

02

组合 GitHub Action 以触发多个工作流

在上面的示例中,你可能已经意识到 GitHub Actions 可以运行 bash 命令。而我们的工作流批量触发脚本也是一个 bash 脚本。要通过 GitHub Actions 触发,我们可以更改我们的 GitHub Actions 示例中的命令。

name: Execute Workflows
on:   
  push:
    branches:
      - main
jobs:
  execute:
    runs-on: ubuntu-latest
    steps:
      - name: Check out repository code
        uses: actions/checkout@v3
      - name: Execute
        run: |
          for file in $(find . -name "*.py"); do
            python "$file"
          done

它只能触发工作流并将其部署到运行主机的 GitHub Actions。DolphinScheduler 集群在自托管服务器上或AWS 等云服务上,而不是 GitHub Actions,所以我们必须告诉 bash 脚本将我们的代码提交到 DolphinScheduler 集群而不是 GitHub Actions 服务器上。幸运的是,DolphinScheduler Python API 提供了三种对用户很友好的配置更改方法。我建议通过 bash 在 GitHub 操作期间更改环境变量,这很简单

# Modify Java Gateway Address
export PYDS_JAVA_GATEWAY_ADDRESS="<YOUR-STATIC-IP-RUN-DOLPHINSCHEDULER-API-SERVER>"
export PYDS_JAVA_GATEWAY_PORT="<PORT-RUN-DOLPHINSCHEDULER-API-SERVER>"


GitHub Actions 在 YAML 文件中支持 `env` 语法,可以在 github-actions: environment-variables 中看到更多详细信息,我们现在可以将 GitHub Actions 配置更改为

name: Execute Workflows
on:
  push:
    branches:
      - main
jobs:
  execute:
    runs-on: ubuntu-latest
    steps:
      - name: Check out repository code
        uses: actions/checkout@v3
      - name: Execute
        env:
          PYDS_JAVA_GATEWAY_ADDRESS: <YOUR-STATIC-IP-RUN-DOLPHINSCHEDULER-API-SERVER>
          PYDS_JAVA_GATEWAY_PORT: <PORT-RUN-DOLPHINSCHEDULER-API-SERVER>
        run: |
          for file in $(find . -name "*.py"); do
            python "$file"
          done

所以,每当我们的主分支有新的提交时,无论是通过合并 PR 生成还是从本地推送,它都会触发并将我们在 DolphinScheduler Python API 中定义的所有工作流部署到你的 DolphinScheduler 集群部署的位置。

在还未发布的版本中,我们为 DolphinScheduler Python API 添加了一个用于身份验证的新机制令牌,这意味着当我们尝试从 Python API 连接到 DolphinScheduler 时,下一个版本必须添加一个令牌,参见 https://github.com /apache/dolphinscheduler-sdk-python/pull/13 了解更多详情。此外,我们强烈建议我们的用户打开令牌身份验证以确保连接安全。就像其他配置一样,令牌也可以通过 bash 通过环境变量更改[https://dolphinscheduler.apache.org/python/3.1.0/config.html#by-bash]。

但是当我们启用和打开令牌时如何从 GitHub Actions 触发呢?在这种情况下,我们需要用 GitHub Encrypted secrets[https://docs.github.com/en/actions/security-guides/encrypted-secrets]来解决。用户可以按照链接中的步骤操作为你的存储库,创建你的第一个安全机密,记得牢记你的 secret 名称,在 GitHub Actions 配置中会用到

name: Execute Workflows
on:
  push:
    branches:
      - main
jobs:
  execute:
    runs-on: ubuntu-latest
    steps:
      - name: Check out repository code
        uses: actions/checkout@v3
      - name: Execute
        env:
          PYDS_JAVA_GATEWAY_ADDRESS: <YOUR-STATIC-IP-RUN-DOLPHINSCHEDULER-API-SERVER>
          PYDS_JAVA_GATEWAY_PORT: <PORT-RUN-DOLPHINSCHEDULER-API-SERVER>
          PYDS_JAVA_GATEWAY_AUTH_TOKEN: ${{ secrets.YOUR-SECRET-NAME }}
        run: |
          for file in $(find . -name "*.py"); do
            python "$file"
          done


看,不复杂吧?就像是在 GitHub Actions 中使用普通的环境变量。这就是我们从 GitHub Actions 部署工作流程所需要做的全部工作。

05.

d35a6976025443d51b30d99d5abf6c0d.png

最后谈谈 CI

DolphinScheduler Python API 脚本是一个 Python 脚本,因此它是 Python 语言的 CI,包括 black、Pylint、flake8、sort、autoflake 等。如果你选择使用 Python API 来创建和维护工作流,而不是通过 Web UI,我相信每个人都有自己偏好的代码格式和样式检查工具。我之所以在 CD 之后再谈 CI,是因为这是一个可选项。如果你有自己喜欢的其他选择,可以直接本节。但如果没有,我接下来会分享一下我喜欢用的东西和 Python API lint。

首先,我更喜欢使用预提交[https://pre-commit.com/],它会在每次 Git 提交时运行,很有用,因为我可以在把代码推送到远程之前检测到一些简单但经常被忽视的细节。预提交需要一个配置文件,我想分享 Python API 自身使用的代码样式和 lint 代码,可以在 https://github.com/apache/dolphinscheduler-sdk-python/blob/ 查看更多详细信息 main/.pre-commit-config.yaml

default_stages: [commit, push]
default_language_version:
  # force all python hooks to run python3
  python: python3
repos:
  # Python API Hooks
  - repo: https://github.com/pycqa/isort
    rev: 5.10.1
    hooks:
      - id: isort
        name: isort (python)
  - repo: https://github.com/psf/black
    rev: 22.3.0
    hooks:
      - id: black
  - repo: https://github.com/pycqa/flake8
    rev: 4.0.1
    hooks:
      - id: flake8
        additional_dependencies: [
          'flake8-docstrings>=1.6',
          'flake8-black>=0.2',
        ]
        # pre-commit run in the root, so we have to point out the full path of configuration
        args: [
          --config,
          .flake8
        ]
  - repo: https://github.com/pycqa/autoflake
    rev: v1.4
    hooks:
      - id: autoflake
        args: [
          --remove-all-unused-imports,
          --ignore-init-module-imports,
          --in-place
        ]

它不会运行复杂的检查,而是简单的检查,可以尽量快地完成预提交。详情如下:

  • isort:自动对 Python 导入进行排序

  • black:自动格式化 Python 代码

  • autoflake:自动删除 pyflakes 报告未使用的导入和未使用的变量

  • flake8:检测其他代码和文档

pre-commit 可用于本地检查,你也可以通过在现有名为 execute 的 job 之前添加一个新 job,在 GitHub Actions 中运行它。

name: Execute Workflows
on:
  push:
    branches:
      - main
  pull_request:
jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - name: Check out repository code
        uses: actions/checkout@v3
      - name: Install Dependencies
        run: |
          python -m pip install --upgrade pre-commit
      - name: lint
        run: |
          pre-commit install
          pre-commit run --all-files
  execute:
    runs-on: ubuntu-latest
    if: github.event_name == 'push'
    needs: lint
    steps:
      - name: Check out repository code
        uses: actions/checkout@v3
      - name: Execute
        env:
          PYDS_JAVA_GATEWAY_ADDRESS: <YOUR-STATIC-IP-RUN-DOLPHINSCHEDULER-API-SERVER>
          PYDS_JAVA_GATEWAY_PORT: <PORT-RUN-DOLPHINSCHEDULER-API-SERVER>
          PYDS_JAVA_GATEWAY_AUTH_TOKEN: ${{ secrets.YOUR-SECRET-NAME }}
        run: |
          for file in $(find . -name "*.py"); do
            python "$file"
          done


有些人可能注意到,除了添加新 job 外,我们还在 `on` 下添加了 `pull_request` 节点,在 `execute` job 下添加了 `if` 节点。因为代码 lint 检查会测试 push 和 pull requests,但我们只想在有新提交到分支 main 时执行工作流。如果我们为 pull requests 创建执行工作流,即使 pull requests 未被访问或未准备好合并,每个 pull requests 提交也都会被执行并部署到我们的生产环境。所以,我们必须设置一个条件来执行工作流。

06.

3c19ad43166a6e3fd1b238417b12df8d.png

回顾

  • 我们展示了什么是 DolphinScheduler 及其 Python API,GitHub Actions,如何通过 DolphinScheduler Python API 创建我们的第一个工作流,以及 GitHub Actions 中的第一个工作流。

  • 演示了如何基于 GitHub Actions 创建 DolphinScheduler Python API 的 CI/CD。

  • 最后,创建一个 GitHub Actions 来检测代码风格,自动检查我们的 DolphinScheduler Python API 的工作流代码。

参与贡献

随着国内开源的迅猛崛起,Apache DolphinScheduler 社区迎来蓬勃发展,为了做更好用、易用的调度,真诚欢迎热爱开源的伙伴加入到开源社区中来,为中国开源崛起献上一份自己的力量,让本土开源走向全球。

f1f8ace12e1882077ee4673b18a5720d.png

参与 DolphinScheduler 社区有非常多的参与贡献的方式,包括:

efb71bfb69fb5c6f0e1e8e8f7f7422a2.png

贡献第一个PR(文档、代码) 我们也希望是简单的,第一个PR用于熟悉提交的流程和社区协作以及感受社区的友好度。

社区汇总了以下适合新手的问题列表:https://github.com/apache/dolphinscheduler/issues/5689

非新手问题列表:https://github.com/apache/dolphinscheduler/issues?q=is%3Aopen+is%3Aissue+label%3A%22volunteer+wanted%22

如何参与贡献链接:https://dolphinscheduler.apache.org/zh-cn/community/development/contribute.html

来吧,DolphinScheduler开源社区需要您的参与,为中国开源崛起添砖加瓦吧,哪怕只是小小的一块瓦,汇聚起来的力量也是巨大的。

参与开源可以近距离与各路高手切磋,迅速提升自己的技能,如果您想参与贡献,我们有个贡献者种子孵化群,可以添加社区小助手微信(Leonard-ds) ,手把手教会您( 贡献者不分水平高低,有问必答,关键是有一颗愿意贡献的心 )。

bda93809d269bfd3a45790d3cde852ef.jpeg

添加社区小助手微信(Leonard-ds) 

添加小助手微信时请说明想参与贡献。

来吧,开源社区非常期待您的参与。

< 🐬🐬 >

更多精彩推荐

☞DolphinScheduler 登陆 AWS AMI 应用市场!

☞DolphinScheduler 机器学习工作流预测今年 FIFA 世界杯冠军大概率是荷兰!

☞手把手教你上手Apache DolphinScheduler机器学习工作流

☞突破单点瓶颈、挑战海量离线任务,Apache Dolphinscheduler在生鲜电商领域的落地实践

☞名额已排到10月 | Apache DolphinScheduler Meetup分享嘉宾继续火热招募中

☞【Meetup讲师】您有一张社区认证讲师证书未领取,点击领取!

☞DolphinScheduler 登上开源热力榜 Top30!云原生推动的开源技术栈大重构正在进行

我知道你在看08a9f5743b071744487bf9a822c81600.png

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

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

相关文章

计算机毕业设计springboot+vue基本微信小程序的二手车交易平台

项目介绍 首先,论文一开始便是清楚的论述了小程序的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,更进一步明确系统的需求。然后在明白了小程序的需求基础上需要进一步地设计系统,主要包罗软件架构模式、整体功能模块、数据…

木字楠后台管理系统开发(2):SpringBoot项目代码生成以及基础接口测试

&#x1f3b6; 文章简介&#xff1a;木字楠后台管理系统开发(2)&#xff1a;SpringBoot项目代码生成以及基础接口测试 &#x1f4a1; 创作目的&#xff1a;为了带大家完整的体验木字楠后台管理系统模版的开发流程 ☀️ 今日天气&#xff1a;一场秋雨一场寒&#xff0c;天气越来…

云原生之使用Docker部署docker-compose-ui工具

云原生之使用Docker部署docker-compose-ui工具一、Docker Compose UI介绍二、检查本地docker环境1.检查系统版本2.检查docker状态三、下载Docker Compose UI镜像四、部署Docker Compose UI服务1.新建安装目录2.创建Docker Compose UI容器3.检查Docker Compose UI容器状态4.查看…

3 - 线程池 Java内置的线程池

1、ExecutorService的介绍 ExecutorService 接口继承了Executor 接口&#xff0c;是Executor 的子接口。 Executors类 提供工厂方法用来创建不同类型的线程池。Executors是工具类&#xff0c;他提供对ThreadPoolExecutor的封装&#xff0c;会产生几种线程池供大家使用。 关于…

20 个超级实用的 CSS 技巧,帮助你成为更好的开发者

在开发项目中&#xff0c;修改输入占位符样式&#xff0c;多行文本溢出&#xff0c;隐藏滚动条&#xff0c;修改光标颜色&#xff0c;水平和垂直居中等等&#xff0c;这些都是我们非常熟悉的开发场景&#xff01;前端开发者几乎每天都会和它们打交道&#xff0c;因此&#xff0…

Visual Studio 平台下基于 C# /.NET 的 Android 开发

文章目录Part.I IntroductionChap.I 环境搭建Part.II ExamplePart.I Introduction 因为想尝试一下移动端的开发&#xff0c;所以在网上简单搜了一下移动端开发可以使用的语言&#xff0c;发现 Java, C# 等都可以。虽然用Java的居多&#xff0c;但是笔者对C#较为熟悉一些&#x…

TikTok变现冲不冲?这些TikTok选品方法赶快用上

TikTok电商商家们通常最忧愁的就是不知道如何有效进行TikTok选品。有时候因为选到难卖的产品&#xff0c;就会导致库存积压、资金紧缺等问题。今天&#xff0c;为TikTok电商商家们分享一些好用、有效的TikTok选品方法~ TikTok选品方法一——利用电商平台数据选品 除了一些偏地…

[附源码]JAVA毕业设计文物管理系统(系统+LW)

[附源码]JAVA毕业设计文物管理系统&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&…

速卖通官方公告:“不活跃商品”管理规则,将于12月12日生效!

最新平台动向&#xff1a;速卖通“黑色星期五”大促开始。作为海外最火的促销购物节黑五与世界杯重叠&#xff0c;速卖通上热销海外的国货有了显著的新趋势&#xff1a;越来越多具有更高科技含量的国货在海外走红。其中&#xff0c;速卖通上国产VR眼镜成为今年最火的商品&#…

Kubernetes 调度器详解

kube-scheduler是 kubernetes 系统的核心组件之一&#xff0c;主要负责整个集群资源的调度功能&#xff0c;根据特定的调度算法和策略&#xff0c;将 Pod 调度到最优的工作节点上面去&#xff0c;从而更加合理、更加充分的利用集群的资源&#xff0c;这也是我们选择使用 kubern…

构建高性能内存队列:Disruptor yyds~

Java中有哪些队列 ArrayBlockingQueue 使用ReentrantLockLinkedBlockingQueue 使用ReentrantLockConcurrentLinkedQueue 使用CAS等等 我们清楚使用锁的性能比较低&#xff0c;尽量使用无锁设计。接下来就我们来认识下Disruptor。 Disruptor简单使用 github地址&#xff1a;P…

R语言建立和可视化混合效应模型mixed effect model

全文下载链接&#xff1a;http://tecdat.cn/?p20631我们已经学习了如何处理混合效应模型。本文的重点是如何建立和_可视化_ 混合效应模型的结果&#xff08;点击文末“阅读原文”获取完整代码数据&#xff09;。相关视频设置本文使用数据集&#xff0c;用于探索草食动物种群对…

Linux Capabilities

Linux Capabilities 入门教程&#xff1a;基础实战篇 为了对 root 权限进行更细粒度的控制&#xff0c;实现按需授权&#xff0c;Linux 引入了另一种机制叫capabilities。Capabilites 作为线程&#xff08;Linux 并不真正区分进程和线程&#xff09;的属性存在&#xff0c;每个…

极客时间Kafka - 06 Kafka 消费者组 Consumer Group 到底是什么?

文章目录1. 消费者组到底是什么&#xff1f;2. Consumer Group下的Consumer实例个数3. 消费者位移Offset4. 重平衡1. 消费者组到底是什么&#xff1f; 消费者组&#xff0c;即 Consumer Group&#xff0c;应该算是 Kafka 比较有亮点的设计了。那么何谓 Consumer Group 呢&…

JAVA SCRIPT设计模式--行为型--设计模式之State状态者模式(20)

JAVA SCRIPT设计模式是本人根据GOF的设计模式写的博客记录。使用JAVA SCRIPT语言来实现主体功能&#xff0c;所以不可能像C&#xff0c;JAVA等面向对象语言一样严谨&#xff0c;大部分程序都附上了JAVA SCRIPT代码&#xff0c;代码只是实现了设计模式的主体功能&#xff0c;不代…

ToDesk企业版使用测试:破解企业远程办公难题,更安全更高效

❤️作者主页&#xff1a;小虚竹 ❤️作者简介&#xff1a;大家好,我是小虚竹。Java领域优质创作者&#x1f3c6;&#xff0c;CSDN博客专家&#x1f3c6;&#xff0c;华为云享专家&#x1f3c6;&#xff0c;掘金年度人气作者&#x1f3c6;&#xff0c;阿里云专家博主&#x1f3…

Phoenix安装部署

目录官网地址Phoenix 部署连接二次连接&#xff0c;连接失败解决官网地址 link Phoenix 部署 上传并解压 tar 包 更名 复制 server 包并拷贝到各个节点的 hbase/lib 配置环境变量 sudo vim /etc/profile.d/my_env.sh#phoenix export PHOENIX_HOME/opt/module/phoenix e…

抗病毒面料之外,安奈儿价值内核彰显

伴随着防控措施的不断优化&#xff0c;消费板块重回资本视野&#xff0c;其中童装巨头安奈儿因将推出“抗病毒抗菌面料”备受关注&#xff0c;14天收获10个涨停板。 目前安奈儿凭借抗病毒面料吸引了无数资本的目光&#xff0c;但这也是一把双刃剑。虽然抗病毒面料为安奈儿带来了…

数字化棋牌室 | 会员管理预约系统 | 棋牌室小程序

棋牌室在城市与农村都是部分老年人与年轻人的经常去的娱乐场所&#xff0c;以前这些场所里总是挤满了人&#xff0c;但现在越来越多的棋牌室即使环境装修的漂亮、设备高端完善等依然面对流量难题及管理难题&#xff0c;同时由于棋牌室具有社区属性&#xff0c;因此也有不少商家…

ARM微控制器MK24FN1M0VDC12、MKV10Z128VLH7低功耗MCU资料

MK24FN1M0VDC12 IC MCU 32BIT 1MB FLASH 121XFBGA 说明&#xff1a;Kinetis K2x 32位微控制器是低功耗mcu&#xff0c;通过智能片上集成大大节省了BOM。这些mcu基于ArmCortex-M4核心&#xff0c;提供完整和可选的高速USB 2.0 on - on - go (OTG)&#xff0c;包括无晶体设备功能…