Dubbo的简单使用

news/2024/5/9 17:48:55/文章来源:https://www.cnblogs.com/fnlingnzb-learner/p/16813981.html

一、架构演进   

发展演变

1.1 单一应用架构

当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。此时,用于简化增删改查工作量的数据访问框架(ORM)是关键。适用于小型网站,小型管理系统,将所有功能都部署到一个功能里,简单易用。

缺点

  • 性能扩展比较难
  • 协同开发问题
  • 不利于升级维护

1.2 垂直应用架构

当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的Web框架(MVC)是关键。通过切分业务来实现各个模块独立部署,降低了维护和部署的难度,团队各司其职更易管理,性能扩展也更方便,更有针对性。

缺点

  • 公用模块无法重复利用,开发性的浪费

1.3 分布式服务架构

当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的**分布式服务框架****(RPC)**是关键。

1.4 流动计算架构

当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)[ Service Oriented Architecture]是关键。

1.5 RPC概念

概述

RPC【Remote Procedure Call】是指远程过程调用,是一种进程间通信方式,他是一种技术的思想,而不是规范。它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。即程序员无论是调用本地的还是远程的函数,本质上编写的调用代码基本相同。

RPC两个核心模块

  • 通讯
  • 序列化

二、注册中心

1、概述

主流的注册中心:

  • Nacos
  • Zookeeper
  • Multicast
  • Redis
  • Simple
  • eureka

2、搭建zk集群

Zookeeper应用及原理_MG-net的博客-CSDN博客

三、RPC及Dubbo

1、什么是PRC

Rpc是一种协议,一种远程过程调用协议,规定了双方通信采用什么格式、以及数据如何传输。

  • 指明调用类或者接口
  • 指名调用的方法及参数

2、手写远程过程调用

  • 准备一个注册中心,保存服务的地址
  • 服务提供者
      • 注册到注册中心
      • 告诉注册中心服务实现类
      • 准备服务协议,根据不同情况,使用不同的协议如http等
      • 接受到参数后,通过参数进行类反射调用
      • 最后将结果返回
  • 服务消费者
      • 使用代理调用服务提供者的实现类
      1. 封装本次调用的参数,类名、方法名、参数名、参数
      2. 获取地址列表
      3. 负载均衡选择服务提供者的地址
      4. 使用指定协议进行调用

总结,RPC解决的问题:

  • 数据怎么封装
  • 数据怎么传输,适配不同的协议

3、什么的Dubbo

Apache Dubbo 是一款微服务开发框架,它提供了 RPC通信 与 微服务治理 两大关键能力。这意味着,使用 Dubbo 开发的微服务,将具备相互之间的远程发现与通信能力, 同时利用 Dubbo 提供的丰富服务治理能力,可以实现诸如服务发现、负载均衡、流量调度等服务治理诉求。同时 Dubbo 是高度可扩展的,用户几乎可以在任意功能点去定制自己的实现,以改变框架的默认行为来满足自己的业务需求。

4、Dubbo是怎么实现远程调用的

5、Dubbo的初体验

5.1、服务提供者配置

在zk中,可以看到相关的节点文件:

5.2 服务消费者 

服务代理的过程: 

可以看出,在dubbo中,服务提供者把提供的服务注册到注册中心中,消费者可以在像使用自己本地的Bean一样使用远程的提供者的服务。dubbo底层采用netty框架进行网络通信。 

6、Dubbo的内部结构

  • 服务提供者(Provider):暴露服务的服务提供方,服务提供者在启动时,向注册中心注册自己提供的服务。
  • 服务消费者(Consumer): 调用远程服务的服务消费方,服务消费者在启动时,向注册中心订阅自己所需的服务,服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
  • 注册中心(Registry):注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者
  • 监控中心(Monitor):服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心
  1. 初始化提供者
  2. 提供者注册到注册中心
  3. 消费者订阅注册中心中的服务,并且把服务提供者的地址缓存到本地
  4. 当提供者下线的时候,注册中心需要消费者服务下线
  5. 消费者同步的调用服务
  6. 监控

四、Springboot中的dubbo

1、服务提供者

double的pom依赖:

 1   <dependency>
 2             <groupId>org.apache.dubbo</groupId>
 3             <artifactId>dubbo-spring-boot-starter</artifactId>
 4             <version>3.0.6</version>
 5         </dependency>
 6  
 7         <dependency>
 8             <groupId>org.apache.dubbo</groupId>
 9             <artifactId>dubbo-registry-zookeeper</artifactId>
10             <version>3.0.6</version>
11         </dependency>

在启动类上增加注解:@EnableDubbo

在实现类上增加注解:@DubboService

配置文件配置dubbo的相关信息:

server:port: 9001
dubbo:application:name: dubbo_providerprotocol:name: dubboport: 20882registry:address: zookeeper://127.0.0.1:2181

启动后,服务提供着就自动注册到zk中了。

2、服务消费者

引入pom依赖:

 1  <dependency>
 2             <groupId>org.apache.dubbo</groupId>
 3             <artifactId>dubbo-spring-boot-starter</artifactId>
 4             <version>3.0.6</version>
 5         </dependency>
 6  
 7         <dependency>
 8             <groupId>org.apache.dubbo</groupId>
 9             <artifactId>dubbo-registry-zookeeper</artifactId>
10             <version>3.0.6</version>
11         </dependency>

在启动类上增加注解:@EnableDubbo

注入类的时候,使用注解:@DubboReference,这个注解做了2件事

  • 订阅服务
  • 建立代理对象

配置文件中配置dubbo信息:

server:port: 8001
dubbo:application:name: consumerregistry:address: zookeeper://127.0.0.1:2181

3、@EnableDubbo的用法

注解流程:

@EnableDubbo->@EnableDubboConfig、@DubboCompentScan

五、dubbo的用法示例

1、version版本号

服务提供者可以指定版本号,这样消费者可以调用需要指定的版本号即可。

2、指定protocol协议

dubbo协议可支持的协议:

  • rest:
  • http
  • dubbo(netty实现)
  • 自定义协议

在配置文件:

在配置文件中,可以使用 protocols 进行多协议配置。

在提供者或者消费者端配置需要使用的协议即可:

如果配置服务未指定协议,但是配置文件配置了多个协议,那么就会生成配置个数的服务,例如配置了2种协议dubbo、rest,那么就会生成2个服务一个是dubbo协议、一个是rest协议。

3、使用rest访问dubbo的服务

需要注意依赖的引入。使用到jboss的依赖

 1        <!-- Dubbo rest protocol -->
 2         <dependency>
 3             <groupId>org.jboss.resteasy</groupId>
 4             <artifactId>resteasy-jaxrs</artifactId>
 5             <version>3.15.1.Final</version>
 6         </dependency>
 7  
 8         <dependency>
 9             <groupId>javax.validation</groupId>
10             <artifactId>validation-api</artifactId>
11             <version>1.1.0.Final</version>
12         </dependency>

同时需要注意,使用服务器,tomcat 

4、消费者通过制定url连接制定服务提供着

如果服务提供者配置了多个协议,那么在启动服务的时候,就会根据不同的协议提供多个服务。

如果在消费者这边 指明消费某个服务,需要配置:

 1 @RestController
 2 @RequestMapping("site")
 3 public class SiteContorller {
 4  
 5     //订阅服务
 6     //生成代理对象
 7     @DubboReference(version = "v2", url = "dubbo://127.0.0.1:20882/com.mg.boot.api.SiteService")
 8     private SiteService siteService;
 9  
10     @GetMapping("getName")
11     public String getName(String name){
12         return siteService.getName(name);
13     }
14  
15 }

5、服务超时

服务超时,就是调用接口超过服务消费者设置的最长时间。

在dubbo中,直接使用timeout,设置服务的超时时间。

服务提供者:如果超时,会打印超时日志,并且会执行完毕。

 1 @DubboService(version = "timeout", timeout = 4000)
 2 public class TimeOutSiteSerivce implements SiteService {
 3  
 4     @Override
 5     public String getName(String name) {
 6         try {
 7             Thread.sleep(5000);
 8         }catch (Exception e){}
 9         System.out.println("服务。。。。");
10         return "timeout service " + name;
11     }
12 }

服务消费者:如果超时,则进行重试,重试失败抛出异常。

1     @DubboReference(version = "timeout", timeout = 6000)
2     private SiteService siteService;

服务提供者在任何情况下,都会执行业务逻辑。重试2次,就会执行3次(第一次是正常调用)。 

6、集群容错

@DubboReference(version = "timeout", timeout = 3000, cluster = "failover", retries = 1)

dubbo提供的集群容错方案:

  • failover(默认、推荐):当出现失败的时候,会进行重试其他的服务器,默认重试2次,会出现幂等性问题,但是可以在业务方面进行解决:
  • 方案1:把数据的业务ID作为数据库的联合主键,此时业务ID不能重复
  • 方案2:使用分布式锁来控制重复消费问题
  • failfast:当出现问题的时候,立即放回错误,不重试,通常用于非幂等操作,如新增记录
  • failsafe:当出现问题的时候,记录日志
  • failback:失败就失败,开启定时任务重发,通常用于通知操作
  • forking:并行访问多个服务器,获取一个结果既视为成功,forks=2,会浪费很多服务器资源
  • broadcast:广播所有服务提供者,逐个调用,任意一台报错则报错

结论:使用dubbo的时候,不推荐把重试关闭,在非幂等操作场景下,服务提供者需要提供幂等解决方案。

7、服务降级

所谓的服务降级,就是当达到流量高峰的时候,需要保留核心业务的使用。

mock:接口提供假数据的功能。

  • mock=force:return+null 表示消费方对该服务的方法调用都直接返回null值,不发起远程调用。用来屏蔽不重要服务不可用时,对调用放的影响。
  • mock=fail:return+null 表示消费方对该服务方法在调用失败后,在返回null值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。
1  @DubboReference(version = "timeout", timeout = 3000, mock = "fail:return timeout")
2     private SiteService siteService;

同时在接口的相同包下建立存根类,这样就会在注入接口的时候,在封装一层存根类的逻辑:

 1 public class SiteServiceStub implements SiteService {
 2  
 3     private final SiteService siteService;
 4  
 5     public SiteServiceStub(SiteService siteService) {
 6         this.siteService = siteService;
 7     }
 8  
 9  
10     @Override
11     public String getName(String name) {
12         try {
13             return siteService.getName(name);
14         }catch (Exception e){
15             return "stub" + name;
16         }
17     }
18 }

9、参数回调

消费者为服务提供者提供一个回调接口,也就是参数回调。

  • 在接口层中增加方法,增加回调参数
 1 package com.mg.boot.api;
 2  
 3 public interface SiteServiceCallBack {
 4  
 5     String siteName(String name);
 6  
 7     default String siteName(String name , String key, SiteServiceCallBackListener siteServiceCallBackListener){
 8         return null;
 9     }
10 }
  • 增加回调接口和实现类
 1  
 2 import java.io.Serializable;
 3  
 4 public class SiteServiceCallBackListenerImpl implements SiteServiceCallBackListener, Serializable {
 5     @Override
 6     public String change(String data) {
 7         System.out.println("change:" + data);
 8         return "change:" + data;
 9     }
10 }
  • 服务提供者,指明了哪个方法、第几个参数是回调参数
 1 @DubboService(version = "callback", methods = {@Method(name="siteName", arguments = {@Argument(index = 2, callback = true)})}, callbacks = 3)
 2 public class SiteServiceCallBackImpl implements SiteServiceCallBack {
 3  
 4  
 5     @Override
 6     public String siteName(String name) {
 7         return null;
 8     }
 9  
10     @Override
11     public String siteName(String name , String key, SiteServiceCallBackListener siteServiceCallBackListener){
12         siteServiceCallBackListener.change("p data");
13         return "cc:" + name;
14     }
15  
16 }
  • 服务消费者
1     @DubboReference(version = "callback")
2     private SiteServiceCallBack siteServiceCallBack;
3  
4     @GetMapping("getName")
5     public String getName(String name){
6         return siteServiceCallBack.siteName(name, "key",  new SiteServiceCallBackListenerImpl());
7     }

10、异步调用

主要使用 CompletableFuture 接口进行一步数据的返回。

1  @Override
2     public CompletableFuture<String> siteNameAsync(String name){
3         System.out.println("data:" + name);
4         return CompletableFuture.supplyAsync(()->{
5             return siteName(name);
6         });
7     }

六、dubbo的负载均衡策略

官方提供的集中负载均衡的策略:

  • 随机
  • 轮训
  • 一致性hash:相同参数的请求,总是发送到一个提供者
  • 最少活跃调用数:就是处理慢的提供者(服务配置低)接收到少的请求,根据调用的计数差
    • 消费者在本地缓存所有的服务提供者
    • 调用的时候,会选择本地所有服务提供者中active最小的
    • 选定该服务提供者和后,并对其active+1
    • 完成服务后,对其active-1
    • 当active越大,则证明该服务提供者处理性能越差

七、安装Dubbo admin监管平台

可以使用本地安装,也可以使用docker安装。这里介绍受用docker安装方式。

docker run --name dubbo-admin -d -p 7001:7001 dubbo-admin:1.0

在admin中,可以配置相关权重、方法路由规则等等。 

八、Dubbo的SPI可扩展机制

1、java中的sip机制

典型的使用sip,就是jdbc。java内部之约定了jdbc的接口,并没有提供具体实现。当需要连接mysql数据库的时候,就需要mysql实现这套jdbc的接口。这就是java中的sip机制。

如mysql jdbc:

java的DriverManager就会读取这个文件,获取实现类的全路径。

简单理解就是定义一套规范,实现来自不同的供应者,当需要使用哪个供应者的相关内容,引入即可。 

2、sip机制的缺点

自己实现的时候,就使用SeviceLoader 进行加载 配置文件中配置的实现类。 

可以看出java中sip存在,当配置多个实现类的时候,使用ServiceLoader可以获取多个,没有办法指定某一个,不够灵活。

3、dubbo中的sip机制

可以看到,在dubbo中,可以指明需要哪个实现类。

在dubbo中,有很多地方使用spi,例如服务调用协议的部分,根据配置文件中的配置,进行协议的使用。

同时,还可以在spi实现类中实现AOP的效果,其实就是在实现代码的时候,在前面或者后面增加相关功能。

九、Dubbo源码分析

1、Dubbo服务调用过程

a、服务消费者获取代理对象

b、 在注册中心获取服务集群(缓存在消费者本地的地址列表),使用ZookeeperRegistry

c、使用服务器集群中的Invoker调用器,Invoker封装了一次调用流程的整体内容

d、参数、方法名称等封装在RpcInvcation中,使用DubboInvoker进行调用

2、关于DubboInvoker的装饰

通过源码可以看出,Invoker调用采用的是装饰着模式,每一层封装不同的功能。

  • DubboInvoker:使用dubbo协议调用提供者
  • AsyncToSyncInvoker:把异步转换成同步
  • ProtocolFilterInvocker:在调用过程中,提供了大量的功能如监控中心发送调用数据、TSP限流等等,所以主要负责维护过滤器链
  • ListenerInvocker:负责监听链,提供业务回调窗口

3、权重轮训算法

权重轮训就是根据权重去轮训相关内容,例如A、B、C三台权重6、2、2,那调用应该是ABACA的顺序。

 

参考:

https://blog.csdn.net/liming0025/article/details/123785898

https://blog.csdn.net/qq_44292366/article/details/124744901

https://segmentfault.com/a/1190000019896723

https://juejin.cn/post/6949558189733969951

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

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

相关文章

操作系统:文件IO

文章目录文件描述符文件描述符池基本文件操作openopen返回文件描述符的规则open的文件描述符与fopen的文件指针closewritereadlseekfcntl共享文件操作同一进程&#xff0c;多次open同一文件多个进程&#xff0c;多次open同一文件dupdup2利用dup、dup2实现重定位高级文件IO非阻塞…

【网络安全-键盘监视】学会以后去捉弄舍友,看他有了什么不可告人的秘密

&#x1f343;博主昵称&#xff1a;一拳必胜客 博主主页面链接&#xff1a;博主主页传送门 博主专栏页面连接&#xff1a;专栏传送门–计算机考研 &#x1f351;创作初心&#xff1a;本博客的初心是每天分享记录自己学习的脚步&#xff0c;和各位技术友探讨交流&#xff0c;同时…

通过jmap、jstack分析问题,以及分析方法

一、问题 多批次导入任务&#xff0c;会出现异步线程停止工作的情况&#xff0c;后续无论导入多少任务&#xff0c;异步线程都不会执行&#xff0c;只有重启能解决。 二、工具使用 进入jdk的bin目录&#xff1a; cd /beeb/ap/uip/jdk1.8.0_231/bin 2.1 拉取jstack日志&…

setContentView源码解析

一、引言 本文将解析activity加载布局文件的setContentView源码&#xff0c;由于会涉及到部分activity的启动流程&#xff0c;这里附上一张activity启动流程图&#xff1a; 关于 setContentView 源码分两种情况&#xff0c;因为我们的 activity 有两个&#xff1a; 一种是继…

halcon脚本-边缘及骨架的识别【附源码】

文章目录前言一、原图1.边缘图2.骨架图二、实现思路1.边缘图2.骨架图三、halcon脚本实现1.边缘图2.骨架图四、实现效果1.边缘图2.骨架图前言 本文实现基于图像进行边缘或者骨架的识别&#xff0c;可实现让机器人画画 一、原图 1.边缘图 2.骨架图 二、实现思路 1.边缘图 提取…

【阅读】一周翻过《构建之法》,笔记整理

文章目录&#x1f6a9; 前言&#x1f966; 阅读笔记&#x1f33e; 结语&#x1f6a9; 前言 我的阅读方式 我拿到这本书挺久了&#xff0c;之前已经零散地看过一部分&#xff0c;最近一周集中地花了一些时间&#xff0c;将整本书看过了一遍。看得比较粗略&#xff0c;正如“好读…

怎么管理员工混工时的现象?

如果员工存在混工时&#xff0c;这表明公司的管理存在漏洞。让懒散的员工认为自己可以混日子&#xff0c;让没有绩效考核的员工默认可以混日子&#xff0c;同时让对公司感到失望的员工可以完全躺平等待被公司解雇。 工时管理一直是企业需求与痛点。特别是在疫情时期&#xff0c…

华为云数据库GaussDB 为企业核心数据运行提供优质保障

华为云数据库GaussDB 为企业核心数据运行提供优质保障 在网络信息科学技术不断发展的今天&#xff0c;海量存储信息数据中大量的存储资源被浪费&#xff1f;你有没有遇见信息数据备份恢复很慢的情况&#xff1f;让人特别的烦躁&#xff0c;特别是企业遇见了这些情况&#xff0c…

JDBC工具类和JDBC登录案例

JDBC工具类: 抽取JDBC工具类:JDBCUtils 目的:简化书写 分析∶ 1.注册驱动也抽取 2.抽取一个方法获取连接对象 3.抽取一个方法释放资源 代码实现:/*** JDBC工具类*/ public class JDBCUtils {private static String url;private static String user;private static Strin…

Cadence Allegro PCB设计88问解析(十一) 之 Allegro中文件自动保存时间设置

一个学习信号完整性的layout工程师 大家在设计图纸或者编辑文档时&#xff0c;最常点击的应该就是保存图标了。谁也不想因为软件闪退、电脑断电等情况&#xff0c;我们的劳动成果就白白的消失了。在我们用Allegro进行PCB设计&#xff0c;就会有一个自动保存的功能&#xff0c;每…

数字化转型大潮下,企业如何做好绩效管理?

久其EPM白皮书的正式发布&#xff0c;为企业财务的数字化转型实践提供了极具价值的参考。企业绩效管理&#xff08;EPM&#xff09;成为行业热点对于一家企业来说&#xff0c;做好绩效管理究竟有多重要&#xff1f;对于这个问题&#xff0c;全球商界传奇人物、GE前CEO杰克韦尔奇…

事件对象的介绍

● 什么是事件对象&#xff1f;就是当你触发一个事件以后&#xff0c;对该事件的一些描述信息 ● 例如&#xff1a; ○ 你触发一个点击事件时&#xff0c;你点了哪个位置&#xff0c;坐标多少&#xff0c;都在事件对象的属性中体现 ○ 你触发一个键盘事件时&#xff0c;你按下…

探索增强型灰狼优化算法

文章目录一、理论基础1、灰狼优化算法2、探索增强型灰狼优化算法&#xff08;1&#xff09;改进的位置更新公式&#xff08;2&#xff09;非线性控制参数策略&#xff08;3&#xff09;EEGWO算法伪代码二、仿真实验与结果分析三、参考文献一、理论基础 1、灰狼优化算法 请参考…

计算机科学与技术是信息文明时代的入口,是数字世界的基石,是人们必须掌握的基本技能之一

从人类科技发展史的角度看&#xff0c;软件工程&#xff08;计算机编程&#xff09;是刚刚开始的信息文明巨大的趋势中的一部份。人类至今经历过三次工业革命。第一次工业革命的代表是蒸汽机&#xff0c;使得人类拥有了强大的动力。第二次工业革命的代表是电力和石油&#xff0…

高数_第6章无穷级数_幂级数之__阿贝尔定理

阿贝尔定理&#xff1a; 如果幂级数 在 点 x x₀(x₀≠0)处收敛&#xff0c; 则对于适合不等式 |x| < |x₀|的一切x, 都有幂级数 在点 x 处绝对收敛&#xff1b; 反之&#xff0c;如果幂级数 在点 x x₀ (x₀≠0)处发散&#xff0c; 则对于适合不等式 |x| >…

使用Code Chart绘制流程图

Code Chart介绍 Code Chart是一个基于 Javascript 的图表和图表工具&#xff0c;它基于 markdown 语法来简化和加速生成流程图的过程&#xff0c;也不止于生成流程图。 工具地址&#xff1a;https://www.iodraw.com/codechart 图形 头部用graph 或flowchart 关键字来声明流程…

Anaconda安装

文章目录1. Anaconda3简介2. Anaconda3下载3. Anaconda3安装1. Anaconda3简介 Anaconda3 是一个用于 Python 科学计算和机器学习的开源工具&#xff0c;它是 Python 的一个科学计算发行版&#xff0c;支持 Linux、macOS 和 Windows 系统&#xff0c;包含 conda 等众多工具包和…

python抓取Prometheus的数据(使用prometheus-api-client库)

python抓取Prometheus的数据(使用prometheus-api-client库) 0、写在前面 我们要想抓取Prometheus的数据,一般想到的就是requests请求,爬虫的方式来抓取,这是可行的,当然,还有一个第三方库直接封装好了,直接用就行,代码也比较少,源码点进去就能看明白,这个库叫promet…

多链世界的“高速公路”:一文读懂跨链协议演进与未来

当我们发现自己正处于另一个“加密货币寒冬”之中——这在很大程度上是由一系列项目破产、监管打击和宏观看跌推动的——但重要的是&#xff0c;我们不要忽视促成下一次牛市的技术突破和将权力下放的精神重新引入大众。 上一个周期的主题之一仍然是行业参与者讨论的最前沿的主…

无网络机器上,win下vscode客户端通过ssh连接linux服务器

目录 参考文献 前言 下载安装VSCode 下载 安装 下载和安装必要的VSCode插件 下载 安装 客户端通过ssh远程连接linux服务器 下载并安装ssh 远程连接linux服务器 参考文献 Windows使用VSCode远程Linux&#xff08;ConteOS&#xff09;开发/调试C/C&#xff08;超详细…