5-3 Dubbo | 负载均衡
Dubbo概述
什么是RPC
RPC是Remote Procedure Call的缩写 翻译为:远程过程调用
目标是为了实现两台(多台)计算机\服务器,互相调用方法\通信的解决方案
RPC的概念主要定义了两部分内容
1.序列化协议
2.通信协议
为了方便大家理解RPC,下面的图片帮助理解
上面图是老婆和老公在家的时,老婆让老公洗碗的调用流程
但这个流程是本地的,
我们再换成远程调用的图片
通信协议
通信协议指的就是远程调用的通信方式
再上面图片调用中,老婆使用手机信息的方法通知老公去洗碗
实际上这个通知的方式可以有多种
例如:写信,飞鸽传书,闪送等等
序列化协议
序列化协议指通信内容的格式,双方都要理解这个格式
上面的图片中,老婆给老公发信息,一定是双方都能理解的信息
发送信息是序列化过程,接收信息需要反序列化
什么是Dubbo
理解了RPC再学习Dubbo就会简单一些了
Dubbo是一套RPC框架。既然是框架,我们可以在框架结构高度,定义Dubbo中使用的通信协议,使用的序列化框架技术,而数据格式由Dubbo定义,我们负责配置之后直接通过客户端调用服务端代码。
简单来说,Dubbo就是RPC概念的实现
Dubbo是Spring Cloud Alibaba提供的一个框架
能够实现微服务项目的互相调用
Dubbo的发展历程
2012年底dubbo停止更新后到2017年dubbo继续更新之前
2015SpringCloud开始兴起,当时没有阿里的框架
国内公司要从SpringCloud和Dubbo中抉择使用哪个微服务方案
在2012年dubbo停止更新后国内的当当网在dubbo的基础上开发了dubboX框架,并进行维护
2019年后,SpringCloud和Dubbo才能共同使用
Dubbo的协议支持
RPC框架分通信协议和序列化协议
Dubbo框架支持多种通信协议和序列化协议,可以通过配置文件进行修改
支持的通信协议有
- dubbo协议(默认)
- rmi协议
- hessian协议
- http协议
- webservice
- .....
支持的序列化协议
- hessian2(默认)
- java序列化
- compactedjava
- nativejava
- fastjson
- dubbo
- fst
- kryo
Dubbo默认情况下,协议的特征如下
- 采用NIO单一长连接
- 优秀的并发性能,但是大型文件的处理差
- Dubbo开发简单,有助于提升开发效率
Dubbo服务的注册与发现
在Dubbo的调用过程中,必须包含注册中心的支持
注册中心推荐使用Nacos,但是如果使用其他软件也能实现例如(Redis,zookeeper等)
服务发现,即消费端自动发现服务地址列表的能力,是微服务框架需要具备的关键能力,借助于自动化的服务发现,微服务之间可以在无需感知对端部署位置与 IP 地址的情况下实现通信。
上面的示例中,老婆就是服务器的发现者,它能够获取老公的所有功能列表
老婆一旦调用公的服务就完成了Dubbo的调用
consumer服务的消费者,指服务的调用者(使用者)也就是老婆的位置
provider服务的提供者,指服务的拥有者(生产者)也就是老公的位置
在Dubbo中,远程调用依据是服务的提供者在Nacos中注册的服务名称
一个服务名称,可能有多个运行的实例,任何一个空闲的实例都可以提供服务
常见面试题:Dubbo的注册发现流程
1.首先服务的提供者启动服务到注册中心注册,包括各种ip端口信息,Dubbo会同时注册该项目提供的远程调用的方法
2.服务的消费者(使用者)注册到注册中心,订阅发现
3.当有新的远程调用方法注册到注册中心时,注册中心会通知服务的消费者有哪些新的方法,如何调用的信息
4.RPC调用,在上面条件满足的情况下,服务的调用者无需知道ip和端口号,只需要服务名称就可以调用到服务提供者的方法
Dubbo实现微服务调用
确定调用关系
在上面的模型中,以order调用stock减少库存的业务举例
order模块是消费者stock模块是生产者
在代码调用时,首先要对项目进行必要的配置
我们调用时一般会在消费者项目的代码业务逻辑层中,编写调用生产者业务逻辑层方法的代码
这样做的好处
我们的生成者正常编写mapper>service>controller这个开发流程不会因为Dubbo的介入而变化
修改stock模块
创建csmall-stock-service项目
stock模块要新建一个项目单独保存要公开给其他微服务项目的方法接口
创建csmall-stock-service项目
删除test\删除resources\删除SpringBoot启动类
csmall-stock父项目pom文件添加必要配置
<groupId>cn.tedu</groupId>
<artifactId>csmall-stock</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>csmall-stock</name>
<description>Demo project for Spring Boot</description>
<!-- ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓-->
<packaging>pom</packaging>
<modules>
<module>csmall-stock-service</module>
</modules>
子项目要编写最低限度的pom依赖
<?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>cn.tedu</groupId>
<artifactId>csmall-stock</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>cn.tedu</groupId>
<artifactId>csmall-stock-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>csmall-stock-service</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<dependency>
<groupId>cn.tedu</groupId>
<artifactId>csmall-commons</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
然后将原有的业务逻辑层接口复制到这个项目中即可
public interface IStockService {
// 减少库存数的业务逻辑层方法
void reduceCommodityCount(StockReduceCountDTO stockReduceCountDTO);
}
创建csmall-stock-webapi项目
创建csmall-stock-webapi项目
删除test测试文件夹
父子相认
csmall-stock的pom文件最终为:
<?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>cn.tedu</groupId>
<artifactId>csmall</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>cn.tedu</groupId>
<artifactId>csmall-stock</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>csmall-stock</name>
<description>Demo project for Spring Boot</description>
<packaging>pom</packaging>
<modules>
<module>csmall-stock-service</module>
<module>csmall-stock-webapi</module>
</modules>
</project>
修改子项目pom文件
<?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>cn.tedu</groupId>
<artifactId>csmall-stock</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>cn.tedu</groupId>
<artifactId>csmall-stock-webapi</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>csmall-stock-webapi</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<!--web实例-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--mybatis整合springboot-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!--alibaba 数据源德鲁伊-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--all-common依赖-->
<dependency>
<groupId>cn.tedu</groupId>
<artifactId>csmall-commons</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!--在线api文档-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>
<!-- nacos注册中心依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- Dubbo依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<!-- 添加camall-stock-service的依赖,以实现业务逻辑层接口 -->
<dependency>
<groupId>cn.tedu</groupId>
<artifactId>csmall-stock-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
将csmall-stock项目的application.yml和application-dev.yml复制到csmall-stock-webapi项目的resources文件夹下
修改application-dev.yml最终内容为
spring:
datasource:
url: jdbc:mysql://localhost:3306/csmall_db?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowMultiQueries=true
username: root
password: root
application:
name: nacos-stock
cloud:
nacos:
discovery:
server-addr: localhost:8848
dubbo:
protocol:
port: -1 # 设置Dubbo服务调用的端口 设置-1能够实现动态自动设置合适端口,生成规则是从20880开始递增
name: dubbo # 设置端口名称,一般固定就叫dubbo
registry:
address: nacos://localhost:8848 # 配置当前Dubbo注册中心的类型和地址
consumer:
check: false # 设置为false表示当前项目启动时,不检查要调用的远程服务是否可用,避免报错
下面复制代码
我们可以先删除业务逻辑层接口
然后直接复制cn.tedu.....这个包中的所有内容
复制到webapi项目包下
注意impl包重命名的问题
然后就可以删除csmall-stock项目的src文件夹了
下面就可以调整webapi项目的中配置路径了
Knife4jConfiguration:
/**
* 【重要】指定Controller包路径
*/
private String basePackage = "cn.tedu.csmall.stock.webapi.controller";
MyBatisConfiguration:
@Configuration
// Mybatis扫描必须指定到mapper包
@MapperScan("cn.tedu.csmall.stock.webapi.mapper")
public class MybatisConfiguration {
}
将业务逻辑层实现类方法声明为Dubbo可调用的方法
// @DubboService注解表示当前业务逻辑层实现类中的所有方法
// 均会注册到Nacos,成为Dubbo可以被发现的业务逻辑层方法
@DubboService
@Service
@Slf4j
public class StockServiceImpl implements IStockService {
@Autowired
private StockMapper stockMapper;
@Override
public void reduceCommodityCount(StockReduceCountDTO stockReduceCountDTO) {
stockMapper.updateStockByCommodityCode(
stockReduceCountDTO.getCommodityCode(), // 第一个参数是商品编号
stockReduceCountDTO.getReduceCount()); // 第二个参数是减少的库存数
log.info("库存减少完成!");
}
}
当前项目的Spring启动类要添加一个注解,表示当前项目有Dubbo服务提供
@SpringBootApplication
// 如果当前项目是Dubbo服务的生产者,必须添加这个注解
@EnableDubbo
public class CsmallStockWebapiApplication {
public static void main(String[] args) {
SpringApplication.run(CsmallStockWebapiApplication.class, args);
}
}
我们可以测试启动stockWebapi项目
修改cart模块
操作步骤和stock完全一致,参考stock模块即可
负载均衡
什么是负载均衡
在实际开发中,一个服务基本都是集群模式的,也就是多个功能相同的项目在运行,这样才能承受更高的并发
这时一个请求到这个服务,就需要确定访问哪一个服务器
Dubbo框架内部支持负载均衡算法,能够尽可能的让请求在相对空闲的服务器上运行
我们要实现设置好负载均衡的策略算法,并设置好每个服务器的运行权重
才能更好的实现负载均衡的效果
Loadbalance:就是负载均衡的意思
Dubbo内置负载均衡策略算法
Dubbo内置4种负载均衡算法
- random loadbalance:随机分配策略(默认)
- round Robin Loadbalance:权重平均分配
- leastactive Loadbalance:活跃度自动感知分配
- consistanthash Loadbalance:一致性hash算法分配
修改order模块支持Dubbo
因为order模块在Dubbo的调用关系中
既是生产者又是消费者
它消费cart和stock的服务
同时又为business模块提供服务
重构的过程和stock\cart有很多相似,但是也要注意不同
创建csmall-order-service项目
这个项目创建的过程和stock\cart模块service项目的步骤和注意事项完全一致
创建csmall-order-webapi项目
创建项目后父子相认正常
当时子项目的pom文件依赖需要添加下面内容
<!-- Dubbo依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<!-- service接口项目依赖 -->
<dependency>
<groupId>cn.tedu</groupId>
<artifactId>csmall-order-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- order模块同时作为服务的消费者要将需要调用的服务所在的业务逻辑层接口依赖添加上 -->
<!-- 我们需要stock模块的减库存方法和cart模块删除购物车商品的方法 -->
<dependency>
<groupId>cn.tedu</groupId>
<artifactId>csmall-cart-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.tedu</groupId>
<artifactId>csmall-stock-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
yml文件的配置一致
代码也都正常从csmall-order复制到csmall-order-webapi中
// 因为business模块要调用这个业务逻辑层中的方法
// 所以这个类中的方法也要注册到Nacos
@DubboService
@Service
@Slf4j
public class OrderServiceImpl implements IOrderService {
@Autowired
private OrderMapper orderMapper;
// 当前order模块消费stock的业务逻辑层方法,以减少库存
// 因为stock模块的减库存方法在Nacos中注册,所以可以使用Dubbo调用
// 要想调用就必须使用@DubboReference,才能获得业务逻辑层实现类对象
@DubboReference
private IStockService dubboStockService;
// order还需要cart模块的删除购物车商品的方法
@DubboReference
private ICartService dubboCartService;
@Override
public void orderAdd(OrderAddDTO orderAddDTO) {
// 1.减少订单商品的库存(要调用stock模块的方法)
StockReduceCountDTO stockReduceCountDTO=new StockReduceCountDTO();
// 为减少库存的商品编号赋值
stockReduceCountDTO.setCommodityCode(orderAddDTO.getCommodityCode());
// 为减少库存的数量赋值
stockReduceCountDTO.setReduceCount(orderAddDTO.getCount());
dubboStockService.reduceCommodityCount(stockReduceCountDTO);
// 2.删除订单中购物车商品的信息(要调用cart模块的方法)
dubboCartService.deleteUserCart(orderAddDTO.getUserId(),
orderAddDTO.getCommodityCode());
// 3.新增订单
// 实例化订单对象
Order order=new Order();
// 赋值同名属性
BeanUtils.copyProperties(orderAddDTO,order);
// 调用持久层方法
orderMapper.insertOrder(order);
log.info("新增订单完成:{}",order);
}
}
因为order模块也是生产者@EnableDubbo注解仍然要写
@SpringBootApplication
@EnableDubbo
public class CsmallOrderWebapiApplication {
public static void main(String[] args) {
SpringApplication.run(CsmallOrderWebapiApplication.class, args);
}
}
我们可以测试这个Dubbo的功能
先启动nacos
然后再启动cart和stock
最后启动order
访问
http://localhost:20002/doc.html运行测试
注意运行前,数据库的数据状态和运行后的比较一下
续 负载均衡
dubbo内置负载均衡策略算法
Dubbo内置4种负载均衡算法
- random loadbalance:随机分配策略(默认)
- round Robin Loadbalance:权重平均分配
- leastactive Loadbalance:活跃度自动感知分配
- consistanthash Loadbalance:一致性hash算法分配
实际运行过程中,每个服务器性能不同
在负载均衡时,都会有性能权重,这些策略算法都考虑权重问题
随机分配策略(默认)
随机生成随机数
在哪个范围内让哪个服务器运行
优点:
算法简单,效率高,长时间运行下,任务分配比例准确
缺点:
偶然性高,如果连续的几个随机请求发送到性能弱的服务器,会导致异常甚至宕机
权重平均分配
如果几个服务器权重一致,那么就是依次运行
3个服务器 1>1 2>2 3>3 4>1
但是服务器的性能权重一致的可能性很小
所以我们需要权重评价分配
Dubbo2.6.4之前平均分配权重算法是有问题的
如果3个服务器的权重比5:3:1
1>1 2>1 3>1 4>1 5>1 6>2 7>2 8>2 9>3
10>1
Dubbo2.7之后更新了这个算法使用"平滑加权算法"优化权重平均分配策略
活跃度自动感知
记录每个服务器处理一次请求的时间
安装时间比例来分配任务数,运行一次需要时间多的分配的请求数较少
一致性Hash算法
根据请求的参数进行hash运算
以后每次相同参数的请求都会访问固定服务器
因为根据参数选择服务器,不能平均分配到每台服务器上
使用的也不多
修改business模块
business模块是我们设计的整体业务的起点
它是单纯的消费者
我们不需要像生产者一样去创建两个子项目
直接在原有项目上修改即可
直接到pom文件中添加dubbo和相关接口的依赖
<!-- dubbo依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<!-- business模块消费order模块的生成订单的方法,所以添加order接口的依赖 -->
<dependency>
<groupId>cn.tedu</groupId>
<artifactId>csmall-order-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
application-dev.yml
spring:
application:
# 当前Springboot项目的名称,用作注册中心服务的名称
name: nacos-business
cloud:
nacos:
discovery:
# 定义nacos运行的路径
server-addr: localhost:8848
# ephemeral设置当前项目启动时注册到nacos的类型 true(默认):临时实例 false:永久实例
ephemeral: true
dubbo:
protocol:
port: -1 # 设置Dubbo服务调用的端口 设置-1能够实现动态自动设置合适端口,生成规则是从20880开始递增
name: dubbo # 设置端口名称,一般固定就叫dubbo
registry:
address: nacos://localhost:8848 # 配置当前Dubbo注册中心的类型和地址
consumer:
check: false # 设置为false表示当前项目启动时,不检查要调用的远程服务是否可用,避免报错
我们要在当前busindess模块的业务逻辑层实现类中
实现Dubbo调用order模块的生成订单方法
@Service
@Slf4j
public class BusinessServiceImpl implements IBusinessService {
// Dubbo在获取order模块的业务逻辑层实现类
@DubboReference
private IOrderService dubboOrderService;
@Override
public void buy() {
// 暂时模拟一个下单业务
// 创建OrderAddDTO类,赋值并输出信息
OrderAddDTO orderAddDTO=new OrderAddDTO();
orderAddDTO.setCommodityCode("PC100");
orderAddDTO.setUserId("UU100");
orderAddDTO.setMoney(500);
orderAddDTO.setCount(8);
// 因为没有持久层,只能输出一下,表示运行正常
log.info("新增订单信息为:{}",orderAddDTO);
// dubbo调用生成订单方法
dubboOrderService.orderAdd(orderAddDTO);
}
}
Springboot启动类不必要写@EnableDubbo因为business是单纯的消费者
@SpringBootApplication
//@EnableDubbo
public class CsmallBusinessApplication {
public static void main(String[] args) {
SpringApplication.run(CsmallBusinessApplication.class, args);
}
}
启动business项目(前提是cart\stock\order正在运行)
http://localhost:20000/doc.html运行测试
Dubbo生产者消费者配置小结
Dubbo生产者消费者相同的配置
pom文件添加dubbo依赖,yml文件配置dubbo信息
生产者
- 要有service接口项目
- 提供服务的业务逻辑层实现类要添加@DubboService注解
- SpringBoot启动类要添加@EnableDubbo注解
消费者
- pom文件添加消费模块的service依赖
- 业务逻辑层远程调用前天模块时使用@DubboReference注解获取业务逻辑层实现类对象
5-3 Dubbo | 负载均衡的更多相关文章
- Dubbo负载均衡与集群容错机制
1 Dubbo简介 Dubbo是一款高性能.轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现. 作为一个轻量级RPC框架,D ...
- dubbo负载均衡策略和集群容错策略都有哪些
dubbo负载均衡策略 random loadbalance 默认情况下,dubbo是random load balance随机调用实现负载均衡,可以对provider不同实例设置不同的权重,会按照权 ...
- dubbo负载均衡策略和集群容错策略
dubbo负载均衡策略 random loadbalance 默认情况下,dubbo是random load balance随机调用实现负载均衡,可以对provider不同实例设置不同的权重,会按照权 ...
- 一文讲透Dubbo负载均衡之最小活跃数算法
本文是对于Dubbo负载均衡策略之一的最小活跃数算法的详细分析.文中所示源码,没有特别标注的地方均为2.6.0版本. 为什么没有用截止目前的最新的版本号2.7.4.1呢?因为2.6.0这个版本里面有两 ...
- 3.dubbo 负载均衡策略和集群容错策略都有哪些?动态代理策略呢?
作者:中华石杉 面试题 dubbo 负载均衡策略和集群容错策略都有哪些?动态代理策略呢? 面试官心理分析 继续深问吧,这些都是用 dubbo 必须知道的一些东西,你得知道基本原理,知道序列化是什么协议 ...
- 分布式的几件小事(四)dubbo负载均衡策略和集群容错策略
1.dubbo负载均衡策略 ①random loadbalance 策略 默认情况下,dubbo是random loadbalance 随机调用实现负载均衡,可以对provider不同实例设置不同的权 ...
- Dubbo入门到精通学习笔记(十一):Dubbo服务启动依赖检查、Dubbo负载均衡策略、Dubbo线程模型(结合Linux线程数限制配置的实战分享)
文章目录 Dubbo服务启动依赖检查 Dubbo负载均衡策略 Dubbo线程模型(结合Linux线程数限制配置的实战分享) 实战经验分享( ** 属用性能调优**): Dubbo服务启动依赖检查 Du ...
- 面试系列24 dubbo负载均衡策略和集群容错策略
(1)dubbo负载均衡策略 1)random loadbalance 默认情况下,dubbo是random load balance随机调用实现负载均衡,可以对provider不同实例设置不同的权重 ...
- 面试系列16 dubbo负载均衡策略和集群容错策略都有哪些?动态代理策略呢
(1)dubbo负载均衡策略 1)random loadbalance 默认情况下,dubbo是random load balance随机调用实现负载均衡,可以对provider不同实例设置不同的权重 ...
- Dubbo 负载均衡的实现
前言 负载均衡是指在集群中,将多个数据请求分散在不同单元上进行执行,主要为了提高系统容错能力和加强系统对数据的处理能力. 在 Dubbo 中,一次服务的调用就是对所有实体域 Invoker 的一次筛选 ...
随机推荐
- NLP教程(4) - 句法分析与依存解析
作者:韩信子@ShowMeAI 教程地址:http://www.showmeai.tech/tutorials/36 本文地址:http://www.showmeai.tech/article-det ...
- 2.Docker安装
CentOS Docker 安装 前提条件 目前,CentOS 仅发行版本中的内核支持 Docker.Docker 运行在CentOS 7 (64-bit)上, 要求系统为64位.Linux系统内核版 ...
- 48. Rotate Image - LeetCode
Question 48. Rotate Image Solution 把这个二维数组(矩阵)看成一个一个环,循环每个环,循环每条边,每个边上的点进行旋转 public void rotate(int[ ...
- 解决windows server 2008r2服务器自动关机
问题 具体表现就是系统自动关机,网上说是开机后2小时就会自动关机 系统版本: 解决 PsTools下载 解压:PSTools.zipg,如解压到C:\PSTools目录下 执行如下命令,打开注册表 W ...
- 安装Python到Linux(Pyenv)
pyenv是一个多Python版本的托管工具,我们可以使用它安装Python和随意的切换系统环境中默认使用的Python版本. 运行环境 系统版本:CentOS Linux release 7.6.1 ...
- 04C++核心编程(二-泛型编程)
Day08 笔记 1 函数模板 1.1 泛型编程 – 模板技术 特点:类型参数化 1.2 template< typename T > 告诉编译器后面紧跟着的函数或者类中出现T,不要报错, ...
- 聊聊 C# 中的多态底层 (虚方法调用) 是怎么玩的
最近在看 C++ 的虚方法调用实现原理,大概就是说在 class 的首位置存放着一个指向 vtable array 指针数组 的指针,而 vtable array 中的每一个指针元素指向的就是各自的 ...
- MTK 平台sensor arch 介绍-hal
MTK 平台sensor arch 介绍-hal 一:整体框架 二:具体流程简介 AP-HAL: (1)init & control flow 我们以前文的originchannel 的 ac ...
- React设置proxy后依旧报CROS错误
1.判断表单数据是否为后端接收的类型 POST GET2.axios自动转换问题 手动添加标头这份表单数据包括了files (二进制数据)而标头显示是JSON格式 不符 所以报CROS 更多文章请移步 ...
- React简单教程-3.1-样式之使用 tailwindcss
前言 本文是作为一个额外内容,主要介绍 tailwindcss 的用法 tailwindcss 是一个功能类优先的 CSS 框架,我在以前的文章里有描述为什么使用功能类优先:为什么我在 css 里使用 ...