springcloud Ribbon的详解

1、Ribbon是什么

Ribbon是Netflix发布的开源项目,Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的框架。

2、Ribbon能干什么

LB负载均衡(Load Balance)是什么?简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA(高可用)。常见的负载均衡有软件Nginx,硬件 F5等。

3.负载均衡使用场景

现在Java非常流行微服务,也就是所谓的面向服务开发,将一个项目拆分成了多个项目,其优点有很多,其中一个优点就是:将服务拆分成一个一个微服务后,我们很容易的来针对性的进行集群部署。例如订单模块用的人比较多,我就可以将这个模块多部署几台机器,来分担单个服务器的压力。

这时候有个问题来了,前端页面请求的时候到底请求集群当中的哪一台?既然是降低单个服务器的压力,所以肯定全部机器都要利用起来,而不是说一台用着,其他空余着。这时候就需要用负载均衡了,像这种前端页面调用后端请求的,要做负载均衡的话,常用的就是Nginx。

4.Ribbon和Nginx负载均衡区别

  • 当后端服务是集群的情况下,前端页面调用后端请求,要做负载均衡的话,常用的就是Nginx。
    Ribbon主要是在服务端内做负载均衡,举例:订单后端服务 要调用 支付后端服务,这属于后端之间的服务调用,压根根本不经过页面,而支付后端服务是集群,这时候订单服务就需要做负载均衡来调用支付服务,记住是订单服务做负载均衡 来调用 支付服务。

5.负载均衡分类

  • 集中式LB:即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5, 也可以是软件,如nginx),由该设施负责把访问请求通过某种策略转发至服务的提供方;
  • 进程内LB:将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。
    Ribbon负载均衡

Ribbon就属于进程内LB,它只是一个类库,集成于消费方进程。

举例:微服务经常会涉及到A服务调用B服务的接口,这时候就需要用HTTP远程调用框架,常见的有Feign、RestTemplate、HttpClient,假如B服务只有一个节点,这时候我们可以在调用的时候写固定ip来进行调用,假如B服务的节点存在多个(也就是集群),那A服务究竟调用B服务的哪个节点呢,这时候可以通过负载均衡框架来计算出调用哪个,比如轮询调用B服务的多个节点,总不可能一直调用人家的一个服务,这样B服务的集群有什么意义呢?或者也可以随机调用任意节点,总之负载均衡的作用就是避免一直调用一个节点。

大概的流程:RestTemplate或者Feign可以通过注册中心拿到服务提供方的IP+端口,假如提供者有多个,那他就会拿到多个地址,有了这些地址就差访问的时候访问哪个地址的服务了,而Ribbon可以很好的和RestTemplate或者Feign进行集成,来决定调用哪个服务,具体是负载均衡还是随机Ribbon都可以设置。

项目处于维护状态 ,已经一年多没有更新过了。

在这里插入图片描述

6.Ribbion架构说明

在这里插入图片描述
在这里插入图片描述

首先通过上图一定要明白一点:ribbon一定是用在消费方,而不是服务的提供方!

Ribbon在工作时分成两步(这里以Eureka为例,consul和zk同样道理):

第一步先选择 EurekaServer ,它优先选择在同一个区域内负载较少的server.
第二步再根据用户指定的策略,在从server取到的服务注册列表中选择一个地址。

之前写样例时候没有引入spring-cloud-starter-ribbon也可以使用ribbon,这是为什么?

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

猜测spring-cloud-starter-netflix-eureka-client自带了spring-cloud-starter-ribbon引用,证明如下: 可以看到spring-cloud-starter-netflix-eureka-client 确实引入了Ribbon(zk和consul注册中心同样是如此

在这里插入图片描述

7 .Ribbon负载均衡策略

Ribbon负载均衡策略是 IRule接口定义的,每一个子接口都是一种策略。下面是常见负载均衡算法

1.负载均衡种类

负载均衡类规则
RoundRobinRule轮询选择服务器。Ribbon默认负载均衡算法。
AvailabilitvFilteringRule(1) 默认情况,服务器连接3次失败,服务器设置为短路状态。短路状态持续30秒,如果再连接失败,短路状态持续时间就会几何级增长。 (2)并发数高的服务器。可配置该规则会忽略并发数高的服务器。并发数上限可以配置。
WeightedResponseTimeRule给服务器赋予权重。响应时间越长,权重越小。权重影响服务器的选择。
ZoneAvoidanceRule使用Zone对服务器进行分类。Zone可以是一个机房、一个机架等。然后对Zone内的服务进行轮询。例如:配置Zone是曹县机房,然后服务提供者会优先选择曹县机房的服务器。
BestAvailableRule忽略短路的服务器并选择并发数低的服务器。
RandomRule随机选择一个可用服务器。
RetryRule重试机制的选择逻辑。

8.置负载均衡

8.1.RestTemplate远程调用配置负载均衡

	@Autowiredprivate RestTemplate restTemplate;public Order queryOrderById(Long orderId) {// 根据订单id查询订单Order order = orderMapper.findById(orderId);// 利用RestTemplate发起http请求,根据用户id查询用户// 把localhost改为服务名称这里这里  String url = "http://userservice/user/" + order.getUserId();//String url = "http://localhost:8081/user/" + order.getUserId();// 发送http请求,实现远程调用,现在是get请求类型User user = restTemplate.getForObject(url, User.class);// 封装user到Orderorder.setUser(user);// 返回值return order;}

注意: Feign集成了Ribbon,不用去特别配置负载均衡。
2.RestTemplate配置类加上注解

	 /*** 创建RestTemplate并注入Spring容器*/@Bean@LoadBalanced //负载均衡注解public RestTemplate restTemplate() {return new RestTemplate();}

8.2 配置负载均衡

(1) 代码类型

注意:这种配置是全局的,订单服务不光调用用户服务是随机的,调用其他的服务也是随机的
//注入新的负载均衡算法 在启动类内注入也可以自定义配置类
@Bean
public IRule randomRule() {//随机选取一个可用服务器return new RandomRule();
}

(2) yml中配置

注意:这种局部配置,只针对用户服务去选择负载均衡的算法

userservice:  # 服务名称ribbon:NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.RandomRule  # 负载均衡规则

(3) Ribbon的饥饿加载配置

Ribbon默认是懒加载: 第一次加载才会创建 LoadBalancerClient ,请求时间会很长。
饥饿加载: 在项目启动时创建,降低第一次访问的耗时。

在Spring Cloud中,Ribbon的饥饿加载是指在启动时就加载并初始化相关的服务调用客户端配置,而不是等到第一次请求时再进行加载。这样做可以提高系统的响应速度,因为它避免了第一次请求的延迟。要配置Ribbon的饥饿加载,你需要在你的应用程序中设置spring.cloud.load-balancer.ribbon.enabled为true,默认情况下它是开启的。如果你需要关闭它,可以设置为false

(1) 单个服务配置饥饿加载(在yml文件配置)

spring:cloud:load-balancer:ribbon:eager-load:enabled: true # 开启Ribbon的饥饿加载clients: # 指定需要进行饥饿加载的服务列表- service-id-1- service-id-2

(1) 多个服务配置饥饿加载(在yml文件配置)

spring:cloud:load-balancer:ribbon:eager-load:enabled: true # 开启饥饿加载clients: # 指定饥饿加载的服务名称- userservice   # 用户服务- cangkuservice # 仓库服务- zhifuservice  # 支付服务

在这个配置中,service-id-1和service-id-2是你希望在启动时就加载并初始化的服务的ID。
注意:开启Ribbon的饥饿加载可能会稍微增加启动时间,因为它会预先初始化与服务相关的客户端。但是,这对于提高系统的整体响应速度是有益的。

九 Ribbon实现负载均衡的原理

Ctrl + N 快速查找类:原理是 LoadBalancerInterceptor 实现了 ClientHttpRequestInterceptor 接口。

客户端http请求拦截器

@FunctionalInterface
public interface ClientHttpRequestInterceptor {ClientHttpResponse intercept(HttpRequest var1, byte[] var2, ClientHttpRequestExecution var3) throws IOException;
}
 
public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {重写ClientHttpRequestInterceptor接口的方法@Overridepublic ClientHttpResponse intercept(final HttpRequest request, final byte[] body,final ClientHttpRequestExecution execution) throws IOException {// 1.获取http的请求地址final URI originalUri = request.getURI();// 2.获取服务的名称String serviceName = originalUri.getHost();Assert.state(serviceName != null,"Request URI does not contain a valid hostname: " + originalUri);//3.我们进去execute方法:就是为了从Eureka-Server拉取信息return this.loadBalancer.execute(serviceName,this.requestFactory.createRequest(request, body, execution));}
}
public class RibbonLoadBalancerClient implements LoadBalancerClient {//4.进入此方法public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {//调用下面的execute方法return this.execute(serviceId, (LoadBalancerRequest)request, (Object)null);}public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint) throws IOException {//5.根据服务名称获取对应的服务列表,loadBalancer里面有List存有服务的地址ILoadBalancer loadBalancer = this.getLoadBalancer(serviceId);//6.根据算法选择要使用的服务,会进入IRule接口里面,默认是轮询算法Server server = this.getServer(loadBalancer, hint);if (server == null) {throw new IllegalStateException("No instances available for " + serviceId);} else {RibbonLoadBalancerClient.RibbonServer ribbonServer = new RibbonLoadBalancerClient.RibbonServer(serviceId, server, this.isSecure(server, serviceId), this.serverIntrospector(serviceId).getMetadata(server));return this.execute(serviceId, (ServiceInstance)ribbonServer, (LoadBalancerRequest)request);}}
}

在这里插入图片描述

十 Ribbon单独使用,配置自动重试,实现负载均衡和高可用

JDK 1.8,SpringCloud Greenwich.SR2,SpringBoot 2.1.3.RELEASE

本文示例,CONSUMER-SERVICE服务调用PRODUCER-SERVICE服务。在进行以下步骤前,请先启动两个普通的SpringBoot服务PRODUCER-SERVICE。

2.1 pom依赖

因为这里独立使用Ribbon,所以CONSUMER-SERVICE只需要spring-cloud-starter-netflix-ribbon,启动主类也无需更多的注解,如

@EnableEurekaClient、@EnableDiscoveryClient、@EnableCircuitBreaker等,只需保留@SpringBootApplication即可。

<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-ribbon</artifactId></dependency>
</dependencies>
<dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Greenwich.SR2</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>

2.2 RestTemplate配置

Ribbon是对RestTemplate的加强,需要为RestTemplate添加注解@LoadBalanced,使之具有负载均衡能力。如下:

@Bean
@LoadBalanced
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {RestTemplate restTemplate = new RestTemplate(factory);restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));return restTemplate;
}

2.3 Ribbon配置

注意:网上和书上很多教程都没有提到ribbon.restclient.enabled这一配置,导致再怎么尝试都无法成功自动重试。

spring.application.name=CONSUMER-SERVICE
server.port=8801ribbon.restclient.enabled=true
#开启重试机制
spring.cloud.loadbalancer.retry.enabled=true
#请求连接的超时时间
PRODUCER-SERVICE.ribbon.ConnectTimeout=250
#请求处理的超时时间
PRODUCER-SERVICE.ribbon.ReadTimeout=1000
#对所有操作请求都进行重试,默认false,只有GET请求会重试;这是防止POST等对数据有影响的请求在重试后因为接口未做幂等性导致数据异常,影响较大
PRODUCER-SERVICE.ribbon.OkToRetryOnAllOperations=true
#指定请求重试开关,经调试源码该属性未被使用,疑似bug,导致不论怎么设置,都是只有服务提供者的Get请求可以被自动重试
#PRODUCER-SERVICE.ribbon.RequestSpecificRetryOn=true
#切换实例的重试次数
PRODUCER-SERVICE.ribbon.MaxAutoRetriesNextServer=2
#对当前实例的重试次数
PRODUCER-SERVICE.ribbon.MaxAutoRetries=1#服务PRODUCER-SERVICE的地址
PRODUCER-SERVICE.ribbon.listOfServers=localhost:8080,localhost:8083

2.4 Ribbon调用服务

在Controller中,注入RestTemplate,使用服务名(即spring.application.name)的方式,调用PRODUCER-SERVICE服务的GET接口,如下:

@Controller
@RequestMapping("consumer/api")
public class ConsumerController {@Autowiredprivate RestTemplate restTemplate;@GetMapping("/test")@ResponseBodypublic String test() {ResponseEntity<String> entity = restTemplate.getForEntity("http://PRODUCER-SERVICE/outer/data?res=3&msgKey=token123", String.class);return entity.getBody();}
}

三、测试运行

3.1 负载均衡测试
启动一个消费者服务CONSUMER-SERVICE,多次访问/consumer/api/test,可以通过给PRODECER-SERVICE服务的/outer/data接口添加调试日志的打印,来确认默认使用了轮询的负载均衡策略。

3.2 高可用测试
停止其中一个PRODECER-SERVICE服务实例,确认轮询到已停止的服务时,可以成功地在未停止的服务上自动重试请求。

四、无法成功自动重试的几种情况
本人在单独使用Ribbon的过程中,碰到以下几种无法自动重试其他服务节点的情况:

4.1 ribbon.restclient.enabled
遇到Ribbon的问题,网上一搜,千篇一律,也不知道作者们是否亲自实践证明可用,就随意发篇文章。言归正传,若不设置ribbon.restclient.enabled=true,在本人的实验环境中是无法自动重试的。

4.2 Maven打包有警告
在SpringCloud生态的开发中,各组件往往自动依赖了很多其他的jar包,如果向Maven本地仓库下载的过程中,网络不好,就会下载到一份不完整的jar包或pom文件,最终可能会导致打包出错。下面是在使用Maven打包项目时,比较常见下面的警告:

[WARNING] The POM for com.sun.jersey:jersey-core:jar:1.19.1 is
invalid, transitive dependencies (if any) will not be available
[WARNING] The POM for com.sun.jersey:jersey-client:jar:1.19.1 is
invalid, transitive dependencies (if any) will not be available

可以看出来,提示我们传递依赖将失效,所以有可能整个打包过程是SUCCESS的,但是最后启动jar包时,却可能报NoClassDef等缺少jar包的错误。因此,我们需要在打包时加上参数 -X 以查看具体原因:

[WARNING] The POM for com.sun.jersey:jersey-core:jar:1.19.1 is
invalid, transitive dependencies (if any) will not be available: 1
problem was encountered while building the effective model for
com.sun.jersey:jersey-core:[unknown-version] [FATAL] Non-parseable POM
E:\maven\repository\com\sun\jersey\jersey-project\1.19.1\jersey-project-1.19.1.pom:
processing instruction can not have PITarget with reserved xml name
(position: END_TAG seen …\n\n\n<?xml …
@627:7) @
E:\maven\repository\com\sun\jersey\jersey-project\1.19.1\jersey-project-1.19.1.pom,
line 627, column 7 [WARNING] The POM for
com.sun.jersey:jersey-client:jar:1.19.1 is invalid, transitive
dependencies (if any) will not be available: 1 problem was encountered
while building the effective model for
com.sun.jersey:jersey-client:[unknown-version] [FATAL] Non-parseable
POM
E:\maven\repository\com\sun\jersey\jersey-project\1.19.1\jersey-project-1.19.1.pom:
processing instruction can not have PITarget with reserved xml name
(position: END_TAG seen …\n\n\n<?xml …
@627:7) @
E:\maven\repository\com\sun\jersey\jersey-project\1.19.1\jersey-project-1.19.1.pom,
line 627, column 7 [WARNING] The POM for
com.sun.jersey.contribs:jersey-apache-client4:jar:1.19.1 is invalid,
transitive dependencies (if any) will not be available: 1 problem was
encountered while building the effective model for
com.sun.jersey.contribs:jersey-apache-client4:[unknown-version]
[FATAL] Non-parseable POM
E:\maven\repository\com\sun\jersey\jersey-project\1.19.1\jersey-project-1.19.1.pom:
processing instruction can not have PITarget with reserved xml name
(position: END_TAG seen …\n\n\n<?xml …
@627:7) @
E:\maven\repository\com\sun\jersey\jersey-project\1.19.1\jersey-project-1.19.1.pom,
line 627, column 7

特别注意FATAL这个最严重的日志级别的信息, 日志提醒我们本地仓库的pom文件E:\maven\repository\com\sun\jersey\jersey-project\1.19.1\jersey-project-1.19.1.pom解析出错,然后我们去此目录下,可以发现这个文件未被下载完整。最后的解决方式是删除此文件的父目录,重新打包,则会自动下载一份完整的pom文件,警告消失,打包成功。

4.3 OkToRetryOnAllOperations和RequestSpecificRetryOn失效
在上文的例子中,消费者服务调用的生产者服务接口是GET类型,自动重试没有任何问题。接着,本人尝试让消费者调用生产者服务的POST接口,同时仍然设置了ribbon.OkToRetryOnAllOperations=true,结果无法成功重试,然后去调试ribbon源码,查看自动重试机制,经查,OkToRetryOnAllOperations和RequestSpecificRetryOn属性可以成功获取到,但RequestSpecificRetryOn并未被获取出来使用,疑似Ribbon的bug。这里记录一下调试的重要部分,

(1)Ribbon配置属性类com.netflix.client.config.CommonClientConfigKey;

(2)Ribbon判断是否重试:

所以,单独使用Ribbon需谨慎!

十一、Spring Cloud Ribbon配置详解

常用配置

1. 禁用 Eureka

当我们在 RestTemplate 上添加 @LoadBalanced 注解后,就可以用服务名称来调用接口了,当有多个服务的时候,还能做负载均衡。

这是因为 Eureka 中的服务信息已经被拉取到了客户端本地,如果我们不想和 Eureka 集成,可以通过下面的配置方法将其禁用。

# 禁用 Eureka
ribbon.eureka.enabled=false

当我们禁用了 Eureka 之后,就不能使用服务名称去调用接口了,必须指定服务地址。

2. 配置接口地址列表

上面我们讲了可以禁用 Eureka,禁用之后就需要手动配置调用的服务地址了,配置如下:

# 禁用 Eureka 后手动配置服务地址
ribbon-config-demo.ribbon.listOfServers=localhost:8081,localhost:8083

这个配置是针对具体服务的,前缀就是服务名称,配置完之后就可以和之前一样使用服务名称来调用接口了。

3. 配置负载均衡策略

Ribbon 默认的策略是轮询,从我们前面讲解的例子输出的结果就可以看出来,Ribbon 中提供了很多的策略,这个在后面会进行讲解。我们通过配置可以指定服务使用哪种策略来进行负载操作。

4. 超时时间

Ribbon 中有两种和时间相关的设置,分别是请求连接的超时时间和请求处理的超时时间,设置规则如下:

# 请求连接的超时时间
ribbon.ConnectTimeout=2000
# 请求处理的超时时间
ribbon.ReadTimeout=5000
也可以为每个Ribbon客户端设置不同的超时时间, 通过服务名称进行指定:
ribbon-config-demo.ribbon.ConnectTimeout=2000
ribbon-config-demo.ribbon.ReadTimeout=5000

5. 并发参数

# 最大连接数
ribbon.MaxTotalConnections=500
# 每个host最大连接数
ribbon.MaxConnectionsPerHost=500

代码配置 Ribbon

配置 Ribbon 最简单的方式就是通过配置文件实现。当然我们也可以通过代码的方式来配置。

通过代码方式来配置之前自定义的负载策略,首先需要创建一个配置类,初始化自定义的策略,代码如下所示。

@Configuration
public class BeanConfiguration {
@Bean
public MyRule rule() {
return new MyRule();
}
}

创建一个 Ribbon 客户端的配置类,关联 BeanConfiguration,用 name 来指定调用的服务名称,代码如下所示。

@RibbonClient(name = "ribbon-config-demo", configuration = BeanConfiguration.class)
public class RibbonClientConfig {
}

可以去掉之前配置文件中的策略配置,然后重启服务,访问接口即可看到和之前一样的效果。

配置文件方式配置 Ribbon

除了使用代码进行 Ribbon 的配置,我们还可以通过配置文件的方式来为 Ribbon 指定对应的配置:

<clientName>.ribbon.NFLoadBalancerClassName: Should implement ILoadBalancer(负载均衡器操作接口)
<clientName>.ribbon.NFLoadBalancerRuleClassName: Should implement IRule(负载均衡算法)
<clientName>.ribbon.NFLoadBalancerPingClassName: Should implement IPing(服务可用性检查)
<clientName>.ribbon.NIWSServerListClassName: Should implement ServerList(服务列表获取)
<clientName>.ribbon.NIWSServerListFilterClassName: Should implement ServerList­Filter(服务列表的过滤)

重试机制

在集群环境中,用多个节点来提供服务,难免会有某个节点出现故障。用 Nginx 做负载均衡的时候,如果你的应用是无状态的、可以滚动发布的,也就是需要一台台去重启应用,这样对用户的影响其实是比较小的,因为 Nginx 在转发请求失败后会重新将该请求转发到别的实例上去。

由于 Eureka 是基于 AP 原则构建的,牺牲了数据的一致性,每个 Eureka 服务都会保存注册的服务信息,当注册的客户端与 Eureka 的心跳无法保持时,有可能是网络原因,也有可能是服务挂掉了。

在这种情况下,Eureka 中还会在一段时间内保存注册信息。这个时候客户端就有可能拿到已经挂掉了的服务信息,故 Ribbon 就有可能拿到已经失效了的服务信息,这样就会导致发生失败的请求。

这种问题我们可以利用重试机制来避免。重试机制就是当 Ribbon 发现请求的服务不可到达时,重新请求另外的服务。

1. RetryRule 重试

解决上述问题,最简单的方法就是利用 Ribbon 自带的重试策略进行重试,此时只需要指定某个服务的负载策略为重试策略即可:

ribbon-config-demo.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RetryRule

2. Spring Retry 重试

除了使用 Ribbon 自带的重试策略,我们还可以通过集成 Spring Retry 来进行重试操作。

在 pom.xml 中添加 Spring Retry 的依赖,代码如下所示。

<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>

配置重试次数等信息:

# 对当前实例的重试次数
ribbon.maxAutoRetries=1
# 切换实例的重试次数
ribbon.maxAutoRetriesNextServer=3
# 对所有操作请求都进行重试
ribbon.okToRetryOnAllOperations=true
# 对Http响应码进行重试
ribbon.retryableStatusCodes=500,404,502

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Python程序设计教案

文章目录&#xff1a; 一&#xff1a;软件环境安装 1.软件环境 2.技巧 3.新建工程项目 二&#xff1a;相关 1.规范 2.关键字 3.Ascll码表 三&#xff1a;语法基础 1.各种符号 1.1 注释 1.2 占位置的 1.3 回车换行 2.输入输出 2.1 输入input 2.2 输出print …

parallels desktop19.3最新版本软件新功能详细介绍

Parallels Desktop是一款运行在Mac电脑上的虚拟机软件&#xff0c;它允许用户在Mac系统上同时运行多个操作系统&#xff0c;比如Windows、Linux等。通过这款软件&#xff0c;Mac用户可以轻松地在同一台电脑上体验不同操作系统的功能和应用程序&#xff0c;而无需额外的硬件设备…

CDN、边缘计算与云计算:构建现代网络的核心技术

在数字化时代&#xff0c;数据的快速传输和处理是保持竞争力的关键。内容分发网络&#xff08;CDN&#xff09;、边缘计算和云计算共同构成了现代互联网基础架构的核心&#xff0c;使内容快速、安全地到达用户手中。本文将探讨这三种技术的功能、相互关系以及未来的发展趋势。 …

3节点ubuntu24.04服务器docker-compose方式部署高可用elk+kafka日志系统并接入nginx日志

一&#xff1a;系统版本: 二&#xff1a;部署环境&#xff1a; 节点名称 IP 部署组件及版本 配置文件路径 机器CPU 机器内存 机器存储 Log-001 10.10.100.1 zookeeper:3.4.13 kafka:2.8.1 elasticsearch:7.7.0 logstash:7.7.0 kibana:7.7.0 zookeeper:/data/zookeep…

探索未来的区块链DApp应用,畅享数字世界的无限可能

随着区块链技术的飞速发展&#xff0c;分布式应用&#xff08;DApp&#xff09;正成为数字经济中的一股强劲力量。DApp以其去中心化、透明公正的特点&#xff0c;为用户带来了全新的数字体验&#xff0c;开创了数字经济的新潮流。作为一家专业的区块链DApp应用开发公司&#xf…

全面了解俄罗斯的VK开户和Yandex投放及内容运营

俄罗斯的VKontakte&#xff08;简称VK&#xff09;和Yandex是两个重要的在线平台&#xff0c;对于希望在俄罗斯市场进行推广的企业来说&#xff0c;了解如何在这些平台上开户和投放广告以及内容运营是非常关键的。 俄罗斯vk广告如何开户&#xff1f; 通过上海上弦进行俄罗斯V…

明日方舟游戏助手:一键完成日常任务 | 开源日报 No.233

MaaAssistantArknights/MaaAssistantArknights Stars: 11.6k License: AGPL-3.0 MaaAssistantArknights 是一款《明日方舟》游戏的小助手&#xff0c;基于图像识别技术&#xff0c;支持一键完成全部日常任务。 刷理智、掉落识别及上传企鹅物流智能基建换班、自动计算干员效率…

c++的策略模式,就是多态

一、定义&#xff1a; 策略模式定义了一系列的算法&#xff0c;并将每一个算法封装起来&#xff0c;而且使它们还可以相互替换。 策略模式让算法独立于使用它的客户而独立变化。 二&#xff0c;核心 抽象策略&#xff08;抽象基类&#xff09;&#xff08;Strategy&#xff09…

面试八股——RabbitMQ

消息丢失问题 消息确认机制 生产者与MQ之间的消息确认&#xff1a; 当MQ成功接收消息后&#xff0c;会返回给生产者一个确认消息。如果在规定时间内生产者未收到确认消息&#xff0c;则任务消息发送失败。 MQ与消费者之间的消息确认&#xff1a; 当MQ成功接收消息后&#…

构建安全高效的前端权限控制系统

✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天开心哦&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; ✨✨ 帅哥美女们&#xff0c;我们共同加油&#xff01;一起进步&am…

【C++】优先队列

优先队结构的不同物理结构与常用操作算法 优先队列是一种特殊的队列,队列中的元素具有优先级,每次弹出操作会弹出优先级最高的元素。 优先队列常用的物理结构有: 1. 数组:简单但不高效,插入和删除操作需要移动大量元素,时间复杂度高。 2. 二叉堆:是一种完全二叉树,通常用数…

新技术前沿-2024-大型语言模型LLM的本地化部署

参考快速入门LLM 参考究竟什么是神经网络 1 深度学习 1.1 神经网络和深度学习 神经网络是一种模拟人脑神经元工作方式的机器学习算法,也是深度学习算法的基本构成块。神经网络由多个相互连接的节点(也称为神经元或人工神经元)组成,这些节点被组织成层次结构。通过训练,…

Keil和VSCode协同开发STM32程序

系列文章 STM32单片机系列专栏 C语言术语和结构总结专栏 文章目录 1. 配置环境 2. 测试打开工程 3. 测试编译工程 随着项目的复杂度上升&#xff0c;开发者不仅需要强大的硬件支持&#xff0c;还需要一个高效和灵活的开发环境。 vscode是一款集成大量可以便携开发插件的代码…

Redis入门到通关之Redis数据结构-List篇

文章目录 ☃️概述☃️数据结构☃️源码☃️其他 欢迎来到 请回答1024 的博客 &#x1f353;&#x1f353;&#x1f353;欢迎来到 请回答1024的博客 关于博主&#xff1a; 我是 请回答1024&#xff0c;一个追求数学与计算的边界、时间与空间的平衡&#xff0c;0与1的延伸的后端…

FSRCNN:加速超分辨率卷积神经网络,SRCNN的加速版

paper&#xff1a;https://arxiv.org/pdf/1608.00367 code: https://github.com/yjn870/FSRCNN-pytorch/tree/master 目录 1. 动机 2. 方法 3. 代码对比 4. 实验结果 1. 动机 作者此前提出的SRCNN证明了CNN在图像超分领域的有效性。然而&#xff0c;SRCNN计算效率较低&#…

《Beginning C++20 From Novice to Professional》第五章 Arrays and Loops

循环和数组确实是联系比较紧密的两个基础语法&#xff0c;数组让我们管理大量同类对象&#xff0c;循环可以简单地遍历一个范围内的元素 本章我们可以学到&#xff1a; Arrays 数组开辟一段连续空间存储同类元素&#xff0c;我们通过【】下标来访问某个元素 如果无符号整型占…

javascript(第三篇)原型、原型链、继承问题,使用 es5、es6实现继承,一网打尽所有面试题

没错这是一道【去哪儿】的面试题目&#xff0c;手写一个 es5 的继承&#xff0c;我又没有回答上来&#xff0c;很惭愧&#xff0c;我就只知道 es5 中可以使用原型链实现继承&#xff0c;但是代码一行也写不出来。 关于 js 的继承&#xff0c;是在面试中除了【 this 指针、命名提…

Python网络爬虫-详解XPath匹配网页数据

前言 XPath&#xff0c;全称XML Path Language&#xff0c;即XML路径语言&#xff0c;它是一门在XML文档中查找信息的语言。XPath使用路径表达式来选取XML文档中的节点或节点集。这些节点是通过沿着路径&#xff08;path&#xff09;或者步&#xff08;steps&#xff09;来选取…

Linux下的UDEV机制/守护进程

一. Udev机制概念引入 ( 需要在 etc/udev/rules.d/ 下创建设备的相关规则&#xff0c;不然有可能udev机制生成的设备文件不具备可读可写的权限&#xff0c;adb无法成功通过该设备文件访问设备 ) a. 创建文件夹 sudo vim Xiaomi-audroid.rules b. 添加规则 …

tiktok如何影响用户行为的分析兼论快速数据分析的策略

tiktok如何影响用户行为的分析 快速数据分析的策略流程&#xff1a; 1.确定指标变量&#xff0c;也就确定了数据分析想要回答的问题。想回答不同的问题&#xff0c;就选择不同的指标变量。 变量筛选方法选出指标变量相关的变量&#xff1b; 针对筛选出的变量进行描述性分析和因…