黑马Hive+Spark离线数仓工业项目-任务流调度工具AirFlow(1)

news2024/11/18 1:51:38

任务流调度工具AirFlow

1. AirFlow介绍【了解】

   - 功能、特点
   - 架构角色、安装部署

2. **AirFlow使用【掌握】**

   - 核心:调度脚本【Python | Shell】
   - 定时调度:Linux Crontab表达式
   - 邮件告警:配置

3. 回顾Spark核心概念

   - 存储:安全性、高效性

   - 计算:使用【API:类、方法】、原理【资源使用】

   - 零碎:采集、调度、选举、可视化

   - Spark概念

     - 分布式资源:Master |  ResourceManager、Worker | NodeManager
     - 分布式程序:Driver 、Executor、Task
     - 原理性概念:Job、DAG、Stage

任务流调度回顾

目标:回顾任务流调度的需求及常用工具

路径

  - step1:需求
  - step2:常用工具

实施

需求

    - 相同的业务线,有不同的需求会有多个程序来实现,这多个程序共同完成的需求,组合在一起就是工作流或者叫做任务流

    - 基于工作流来实现任务流的自动化运行

- 需求1:基于时间的任务运行

- job1和job2是每天0点以后自动运行

- 需求2:基于运行依赖关系的任务运行

      - job3必须等待job1运行成功才能运行
      - job5必须等待job3和job4都运行成功才能运行

    - 调度类型

 定时调度:基于某种时间的规律进行调度运行
   - 调度工作流
依赖调度:基于某种依赖关系进行调度运行
   - 工作流中的程序的依赖关系

常用工具

    - Oozie:Cloudera公司研发,功能强大,依赖于MR实现分布式,集成Hue开发使用非常方便

      - 传统开发:xml文件

 ```xml
        <workflow>
            <start to="action1">
            </start>
            <action name='action1'>
                <shell>
                </shell>
                <ok to='action2'>
                <kill to='killAction'>
            </action>
            <action name='action2'>
                <shell>
                </shell>
                <ok to='action3'>
                <kill to='killAction'>
            </action>
            ……
        </workflow>
        ```

      - 现在开发:Hue通过图形化界面自主编辑DAG

      - 场景:CDH大数据平台

    - Azkaban:LinkedIn公司研发,界面友好、插件支持丰富、自主分布式,可以使用properties或者JSON开发

      - 开发properties文件,压缩成zip压缩包

        ```properties
        name='appname2'
        type=command
        dependencies=appname1
        comman='sh xxxx.sh'
        ```

      - 上传到web界面中

      - 场景:Apache平台

    - AirFlow:Airbnb公司研发,自主分布式、Python语言开发和交互,应用场景更加丰富

      - 开发Python文件

     ```python
        # step1:导包
        # step2:函数调用
        ```

      - 提交运行

      - 场景:整个数据平台全部基于Python开发

    - DolphinScheduler:易观公司研发,国产开源产品,高可靠高扩展、简单易用

AirFlow的介绍

目标:了解AirFlow的功能特点及应用场景

路径

  - step1:背景
  - step2:设计
  - step3:功能
  - step4:特点
  - step5:应用

实施

起源
    - 2014年,Airbnb创造了一套工作流调度系统:Airflow,用来替他们完成业务中复杂的ETL处理。从清洗,到拼接,只用设置好一套Airflow的流程图。
    - 2016年开源到了Apache基金会。
    - 2019年成为了Apache基金会的顶级项目:http://airflow.apache.org/。
  - **设计**:利用Python的可移植性和通用性,快速的构建的任务流调度平台
  - **功能**:基于Python实现依赖调度、定时调度
特点
    - 分布式任务调度:允许一个工作流的Task在多台worker上同时执行
    - DAG任务依赖:以有向无环图的方式构建任务依赖关系
    - Task原子性:工作流上每个task都是原子可重试的,一个工作流某个环节的task失败可自动或手动进行重试
    - 自主定制性:可以基于代码构造任何你需要调度的任务或者处理工具
      - 优点:灵活性好
      - 缺点:开发复杂
应用
    - 基于Python开发背景下的系统建议使用

AirFlow的部署启动

目标:了解AirFlow的工具部署及管理

路径

  - step1:安装部署
  - step2:启动测试
  - step3:关闭

实施

安装部署

    - 自行安装:《参考附录一》
    - 放弃安装:请将虚拟机快照恢复到《AirFlow安装完成》

启动测试

      - 测试网络端口
      - Airflow Web UI:`node1:8085`
          - 用户名密码:admin
        - Celery Web UI:`node1:5555`

AirFlow的架构组件

目标:了解AirFlow的架构组件

路径

  - step1:架构
  - step2:组件

实施

架构

    - Client:开发AirFlow调度的程序的客户端,用于开发AirFlow的Python程序
    - Master:分布式架构中的主节点,负责运行WebServer和Scheduler
    - Worker:负责运行Execution执行提交的工作流中的Task

组件

   ```
    A scheduler, which handles both triggering scheduled workflows, and submitting Tasks to the executor to run.
    An executor, which handles running tasks. In the default Airflow installation, this runs everything inside the scheduler, but most production-suitable executors actually push task execution out to workers.
    A webserver, which presents a handy user interface to inspect, trigger and debug the behaviour of DAGs and tasks.
    A folder of DAG files, read by the scheduler and executor (and any workers the executor has)
    A metadata database, used by the scheduler, executor and webserver to store state.
    ```

    - WebServer:提供交互界面和监控,让开发者调试和监控所有Task的运行
    - Scheduler:负责解析和调度Task任务提交到Execution中运行
    - Executor:执行组件,负责运行Scheduler分配的Task,运行在Worker中
    - DAG Directory:DAG程序的目录,将自己开发的程序放入这个目录,AirFlow的WebServer和Scheduler会自动读取
      - airflow将所有程序放在一个目录中
      - 自动检测这个目录有么有新的程序
    - MetaData DataBase:AirFlow的元数据存储数据库,记录所有DAG程序的信息

AirFlow的开发规则 

目标:掌握AirFlow的开发规则

路径

  - step1:开发Python调度程序
  - step2:提交Python调度程序

实施

  - 官方文档

    - 概念:http://airflow.apache.org/docs/apache-airflow/stable/concepts/index.html
  - 示例:http://airflow.apache.org/docs/apache-airflow/stable/tutorial.html
    
开发Python调度程序

    - 开发一个Python程序,程序文件中需要包含以下几个部分

    - 注意:该文件的运行不支持utf8编码,**不能写中文**

step1:导包

  # 必选:导入airflow的DAG工作流
      from airflow import DAG
      # 必选:导入具体的TaskOperator类型
      from airflow.operators.bash import BashOperator
      # 可选:导入定时工具的包
      from airflow.utils.dates import days_ago
      ```

 step2:定义DAG及配置

 # 当前工作流的基础配置
      default_args = {
          # 当前工作流的所有者
          'owner': 'airflow',
          # 当前工作流的邮件接受者邮箱
          'email': ['airflow@example.com'],
          # 工作流失败是否发送邮件告警
          'email_on_failure': True,
          # 工作流重试是否发送邮件告警
          'email_on_retry': True,
          # 重试次数
          'retries': 2,
          # 重试间隔时间
          'retry_delay': timedelta(minutes=1),
      }
      
      # 定义当前工作流的DAG对象
      dagName = DAG(
          # 当前工作流的名称,唯一id
          'airflow_name',
          # 使用的参数配置
          default_args=default_args,
          # 当前工作流的描述
          description='first airflow task DAG',
          # 当前工作流的调度周期:定时调度【可选】
          schedule_interval=timedelta(days=1),
          # 工作流开始调度的时间
          start_date=days_ago(1),
          # 当前工作流属于哪个组
          tags=['itcast_bash'],
      )
      ```

      - 构建一个DAG工作流的实例和配置

step3:定义Tasks

      - Task类型:http://airflow.apache.org/docs/apache-airflow/stable/concepts/operators.html
      - 常用
        - [`BashOperator`](http://airflow.apache.org/docs/apache-airflow/stable/_api/airflow/operators/bash/index.html#airflow.operators.bash.BashOperator) - executes a bash command
          - 执行Linux命令
        - [`PythonOperator`](http://airflow.apache.org/docs/apache-airflow/stable/_api/airflow/operators/python/index.html#airflow.operators.python.PythonOperator) - calls an arbitrary Python function
          - 执行Python代码
        - [`EmailOperator`](http://airflow.apache.org/docs/apache-airflow/stable/_api/airflow/operators/email/index.html#airflow.operators.email.EmailOperator) - sends an email
          - 发送邮件的
      - 其他
        - [`MySqlOperator`](http://airflow.apache.org/docs/apache-airflow-providers-mysql/stable/_api/airflow/providers/mysql/operators/mysql/index.html#airflow.providers.mysql.operators.mysql.MySqlOperator)
        - [`PostgresOperator`](http://airflow.apache.org/docs/apache-airflow-providers-postgres/stable/_api/airflow/providers/postgres/operators/postgres/index.html#airflow.providers.postgres.operators.postgres.PostgresOperator)
        - [`MsSqlOperator`](http://airflow.apache.org/docs/apache-airflow-providers-microsoft-mssql/stable/_api/airflow/providers/microsoft/mssql/operators/mssql/index.html#airflow.providers.microsoft.mssql.operators.mssql.MsSqlOperator)
        - [`OracleOperator`](http://airflow.apache.org/docs/apache-airflow-providers-oracle/stable/_api/airflow/providers/oracle/operators/oracle/index.html#airflow.providers.oracle.operators.oracle.OracleOperator)
        - [`JdbcOperator`](http://airflow.apache.org/docs/apache-airflow-providers-jdbc/stable/_api/airflow/providers/jdbc/operators/jdbc/index.html#airflow.providers.jdbc.operators.jdbc.JdbcOperator)
        - [`DockerOperator`](http://airflow.apache.org/docs/apache-airflow-providers-docker/stable/_api/airflow/providers/docker/operators/docker/index.html#airflow.providers.docker.operators.docker.DockerOperator)
        - [`HiveOperator`](http://airflow.apache.org/docs/apache-airflow-providers-apache-hive/stable/_api/airflow/providers/apache/hive/operators/hive/index.html#airflow.providers.apache.hive.operators.hive.HiveOperator)
        - [`PrestoToMySqlOperator`](http://airflow.apache.org/docs/apache-airflow-providers-mysql/stable/_api/airflow/providers/mysql/transfers/presto_to_mysql/index.html#airflow.providers.mysql.transfers.presto_to_mysql.PrestoToMySqlOperator)
        - ……

      - BashOperator:定义一个Shell命令的Task

   # 导入BashOperator
        from airflow.operators.bash import BashOperator
        # 定义一个Task的对象
        t1 = BashOperator(
            # 指定唯一的Task的名称
            task_id='first_bashoperator_task',
            # 指定具体要执行的Linux命令
            bash_command='echo "hello airflow"',
            # 指定属于哪个DAG对象
            dag=dagName
        )
        ```

      - PythonOperator:定义一个Python代码的Task

 # 导入PythonOperator
        from airflow.operators.python import PythonOperator
        
        # 定义需要执行的代码逻辑
        def sayHello():
            print("this is a programe")
        
        #定义一个Task对象
        t2 = PythonOperator(
            # 指定唯一的Task的名称
            task_id='first_pyoperator_task',
            # 指定调用哪个Python函数
            python_callable=sayHello,
            # 指定属于哪个DAG对象
            dag=dagName
        )
        ```

step4:运行Task并指定依赖关系

      - 定义Task
        Task1:runme_0
        Task2:runme_1
        Task3:runme_2
        Task4:run_after_loop
        Task5:also_run_this
        Task6:this_will_skip
        Task7:run_this_last

      - 需求

        - Task1、Task2、Task3并行运行,结束以后运行Task4
        - Task4、Task5、Task6并行运行,结束以后运行Task7

      - 代码

    task1 >> task4
        task2 >> task4
        task3 >> task4
        task4 >> task7
        task5 >> task7
        task6 >> task7
        ```

      - 如果只有一个Task,只要直接写上Task对象名称即可
   

    ```
        task1
        ```

提交Python调度程序

    - 哪种提交都需要等待一段时间

    - 自动提交:需要等待自动检测

      - 将开发好的程序放入AirFlow的DAG Directory目录中
      - 默认路径为:/root/airflow/dags

    - 手动提交:手动运行文件让airflow监听加载

python xxxx.py

    - 调度状态

      - No status (scheduler created empty task instance):调度任务已创建,还未产生任务实例
      - Scheduled (scheduler determined task instance needs to run):调度任务已生成任务实例,待运行

      - Queued (scheduler sent task to executor to run on the queue):调度任务开始在executor执行前,在队列中

      - Running (worker picked up a task and is now running it):任务在worker节点上执行中

      - Success (task completed):任务执行成功完成

Shell调度测试

目标:实现Shell命令的调度测试

实施

需求:使用BashOperator调度执行一条Linux命令

代码

    - 创建

# 默认的Airflow自动检测工作流程序的文件的目录
      mkdir -p /root/airflow/dags
      cd /root/airflow/dags
      vim first_bash_operator.py

- 开发

# import
      from airflow import DAG
      from airflow.operators.bash import BashOperator
      from airflow.utils.dates import days_ago
      from datetime import timedelta
      
      # define args
      default_args = {
          'owner': 'airflow',
          'email': ['airflow@example.com'],
          'email_on_failure': True,
          'email_on_retry': True,
          'retries': 1,
          'retry_delay': timedelta(minutes=1),
      }
      
      # define dag
      dag = DAG(
          'first_airflow_dag',
          default_args=default_args,
          description='first airflow task DAG',
          schedule_interval=timedelta(days=1),
          start_date=days_ago(1),
          tags=['itcast_bash'],
      )
      
      # define task1
      run_bash_task = BashOperator(
          task_id='first_bashoperator_task',
          bash_command='echo "hello airflow"',
          dag=dag,
      )
      
      # run the task
      run_bash_task

      - 工作中使用bashOperator

 bash_command='sh xxxx.sh'

xxxx.sh:根据需求
      
        - Linux命令
        - hive -f 
        - spark-sql -f 
        - spark-submit python | jar

提交
   

 python first_bash_operator.py 

查看

 执行

依赖调度测试

目标:实现AirFlow的依赖调度测试

实施

 需求:使用BashOperator调度执行多个Task,并构建依赖关系

 代码

    - 创建

     cd /root/airflow/dags
      vim second_bash_operator.py
      ```

    - 开发

 # import
      from datetime import timedelta
      from airflow import DAG
      from airflow.operators.bash import BashOperator
      from airflow.utils.dates import days_ago
      
      # define args
      default_args = {
          'owner': 'airflow',
          'email': ['airflow@example.com'],
          'email_on_failure': True,
          'email_on_retry': True,
          'retries': 1,
          'retry_delay': timedelta(minutes=1),
      }
      
      # define dag
      dag = DAG(
          'second_airflow_dag',
          default_args=default_args,
          description='first airflow task DAG',
          schedule_interval=timedelta(days=1),
          start_date=days_ago(1),
          tags=['itcast_bash'],
      )
      
      # define task1
      say_hello_task = BashOperator(
          task_id='say_hello_task',
          bash_command='echo "start task"',
          dag=dag,
      )
      
      # define task2
      print_date_format_task2 = BashOperator(
          task_id='print_date_format_task2',
          bash_command='date +"%F %T"',
          dag=dag,
      )
      
      # define task3
      print_date_format_task3 = BashOperator(
          task_id='print_date_format_task3',
          bash_command='date +"%F %T"',
          dag=dag,
      )
      
      # define task4
      end_task4 = BashOperator(
          task_id='end_task',
          bash_command='echo "end task"',
          dag=dag,
      )
      
      say_hello_task >> [print_date_format_task2,print_date_format_task3] >> end_task4

提交

  python second_bash_operator.py 

 查看

Python调度测试

目标:实现Python代码的调度测试

实施

  需求:调度Python代码Task的运行

 代码

    - 创建

 cd /root/airflow/dags
      vim python_etl_airflow.py

    - 开发

  # import package
      from airflow import DAG
      from airflow.operators.python import PythonOperator
      from airflow.utils.dates import days_ago
      import json
      
      # define args
      default_args = {
          'owner': 'airflow',
      }
      
      # define the dag
      with DAG(
          'python_etl_dag',
          default_args=default_args,
          description='DATA ETL DAG',
          schedule_interval=None,
          start_date=days_ago(2),
          tags=['itcast'],
      ) as dag:
          # function1
          def extract(**kwargs):
              ti = kwargs['ti']
              data_string = '{"1001": 301.27, "1002": 433.21, "1003": 502.22, "1004": 606.65, "1005": 777.03}'
              ti.xcom_push('order_data', data_string)
              
          # function2
          def transform(**kwargs):
              ti = kwargs['ti']
              extract_data_string = ti.xcom_pull(task_ids='extract', key='order_data')
              order_data = json.loads(extract_data_string)
              total_order_value = 0
              for value in order_data.values():
                  total_order_value += value
              total_value = {"total_order_value": total_order_value}
              total_value_json_string = json.dumps(total_value)
              ti.xcom_push('total_order_value', total_value_json_string)
              
          # function3
          def load(**kwargs):
              ti = kwargs['ti']
              total_value_string = ti.xcom_pull(task_ids='transform', key='total_order_value')
              total_order_value = json.loads(total_value_string)
              print(total_order_value)
              
          # task1
          extract_task = PythonOperator(
              task_id='extract',
              python_callable=extract,
          )
          extract_task.doc_md = """\
      #### Extract task
      A simple Extract task to get data ready for the rest of the data pipeline.
      In this case, getting data is simulated by reading from a hardcoded JSON string.
      This data is then put into xcom, so that it can be processed by the next task.
      """
          # task2
          transform_task = PythonOperator(
              task_id='transform',
              python_callable=transform,
          )
          transform_task.doc_md = """\
      #### Transform task
      A simple Transform task which takes in the collection of order data from xcom
      and computes the total order value.
      This computed value is then put into xcom, so that it can be processed by the next task.
      """
          # task3
          load_task = PythonOperator(
              task_id='load',
              python_callable=load,
          )
          load_task.doc_md = """\
      #### Load task
      A simple Load task which takes in the result of the Transform task, by reading it
      from xcom and instead of saving it to end user review, just prints it out.
      """
      
      # run
      extract_task >> transform_task >> load_task

提交 

    python python_etl_airflow.py

查看

 

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

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

相关文章

【10个基本网络故障排查工具-每个IT专业人员应了解】

网络故障排除工具是每个网络管理员的必需品。 在网络领域入门时&#xff0c;重要的是要积累一些可用于解决各种不同网络状况的工具。 虽然特定工具的使用确实是主观的并且由工程师自行决定&#xff0c;但本文中的工具选择是基于它们的一般性和通用性。 本文回顾了可帮助您解决大…

聊聊业务项目如何主动感知mysql是否存活

前言 先前写过一篇文章聊聊如何利用redis实现多级缓存同步,里面讲到业务部门因数据库宕机&#xff0c;有技术提出当数据库宕机&#xff0c;切换到redis&#xff0c;今天我们就来聊聊如何触发这个切换动作&#xff1f; 1、方案一&#xff1a;利用异常机制 伪代码如下&#xf…

大三寒假人生第一次面试失败

2022/12/28&#xff0c;今天是人生第一次面试。坐了2个小时的地铁去面试结果却很惨。一开始进门就笔试&#xff0c;当看到笔试题时发现很多基础&#xff0c;平时耳熟能详的词汇却怎么样也回答不出来。做了一个多小时&#xff0c;当面试官把题改了以后一句笔试没过。说真的在出门…

RocketMQ消息队列的下载、配置、启动、测试

目录 下载 环境变量的配置 新建一个变量 配置path 新建变量 启动 命名服务器 启动broker 测试是否启动成功 下载 地址&#xff1a;RocketMQ 官方网站 | RocketMQ 切换到中文模式很容易看的 下载那一列就行了 安装很容易的。 环境变量的配置 新建一个变量 就是你的bin文…

No.181# 点直播简要架构梳理走查

引言直播带货、潮流电商、短视频不断融合&#xff0c;本文走查下音视频直播的简要架构和角色。选择UDP&#xff0c;注重传输实时性&#xff0c;在线教育、音视频会议等。选择TCP&#xff0c;注重画面质量、是否卡顿等&#xff0c;娱乐直播、直播带货等。本文主要内容有&#xf…

RPA:帮助企业完成财务数字化转型

为什么要做财务的数字化转型 a. 传统企业财务的现状 “重复性强、耗时耗力、效率低下”是目前大家对传统企业财务的固有印象。很多企业的财务部门仍然采用传统的手工操作模式&#xff0c;财务流程繁琐分散&#xff0c;且财务部门缺乏获取、处理数据的工具。绝大部分的人力都投…

2022LOL微博杯模糊问题,1080p高清看微博杯the shy比赛直播

2022LOL微博杯的直播模糊&#xff0c;看着不爽 观看方法 1.打开下面在线播放m3u8文件的地址 http://www.m3u8.zone/ 如图 2.输入播放地址 微博杯的播放地址&#xff1a; &#xff08;1月三号的地址 如果失效往下看解决方法&#xff09; https://plwb01.live.weibo.com/ali…

前端数据结构与算法

前端数据结构与算法 文章宝典 链表 可以快速删除和插入节点&#xff0c;只用修改节点的引用 实例 队列 实例 栈 实例 树 并且左节点的值和后续节点的值都要小于等于该节点的值 图 根据图的节点之间的边是否有方向&#xff0c;可以分为有向图和无向图。 在有向图…

数字调制系列:如何理解IQ ?

最近在筹划写一系列关于数字IQ 调制的短文&#xff0c;以帮助初学者能够更好地理解和掌握。虽然IQ 调制技术已经非常广泛地应用于各种无线通信应用中&#xff0c;但是究其细节&#xff0c;仍有很多人存在疑惑&#xff0c;尤其对于初学者。作者从事测试工作多年&#xff0c;对IQ…

强化学习的Sarsa与Q-Learning的Cliff-Walking对比实验

强化学习的Sarsa与Q-Learning的Cliff-Walking对比实验Cliff-Walking问题的描述Sarsa和Q-Learning算法对比代码分享需要改进的地方引用和写在最后Cliff-Walking问题的描述 悬崖行走&#xff1a;从S走到G&#xff0c;其中灰色部分是悬崖不可到达&#xff0c;求可行方案 建模中&am…

(Java)【深基9.例4】求第 k 小的数

【深基9.例4】求第 k 小的数 一、题目描述 输入 nnn&#xff08;1≤n<50000001 \le n < 50000001≤n<5000000 且 nnn 为奇数&#xff09;个数字 aia_iai​&#xff08;1≤ai<1091 \le a_i < {10}^91≤ai​<109&#xff09;&#xff0c;输出这些数字的第 kk…

元旦礼第三弹!玻色量子荣登2022年中国创新力量50榜单

​2022年12月&#xff0c;国内最大的创新者社区极客公园重磅发布了全新的「中国创新力量 50 榜单&#xff08;InnoForce 50&#xff09;」——在过去一年为泛计算机科学领域及其交叉领域带来创新和突破的中国公司/机构。玻色量子凭借在光量子计算领域突出的核心竞争力&#xff…

配电网前推后带法求电力系统潮流(PythonMatlab实现)

目录 1 概述 2 数学模型 3 节点分层前推回代潮流计算及步骤 3.1 计算方法 3.2 计算步骤 4 算例及数据 5 Matlab&Python代码实现 1 概述 配电网通常是单电源全网连接、开环运行&#xff0c;即呈树状。针对配电系统分析&#xff0c;其根本就是进行潮流计算。潮流计算的…

通过反射机制访问java对象的属性 给属性赋值 读取属性的值

package com.javase.reflect;import java.lang.reflect.Field;/*** 通过反射机制&#xff0c;访问java对象的属性&#xff0c;给属性赋值&#xff0c;读取属性的值&#xff08;重点&#xff1a;五颗星*****&#xff09;* 本例中使用反射机制编写代码&#xff0c;看起来比不使用…

Hi3861鸿蒙物联网项目实战:智能温度计

华清远见FS-Hi3861开发套件&#xff0c;支持HarmonyOS 3.0系统。开发板主控Hi3861芯片内置WiFi功能&#xff0c;开发板板载资源丰富&#xff0c;包括传感器、执行器、NFC、显示屏等&#xff0c;同时还配套丰富的拓展模块。开发板配套丰富的学习资料&#xff0c;包括全套开发教程…

art-template模板引擎

1、模板引擎的基本概念 1.1、渲染UI结构时遇到的问题 var rows [] $.each(res.data, function (i, item) { // 循环拼接字符串 rows.push(<li class"list-group-item"> item.content <span class"badge cmt-date">评论时间&#xff1a; item…

C++ 使用Socket实现主机间的UDP/TCP通信

前言 完整代码放到github上了&#xff1a;cppSocketDemo 服务器端的代码做了跨平台&#xff08;POSIX和WINDOWS&#xff09;&#xff0c;基于POSIX平台&#xff08;Linux、Mac OS X、PlayStation等&#xff09;使用sys/socket.h库&#xff0c;windows平台使用winsock2.h库。 客…

STM32配置LED模块化

文章目录前言一、LED的模块化二、GPIO初始化详细解析三、LED代码封装总结前言 本篇文章将带大家深入了解GPIO的配置&#xff0c;并带大家实现LED模块化编程。 一、LED的模块化 什么叫模块化编程&#xff1f;我的理解就是每一个模块都分别写成对应的.c和.h文件&#xff0c;有…

S32K144—从0到1一个MBD模型的诞生

一个MBD模型的诞生&#xff0c;分为以下几步&#xff1a; 1、连接好硬件S32K144 EVB 2、选择一个合适的工作空间&#xff0c;新建一个simulink模型&#xff0c;保存 3、在模型中拖入模块&#xff1a; MBD_S32K1xx_Config_Information Digital_Input_ISR Periodic_Interrupt…

C++ 设计模式

设计模式序创建型模式工厂方法模式抽象工厂模式单例模式建造者模式&#xff08;生成器模式&#xff09;原型模式结构型模式适配器模式装饰器代理模式外观模式桥接模式组合模式&#xff08;部分--整体模式&#xff09;享元模式行为型模式策略模式模板模式观察者模式迭代器模式责…