springcloud微服务架构搭建过程
项目地址:源代码
仅作为学习用例使用,是我开发过程中的总结、实际的一部分使用方式
开发环境:
jdk11
springboot2.7.6
springcloud2021.0.5
alibabacloud 2021.0.4.0
redis6.0
mysql8.0
一、项目搭建

wdz-api:存放远程服务调用相关接口
wdz-auth:认证业务
wdz-gateway:网关
wdz-modules:业务模块微服务
wdz-common:存放公用中间件、数据库等服务
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><packaging>pom</packaging><modules><module>wdz-common</module><module>wdz-gateway</module><module>wdz-api</module><module>wdz-auth</module><module>wdz-modules</module></modules><groupId>com.wdz</groupId><artifactId>wdz-ruzhou</artifactId><version>1.0.0</version><name>wdz-ruzhou</name><description>微服务架构</description><properties><java.version>11</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.version>2.7.6</spring-boot.version><spring-cloud.version>2021.0.5</spring-cloud.version><spring-cloud.alibaba>2021.0.4.0</spring-cloud.alibaba><fastjson2.version>2.0.14</fastjson2.version><lombok.version>1.18.24</lombok.version></properties><dependencyManagement><dependencies><!--springcloud 微服务依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency><!--springboot 依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency><!--alibaba 微服务依赖--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>${spring-cloud.alibaba}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.version}</version></dependency><dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId><version>${fastjson2.version}</version></dependency></dependencies></dependencyManagement><!--配置打包环境数据--><profiles><profile><id>dev</id><properties><profiles.active>dev</profiles.active><nacos.username>nacos</nacos.username><nacos.password>nacos</nacos.password><nacos.server>127.0.0.1:8848</nacos.server><nacos.discovery.namespace>5efed786-91f6-44c4-8e14-049df72b2a48</nacos.discovery.namespace><nacos.config.namespace>5efed786-91f6-44c4-8e14-049df72b2a48</nacos.config.namespace></properties><activation><activeByDefault>true</activeByDefault></activation></profile><profile><id>test</id><properties><profiles.active>test</profiles.active><nacos.username>nacos</nacos.username><nacos.password>nacos</nacos.password><nacos.server>127.0.0.1:8848</nacos.server><nacos.discovery.namespace>f02ccd30-e3d5-4235-9282-d0a613bd322b</nacos.discovery.namespace><nacos.config.namespace>f02ccd30-e3d5-4235-9282-d0a613bd322b</nacos.config.namespace></properties></profile><profile><id>prod</id><properties><profiles.active>prod</profiles.active><nacos.username>nacos</nacos.username><nacos.password>nacos</nacos.password><nacos.server>127.0.0.1:8848</nacos.server><nacos.discovery.namespace>747829ca-6d8a-4417-a46a-bd31a6f5e442</nacos.discovery.namespace><nacos.config.namespace>747829ca-6d8a-4417-a46a-bd31a6f5e442</nacos.config.namespace></properties></profile></profiles><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>3.0.0</version></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>${java.version}</source><target>${java.version}</target><encoding>${project.build.sourceEncoding}</encoding></configuration></plugin></plugins><!--用于yml配置中变量替换如: @nacos.name@--><resources><resource><directory>src/main/resources</directory><!-- 引入所有 匹配文件进行过滤 --><includes><include>application*</include><include>bootstrap*</include><include>logback*</include></includes><!-- 启用过滤 即该资源中的变量将会被过滤器中的值替换 --><filtering>true</filtering></resource></resources></build>
</project>
nacos(2.2.0.1)
我为什么选择nacos作为注册中心?
1、独立的可视化管理后台
2、持久化,配置数据直接存储在数据库中
3、动态配置,修改配置可实时生效,不用重启
4、活跃度高,资料文件丰富
5、功能全面
6、是经过阿里巴巴考验的
戳==>官网
安装nacos
点击选择版本下载
windows建议下载zip
linux 建议下载tar.gz
下载完成解压即可
配置数据库
打开conf下的application.properties文件:
修改数据库配置,将注释打开,并配置数据源
创建数据库目前只支持mysql,版本要求:5.6.5+
需要IPV6支持使用:derby-schema.sql 否则使用:mysql-schema.sql 配置完成后
单机启动nacos:
Linux/Unix/Mac使用命令:sh startup.sh -m standalone
windows使用命令:./startup.cmd -m standalone
standalone:表示单机模式运行,非集群模式
官方文档
启动过程中如果出现jwt认证问题启动失败,请参考:戳详情
错误示例

修改文件:
nacos.core.auth.plugin.nacos.token.secret.key
使用base64 处理数据长度大于等于32即可


访问:http://localhost:8848/nacos,默认用户名密码:nacos
集群启动 官方文档
如果是在一台电脑上/服务器上模拟集群:
将nacos解压之后的文件nacos复制多份,
并修改对应conf文件夹下的application.properties文件端口配置
再将conf下的cluster.conf.example 复制一份并修改后缀为conf
将其他nacos地址配置在cluster.conf中
依次启动服务:
windows命令:./startup.cmd
linux命令: sh ./startup.sh
访问对应nacos
nacos 服务配置config与发现 discovery
创建测试注册服务网关服务,nacos作为注册中心有多种方式,本文用javaSDK的方式
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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>wdz-ruzhou</artifactId><groupId>com.wdz</groupId><version>1.0.0</version></parent><modelVersion>4.0.0</modelVersion><groupId>com.wdz</groupId><artifactId>wdz-gateway</artifactId><packaging>jar</packaging><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>
yml配置:
server:port: 8080servlet:context-path: /spring:application:name: wdz-gatewayprofiles:active: @profiles.active@
---
# 使用导入的方式读取所有需要的nacos中的配置文件
spring:config:import:- optional:nacos:application-common.yml- optional:nacos:${spring.application.name}.ymlcloud:nacos:username: @nacos.username@password: @nacos.password@server-addr: @nacos.server@# 服务发现discovery:namespace: @nacos.discovery.namespace@# 配置config:namespace: @nacos.config.namespace@
集群nacos负载配置:
通过nginx配置服务访问的nacos
upstream nacos-cluster{server 127.0.0.1:8247;server 127.0.0.1:8549;server 127.0.0.1:8848;
}
server{listen 801;server_name localhost;location /nacos{proxy_pass http://nacos-cluster;}
}
结果


负载均衡Ribbon
| 内置负载均衡规则类 | 规则描述 |
|---|---|
| RoundRobinRule | 简单轮询服务列表选择服务器,它是Ribbon默认的负载均衡规则 |
| AvailabilityFilteringRule | 忽略规则:1、链接3次失败,会标记为短路状态,将持续30秒,如果还是失败则持续短路,时间增长,2、并发数过高的服务链接,并发数达到上限则会被忽略 |
| WeightedResponseTimeRule | 权重策略,每个服务器配置一个权重值,权重值越小,选择这个服务器的比重就会越小 |
| ZoneAvooidanceRule | 以区域可用的服务器为基础进行服务器的选择,使用Zone对服务器进行分类,Zone相当于一个机房,一个区域,然后再对Zone内的多个服务做轮询 |
| BestAvailableRule | 忽略哪些短路服务器,并选择并发数较低的服务器 |
| RandomRule | 随机选择一个可用服务器 |
| RetryRule | 重试机制的选择逻辑 |
自定义策略方式:
代码方式:作用的是所有服务
@Bean
public IRule diyRule(){return new RandomRule();
}
yml方式:作用的是所配置的服务
servicename: # 服务名称如:userserviceribbon:NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
ribbon默认是懒加载,第一次访问的时候响应时间会比较长,初次加载之后响应就会变短。
开启ribbon饥饿加载有效提高第一次访问响应时间
ribbon:eager-load:enabled: true # 开启饥饿加载clients: # 指定加载的服务名称- userservice- orderservice- systemservice- XXXservice
nacos服务分级存储模型
一级是服务:如:userservice、orderservice
二级是集群:配置了同一个discovery.cluster-name:
三级是实例:如杭州机房的某台部署了要访问的服务器
设置实例的集群属性:名称一样的在同一个集群内
spring.cloud.nacos.discovery.cluster-name:NacosRule负载均衡策略:
1、优先选择同集群的服务
2、本地集群找不到提供者,才去其他集群找,并且会报警告
3、确定了可用实例列表后,再采用随机负载均衡挑选实例
NacosRule配置:
servicename: # 服务名称如:userserviceribbon:NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule
环境隔离:namespace
spring:cloud:nacos:discovery:namespace: @nacos.discovery.namespace@
# 不同名称空间之间的服务不能互通,如user使用的prod order使用的dev,这两个服务不能互通
nacos特点
1、支持服务端主动监测提供者状态,临时实例采用心跳模式,非临时实例采用主动监测模式
2、林实施例心跳不正常会被剔除nacos的服务列表,非临时实例不会被剔除
3、服务列表变更消息推送模式,服务列表更新及时
4、nacos集群默认采用AP方式,集群中存在非临时实例时,采用CP模式
CAP:C(一致性),A(可用性),P(分区容错)原文
Feign 源码
feign是声明式的http客户端
使用方式
pom引入依赖
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
java代码
@FeignClient("applicationName")
public interface ApplicationName{@GetMapping("/get")Object queryById(Long id);
}
自定义feign配置
类型 作用 说明 feign.Logger.Level 修改日志级别 包含四种不同的级别:none、basic、headers、full feign.codec.Decoder 响应结果解析器 http远程调用的结果做解析,例如解析json字符串为java对象 feign.codec.Encoder 请求参数编码 将请求参数编码,便于通过http请求发送 feign.Contract 支持注解格式 默认是SpringMvc的注解 feign.Retryer 失败重试机制 请求失败的重试机制,默认没有,会使用Ribbon的重试 none: 不记录日志
basic:只记录请求方法和URL以及响应状态代码和执行时间
headers:记录基本信息以及请求和响应标头
full:记录请求和响应的头部、主体和元数据
yml日志配置
feign:client:config:default: # DETAULT 是全局配置,如果换成application.name 则是指定服务有效loggerLevel: FULL
feign:client:config:userservice: # 针对userservice有效loggerLevel: FULL
代码方式:
public class FeignClientConfig{@Beanpublic Logger.Level feignLogLevel(){return Logger.Level.BASIC;}
}
然后将该配置添加到:
全局配置方式启动类上
EnableFeignClients(defaultConfiguration=FeignClentConfig.class)
局部配置方式
@FeignClient(value="applicationname",configuration=FeignClientConfig)
feign性能优化
URLConnection:默认实现,不支持连接池
Apache HttpClient:支持链接池
OKHttp:支持连接池
因为http链接时要三次握手,断开时要4次挥手,导致的性能浪费
优化的性能主要包括:
1、使用连接池代替默认的URLConnection
2、日志级别,最好用basic或none,日志也会浪费性能
连接池配置:
引入依赖
<!--优化feignURLConnection-->
<dependency><groupId>io.github.openfeign</groupId><artifactId>feign-httpclient</artifactId>
</dependency>
配置yml
feign:httpclient:enabled: true # 开启feign对httpClient的支持max-connections: 200 # 最大链接数 可根据测试结果最优配置max-connections-per-route: 50 # 每个路径最大链接数 可根据测试结果最优配置
实践:

system项目引用
EnableFeignClients.clients 指定feignClient接口,及默认配置

如果发现RemoteUserService 加载不到提示,spring-cloud-starter-loadbalancer依赖缺失
在api中添加依赖:负载均衡依赖
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
测试接口

目标服务接口

测试结果:

SpringAMQP
springboot封装的消息队列,使用的是rabbitmq
生产端
引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>
配置
spring:rabbitmq:host: 127.0.0.1 # 主机port: 5672 # 端口virtual-host: / # 虚拟主机username: rabbitmq # 用户名password: 123456 # 密码
消费端
引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>
配置
spring:rabbitmq:host: 127.0.0.1 # 主机port: 5672 # 端口virtual-host: / # 虚拟主机username: rabbitmq # 用户名password: 123456 # 密码
监听java代码:
@Component
public class RabbitMqListener {@RabbitListener(queues = "mq-user")public void listenerQueueMsg(String msg){System.out.println(msg);}
}
如果提示异常:队列不存在,且启动失败
添加配置:
@Configuration
public class RabbitMqConfig {@Beanpublic Queue initQueue(){return new Queue("mq-user");}
}
由于rabbitmq的消费预取机制,会导致处理能力弱的消费端处理速度变慢,所以限制预取信息条数
spring:rabbitmq:listener:simple:prefetch: 1 # 每次只能获取一条消息,处理完成之后才能获取下一个
监听端信息:
@Slf4j
@Component
public class RabbitMqListener {@RabbitListener(queues = "mq-user")public void listenerQueueMsg(String msg) {log.info("[listenerQueueMsg]=========:{}",msg);}@RabbitListener(queues = "mq-user")public void listenerQueueMsg2(String msg) {log.info("[listenerQueueMsg2]=========:{}",msg);}
}
消息发布/订阅
发布订阅模式允许将同一消息发送给多个消费者,实现方式是加入exchange(交换机):
fanout:广播
direct:路由
topic:话题
交换机只处理转发,会造成消息丢失
FanoutExchange 方式
发送消息用户服务:
@GetMapping("/send")public LoginUser send(String username) {String queueName = "demo.fanout";String message = username;rabbitTemplate.convertAndSend(queueName,"", message);return new LoginUser(1L, username, "123456");}@GetMapping("/to")public LoginUser to(String username) {String queueName = "demo.fanout";String message = username;rabbitTemplate.convertAndSend(queueName,"", message);return new LoginUser(1L, username, "123456");}
接收消息 system服务:
监听代码@RabbitListener(queues = "demo.fanout2")public void listenerFanoutMsg2(String msg) {log.info("[demo.fanout2]=========:{}", msg);}
@Configuration
public class FanoutExchangeConfig {/*** 一个消息多个消费者监* fanout 广播模式* 定义交换机*/@Beanpublic FanoutExchange fanoutExchange() {return new FanoutExchange("demo.fanout");}@Beanpublic Queue fanoutQueue() {return new Queue("demo.fanout");}/*** 绑定交换机与队列关系** @param fanoutExchange* @param fanoutQueue* @return*/@Beanpublic Binding fanoutBinding(FanoutExchange fanoutExchange,Queue fanoutQueue) {return BindingBuilder.bind(fanoutQueue).to(fanoutExchange);}
}
接收消息 order服务:
监听
@Slf4j
@Component
public class RabbitMqListener {@RabbitListener(queues = "demo.fanout")public void listenerFanoutMsg(String msg) {log.info("[demo.fanout]=========:{}", msg);}
}
fanout 配置
@Configuration
public class FanoutExchangeConfig {/*** 一个消息多个消费者监* fanout 广播模式* 定义交换机*/@Beanpublic FanoutExchange fanoutExchange() {return new FanoutExchange("demo.fanout");}@Beanpublic Queue fanoutQueue() {return new Queue("demo.fanout2");}/*** 绑定交换机与队列关系** @param fanoutExchange* @param fanoutQueue* @return*/@Beanpublic Binding fanoutBinding(FanoutExchange fanoutExchange,Queue fanoutQueue) {return BindingBuilder.bind(fanoutQueue).to(fanoutExchange);}
}
均可接收到消息
DirectExchange 方式
direct exchange 会将接收到的消息根据规则路由到指定的queue
每个queue都与exchange设置一个bindingkey
发布者发送消息时指定消息的RoutingKey
exchange将消息路由到BingingKey与消息RoutingKey一致的队列
order/system中的监听
// 注解方式处理监听信息
// bindings 代码实现的Binding
// @QueueBinding 绑定信息
// value = @Queue(name = "direct.queue")绑定消息队列
// exchange = @Exchange(name = "demo.direct",type = ExchangeTypes.DIRECT)
// 绑定交换机,名称是demo.direct 类型是direct
// key 是direct模式的主要配置,可同时监听多个key
@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "direct.queue"),exchange = @Exchange(name = "demo.direct",type = ExchangeTypes.DIRECT),key = {"system","direct"}))public void listenerMessage(String msg) {log.info("[system.direct]=========:{}", msg);}
消息发送者:
/***@param exchange 交换机名称*@param message 消息内容*@param routingKey direct 路由key*@return*/@GetMapping("/direct")public void direct(String exchange,String message,String routingKey) {rabbitTemplate.convertAndSend(exchange,routingKey, message);}
发送信息:
http://localhost/user/direct?exchange=demo.direct&message=发送的消息内容&routingKey=system
Topic 方式
topic方式与direct方式类似,只是key由精准匹配转换为模糊匹配
// 监听@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "topic.queue"),exchange = @Exchange(name = "topic-wdz",type = ExchangeTypes.TOPIC),key = "#.order"))public void listenerTopicMessage(String msg) {log.info("[listenerTopicMessage]=========:{}", msg);}
发送
@GetMapping("/direct")
public void direct(String exchange,String message,String routingKey) {rabbitTemplate.convertAndSend(exchange,routingKey, message);
}
优化
由于springamqp默认使用的是jdk默认的序列化(ObjectOutputStream)方式,性能问题有待提升。
更换为JSON方式序列化。
生产者/消费者引入依赖
<dependency><groupId>com.fasterxml.jackson.dataformat</groupId><artifactId>jackson-dataformats-binary</artifactId><version>2.13.4</version></dependency>
初始化bean即可
@Bean
publicMessageConverter messageConverter(){return new Jackson2JsonMessageConverter();
}
Sentinel
分布式事务seata
事务(transaction):遵守ACID原则
原子性(Atomicity):事务中的所有操作,要么全部成功,要么全部失败
一致性(consistency):要保证数据库内部完整性的约束、声明性约束
隔离性(isolation):对同一自愿操作的事务不能同时发生
持久性(durability):对数据库的一切修改将永久保存,不管是否出现故障
演示案例:
下单流程:
订单服务创建订单–>账户服务扣减余额–>商品服务扣减库存
1、访问订单服务创建订单
2、通过feign调用user扣减余额
3、通过feign调用goods扣减库存

feign接口
@FeignClient(value = "wdz-goods")
public interface RemoteGoodsService {@GetMapping("/goods/subtractStock")void subtractStock(@PathVariable("username") String username);}
@FeignClient(value = "wdz-user")
public interface RemoteUserService {@GetMapping("/user/subtractBalance")void subtractBalance();
}
控制器代码
订单服务控制器
@RestController
@RequestMapping("order")
public class OrderController {@Autowiredprivate RemoteGoodsService remoteGoodsService;@Autowiredprivate RemoteUserService remoteUserService;@GetMapping("create")public void create(){System.out.println("订单服务:创建了订单");remoteGoodsService.subtractStock();remoteUserService.subtractBalance();}
}
用户服务控制器代码
@RestController
@RequestMapping("user")
public class UserController {@GetMapping("subtractBalance")public void subtractBalance(){System.out.println("用戶服务:减余额");}
}
商品控制器代码
@RestController
@RequestMapping("goods")
public class GoodsController {@GetMapping("subtractStock")public void subtractStock(){System.out.println("商品服务:减少了库存");}
}
依次启动nacos-->gateway-->user-->goods-->order
访问:http://localhost:8080/order/order/create
订单服务:创建了订单
用戶服务:减余额
商品服务:减少了库存
相关文章:
springcloud微服务架构搭建过程
项目地址:源代码 仅作为学习用例使用,是我开发过程中的总结、实际的一部分使用方式 开发环境: jdk11 springboot2.7.6 springcloud2021.0.5 alibabacloud 2021.0.4.0 redis6.0 mysql8.0 一、项目搭建 wdz-api:存放远程服务调用相关…...
LeetCode:215. 数组中的第K个最大元素
🍎道阻且长,行则将至。🍓 🌻算法,不如说它是一种思考方式🍀算法专栏: 👉🏻123 一、🌱215. 数组中的第K个最大元素 题目描述:给定整数数组nums和整…...
vue面试题(day06)
文章目录前言请谈谈WXML与标准的html的异同?请谈谈WXSS和CSS的异同?请谈谈微信小程序主要目录和文件的作用?请谈谈小程序的双向绑定和vue的异同?简单描述下微信小程序的相关文件类型?微信小程序有哪些传值(传递数据)方…...
22 k8s常用命令
一、k8s网络 service网络 pod网络 节点网络 》 svc、pod网络都是虚拟机网络,真实网络是节点网络 二、内核升级 因为coentos系统3.10存在一些bug,docker、kubernetes不稳定,建议升级到4.4版本以上 三、集群资源分类 名称空间级别࿱…...
基于ESP32做低功耗墨水屏时钟
基于ESP32做低功耗墨水屏时钟电子墨水屏概述ESP32实验低功耗电子时钟功能描述接线开发实验结果电子墨水屏 概述 电子墨水是一种革新信息显示的新方法和技术。和传统纸差异是电子墨水在通电时改变颜色,并且可以显示变化的图象,像计算器或手机那样的显示。…...
常见路由器开源系统(固件)简介
前段时间在折腾如何通过 SD-WAN 组网方式打通办公室和家里的异地局域网。需要用到路由器的静态路由表功能,但是遍历整个家用路由器市场几乎没有支持这个功能的路由器(只有华硕 RT-AX57 有这个功能,但是成本超出了我的预算)。所有就…...
HCIE-Cloud Computing LAB备考第二步:逐题攻破--第二题:FusionAccess-搭建FA实验环境之安装基础组件和初始化ITA组件
HCIE-Cloud Computing LAB备考第二步:逐题攻破–第二题:FusionAccess-思维导图+题目=建立逻辑 专业术语 名词描述备注FusionAccess华为推出的桌面云产品,是一种虚拟桌面应用,它主要通过在硬件上部署FusionAccess配套的软件基础上,虚拟化出相互隔离的桌面,用户通过瘦客户端…...
Android APP检查设备是否为平板
正文 Android APP判断设备是否为平板的三种方法: 通过屏幕尺寸判断。一般来说,平板电脑的屏幕尺寸比手机大很多,可以根据屏幕的长宽比和尺寸等信息来区分设备类型。通过屏幕像素密度判断。一般来说,平板电脑的屏幕像素密度比手机…...
MP:使用步骤、分页、queryWrapper
Mybatis-Plus 官网: MyBatis-Plus (baomidou.com) 1. 意义 mybatis-plus是一个插件,它不能单独使用,必须配合mybatis使用,作用是简化mybatis操作,通过使用MP提供的方法,自动生成SQL语句进行CRUD 2. 使用步骤…...
C++ string类
C string类讲解 1、为什么学习string类? C语言中的字符串 在C语言中,字符串是以’\0’结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符…...
虚拟机断电centos无法启动
虚拟机断电后centos7无法正常启动 XFS(sda3) 首先需要查找日志 在界面中查找日志是 journalctl 1.由于我的电脑死机,虚拟机没有正常关闭导致重启后 node1节点:可以登陆但是出现XFS(sda3):Corruption of in-memoru data detectednode2节点&…...
python学习之基于Python的人脸识别技术学习
摘要: 面部识别技术的应用越来越广泛,它广泛应用于安全系统、人机交互、社交媒体、医疗保健等领域。本文介绍了基于Python的人脸识别技术,包括人脸检测、人脸特征提取和人脸识别三个部分。我们使用OpenCV和Dlib库来实现这些功能,…...
[Qt][Android] Qt for Android 环境搭建
建议使用 Linux 环境开发 Qt for Android,Windows 环境不好弄,问题多。 直接按照官方文档给的流程进行一步步做就行了: Getting Started with Qt for Android | Qt 6.4https://doc.qt.io/qt-6/android-getting-started.html建议使用 ubuntu…...
maven setting 配置
<?xml version"1.0" encoding"UTF-8"?><settings xmlns"http://maven.apache.org/SETTINGS/1.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/SETTINGS/1.0.0…...
【0基础学爬虫】爬虫基础之网络请求库的使用
大数据时代,各行各业对数据采集的需求日益增多,网络爬虫的运用也更为广泛,越来越多的人开始学习网络爬虫这项技术,K哥爬虫此前已经推出不少爬虫进阶、逆向相关文章,为实现从易到难全方位覆盖,特设【0基础学…...
超级实用,解密云原生监控技术,使用prometheus轻松搞定redis监控
前言 大家好,我是沐风晓月,本文收录于《 prometheus监控系列》 ,截止目前prometheus专栏已经更新到第8篇文章。 本文中的是prometheus已经安装好,如果你还未安装,可以参考 prometheus安装及使用入门 若你想监控其他…...
音视频开发—MediaCodec 解码H264/H265码流视频
使用MediaCodec目的 MediaCodec是Android底层多媒体框架的一部分,通常与MediaExtractor、MediaMuxer、AudioTrack结合使用,可以编码H264、H265、AAC、3gp等常见的音视频格式 MediaCodec工作原理是处理输入数据以产生输出数据 MediaCodec工作流程 Med…...
CVPR 2023|淘宝视频质量评价算法被顶会收录
近日,阿里巴巴大淘宝技术题为《MD-VQA: Multi-Dimensional Quality Assessment for UGC Live Videos》—— 适用于无参考视频质量评价的最新研究成果被计算机视觉领域顶级会议IEEE/CVF Computer Vision and Pattern Recognition Conference 2023(CVPR 20…...
【C++学习】继承
🐱作者:一只大喵咪1201 🐱专栏:《C学习》 🔥格言:你只管努力,剩下的交给时间! C是面向对象的编程语言,它有很多的特性,但是最重要的就是封装,继承…...
【03173】2020年8月高等教育自学考试-软件开发工具
一、单项选择题:1. 区别于一般软件,对软件开发工具而言,下列各项最重要的性能是 A. 效率 B. 响应速度C. 资源消耗 D. 使用方便2. 在软件开发过程的信息需求中,属于跨开发周期的信息是A. 有关系统环境的需求信息 B. 有关软件设计的…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...
逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...
Ubuntu Cursor升级成v1.0
0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开,快捷键也不好用,当看到 Cursor 升级后,还是蛮高兴的 1. 下载 Cursor 下载地址:https://www.cursor.com/cn/downloads 点击下载 Linux (x64) ,…...
嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)
目录 一、网络编程--OSI模型 二、网络编程--TCP/IP模型 三、网络接口 四、UDP网络相关编程及主要函数 编辑编辑 UDP的特征 socke函数 bind函数 recvfrom函数(接收函数) sendto函数(发送函数) 五、网络编程之 UDP 用…...









