Dubbo基础入门一

1、什么是Dubbo3

Apache Dubbo 是一款易用、高性能的 WEB 和 RPC 框架,同时为构建企业级微服务提供服务发现、流量治理、可观测、认证鉴权等能力、工具与最佳实践。

“Dubbo3 已在阿里巴巴内部微服务集群全面落地,成功取代运行多年的 HSF 框架。”

2、构建Dubbo3脚手架

2.1 框架依赖

  • Maven
  • SpringCloud 2.6.11
  • Dubbo 3.1.8 + zookeeper 3.4.14

2.2 搭建Zookeeper

  • 解压

    image.png

  • 修改zk的配置文件

    进入conf,将文件zoo_sample.cfg 改为zoo.cfg

    image.png

  • 测试zk

    启动zookeeper

    执行zookeeper根目录下,bin文件中的zkServer.cmd

    image.png

    上面的CMD窗口不要关闭,这样zookeeper就是出于运行状态了

2.3 创建工程

2.3.1 创建父工程

mdb-dubbo-ann

父工程控制版本:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.11</version><relativePath/> <!-- lookup parent from repository --></parent><modules><module>dubbo-consumer</module><module>dubbo-provider</module><module>dubbo-common</module></modules><groupId>com.msb</groupId><artifactId>msb-dubbo-ann</artifactId><version>0.0.1-SNAPSHOT</version><name>msb-dubbo-ann</name><packaging>pom</packaging><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version><dubbo-version>3.1.8</dubbo-version></properties><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-spring-boot-starter</artifactId><version>${dubbo-version}</version></dependency><dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-rpc-dubbo</artifactId><version>${dubbo-version}</version></dependency><dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-registry-zookeeper</artifactId><version>${dubbo-version}</version></dependency></dependencies></dependencyManagement></project>

2.3.2 创建提供者

dubbo-provider

引入依赖:

<dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-rpc-dubbo</artifactId>
</dependency>
<dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-registry-zookeeper</artifactId>
</dependency>

增加配置

server:port: 8002
logging:config: classpath:logback.xml
dubbo:application:name: dubbo-providerprotocol:name: dubbo#客户端链接20880就可以访问我们的dubboport: 20883registry:address: zookeeper://127.0.0.1:2181

更改主类

import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
// 因为是自动装配也可以不加这个注解
@EnableDubbo(scanBasePackages = "com.msb.dubbo.provider.service")
@SpringBootApplication
public class DubboProviderApplication {public static void main(String[] args) {SpringApplication.run(DubboProviderApplication.class);}
}

接着增加通信端口

public interface IUserService {User getUserById(Long id);
}
@Data
@AllArgsConstructor
@Builder
public class User implements Serializable {private static final long serialVersionUID = 1L;private Long id;private String name;private int age;}

增加实现类

@DubboService// 定义一个dubbo服务
public class UserServiceImpl implements IUserService {@Overridepublic User getUserById(Long id) {User user = User.builder().id(id).age(12).name("天涯").build();return user;}

2.3.3 创建客户端

引入依赖

<!--这里是dubbo和SpringBoot桥梁的整合-->
<dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<!--每一种协议都会对应的一个jar比方:dubbo、rest、tripe 三种协议-->
<dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-rpc-dubbo</artifactId>
</dependency>
<!--注册中心可以是zk,nacos -->
<dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-registry-zookeeper</artifactId>
</dependency>

更改配置

server:port: 8001
logging:config: classpath:logback.xml
dubbo:application:name: dubbo-consumerregistry:address: zookeeper://127.0.0.1:2181

更改主类

@EnableDubbo
@SpringBootApplication
public class DubboConsumeApplication {public static void main(String[] args) {SpringApplication.run(DubboConsumeApplication.class);}
}

增加调用接口

public interface IUserService {User getUserById(Long id);
}
@Data
@AllArgsConstructor
@Builder
public class User implements Serializable {private static final long serialVersionUID = 1L;private Long id;private String name;private int age;}

增加业务调用处理

@RestController
public class OrderController {@Autowiredprivate OrderService orderService;@RequestMapping("/createOrder/{userId}")public String createOrder(@PathVariable("userId") Long userId){return orderService.createOrder(userId);}
}
@Slf4j
@Service
public class OrderService {// 引用对应的dubbo服务@DubboReferenceprivate IUserService iUserService;public String createOrder(Long userId){User user = iUserService.getUserById(userId);log.info("用户用户信息:{}",user);return "创建订单成功";}
}

2.3.4 测试

http://localhost:8001/createOrder/232

image.png

2.3.5 重构创建公共模块

dubbo-common 存放IUserService 和User

提供端和消费端

<dependency><groupId>com.msb</groupId><artifactId>dubbo-common</artifactId><version>0.0.1-SNAPSHOT</version>
</dependency>

2.3.6 测试

http://localhost:8001/createOrder/232

image.png

2.4 开启rest协议

如果我们的服务希望既要支持dubbo协议调用,也要能支持http调用,所以,要么仍然保留SpringMVC那一套,如果不想保留那一套,就可以开启 dubbo中的rest协议。

2.4.1 增加依赖

<dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-rpc-rest</artifactId>
</dependency>

2.4.2 更改配置

dubbo:application:name: dubbo-provider# 这里的协议加了s,所以可以设置多个通信协议protocols:p1:name: dubbo#客户端链接20883就可以访问我们的dubboport: 20883p2:name: rest#客户端链接20884就可以访问我们的restport: 20884

2.4.3 更改对应代码服务

@DubboService// 定义一个dubbo服务
@Path("/user")
public class UserServiceImpl implements IUserService {@GET@Path("/{userId}")@Produces(MediaType.APPLICATION_JSON)@Overridepublic User getUserById(@PathParam("userId") Long userId) {User user = User.builder().id(userId).age(12).name("天涯").build();return user;}}

2.4.4 测试

在消费端增加RestTemplate

@EnableDubbo
@SpringBootApplication
public class DubboConsumeApplication {@Beanpublic RestTemplate restTemplate(){return new RestTemplate();}public static void main(String[] args) {SpringApplication.run(DubboConsumeApplication.class);}
}
@Slf4j
@Service
public class OrderService {@DubboReferenceprivate IUserService iUserService;@AutowiredRestTemplate restTemplate;public String createOrder(Long userId){User user = restTemplate.getForObject("http://localhost:20884/user/232",User.class);log.info("用户用户信息:{}",user);return "创建订单成功";}
}

http://localhost:8001/createOrder/232

image.png

2.4.5 使用接口调用Rest

将rest协议放到common中

 <dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-rpc-rest</artifactId></dependency>

修改IUserService

@Path("/user")
public interface IUserService {@GET@Path("/{userId}")@Produces(MediaType.APPLICATION_JSON)User getUserById(@PathParam("userId") Long id);
}

修改consume里面内容

@Slf4j
@Service
public class OrderService {// 指定写协议@DubboReference(protocol = "rest")private IUserService iUserService;@AutowiredRestTemplate restTemplate;public String createOrder(Long userId){User user = iUserService.getUserById(userId);log.info("用户用户信息:{}",user);return "创建订单成功";}
}

如果我们不能确定是否是走的http,我们可以DispatcherServlet#service 里面打个端点,看是否进入

image.png

3、Dubbo 架构

Dubbo 是一种高性能、轻量级的开源 Java RPC 框架,由阿里巴巴开发并开源。它提供了一种基于 Java 的远程过程调用(RPC)服务框架,用于快速地构建分布式服务和应用。Dubbo 的架构主要由以下几个核心组件组成:

Provider(服务提供者):提供服务的节点。服务提供者将自己的服务注册到注册中心,并监听客户端的调用请求,处理请求并返回结果。

Consumer(服务消费者):调用远程服务的节点。服务消费者从注册中心订阅服务提供者的信息,然后根据负载均衡策略选择合适的提供者进行调用。

Registry(注册中心):用于服务的注册与发现。Dubbo 支持多种注册中心,如 ZooKeeper、Redis、Multicast 等。服务提供者将自己的服务信息注册到注册中心,而服务消费者从注册中心获取提供者的地址列表。

Monitor(监控中心):用于监控 Dubbo 的运行状态,如服务的调用次数、响应时间等。监控中心可以帮助开发人员实时地监控服务的健康状态,并进行故障排查和性能优化。

Container(容器):用于加载和运行 Dubbo 服务。Dubbo 支持多种容器,如 Spring、Servlet、Main 等,开发人员可以根据自己的需求选择合适的容器来运行 Dubbo 服务。

Protocol(通信协议):定义了服务提供者和服务消费者之间的通信规范。Dubbo 支持多种通信协议,如 Dubbo 协议、HTTP 协议、RMI 协议等。

Cluster(集群容错):用于处理服务提供者的高可用性和容错能力。Dubbo 提供了多种集群容错策略,如 Failover、Failfast、Failsafe 等,开发人员可以根据自己的需求选择合适的策略。

Proxy(服务代理):用于生成服务提供者和服务消费者的代理对象。Dubbo 使用 JDK 动态代理和 Javassist 字节码生成技术来生成代理对象,实现了服务的远程调用。

4、服务注册

4.1 Zookeeper注册数据基本结构

我们可以用zkCli.cmd来链接服务,查看对应的节点, 我们可以想象成一个一个的文件夹,

image.png

使用ZooInspector来查看对应的节点

=image.png

4.2 接口级注册

image.png

在这个过程中:

  • 每个 Provider 通过特定的 key 向注册中心注册本机可访问地址;
  • 注册中心通过这个 key 对 provider 实例地址进行聚合;
  • Consumer 通过同样的 key 从注册中心订阅,以便及时收到聚合后的地址列表;

4.2.1 数据结构

image.png

4.1.2 接口易用性代价

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一个事物总是有其两面性,Dubbo2 地址模型带来易用性和强大功能的同时,也给整个架构的水平可扩展性带来了一些限制。这个问题在普通规模的微服务集群下是完全感知不到的,而随着集群规模的增长,当整个集群内应用、机器达到一定数量时,整个集群内的各个组件才开始遇到规模瓶颈。在总结包括阿里巴巴、工商银行等多个典型的用户在生产环境特点后,我们总结出以下两点突出问题(如图中红色所示):

  • 首先,注册中心集群容量达到上限阈值。由于所有的 URL 地址数据都被发送到注册中心,注册中心的存储容量达到上限,推送效率也随之下降。
  • 而在消费端这一侧,Dubbo2 框架常驻内存已超 40%,每次地址推送带来的 cpu 等资源消耗率也非常高,影响正常的业务调用。

为什么会出现这个问题?我们以一个具体 provider 示例进行展开,来尝试说明为何应用在接口级地址模型下容易遇到容量问题。 青蓝色部分,假设这里有一个普通的 Dubbo Provider 应用,该应用内部定义有 10 个 RPC Service,应用被部署在 100 个机器实例上。这个应用在集群中产生的数据量将会是 “Service 数 * 机器实例数”,也就是 10 * 100 = 1000 条。数据被从两个维度放大:

  • 从地址角度。100 条唯一的实例地址,被放大 10 倍
  • 从服务角度。10 条唯一的服务元数据,被放大 100 倍

4.3 应用级注册

image.png

那这样 1个服务有10个服务接口 100个实例对应数据应该

mapping里面有 10条 services 里面就100 条 总共是110条

这里元数据可以放到元数据中心(可以和注册中心一样),也可以放到本地,消费者获取需要发送rpc调用

默认发送本地 ,对应配置

image.png

4.4 Provider和Consumer双版本支持参数讲解

Provicer提供方

dubbo.application.register-mode

参数参数含义
interface只有接口级注册
instance只有应用级注册
all(默认)接口级注册和应用级注册并存

image.png

Consumer消费方

dubbo.application.service-discovery.migration:FORCE_INTERFACE

参数参数含义
FORCE_INTERFACE只消费接口级地址,如无地址则报错,单订阅2.x地址
APPLICATION_FIRST(默认)智能决策接口级/应用级地址,双订阅
FORCE_APPLICATION只消费应用级地址,如无地址则报错,单订阅3.x地址

image.png

4.5 为什么Dubbo3支持双版本注册

为了方便迁移, Dubbo3.0之前都是接口级别注册,Dubbo3之后都是应用级注册

5、服务注册源码分析

5.1 服务启动

找入口 是@EnableDubbo

image.png

5.1.1 注册DubboDeployApplicationListener

这里监听器是监听Spring容器启动之后,我们再进行服务注册,不符订阅,应用注册,启动本地服务

image.png

image.png

image.png

image.png

image.png

image.png

5.1.2 扫描我们@DubboService 注册BeanDefinition

image.png

image.png

DubboComponentScanRegistrar 执行的时候会调用registerBeanDefinitions

image.png

注册后置处理器ServiceAnnotationPostProcessor

image.png

image.png

ServiceAnnotationPostProcessor 实现BeanDefinitionRegistryPostProcessor则进行BeanDefintion的注册

image.png

image.png

注册userServiceImpl

image.png

注册ServieBean的BeanDefinition

image.png

5.1.3 加载配置文件

image.png

image.png

image.png

image.png

配置的加载

image.png

image.png

5.2 服务导出

面试题:Dubbo3是什么时候进行服务导出的?

Dubbo3通过DubboDeployApplicationListener监听Spring的启动,当Spring启动会发送ContextRefreshedEvent事件,DubboDeployApplicationListener监听这个事件进行服务导出,会把我们服务注册到注册中心,并且启动本地服务。

问题: 服务导出 :获取服务配置 + 服务注册(服务) + 启动服务(Netty/Tomcat),那先注册再启动,还是先启动再注册?

先启动再注册,如果先注册再启动,那么注册完还没有启动的时候,别的服务就调用进来这就会出现调用失败

这里注意有接口级的注册和应用的注册

5.2.1 入口分析

我们通过DubboDeployApplicationListener

image.png

image.png

image.png

如下图这里就是核心内容

image.png

5.2.2 接口级注册

image.png

5.2.2.1 判断注册方式

exportServices是进行接口级注册,由于他的调用链路比较长我们直接来到 ServiceConfig#doExportUrls

通过配置的模式获取对应注册地址

image.png

image.png

image.png

image.png

可以看到这里简化的配置比较容易理解了

  • 双注册模式配置查询 对应参数为dubbo.application.register-mode ,默认值为all
  • 如果用户配置了接口注册模式配置则只走接口级配置 这里默认值为interface
  • 满足应用级注册就添加一个应用级注册的地址
  • 满足接口级注册配置就添加一个接口级注册地址

这个方法是根据服务注册模式来判断使用接口级注册地址还是应用级注册地址分别如下所示: 配置信息: dubbo.application.register-mode 配置值:

  • interface
    • 接口级注册
  • instance
    • 应用级注册
  • all
    • 接口级别和应用级都注册

最终的注册地址配置如下: 接口级注册地址

registry://127.0.0.1:2181/org.apache.dubbo.registry.RegistryService?application=dubbo-demo-api-provider&dubbo=2.0.2&pid=9008&registry=zookeeper&release=3.0.8&timestamp=1653703292768

应用级注册地址:

service-discovery-registry://127.0.0.1:2181/org.apache.dubbo.registry.RegistryService?application=dubbo-demo-api-provider&dubbo=2.0.2&pid=10275&registry=zookeeper&release=3.0.8&timestamp=1653704425920

前面说了这个注册服务的配置地址会由Dubbo内部进行判断如果判断是all的话会自动将一个配置的注册地址转变为两个一个是传统的接口级注册,一个是应用级注册使用的配置地址

5.2.2.2 生成invoke

image.png

我们来看key1:获取对应的invoke

image.png

然后我们再看注册中心,注册服务数据的源码 如果想要查看源码细节可以在RegistryProtocol类型的export(final Invoker originInvoker) 方法的如下代码位置打断点:

RegistryProtocol的export方法的注册中心注册数据代码如下:

image.png

1、暴露本地服务,就是提供给调用方一个调用的接口服务,这个我们后面来说

2、获取注册Registry ,这里如果是接口级注册则是ZookeeperRegistry,如果应用级注册:ServiceDiscoveryRegistry

3、我们看一下registry

5.2.2.3 接口级注册

我们再ZookeeperRegistry#doRegistry打上端点

image.png

image.png

堆栈信息中我们可以看到调用它的方法是

image.png

image.png

5.2.2.4 应用级注册将服务提供者数据转换到本地内存的元数据信息中

image.png

image.png

5.2.2.5 映射数据注册(应用)

image.png

image.png

image.png

5.2.3 应用级注册

image.png

5.2.3.1 应用元数据信息注册

image.png

image.png

image.png

5.2.3.2 实例信息

image.png

image.png

这里最终会调用到ZookeeperServiceDiscovery#doRegister

image.png

image.png

image.png

image.png

6、本地服务暴露

那我们注意点如果是dubbo我们应该用netty绑定一个端口

image.png

image.png

image.png

image.png

image.png

image.png

这里最终会调用到 NettyServer#doOpen

image.png

7、Consumer的订阅服务

image.png

7.1 订阅入口

来到关键入口类DefaultModuleDeployer#startSync 方法

image.png

image.png

image.png

image.png

image.png

这里分两点:1、是创建一个远程调用 invoke,2、创建代理类

我们先看第1点

image.png

image.png

image.png

image.png

image.png

image.png

image.png

7.2 接口级订阅

这里我们进入选择应用级订阅、接口级订阅、应用和接口级订阅, 我们进入应用和接口级订阅

image.png

image.png

首先进入接口级订阅:

image.png

image.png

image.png

最终会到 FailbackRegistry#subscribe

image.png

image.png

image.png

image.png

上面是进行目录 创建,有则忽略,没有则创建, 让后给子节点增加监听器

最后将数据urls放到缓存

image.png

image.png

image.png

image.png

7.3 应用级订阅

这里我们进入选择应用级订阅、接口级订阅、应用和接口级订阅, 我们进入应用和接口级订阅

image.png

image.png

应用级订阅

image.png

image.png

最终会调用到ServiceDiscoveryRegistry#doSubscribe

这里面设计到两个关键点、

image.png

1、获取接口对应的应用名称

image.png

image.png

image.png

image.png

2、subscribedServices为接口所对应的应用名,接下来就会取获取该应用的所有实例

image.png

获取对应实例的元数据信息

循环发送事件ServiceInstancesChangedEvent,ServiceInstancesChangedListener#onEvent获取对应事件来获取对应的元数据信息

image.png

image.png

这里我们重点分析一下从远端获取数据

image.png

image.png

7.4 智能选择 接口级还是应用级

image.png

image.png

image.png

如果应用级注册为空,接口级注册不为空,则是使用接口级注册

如果接口级注册为空,应用级注册不为空,则是使用应用级注册

如果接口级和应用级都不为空,则用应用级

7.5 创建代理类

image.png

最终回到用到JavassistProxyFactory

image.png

7.6 @DubboReference标注对象的引入

image.png

image.png

我们看一下ReferenceAnnotationBeanPostProcessor的继承关系

image.png

它继承BeanFactoryPostProcessor,所以他一定为实现postProcessBeanFactory

image.png

image.png

image.png

后面会将@DubboReference标注类对应的BeanDefinition进行实例化,我们看一下对应class类ReferenceBean

image.png

问题:我们如果想往IOC容器中注入一个对象应该怎样处理

使用@Bean进行方法的标注 或者实现接口FactoryBean

所以此时应该关注ReferenceBean#getObject

image.png

image.png

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

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

相关文章

5G 网络切片VLAN ID配置错误导致业务不可用

【摘要】随着电联5G共建共享工作的开展&#xff0c;无法及时有效观测到单逻辑站点的相关指标&#xff0c;导致单运营商用户业务出现异常。本案例中着重对单运营商用户无法使用网络进行相关参数排查&#xff0c;从KPI性能指标结合故障告警发生时间&#xff0c;从而分析由于网络切…

稀碎从零算法笔记Day6-LeetCode:长度最小的子数组

前言&#xff1a;做JD的网安笔试题&#xff0c;结果查找子串&#xff08;单词&#xff09;这个操作不会。痛定思痛&#xff0c;决定学习滑动数组 题型&#xff1a;数组、双指针、滑动窗口 链接&#xff1a;209. 长度最小的子数组 - 力扣&#xff08;LeetCode&#xff09; 来…

(学习日记)2024.03.06:UCOSIII第八节:空闲任务+阻塞延时+main函数修改

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

CSS字体样式值,前端开发基础学习

元素特点&#xff1a; 块状元素&#xff1a; 在页面中以矩形区域显示。自上而下排列&#xff0c;独占一行可以直接添加宽高一般情况下&#xff0c;作为其他元素或内容的容器 行内元素&#xff1a; 在页面中最小单位也是矩形。在一行内逐个排列。不可以直接添加宽高&#xf…

OWASP Top 10 网络安全10大漏洞——A01:2021-访问控制中断

10大Web应用程序安全风险 2021年top10中有三个新类别、四个类别的命名和范围变化&#xff0c;以及一些合并。 A01&#xff1a;2021-访问控制中断 从第五位上升到top1&#xff0c;94%的应用程序都经过了某种形式的访问控制破坏测试&#xff0c;平均发生率为 3.81%且在贡献的…

flutter弹窗输入,Android学习的三个终极问题及学习路线规划

题库非常全面包括&#xff1a; Android基础知识: 基本涵盖Android所有知识体系&#xff0c;四大组件&#xff0c;Fragment,WebView,事件分发&#xff0c;View绘制…Java基础知识&高阶知识点: 基础部分不谈了&#xff0c;高阶部分&#xff1a;泛型&#xff0c;反射&#xff…

蓝桥杯刷题(一)

一、 import os import sys def dps(s):dp [0] * len(s)dp[0] ord(s[0]) - 96if len(s) 1:return dp[-1]dp[1] max(ord(s[0]) - 96, ord(s[1]) - 96)for i in range(2, len(s)):dp[i] max(dp[i - 1], dp[i - 2] (ord(s[i])) - 96)return dp[-1] s input() print(dps(s))…

【SpringBoot3.x教程 01】SpringBoot简介及工程搭建

前言&#xff1a;什么是SpringBoot&#xff1f; SpringBoot是一个开源的Java基础框架&#xff0c;它被设计来简化Spring应用的初始搭建以及开发过程。这个框架利用了“约定优于配置”的理念&#xff0c;提供了一系列大型项目中常用的默认配置&#xff0c;让开发者可以快速启动和…

stm32学习笔记:I2C通信外设原理(未完)

软件实现和硬件实现 串口通信为异步时序&#xff0c;用软件实现很麻烦&#xff0c;基本上用硬件实现 而I2C协议通信为同步时序&#xff0c;软件实现简单且灵活&#xff0c;硬件实现比较麻烦&#xff0c;故软件比较常用 但I2C硬件实现功能比较大&#xff0c;执行效率高&#xff…

【数据分享】1984~2020年中国长时间序列逐年人造夜间灯光数据集

各位同学们好&#xff0c;今天和大伙儿分享的是1984~2020年中国长时间序列逐年人造夜间灯光数据集。如果大家有下载处理数据等方面的问题&#xff0c;您可以私信或评论。 张立贤, 任浙豪, 陈斌, 宫鹏, 付昊桓, 徐冰. (2021). 中国长时间序列逐年人造夜间灯光数据集&#xff08;…

大数据开发-Hadoop分布式集群搭建

大数据开发-Hadoop分布式集群搭建 文章目录 大数据开发-Hadoop分布式集群搭建环境准备Hadoop配置启动Hadoop集群Hadoop客户端节点Hadoop客户端节点 环境准备 JDK1.8Hadoop3.X三台服务器 主节点需要启动namenode、secondary namenode、resource manager三个进程 从节点需要启动…

42岁前TVB女星近况曝光,曾因山头靠不住被雪藏兼生意失败

自从2021年前TVB高层余咏珊倒台离巢后&#xff0c;大批「余派」被雪藏&#xff0c;随即跟着走人&#xff0c;今年42岁的「元老级是非精」梁嘉琪就是其中之一。 梁嘉琪在离巢后就重新签约有线做回老本行主持节目&#xff0c;去年3月又与森美、小仪主持商台903节目《早霸王》&…

Zynq—AD9238数据采集DDR3缓存千兆以太网发送实验(二)

Zynq—AD9238数据采集DDR3缓存千兆以太网发送实验&#xff08;前导&#xff09; Zynq—AD9238数据采集DDR3缓存千兆以太网发送实验&#xff08;一&#xff09; Zynq—AD9238数据采集DDR3缓存千兆以太网发送实验&#xff08;三&#xff09; 五、实验目的 本次实验使用电脑上的…

动态规划(算法竞赛、蓝桥杯)--背包DP求具体方案

1、B站视频链接&#xff1a;E20 背包DP 求具体方案_哔哩哔哩_bilibili #include <bits/stdc.h> using namespace std; const int N1010; int v[N],w[N]; int f[N][N],p[N][N];int main(){int n,m;cin>>n>>m;for(int i1;i<n;i)cin>>v[i]>>w[i…

mybatis的xml文件如何配置能被识别

为了让MyBatis能够识别和使用XML Mapper文件&#xff0c;你需要确保这些文件被正确放置和配置。下面是确保MyBatis XML Mapper文件被识别的步骤&#xff1a; 1. 正确放置XML Mapper文件 通常&#xff0c;XML Mapper文件应该放在src/main/resources目录下。为了更好的组织这些…

基于SSM的农业信息管理系统的设计与实现(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于SSM的农业信息管理系统的设计与实现&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;…

字节跳动热门的前端开源项目

字节跳动开源官网 Arco Dsign Arco Design 是一套设计系统&#xff0c;主要服务于字节跳动旗下中后台产品的体验设计和技术实现。它的目标在于帮助设计师与开发者解放双手、提升工作效率&#xff0c;并高质量地打造符合业务规范的中后台应用。它拥有系统的设计规范和资源&…

运维知识点-hibernate引擎-HQL

HQL有两个主要含义&#xff0c;分别是&#xff1a; HQL&#xff08;Hibernate Query Language&#xff09;是Hibernate查询语言的缩写&#xff0c;它是一种面向对象的查询语言&#xff0c;类似于SQL&#xff0c;但不是去对表和列进行操作&#xff0c;而是面向对象和它们的属性…

ArmSoM Rockchip系列产品 通用教程 之 UART 使用

1. UART 简介​ Rockchip UART (Universal Asynchronous Receiver/Transmitter) 基于16550A串口标准&#xff0c;完整模块支持以下功能&#xff1a; 支持5、6、7、8 bits数据位。支持1、1.5、2 bits停止位。支持奇校验和偶校验&#xff0c;不支持mark校验和space校验。支持接…

Yolov8有效涨点,添加多种注意力机制,修改损失函数提高目标检测准确率

目录 简介 CBAM注意力机制原理及代码实现 原理 代码实现 GAM注意力机制 原理 代码实现 修改损失函数 YAML文件 完整代码 &#x1f680;&#x1f680;&#x1f680;订阅专栏&#xff0c;更新及时查看不迷路&#x1f680;&#x1f680;&#x1f680; http://t.csdnimg.c…