当前位置: 首页 > news >正文

微服务初步学习

系统架构演变过程

一、单体架构

        前后端都在一个项目中,包括我们现在的前后端分离开发,都可以看作是一个单体项目。

二、集群架构

        把一个服务部署多次,可以解决服务不够的问题,但是有些不必要的功能也跟着部署多次。

三、垂直架构

        把不同的模块进行拆分,可以单独的部署访问量大的模块,模块之间、服务之间没有统一的管理,各自都是独立的。

四、微服务架构

        是一套完整的服务管理架构。

微服务的优势

1、独立开发:把服务进行拆分,不同的服务单独开发。

2、独立部署

3、故障隔离:一个服务可以部署多份,一台服务器瘫痪,不会影响全局。

4、混合技术堆栈

5、粒度缩放:单个组件可以根据需要进行缩放,无需将所有组件放在一起

微服务中需要考虑到的问题?

1、多个小服务,如何对他们进行管理?(服务治理)

2、多个小服务,服务之间如何通讯?(服务调用)

3、多个小服务,客户端如何访问?(服务网关)

4、多个小服务,一旦出现了问题,应该如何自处理?

5、多个小服务,一旦出现了问题,应该如何排查错误?(链路追踪)

微服务中常见的概念

服务治理

服务调用

服务网关

服务容错

链路追踪

MQ消息队列

分布式锁

分布式事务

服务治理

        服务治理是服务注册中心,所有的服务启动后,都在注册中心进行注册,每一个服务都有一个自己的服务名称。

常见的注册中心:

Apache的Zookeeper、Spring Cloud的Eureka、Alibaba的Nacos

搭建Nacos环境

第一步:安装nacos,下载地址:https://github.com/alibaba/nacos/releases,安装nacos下载zip的格式的安装包,然后进行解压缩操作。

第二步:启动nacos

        切换目录 :cd nacos/bin

        命令启动:startup.cmd -m standalone

第三步:访问nacos

打开浏览器输入 http://localhost:8848/nacos,即可访问服务,默认密码是 nacos/nacos

将用户微服务注册到nacos

接下来将其注册到nacos服务

1、在pom.xml中添加nacos依赖

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>

2、在启动类上添加@EnableDiscoveryClient注解

3、在每个application.yml中为每一个微服务定义服务名,并添加nacos地址

spring:application:name: service-user #服务名cloud:nacos:discovery:server-addr: 127.0.0.1:8848 #nacos 地址

 4、启动服务,观察nacos的控制面板上是否有注册上来的用户微服务

同样方法,将其他服务注册到nacos

服务调用

使用nacos客户端根据服务名动态获取服务地址和端口

@AutowiredDiscoveryClient discoveryClient;

 从nacos中获取服务地址

ServiceInstance serviceInstance =discoveryClient.getInstances("service-user").get(0);//getInstances获取对应服务名的服务返回的是List<ServiceInstance>集合,获取第0个服务
String purl = serviceInstance.getHost() + ":" +serviceInstance.getPort();
//使用
Product p = restTemplate.getForObject( "http://" + purl + "/product/get/"
+ pid, Product.class);

 服务调用负载均衡

  什么是负载均衡?

        就是将负载(工作任务,访问请求)进行分摊到多个操作单元(服务器,组件)上进行执行。

自定义实现负载均衡

通过修改端口启动两个商品服务

server:port: 8091
server:port: 8092

 可以将获取服务的方式改为随机获取

//获取服务列表
List<ServiceInstance> instances =discoveryClient.getInstances("service-product");
//随机生成索引
Integer index = new Random().nextInt(instances.size());
//获取服务
ServiceInstance productService = instances.get(index);
//获取服务地址
String purl = productService.getHost() + ":" +productService.getPort();
基于Ribbon实现负载均衡

Ribbon是Spring Cloud的一个组件,它可以让我们使用一个注解就能轻松的搞定负载均衡。

在商品服务的application.yml中

ribbon:ConnectTimeout: 2000 # 请求连接的超时时间ReadTimeout: 5000 # 请求处理的超时时间
service-product: # 调用的提供者的名称ribbon:NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

第一步:在RestTemplate的生产方法上添加一个@LoadBlanced注解

第二步:修改服务调用的方法

restTemplate.getForObject("http://服务名/product/get/"+pid, Product.class);

七种负载均衡策略

1、轮询策略:RoundRobinRule,按照一定的顺序依次调用服务实例。比如一共3个服务,第一次调用服务1,第二次调用服务2,第三次调用服务3,依次类推。

NFLoadBalancerRuleClassName : com.netflix.loadbalancer.RoundRobinRule

2、权重策略:WeightedResponseTimeRule,根据每个服务提供者的响应时间分配一个权重,响应时间越长,权重越小,被选中的可能性也就越低。

实现原理是,刚开始使用轮询策略并开启一个计时器,每一段时间收集一次所有服务提供者的平均响应时间,然后再给每个服务提供者附上一个权重,权重越高被选中的概率越大。

NFLoadBalancerRuleClassName : com.netflix.loadbalancer.WeightedResponseTimeRule

 3、随机策略:RandomRule,从服务提供者的列表中随机安排一个服务实例。

NFLoadBalancerRuleClassName : com.netflix.loadbalancer.RandomRule

 4、最小连接数策略:BestAvailableRule,也叫最小并发数策略,它是遍历服务者提供列表,选取连接数最小的服务实例。如果有相同的最小连接数,那么会调用轮询策略进行选取。

NFLoadBalancerRuleClassName : com.netflix.loadbalancer.BestAvailableRule

 5、可用敏感性策略:AvailabilityFilteringRule,先过滤掉非健康的服务实例,然后再选择连接数较小的服务实例。

NFLoadBalancerRuleClassName: com.netflix.loadbalancer.AvailabilityFilteringRule

 6、区域敏感策略:ZoneAvoidanceRule,根据服务所在区域(Zone)的性能和服务的可用性来选择服务实例,在没有区域的环境下,该策略和轮询策略略类似。

7、重试策略:

Ribbon 的重试机制允许在服务请求失败时,根据预先设定的策略进行重试。重试机制能够显著提高系统的容错能力,尤其在网络波动和服务临时不可用的情况下,可以确保请求能够成功完成。

Ribbon 重试机制主要包括两种重试场景:

同一服务实例的重试:当请求某个服务实例时,如果请求失败,Ribbon 会在同一个服务实例上进行多次重试。
切换服务实例的重试:如果在同一服务实例上重试多次后仍然失败,Ribbon 会尝试切换到其他可用的服务实例进行重试

ribbon:ConnectTimeout: 2000 # 请求连接的超时时间ReadTimeout: 5000 # 请求处理的超时时间
service-product: # 调用的提供者的名称ribbon:MaxAutoRetries: 2  # 在同一个实例上的最大重试次数MaxAutoRetriesNextServer: 1  # 切换到下一个实例的最大重试次数OkToRetryOnAllOperations: true  # 对所有操作(包括非GET)进行重试ReadTimeout: 2000  # 读超时ConnectTimeout: 1000  # 连接超时
基于Fegin实现服务调用

什么Fegin?

        Fegin是Spring Cloud提供的一个声明式的伪Http客户端,它使得调用远程服务就像调用本地服务一样简单,只需要创建一个接口并添加一个注解即可。

        Nacos很好的兼容了Fegin,Fegin默认集成了Ribbon,所以在Nacos下使用Fegin默认实现了负载均衡的效果。

Fegin的使用

1、在使用Fegin的服务中导入Fegin依赖

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2、在启动类上添加Fegin的注解

3、创建对应服务的接口,并使用Fegin实现微服务调用

4、修改controller代码,并启动验证

服务容错

高并发情况下,如果访问量过大,不加以控制,大量的请求堆积,会击跨整个服务。

需要在某些场景下,为了保证服务不宕机,使用jmeter测试工具,模拟多线程,向后端发起请求。

要对请求进行限制   限流

Sentinel

Sentinel的主要功能就是容错,主要体现在三个方面:

流量控制:限制每秒查询的访问量

熔断降级:当检测到调用链路中某个资源出现不稳定的表现,例如:请求响应时间长或异常比例升高的时候,则对这个资源的调用进行限制,让请求快速失败,避免影响到其他的资源而导致级联故障。

Sentinel对这个问题采用两种手段:

1、通过并发线程数进行限制

        Sentinel 通过限制资源并发线程的数量,来减少不稳定资源对其它资源的 影响。当某个资源出现不稳定的情况下,例如响应时间变长,对资源的直接影响 就是会造成线程数的逐步堆积。当线程数在特定资源上堆积到一定的数量之后, 对该资源的新请求就会被拒绝。堆积的 线程完成任务后才开始继续接收请求。

2、响应时间对资源进行降级

        除了对并发线程数进行控制以外,Sentinel 还可以通过响应时间来快速降 级不稳定的资源。当依赖的资源出现响应时间过长后,所有对该资源的访问都会 被直接拒绝,直到过了指定的时间窗口之后才重新恢复。

系统负载保护:

        Sentinel 同时提供系统维度的自适应保护能力。当系统负载较高的时候, 如果还持续让请求进入可能会导致系统崩溃,无法响应。在集群环境下,会把本 应这台机器承载的流量转发到其它的机器上去。如果这个时候其它的机器也处在 一个边缘状态的时候,Sentinel 提供了对应的保护机制,让系统的入口流量和 系统的负载达到一个平衡,保证系统在能力范围之内处理最多的请求。
总之一句话: 我们需要做的事情,就是在 Sentinel 的资源上配置各种各样的规 则,来实现各种容错的功能。
实现一个接口的限流
为某个接口添加访问控制
访问数量超时限流

 服务网关

在微服务架构中有很多服务,那么客户端要记录很多的服务地址,在每一个服务中都要进行权限认证、授权等操作。
解决方案:
在微服务架构中,我们提供一个 统一访问入口---网关

在网关中做俩件事情:
1、全局过滤器
2、在网关中进行限流
后面访问的地址:网关地址+服务名+接口地址

消息队列MQ

什么是MQ?

        Message Queue:消息队列,是一个组件,是一种提供消息队列服务的中间件,也称消息中间件,是一套提供了消息生产、存储、消费全过程API的软件系统(消息即数据),简单来说就是一个先进先出的数据结构。

常见的MQ应用场景:

异步解耦:

        常见的一个场景是用户注册后,需要发送邮件和短信通知,已告知用户注册成功。传统的做法如下:

        此架构下注册、邮件、短信三个任务全部完成后,才会注册结构到客户端,用户才可以使用账号登录。但是对与用户来说,注册功能实际只需要注册系统存储用户的信息后,用户就可以登录,而后续的注册短信和邮件不是及时需要关注的,所以实际当数据写入注册系统后,注册系统就可以把其他的操作放入对应的消息队列MQ中然后返回用户结果,有消息队列MQ异步进行其他操作。

        异步解耦是消息队列MQ的主要特点,主要目的是减少请求响应时间和解耦。主要的使用场景就是将比叫消耗时间且不需要及时同步返回结果的操作放入消息队列。同时,由于使用了消息队列MQ,只要保证消息格式不变,消息的发送方和接收方并不需要彼此联系,也不需要接收对方的影响,即解耦。

RocketMQ架构

NameServer:消息队列的协调者,Broker向它注册路由信息,同时Producer和Consumer向其获取路由信息

Broker:是RocketMQ的核心,负责消息的接收,存储,发送等功能

Producer:消息的生产者,需要从NameServer获取Boker的信息,然后与Broker建立连接,向Broker发送消息

Consumer:消息的接收者,需要从NameServer获取Broker信息,然后与Broker建立连接,从Broker中获取消息。

Topic:用来区分不同类型的消息,发送和接收消息前都需要先创建Topic,针对Topic来发送和接收消息

Message Queue:为了提高性能和吞吐量,引入了Message Queue,一个Topic可以设置一个或多个Message Queue,这样消息就可以并行往各个Message Queue发送消息,消费者也可以并行的从多个Message Queue读取消息。就是消息的载体。

Producer Group:生产者组,简单来说就是多个发送同一类消息的生产者。

Consumer Group:接收者组,接收同一类消息的多个consumer实例组成的。

java代码演示消息发送和接收

导入依赖

<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.0.2</version>
</dependency>

发送消息:

1、创建消息生产者,指定生产者所属的组名

2、指定NameServer地址

3、启动生产者

4、创建消息对象,指定主题、标签、消息体。

5、发送消息

6、关闭生产者

package org.example;import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;public class Productor {public static void main(String[] args) throws Exception {
//1. 创建消息生产者, 指定生产者所属的组名DefaultMQProducer producer = new DefaultMQProducer("myproducer-group");
//2. 指定 Nameserver 地址producer.setNamesrvAddr("127.0.0.1:9876");
//3. 启动生产者producer.start();
//4. 创建消息对象,指定主题、标签和消息体Message msg = new Message("myTopic", "myTag",("RocketMQ Message哇哇哇哇").getBytes());Message msg2 = new Message("myTopic", "myTa",("RocketMQ Message哇哇哇哇222").getBytes());
//5. 发送消息SendResult sendResult = producer.send(msg, 10000);SendResult send = producer.send(msg2, 10000);System.out.println(sendResult);System.out.println(send);
//6. 关闭生产者producer.shutdown();}
}

接收消息

1、创建消息接收者,指定消费者所属的组名

2、指定NameServer地址

3、指定接收者订阅的主题和标签

4、设置回调函数,编写处理消息的方法

5、启动消息接收者

package org.example;import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.message.MessageExt;import java.util.List;public class Comsumer {public static void main(String[] args) throws Exception {
//1. 创建消息消费者, 指定消费者所属的组名DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("myconsumergroup");
//2. 指定 Nameserver 地址consumer.setNamesrvAddr("127.0.0.1:9876");
//3. 指定消费者订阅的主题和标签consumer.subscribe("myTopic", "*");
//4. 设置回调函数,编写处理消息的方法consumer.registerMessageListener(new MessageListenerConcurrently() {@Overridepublic ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {System.out.println("Receive New Messages: " + new String(msgs.get(0).getBody()));//返回消费状态return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;}});
//5. 启动消息消费者consumer.start();System.out.println("Consumer Started.");}
}
在微服务中RocketMQ的使用

订单服务是发送消息

添加依赖

<!--rocketmq-->
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>4.4.0</version>
</dependency>

添加配置

rocketmq:
name-server: 127.0.0.1:9876 #rocketMQ 服务的地址
producer:
group: shop-order # 生产者组

 编写测试代码

@Autowired
private RocketMQTemplate rocketMQTemplate;//主题,消息
rocketMQTemplate.convertAndSend("order-topic", order);

用户服务接收消息

添加依赖

<!--rocketMQ-->
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>4.4.0</version>
</dependency>

修改配置文件

rocketmq:
name-server: 127.0.0.1:9876

编写消息接收服务

@Service
@RocketMQMessageListener(consumerGroup = "shop-user", topic = "order-topic")
public class SmsService implements RocketMQListener<Order> {
@Override
public void onMessage(Order order) {
System.out.println("收到一个订单信息:"+ JSON.toJSONString(order)+",接
下来发送短信");
}
}

启动服务,执行下单操作,查看控制台

成功接收到消息。

Redis实现分布式锁

什么是分布式锁?

        即分布式系统中的锁,在单体项目中我们通过Java中的锁解决多线程访问共享资源的问题,而分布式锁,解决了分布式系统中控制共享资源访问的问题。与单体项目不同的是,分布式系统中竞争共享资源的最小粒度从线程升级到了进程。

为什么需要分布式锁?

        在分布式微服务架构中,一个应用往往需要开启多个服务(每一个服务都是一个独立的进程),这样依赖Java中的锁synchronized和Lock失效了,只有在同一个进程是有效的。

如何实现分布式锁

可以通过redis实现分布式锁,在redis中存放一个标志,当一个请求到达时修改标志

方式一:redis+setnx命令,自己实现一个分布式锁,虽然可以实现,在一些简单的场景下,没有问题的,在复杂的情况下还是会出现问题的。

setnx key value 设置键值时,会先判断键是否存在,键如果不存在,设置成功,键如果存在,就设置失败

如果不将锁释放当代finally中,就会造成死锁,原因是1、程序处理逻辑出现了问题,没有及时释放锁2、进程挂了,没有机会释放锁。

@RequestMapping("/sub")public void sub(){// 使用redis,以及redis中的setnx命令实现分布式锁// setnx key value 设置键值时,会先判断键是否存在,键如果不存在,设置成功,键如果存在,就设置失败//设置失效时间,第一个线程进来后就会,就会获取锁,第一个线程执行的业务超过失效时间,key就会失效,其他线程进来获取锁//第一个线程业务执行完之后就回去释放锁,那么锁就会释放成其他线程的锁,所以设置失效时间也是会出现问题的。try{// 针对进程可能挂掉的情况,为ket设置一个失效时间,即使服务挂了,也会删除keyboolean res = redisTemplate.opsForValue().setIfAbsent("lock",10, TimeUnit.SECONDS);if (!res){return;}// 从数据库查询一下库存Integer stock = (Integer) redisTemplate.opsForValue().get("");// 如果库存>0,就扣库存if (stock>0){Integer real = stock-1;redisTemplate.opsForValue().set("stock", real); // 把释放锁写在finally中,即使出现异常也,会释放锁System.out.println("成功");}else {System.out.println("扣库存失败");}}finally {redisTemplate.delete("lock");}}

在finally中释放锁以及设置键的失效时间,也是会出现问题的。

例如:程序的业务逻辑执行时间大于失效时间,那么锁就会失效,其他线程就会进来,这时,当第一个线程执行完成之后,会误删除第二个线程的锁的,导致其他线程的锁失效。

解决办法:为每一个线程添加一个版本号,删除锁时判断版本号。

 @RequestMapping("/sub")public void sub(){// 使用redis,以及redis中的setnx命令实现分布式锁// setnx key value 设置键值时,会先判断键是否存在,键如果不存在,设置成功,键如果存在,就设置失败//设置失效时间,第一个线程进来后就会,就会获取锁,第一个线程执行的业务超过失效时间,key就会失效,其他线程进来获取锁//第一个线程业务执行完之后就回去释放锁,那么锁就会释放成其他线程的锁,所以设置失效时间也是会出现问题的。String createId = UUID.randomUUID().toString();//生产一个32位不重复的字符串,版本号try{// 针对进程可能挂掉的情况,为ket设置一个失效时间,即使服务挂了,也会删除keyboolean res = redisTemplate.opsForValue().setIfAbsent("lock",createId ,10, TimeUnit.SECONDS);if (!res){return;}// 从数据库查询一下库存Integer stock = (Integer) redisTemplate.opsForValue().get("");// 如果库存>0,就扣库存if (stock>0){Integer real = stock-1;redisTemplate.opsForValue().set("stock", real); // 把释放锁写在finally中,即使出现异常也,会释放锁System.out.println("成功");}else {System.out.println("扣库存失败");}}finally {String lock=(String)redisTemplate.opsForValue().get("lock");if (createId.equals(lock)){//版本号相同,可以释放锁,不一样则说明已经过期了,则不需要管了。redisTemplate.delete("lock");}}}

 方式2:使用redisson

导入依赖

<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.6.5</version></dependency>

 创建redisson对象

package com.ffyc.springcloudshop.config;import org.redisson.Redisson;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RedissonConfig {//创建 Redisson 对象@Beanpublic Redisson getRedisson(){Config config = new Config();config.useSingleServer().setAddress("redis://127.0.0.1:6379").setDatabase(0);return (Redisson)Redisson.create(config);}}

使用redisson实现加锁释放锁

 @RequestMapping("/sub")public void sub(){RLock lock=redisson.getLock("stock-lock");//定义redis中锁的标志keytry {lock.lock(30,TimeUnit.SECONDS);//获取锁// 从数据库查询一下库存Integer stock = (Integer) redisTemplate.opsForValue().get("stock");// 如果库存>0,就扣库存if (stock>0){Integer real = stock-1;redisTemplate.opsForValue().set("stock", real); // 把释放锁写在finally中,即使出现异常也,会释放锁System.out.println("成功");}else {System.out.println("扣库存失败");}}finally {lock.unlock();//释放锁}}
为什么要使用redisson?
  • 可靠性优先:Redisson 解决了原生 SETNX 的核心缺陷(如非原子性、误释放、超时问题),确保锁在复杂场景下的正确性。
  • 开发效率优先:无需重复造轮子,直接使用成熟的分布式锁实现,专注业务逻辑开发。
  • 扩展性优先:支持多种锁类型、高可用架构(主从 / 集群)、监控功能,适应微服务、分布式系统的复杂需求。

相关文章:

微服务初步学习

系统架构演变过程 一、单体架构 前后端都在一个项目中&#xff0c;包括我们现在的前后端分离开发&#xff0c;都可以看作是一个单体项目。 二、集群架构 把一个服务部署多次&#xff0c;可以解决服务不够的问题&#xff0c;但是有些不必要的功能也跟着部署多次。 三、垂直架…...

旧 docker 版本通过 nvkind 搭建虚拟多节点 gpu 集群的坑

踩坑 参考nvkind教程安装到Setup这一步&#xff0c;由于docker版本较旧&#xff0c;–cdi.enabled 和 config 参数执行不了 手动修改 /etc/docker/daemon.json 配置文件 "features": {"cdi": true}手动修改 /etc/nvidia-container-runtime/config.toml 配…...

Fabric 服务端插件开发简述与聊天事件监听转发

原文链接&#xff1a;Fabric 服务端插件开发简述与聊天事件监听转发 < Ping通途说 0. 引言 以前写过Spigot的插件&#xff0c;非常简单&#xff0c;仅需调用官方封装好的Event类即可。但Fabric这边在开发时由于官方文档和现有互联网资料来看&#xff0c;可能会具有一定的误…...

Wise Disk Cleaner:免费系统清理工具,释放空间,提升性能

Wise Disk Cleaner是一款功能强大且完全免费的系统清理工具&#xff0c;专为帮助用户清理系统中的无用文件和垃圾文件而设计。它能够有效释放磁盘空间&#xff0c;提高系统运行速度&#xff0c;确保电脑始终保持最佳性能。无论是日常维护还是深度清理&#xff0c;Wise Disk Cle…...

排序算法之高效排序:快速排序,归并排序,堆排序详解

排序算法之高效排序&#xff1a;快速排序、归并排序、堆排序详解 前言一、快速排序&#xff08;Quick Sort&#xff09;1.1 算法原理1.2 代码实现&#xff08;Python&#xff09;1.3 性能分析 二、归并排序&#xff08;Merge Sort&#xff09;2.1 算法原理2.2 代码实现&#xf…...

主打「反激进」的一汽丰田,靠稳扎稳打的技术实现突围

文/王俣祺 导语&#xff1a;今年的上海车展&#xff0c;当新势力都在用“1000TOPS算力”“激光雷达矩阵”等参数堆砌着一个个技术神话的时候&#xff0c;一汽丰田却选择了一条不同的路——用“反激进”的技术哲学&#xff0c;在电动化和智能化的大风向中&#xff0c;构建独特的…...

变量赋值和数据类型

对象 Python是面相对象的编程语言&#xff0c;在Python一些都是对象&#xff0c;对象由标识、类型、值三部分组成&#xff0c;本质上来讲&#xff0c;系统分配一块内存&#xff0c;这块内存中存储了特定了的值&#xff0c;还支持特定类型的相关操作。 标识&#xff1a;即对象…...

【笔记】cri-docker.service和containerd

cri-docker.service 和 containerd 都是 Kubernetes 支持的容器运行时组件&#xff0c;但它们的架构、功能定位及与 Docker 的关系有显著差异。以下是它们的核心区别和关联&#xff1a; 1. 功能定位 组件核心角色是否直接支持 CRIcontainerd轻量级容器运行时&#xff0c;直接管…...

技术文章:解决汇川MD500系列变频器干扰问题——GRJ9000S EMC滤波器的应用

1. 引言 汇川MD500系列变频器&#xff08;Variable Frequency Drive, VFD&#xff09;以其高性能、宽功率范围&#xff08;0.4kW-500kW&#xff09;和灵活的控制方式&#xff0c;广泛应用于工业自动化领域&#xff0c;如风机、水泵、传送带和压缩机等。然而&#xff0c;MD500系…...

频域中的反射-信号完整性分析

频域中的反射: 频域与时域的桥梁是傅里叶变换,一个周期信号可以拆分为许多个正弦波。所谓从频域中看信号,看到的可以是很多个频域中的点,也可以是许多个正弦波。 所以在大家眼中看到的信号如图4-13所示。我们可以将该信号分解为图4-14所示信号。 让我们来思考下面这个问题:…...

window nvidia-smi命令 Failed to initialize NVML: Unknown Error

如果驱动目录下的可以执行&#xff0c;那可能版本原因 "C:\Program Files\NVIDIA Corporation\NVSMI\nvidia-smi"复制"C:\Program Files\NVIDIA Corporation\NVSMI\nvidia-smi.exe"替换 C:\Windows\System32\nvidia-smi.exe 或者 把C:\Windows\System3…...

ubuntu 20.04 更改国内镜像源-阿里源 确保可用

镜像源是跟linux版本一一对应的,查询自己系统的版本号&#xff1a; 命令&#xff1a;lsb_release -a macw:~$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 20.04.6 LTS Release: 20.04 Codename: focal macw:~$…...

Elasticsearch 学习(一)如何在Linux 系统中下载、安装

目录 一、Elasticsearch 下载二、使用 yum、dnf、zypper 命令下载安装三、使用 Docker 本地快速启动安装&#xff08;ESKibana&#xff09;【测试推荐】3.1 介绍3.2 下载、安装、启动3.3 访问3.4 修改配置&#xff0c;支持ip访问 官网地址&#xff1a; https://www.elastic.co/…...

PYTHON训练营DAY27

装饰器 编写一个装饰器 logger&#xff0c;在函数执行前后打印日志信息&#xff08;如函数名、参数、返回值&#xff09; logger def multiply(a, b):return a * bmultiply(2, 3) # 输出: # 开始执行函数 multiply&#xff0c;参数: (2, 3), {} # 函数 multiply 执行完毕&a…...

Shell脚本日志输出完整指南(AI)

一、基础日志输出方法 1. 标准输出与错误重定向 在Shell脚本中&#xff0c;可以使用重定向操作符将命令输出记录到日志文件&#xff1a; >&#xff1a;覆盖写入文件>>&#xff1a;追加写入文件2>&#xff1a;重定向错误输出&>&#xff1a;同时重定向标准…...

node.js文件系统(fs) - 创建文件、打开文件、写入数据、追加数据、读取数据、创建目录、删除目录

注意&#xff1a;以下所有示例均是异步语法&#xff01; 注意&#xff1a;以下所有示例均是异步语法&#xff01; 创建文件 node.js 允许我们在计算机本地创建文件&#xff0c;例如创建一个 word 文件&#xff1a; // 引入核心模块(fs) var fs require(fs)// API fs.writeF…...

关于如何本地启动xxl-job,并且整合SpringBoot

1. 本地安装xxl-job并启动 拉取xxl-job的代码 git clone gitgithub.com:xuxueli/xxl-job.git配置xxl-job数据库 拉取代码后&#xff0c;代码的doc/db目录下有官方配置好的sql脚本&#xff0c;执行里面的sql脚本至本地数据库 3. 修改xxl-job默认的数据库配置 spring.dataso…...

基于Unity的简单2D游戏开发

基于Unity的简单2D游戏开发 摘要 本文围绕基于Unity的简单2D游戏开发进行深入探讨,旨在分析其开发过程中的技术架构与实现策略。通过文献综述与市场分析,研究发现,近年来Unity引擎因其优秀的跨平台特性及可视化编程理念,成为2D游戏开发的主要工具。文章首先梳理了游戏开发的…...

在服务器上安装AlphaFold2遇到的问题(3)_cat: /usr/include/cudnn_version.h: 没有那个文件或目录

[rootlocalhost ~]# cat /usr/include/cudnn_version.h cat: /usr/include/cudnn_version.h: 没有那个文件或目录这个错误表明系统找不到 cudnn_version.h 头文件&#xff0c;说明 cuDNN 的开发文件&#xff08;头文件&#xff09;没有正确安装。以下是完整的解决方案&#xff…...

Java生产环境设限参数教学

哈哈&#xff0c;这个问题问得好&#xff01;咱们用开餐厅的比喻来理解生产环境的四大必须设限参数&#xff0c;保证你听完再也不会忘&#xff01;&#xff08;搓手手&#xff09; 1. 堆内存上限&#xff1a;-Xmx&#xff08;厨房的最大容量&#xff09; 问题&#xff1a;想象…...

武汉火影数字全息剧秀制作:科技与艺术的梦幻联动

全息剧秀是通过全息投影技术、多媒体互动技术、舞台表演艺术等元素深度融合的新型演出形式。 随着科技的不断进步&#xff0c;投影技术的更加成熟&#xff0c;全息剧秀作为演艺行业的创新力量&#xff0c;正以其独特的魅力和无限的潜力&#xff0c;为观众带来全新的视听盛宴。 …...

MySQL锁机制详解与加锁流程全解析

一、MySQL锁机制全景图 1.1 锁类型体系 #mermaid-svg-czUB6iJgmHuOPdN1 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-czUB6iJgmHuOPdN1 .error-icon{fill:#552222;}#mermaid-svg-czUB6iJgmHuOPdN1 .error-text{f…...

云轴科技ZStack官网上线Support AI,智能助手助力高效技术支持

5月16日&#xff0c;云轴科技ZStack在官网&#xff08;www.zstack.io&#xff09;正式上线ZStack Support AI智能助手。该系统是ZStack应用人工智能于技术支持服务领域的重要创新&#xff0c;基于自研ZStack AIOS平台智塔及LLMOPS技术打造。 ZStack Support AI定位为智能客服&…...

深度学习笔记23-LSTM实现火灾预测(Tensorflow)

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客&#x1f356; 原作者&#xff1a; 一、前期准备 1.导入数据 import pandas as pd import numpy as npdf_1 pd.read_csv("D:\TensorFlow1\woodpine2.csv") df_1import matplotlib.pyplot as…...

单例模式(Singleton Pattern)详解

单例模式(Singleton Pattern)详解 1. 定义与核心目标 单例模式是一种创建型设计模式,确保一个类只有一个实例,并提供全局访问点。核心目标: 控制实例数量:防止重复创建对象,节省资源。统一管理共享资源:如配置管理、数据库连接池、日志处理器等。2. 实现方式及对比 (…...

IntelliJ IDEA打开项目后,目录和文件都不显示,只显示pom.xml,怎样可以再显示出来?

检查.idea文件夹 如果项目目录中缺少.idea文件夹&#xff0c;可能导致项目结构无法正确加载。可以尝试删除项目根目录下的.idea文件夹&#xff0c;然后重新打开项目&#xff0c;IDEA会自动生成新的.idea文件夹和相关配置文件&#xff0c;从而恢复项目结构。 问题解决&#xff0…...

LongRefiner:解决长文档检索增强生成的新思路

大语言模型与RAG的应用越来越广泛&#xff0c;但在处理长文档时仍面临不少挑战。今天我们来聊聊一个解决这类问题的新方法——LongRefiner。 背景问题&#xff1a;长文档处理的两大难题 使用检索增强型生成&#xff08;RAG&#xff09;系统处理长文档时&#xff0c;主要有两个…...

Tcping详细使用教程

Tcping详细使用教程 下载地址 https://download.elifulkerson.com/files/tcping/0.39/在windows环境下安装tcping 在以上的下载地中找到exe可执行文件&#xff0c;其中tcping.exe适用于32位Windows系统&#xff0c;tcping64.exe适用于64位Windows操作系统。 其实tcping是个…...

Java + 鸿蒙双引擎:ZKmall开源商城如何定义下一代B2C商城技术标准?

在 B2C 电商领域持续革新的当下&#xff0c;技术架构的优劣成为决定商城竞争力的核心要素。ZKmall开源商城以其创新融合的 Java 与鸿蒙双引擎&#xff0c;为下一代 B2C 商城技术标准勾勒出全新蓝图&#xff0c;在性能、兼容性、拓展性等关键维度实现了重大突破。 一、Java 技术…...

华为云Flexus+DeepSeek征文|基于Dify平台tiktok音乐领域热门短视频分析Ai agent

前言 在当今数字化快速发展的时代&#xff0c;人工智能技术尤其是大模型的应用&#xff0c;正逐渐成为推动各行业创新与变革的关键力量。大模型凭借其强大的语言理解、生成和逻辑推理能力&#xff0c;为企业和开发者提供了全新的解决方案和应用可能性。然而&#xff0c;将这些…...

排序算法之线性时间排序:计数排序,基数排序,桶排序详解

排序算法之线性时间排序&#xff1a;计数排序、基数排序、桶排序详解 前言一、计数排序&#xff08;Counting Sort&#xff09;1.1 算法原理1.2 代码实现&#xff08;Python&#xff09;1.3 性能分析1.4 适用场景 二、基数排序&#xff08;Radix Sort&#xff09;2.1 算法原理2…...

HarmonyOS 开发之 —— 合理使用动画与转场

HarmonyOS 开发之 —— 合理使用动画与转场 谢谢关注!! 前言:上一篇文章主要介绍HarmonyOs开发之———UIAbility进阶:https://blog.csdn.net/this_is_bug/article/details/147976323?spm=1011.2415.3001.10575&sharefrom=mp_manage_link 在移动应用开发中,动画与转…...

网络流量分析 | NetworkMiner

介绍 NetworkMiner 是一款适用于Windows&#xff08;也适用于Linux/Mac&#xff09;的开源网络取证分析工具。它可被用作被动网络嗅探器/数据包捕获工具&#xff0c;也可被用于检测操作系统、会话、主机名、开放端口等&#xff0c;还能被用于解析pcap文件进行离线分析。点击此…...

EtherCAT转ProfiNet智能网关选型策略匹配S7-1500与CX5140通讯需求的关键参数对比

一、案例背景 随着新能源行业的迅猛发展&#xff0c;锂电池生产制造企业面临着日益激烈的市场竞争和不断增长的生产需求。某锂电池生产企业在扩大产能的过程中&#xff0c;新建了一条锂电池生产线。该生产线采用了倍福CX5140PLC作为EtherCAT协议主站&#xff0c;控制着涂布机、…...

适合学校使用的桌面信息看板,具有倒计时、桌面时钟、课程表、天气预报、自动新闻联播、定时关机、消息通知栏、随机点名等功能。

简介 教育时钟&#xff08;Education Clock&#xff09; 是一款致力于帮助学习者科学规划学习时间、提高学习效率的开源工具。由 Return-Log 团队开发&#xff0c;适配多平台&#xff08;Windows、Mac、Linux&#xff09;&#xff0c;界面简洁直观&#xff0c;操作便捷。通过设…...

兰亭妙微设计:为生命科技赋予人性化的交互语言

在医疗科技日新月异的今天&#xff0c;卓越的硬件性能唯有匹配恰如其分的交互语言&#xff0c;方能真正发挥价值。作为专注于医疗UI/UX设计的专业团队&#xff0c;兰亭妙微设计&#xff08;www.lanlanwork.com&#xff09;始终相信&#xff1a;每一处像素的排布&#xff0c;都应…...

redis数据结构-12(配置 RDB 快照:保存间隔和压缩)

配置 RDB 快照&#xff1a;保存间隔和压缩 Redis 持久性对于确保在服务器重启或发生故障时数据不会丢失至关重要。虽然 Redis 以其内存中数据存储而闻名&#xff0c;但它提供了将数据持久化到磁盘的机制。本章节重点介绍其中一种机制&#xff1a;Redis 数据库 &#xff08;RDB…...

SG7050VAN差分晶振,X1G0042810033,EPSON爱普生以太网6G晶振

产品简介 SG7050VAN差分晶振,X1G0042810033,EPSON爱普生以太网6G晶振&#xff0c;日本EPSON爱普生株式会社&#xff0c;进口晶振型号&#xff1a;SG7050VAN&#xff0c;编码为&#xff1a;X1G0042810033&#xff0c;频率为&#xff1a;156.250000 MHz&#xff0c;小体积晶振尺…...

nfs网络文件系统

nfs网络文件系统简介 NFS (Network File system ,网络文件系统)是由SUN公司研制的UNIX表示层协议&#xff0c;它允许网络中的计算机(不同的计算机、不同的操作系统)之间通过TCP/IP网络共享资源&#xff0c;主要在unix系列操作系统上使用。在NFS的应用中&#xff0c;本地NFS的客…...

西安前端面试

面试1 1.vue2和vue3的原理及区别 2.伪数组 3.对箭头函数怎么理解的 4.vue父子组件传值的几种方式 5.对Promise的理解 面试2 1.两个升序数组实现合并升序排序 2.数组拍平[3, [[7, [1, 5]], 4], 8, [6]] 面试3 1.let var const的区别&#xff0c;什么时候const能改变 …...

Linux常用命令42——tar压缩和解压缩文件

在使用Linux或macOS日常开发中&#xff0c;熟悉一些基本的命令有助于提高工作效率&#xff0c;tar 是 Linux 和 Unix 系统中用于归档文件和目录的强大命令行工具。tar 名字来自 "tape archive"&#xff08;磁带归档&#xff09;&#xff0c;最初用于将文件打包到磁带…...

AML 数据集

在公开的AML&#xff08;急性髓性白血病&#xff09;数据集中&#xff0c;有几个包含图像和多组学数据的资源&#xff0c;且部分带有生存状态和生存时间的标签。以下是一些相关数据集&#xff1a; 1. TCGA-AML (The Cancer Genome Atlas - Acute Myeloid Leukemia) 描述&…...

什么是Rosetta?

Apple 提供的「动态二进制翻译器」&#xff0c;让基于 Intel 的 x86_64 应用/二进制在 Apple Silicon&#xff08;M1/M2/M3&#xff0c;ARM 架构&#xff09;上运行 项目说明&#x1f9e0; Rosetta 2是 Apple 提供的一种「Intel → ARM 翻译器」&#x1f5a5;️ 功能让你的 AR…...

Redis解析

Redis解析 一、单线程模型 redis在io层面是多线程的&#xff0c;在数据处理层面是单线程的。 多线程一般用于&#xff1a; 关闭连接删除/淘汰内存网络IO 1.1 io多路复用 redis使用nio&#xff08;select、poll、epoll&#xff09;的方式处理socket 主线程负责接收建立连接…...

轨迹误差评估完整流程总结(使用 evo 工具)

roslaunch .launch rosbag play your_dataset.bag -r 2.0 ✅ 第二步&#xff1a;录制估计轨迹 bash 复制编辑 rosbag record -O traj_only.bag /aft_mapped_to_init 运行一段时间后 CtrlC 停止&#xff0c;生成 traj_only.bag 第三步&#xff1a;提取估计轨迹和真值轨迹为…...

服务器死机了需要检查哪些问题

在这个数字化的时代&#xff0c;服务器就像是我们信息世界的“大管家”&#xff0c;可要是它突然死机了&#xff0c;那可真是让人头疼。今天咱们就来聊聊&#xff0c;服务器死机了&#xff0c;到底需要检查哪些问题。 一、硬件问题 电源供应&#xff1a;检查电源是否稳定&…...

秒杀案例讲解

技术择型 Springboot 接收请求并操作 redis 和 mysqlRedis 用于缓存分布式锁Rocketmq 用于解耦 削峰&#xff0c;异步Mysql 用于存放真实的商品信息Mybatis 用于操作数据库的 orm 框架 架构图 spike-web&#xff08;接受用户秒杀请求&#xff09; pom.xml <?xml versio…...

Qt图表绘制(QtCharts)- 性能优化(13)

文章目录 1 批量替换代替追加1.1 测试11.2 测试21.3 测试3 2 开启OpenGL2.1 测试12.2 测试22.3 测试32.4 测试4 更多精彩内容&#x1f449;内容导航 &#x1f448;&#x1f449;Qt开发 &#x1f448;&#x1f449;QtCharts绘图 &#x1f448;&#x1f449;python开发 &#x1f…...

[逆向工程]DebugView捕获WPS日志?解析未运行WPS时Shell扩展加载的原因与解决方案(二十五)

[逆向工程]DebugView捕获WPS日志&#xff1f;解析未运行WPS时Shell扩展加载的原因与解决方案&#xff08;二十五&#xff09; 引言&#xff1a;一个“幽灵”般的日志问题 你是否在使用 DebugView 排查系统问题时&#xff0c;发现日志中频繁出现 WPS 相关模块&#xff08;如 k…...

【打破信息差】萌新认识与入门算法竞赛

阅前须知 XCPC萌新互助进步群2️⃣&#xff1a;174495261 博客主页&#xff1a;resot (关注resot谢谢喵) 针对具体问题&#xff0c;应当进行具体分析&#xff1b;并无放之四海而皆准的方法可适用于所有人。本人尊重并支持每位学习者对最佳学习路径的自主选择。本篇所列训练方…...