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

SpringCloud(二)负载均衡服务调用Ribbon、服务接口调用OpenFeign案例详解

五、负载均衡服务调用Ribbon

技术版本
Spring Cloud版本Hoxton.SR1
Spring Boot版本2.2.2RELEASE
Cloud Alibaba版本2.1.0.RELEASE

Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。

简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们很容易使用Ribbon实现自定义的负载均衡算法。

官网:https://github.com/Netflix/ribbon/wiki/Getting-Started

5.1 简介

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

  • Ribbon本地负载均衡客户端 VS Nginx服务端负载均衡区别
    Nginx是服务器负载均衡,客户端所有请求都会交给nginx,然后由nginx实现转发请求。即负载均衡是由服务端实现的。

    Ribbon本地负载均衡,在调用微服务接口时候,会在注册中心上获取注册信息服务列表之后缓存到JVM本地,从而在本地实现RPC远程服务调用技术。Ribbon概括起来,就是负载均衡+RestTemplate调用

在这里插入图片描述

Ribbon在工作时分成两步

  • 第一步先选择 EurekaServer ,它优先选择在同一个区域内负载较少的server.

  • 第二步再根据用户指定的策略,在从server取到的服务注册列表中选择一个地址。其中Ribbon提供了多种策略:比如轮询、随机和根据响应时间加权。

在做Eureka集群配置的时候,并没有引入如下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引用

<!--添加eureka-client-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

在这里插入图片描述

  • RestTemplate调用

getForObject方法/getForEntity方法

getForObject方法: 返回对象为响应体中数据转化成的对象,基本上可以理解为Json

getForEntity方法: 返回对象为ResponseEntity对象,包含了响应中的一些重要信息,比如响应头、响应状态码、响应体等

	@GetMapping("/get/{id}")public CommonResult<Payment> getPayment(@PathVariable("id") Long id) {return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);}@GetMapping("/get/entity/{id}")public CommonResult<Payment> getPaymentEntity(@PathVariable("id") Long id) {ResponseEntity<CommonResult> entity = restTemplate.getForEntity(PAYMENT_URL + "/payment/get/" + id, CommonResult.class);if(entity.getStatusCode().is2xxSuccessful()){return entity.getBody();}else {return new CommonResult(444,"操作失败");}}

postForObject/postForEntity

	@GetMapping("/create")public CommonResult<Payment> create(Payment payment) {return restTemplate.postForObject(PAYMENT_URL +"/payment/create",payment,CommonResult.class);}@GetMapping("/entity/create")public CommonResult<Payment> createEntity(Payment payment) {return restTemplate.postForEntity(PAYMENT_URL +"/payment/create",payment,CommonResult.class).getBody();}

5.2 核心组件IRule

5.2.1 IRule实现的负载均衡算法

在这里插入图片描述

  • com.netflix.loadbalancer.RoundRobinRule

    ​ 轮询

  • com.netflix.loadbalancer.RandomRule

    ​ 随机

  • com.netflix.loadbalancer.RetryRule

    ​ 先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行重试,获取可用的服务

  • WeightedResponseTimeRule

    ​ 对RoundRobinRule的扩展,响应速度越快的实例选择权重越大,越容易被选择

  • BestAvailableRule

    ​ 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务

  • AvailabilityFilteringRule

    ​ 先过滤掉故障实例,再选择并发较小的实例

  • ZoneAvoidanceRule

    ​ 默认规则,复合判断server所在区域的性能和server的可用性选择服务器

5.2.2 如何改变负载算法

修改cloud-consumer-order80

@Configuration
public class ApplicationContextConfig {@Bean@LoadBalancedpublic RestTemplate getRestTemplate(){return new RestTemplate();}
}
package com.yyds.myrule;import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MySelfRule {@Beanpublic IRule myRule(){// 随机负载return new RandomRule();}
}
package com.yyds.springcloud;import com.yyds.myrule.MySelfRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;@SpringBootApplication
@EnableEurekaClient
// 添加
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MySelfRule.class)
public class OrderMain80 {public static void main(String[] args) {SpringApplication.run(OrderMain80.class, args);System.out.println("***************OrderMain80启动成功********************");}
}

注意:自定义配置类不能放在@ComponentScan所扫描的当前包下以及子包下,否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,达不到特殊化定制的目的了。

在这里插入图片描述

注意:一些新spring cloud的版本的Eureka starter已经不在集成Ribbon所以新版本不会在使用@RibbonClient(name = "",configuration = "" ) 以及@RibbonClients使用@LoadBalancerClient来进行对@LoadBalanced的配置修改。可以查阅新版本的修改方法。

5.3 负载均衡算法

5.3.1 原理

负载均衡算法:rest接口第几次请求数 % 服务器集群总数量 = 实际调用服务器位置下标  ,每次服务重启动后rest接口计数从1开始。List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");如:   List [0] instances = 127.0.0.1:8002List [1] instances = 127.0.0.1:80018001 + 8002 组合成为集群,它们共计2台机器,集群总数为2, 按照轮询算法原理:当总请求数为1时: 1 % 2 =1 对应下标位置为1 ,则获得服务地址为127.0.0.1:8001
当总请求数位2时: 2 % 2 =0 对应下标位置为0 ,则获得服务地址为127.0.0.1:8002
当总请求数位3时: 3 % 2 =1 对应下标位置为1 ,则获得服务地址为127.0.0.1:8001
如此类推......

5.3.2 手动实现

  • 支付服务提供者8001和8002接口添加
	@GetMapping(value = "/lb")public String getPaymentLB() {return serverPort;}
  • 在订单服务消费者80中

自定义LoadBalancer接口

package com.yyds.springcloud.myloadbalancer;import org.springframework.cloud.client.ServiceInstance;import java.util.List;public interface LoadBalancer {ServiceInstance instances(List<ServiceInstance> serviceInstances);
}

自定义LoadBalancer实现类

package com.yyds.springcloud.myloadbalancer;import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.stereotype.Component;import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;@Component
@Slf4j
public class MyLoadBalancer implements LoadBalancer {private AtomicInteger atomicInteger = new AtomicInteger(0);public  final int getAndIncrement(){int current;int next;do{current = this.atomicInteger.get();next = current >= 2147483647 ? 0 : current + 1;}while (!this.atomicInteger.compareAndSet(current,next));log.info("--------------next="+ next);return next;}@Overridepublic ServiceInstance instances(List<ServiceInstance> serviceInstances) {int index = getAndIncrement() % serviceInstances.size();return serviceInstances.get(index);}
}

ApplicationContextBean去掉注解@LoadBalanced(注意,此时原来接口报异常)

@Configuration
public class ApplicationContextConfig {@Bean// @LoadBalancedpublic RestTemplate getRestTemplate(){return new RestTemplate();}
}

Controller中添加接口,使用自定义负载均衡策略

	//可以获取注册中心上的服务列表@Resourceprivate DiscoveryClient discoveryClient;@Resourceprivate LoadBalancer loadBalancer;@GetMapping("/lb")public String getPaymentLB() {List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");if (instances == null || instances.size() <= 0) {return null;}ServiceInstance serviceInstance = loadBalancer.instances(instances);URI uri = serviceInstance.getUri();return restTemplate.getForObject(uri + "/payment/lb", String.class);}

测试 http://localhost/consumer/payment/lb

在这里插入图片描述

5.3.3 RoundRobinRule源码

package com.netflix.loadbalancer;import com.netflix.client.config.IClientConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;/*** The most well known and basic load balancing strategy, i.e. Round Robin Rule.** @author stonse* @author Nikos Michalakis <nikos@netflix.com>**/
public class RoundRobinRule extends AbstractLoadBalancerRule {private AtomicInteger nextServerCyclicCounter;private static final boolean AVAILABLE_ONLY_SERVERS = true;private static final boolean ALL_SERVERS = false;private static Logger log = LoggerFactory.getLogger(RoundRobinRule.class);public RoundRobinRule() {nextServerCyclicCounter = new AtomicInteger(0);}public RoundRobinRule(ILoadBalancer lb) {this();setLoadBalancer(lb);}public Server choose(ILoadBalancer lb, Object key) {if (lb == null) {log.warn("no load balancer");return null;}Server server = null;int count = 0;while (server == null && count++ < 10) {List<Server> reachableServers = lb.getReachableServers();List<Server> allServers = lb.getAllServers();int upCount = reachableServers.size();int serverCount = allServers.size();if ((upCount == 0) || (serverCount == 0)) {log.warn("No up servers available from load balancer: " + lb);return null;}// 利用下标,从服务提供者中选取服务提供者int nextServerIndex = incrementAndGetModulo(serverCount);server = allServers.get(nextServerIndex);if (server == null) {/* Transient. */Thread.yield();continue;}if (server.isAlive() && (server.isReadyToServe())) {return (server);}// Next.server = null;}if (count >= 10) {log.warn("No available alive servers after 10 tries from load balancer: "+ lb);}return server;}/*** Inspired by the implementation of {@link AtomicInteger#incrementAndGet()}.** @param modulo The modulo to bound the value of the counter.* @return The next value.*/private int incrementAndGetModulo(int modulo) {// 使用AtomicInteger的CASfor (;;) {int current = nextServerCyclicCounter.get();int next = (current + 1) % modulo;if (nextServerCyclicCounter.compareAndSet(current, next))return next;}}@Overridepublic Server choose(Object key) {return choose(getLoadBalancer(), key);}@Overridepublic void initWithNiwsConfig(IClientConfig clientConfig) {}
}

六、服务接口调用OpenFeign

6.1 简介

  • Feign能干什么

Feign旨在使编写Java Http客户端变得更容易。
前面在使用Ribbon+RestTemplate时,利用RestTemplate对http请求的封装处理,形成了一套模版化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。所以,Feign在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义。在Feign的实现下,我们只需创建一个接口并使用注解的方式来配置它,即可完成对服务提供方的接口绑定,简化了使用Spring cloud Ribbon时,自动封装服务调用客户端的开发量。

  • Feign集成了Ribbon

利用Ribbon维护了Payment的服务列表信息,并且通过轮询实现了客户端的负载均衡。而与Ribbon不同的是,通过feign只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用

  • Feign和OpenFeign

​ Feign是Spring Cloud组件中的一个轻量级RESTful的HTTP服务客户端Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。Feign的使用方式是:使用Feign的注解定义接口,调用这个接口,就可以调用服务注册中心的服务

​ OpenFeign是Spring Cloud 在Feign的基础上支持了SpringMVC的注解,如@RequesMapping等等。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。

6.2 OpenFeign使用案例

新建cloud-consumer-feign-order80

6.2.1 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>springcloud</artifactId><groupId>com.yyds</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>cloud-consumer-feign-order80</artifactId><dependencies><!--openfeign--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!--添加eureka-client--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!--引入自己定义的api通用包--><dependency><groupId>com.yyds</groupId><artifactId>cloud-api-commons</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies></project>

6.2.2 yml配置

server:port: 80spring:application:name: cloud-order-feign-service# 添加下面配置信息
eureka:client:service-url:defaultZone: http://localhost:7001/eureka
#      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka  # 集群版本register-with-eureka: true # 是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡fetch-registry: true

6.2.3 主启动类

package com.yyds.springcloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients // 添加此注解
public class OpenFeignOrderMain80 {public static void main(String[] args) {SpringApplication.run(OpenFeignOrderMain80.class, args);System.out.println("***************OpenFeignOrderMain80启动成功********************");}
}

6.2.4 业务类

业务逻辑接口+@FeignClient配置调用provider服务

package com.yyds.springcloud.service;import com.yyds.springcloud.entities.CommonResult;
import com.yyds.springcloud.entities.Payment;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")
public interface PaymentFeignService {@GetMapping("/payment/get/{id}")CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) ;
}
package com.yyds.springcloud.controller;import com.yyds.springcloud.entities.CommonResult;
import com.yyds.springcloud.entities.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.yyds.springcloud.service.PaymentFeignService;import javax.annotation.Resource;@RestController
@RequestMapping("/consumer/payment")
@Slf4j
public class OrderController {@Resourceprivate PaymentFeignService service;@GetMapping("/get/{id}")public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {return service.getPaymentById(id);}}

6.2.5 测试

http://localhost/consumer/payment/get/1{"code":200,"message":"查询成功,serverPort+8002","data":{"id":1,"serial":"00001a"}}

6.3 更多用法

6.3.1 超时功能

默认Feign客户端只等待一秒钟,但是服务端处理需要超过1秒钟,导致Feign客户端不想等待了,直接返回报错。为了避免这样的情况,有时候我们需要设置Feign客户端的超时控制。

#设置feign客户端超时时间(OpenFeign默认支持ribbon)
ribbon:#指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间ReadTimeout: 5000#指的是建立连接后从服务器读取到可用资源所用的时间ConnectTimeout: 5000

6.3.2 日志打印功能

Feign 提供了日志打印功能,我们可以通过配置来调整日志级别,从而了解 Feign 中 Http 请求的细节。

日志的级别如下:NONE:默认的,不显示任何日志;BASIC:仅记录请求方法、URL、响应状态码及执行时间;HEADERS:除了 BASIC 中定义的信息之外,还有请求和响应的头信息;FULL:除了 HEADERS 中定义的信息之外,还有请求和响应的正文及元数据。

配置日志Bean

package com.yyds.springcloud.config;import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class FeignConfig {@BeanLogger.Level feignLoggerLevel() {return Logger.Level.FULL;}
}

Yml文件

logging:level:# feign日志以什么级别监控哪个接口com.yyds.springcloud.service.PaymentFeignService: debug

在这里插入图片描述

相关文章:

SpringCloud(二)负载均衡服务调用Ribbon、服务接口调用OpenFeign案例详解

五、负载均衡服务调用Ribbon 技术版本Spring Cloud版本Hoxton.SR1Spring Boot版本2.2.2RELEASECloud Alibaba版本2.1.0.RELEASE Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。 简单的说&#xff0c;Ribbon是Netflix发布的开源项目&#xff0c;主…...

大数据第一轮复习笔记(2)

Spark ./spark-submit --class com.kgc.myspark01.WordCount --master yarn --deploy-mode cluster /opt/myspark01-1.0-SNAPSHOT.jar 1.Client向YARN的ResourceManager申请启动Application Master。Client中创建SparkContext同时初始化中将创建DAGScheduler和TASKScheduler…...

3|射频识别技术|期末考试知识点|第3讲_RFID射频前端|重点题目

...

LeetCode 2108. 找出数组中的第一个回文字符串

给你一个字符串数组 words &#xff0c;找出并返回数组中的 第一个回文字符串 。如果不存在满足要求的字符串&#xff0c;返回一个 空字符串 “” 。 回文字符串 的定义为&#xff1a;如果一个字符串正着读和反着读一样&#xff0c;那么该字符串就是一个 回文字符串 。 示例 …...

第63章 SQL 快速参考教程

第63章 SQL 快速参考教程 SQL 语句语法AND / ORSELECT column_name(s) FROM table_name WHERE condition AND|OR conditionALTER TABLEALTER TABLE table_name ADD column_name datatypeor ALTER TABLE table_name DROP COLUMN column_name AS (alias)SELECT column_name AS …...

机器学习笔记

一 1.类型 有监督&#xff1a;分类、回归 无监督&#xff1a;聚类、降维 2.挑战&#xff1a; 过拟合&#xff1a;泛化能力弱 欠拟合&#xff1a;模型过于简单 二、 1.开发流程 数据收集->数据清洗->特征工程->数据建模 2.选择性能指标&#xff1a; 回归问题 均方根…...

L1-072 刮刮彩票

“刮刮彩票”是一款网络游戏里面的一个小游戏。如图所示&#xff1a; 每次游戏玩家会拿到一张彩票&#xff0c;上面会有 9 个数字&#xff0c;分别为数字 1 到数字 9&#xff0c;数字各不重复&#xff0c;并以 33 的“九宫格”形式排布在彩票上。 在游戏开始时能看见一个位置上…...

互联网摸鱼日报(2023-02-18)

互联网摸鱼日报&#xff08;2023-02-18&#xff09; InfoQ 热门话题 从用云焦虑到“深度云化”&#xff0c;新云原生时代带给我们哪些思考&#xff1f; 数据治理之需求层次 GitHub 更新 Copilot 以阻止不安全代码&#xff0c;并称其支持了超 60% 的 Java 开发者 数据库隔离…...

Spring 中经典的 9 种设计模式

1.简单工厂(非23种设计模式中的一种) 2.工厂方法 3.单例模式 4.适配器模式 5.装饰器模式 6.代理模式 7.观察者模式 8.策略模式 9.模版方法模式 Spring中涉及的设计模式总结 1.简单工厂(非23种设计模式中的一种) 实现方式&#xff1a; BeanFactory。Spring中的BeanFa…...

CentOS7突然没法上网【Network 中wired 图标消失】

参考文章(七种办法)&#xff1a;CentOS 7 右上角网络连接图标消失,设置网络有线消失解决办法 正常图标消失&#xff0c;先在 终端命令 依次执行以下命令 service NetworkManager stop service network restart service NetworkManager start 一、问题真烦 CentOS7图形化界面安装…...

SpringBoot3集成TDengine自适应裂变存储

前言 首先很遗憾的告诉大家&#xff0c;今天这篇分享要关注才可以看了。原因是穷啊&#xff0c;现在基本都是要人民币玩家了&#xff0c;就比如chatGPT、copilot&#xff0c;这些AI虽然都是可以很好的辅助编码&#xff0c;但是都是要钱。入驻CSDN有些年头了&#xff0c;中间有几…...

golang alpine 配置gstreamer开发环境

启动容器 sudo docker run -it --name golang -v $PWD:/home/leon -d golang:1.18-alpine3.17tar zxvf x86_64-linux-musl-cross.tgz mv x86_64-linux-musl-cross /usr/local/musl export PATH$PATH:/usr/local/musl/bin/:/usr/local/musl/x86_64-linux-musl/bin 下载gstre…...

SAP ABAP GUI_DOWNLOAD中下载乱码的问题

1 GUI_DOWNLOAD 1.1 问题表现 GUI_DOWNLOAD在应用当中有时会导致输出的文件在某些电脑正常显示&#xff0c;在某些电脑乱码显示。这个固然是由于各个电脑系统配置有差异&#xff0c;但是我们可以在应用该函数时就排除该差异来保证任意台电脑正常显示输出的文件。 如下…...

接口和抽象类

接口(Interface)和抽象类(Abstract Class)是支持抽象类定义的两种机制。 1.抽象类 (1)说明 在Java中被abstract关键字修饰的类称为抽象类&#xff0c;被abstract关键字修饰的方法称为抽象方法&#xff0c;抽象方法只有方法的声明&#xff0c;没有方法体。抽象类是用来捕捉子…...

ES7新特性

1. ES7 新特性 1.1. Array.prototype.includes includes 方法用来检测是否包含某个数组&#xff0c;返回布尔类型值 其他检测包含字符串的方法&#xff1a; indexOf&#xff08;&#xff09;&#xff0c;返回的是下标值&#xff0c;如果没有则返回-1 1.2 指数操作符 指数…...

【软件测试】资深测试总结的几个自动化测试点,提升跨越一大步......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 自动化的软件测试与…...

GEE:时间序列分析1——认识arraySlice()

本文是记录时间序列分析系列教程的开篇之作,教程由浅入深介绍在GEE平台上进行时间序列分析的方法和代码。本教程会从操作时间序列的基本函数开始讲解,到后续更新会加入一些成熟的时间序列分析方法。随着本教程文章数量增加到一定数量,本专栏会适当涨价。欢迎乐多们订阅。 文…...

【react实战小项目:笔记】用React 16写了个订单页面

视频地址 React 16 实现订单列表及评价功能 简介&#xff1a;React 以其组件化的思想在前端领域大放异彩&#xff0c;但其革命化的前端开发理念对很多 React 初学者来说&#xff0c; 却很难真正理解和应用到真实项目中。本课程面向掌握了 React 基础知识但缺乏实战经验的开发…...

30岁+的人如何进行自我提升和职场规划

今天非常忙一天开了N个会&#xff0c;一堆头疼的事情要解决&#xff0c;一晃就加班到现在&#xff0c;刚打到了的士开始想今天分享点什么。 实在不知道写什么了&#xff0c;突然想起下午部门茶话会小伙伴问的问题&#xff1a;“30岁的人如何进行自我提升和职场规划”。 这是个…...

创建基于Vue2.0开发项目的两种方式

前天开始接触基于Vue2.0的前端项目&#xff0c;实际操作中肯定会遇到一些问题&#xff0c;慢慢摸索和总结。   其实&#xff0c;作为开发一般企事业单位应用的小项目&#xff0c;前端的懂一点HTMLCSSJavaScroptJQueryJson&#xff08;或者Xml&#xff09;&#xff0c;后端懂一…...

[测试]性能测试

最近遇到一个性能测试的问题&#xff0c;虽然最后确定是一个乌龙问题。这里还是总结一下&#xff0c;看是否有可以从中学到什么。 场景&#xff1a; 月底要出一个新版本。测试人员发现这个新版本在相同的负载的情况下&#xff0c;会有队列使用负荷过高的警告。之前的版本没有。…...

剑指 Offer 21. 调整数组顺序使奇数位于偶数前面

摘要 剑指 Offer 21. 调整数组顺序使奇数位于偶数前面 一、双指针解析 考虑定义双指针 i , j分列数组左右两端&#xff0c;循环执行&#xff1a; 指针 i从左向右寻找偶数&#xff1b;指针 j从右向左寻找奇数&#xff1b;将偶数nums[i]和奇数 nums[j]交换。 可始终保证&…...

实用版ChatBing论文阅读助手教程+新测评

实用版ChatBing论文阅读助手新测评 AI进化&#xff08;更新&#xff09;的速度太快了&#xff01;距离我上次的【Chat嘴硬&#xff01;基于NewBing的论文调研评测报告】&#xff0c;才四天&#xff0c;它已经进化到快能用的地步了&#xff01; 这次是我刷B站看到热门推荐&…...

Linux生产者消费模型

1.生产者消费者模型 1.1 为何要使用生产者消费者模型 生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯&#xff0c;而通过阻塞队列来进行通讯&#xff0c;所以生产者生产完数据之后不用等待消费者处理&#xff0c;直接…...

动态网站开发讲课笔记01:网页开发基础

文章目录零、本讲学习目标一、HTML基础&#xff08;一&#xff09;HTML简介1、HTML2、HTML语言的基本格式3、<!DOCTYPE>声明4、html标签5、head标签6、body标签7、编写第一个网页8、关于编写HTML文件的工具9、HTML标签概述&#xff08;1&#xff09;单标签&#xff08;2&…...

互联网新时代要到来了(三)什么是ChatGPT?

什么是ChatGPT? tips&#xff1a;资料来自百度百科、openAi、CSDN博主「琦在江湖飘」、Info写作社区、CSDN博主「夕小瑶」等网页资料。 1.什么是ChatGPT&#xff1f; ChatGPT&#xff08;全名&#xff1a;Chat Generative Pre-trained Transformer&#xff09;&#xff0c;…...

华为OD机试 - 环中最长子串(Python)

环中最长子串 题目 给你一个字符串s,首尾相连成一个环形, 请你在环中找出o字符出现了偶数次最长子字符串的长度. 备注: 1 <= s.lenth <= 5x10^5 s只包含小写英文字母 输入 输入是一个小写字母组成的字符串 输出描述 输出是一个整数 示例一 输入 alolobo输出 6说…...

安全—08day

ApabilitiesapabilitiesLinux Capabilities线程的 capabilitiesPermitted 允许Effective 有效InheritableBoundingAmbient文件的 capabilitiesPermittedInheritableEffective运行 execve() 后 capabilities 的变化案例分析方法一、依次执行如下命令方法二、iptables端口转发方案…...

【看表情包学Linux】进程地址空间 | 区域和页表 | 虚拟地址空间 | 初识写时拷贝

&#x1f923; 爆笑教程 &#x1f449; 《看表情包学Linux》&#x1f448; 猛戳订阅 &#x1f525; &#x1f4ad; 写在前面&#xff1a;本章核心主题为 "进程地址空间"&#xff0c;会通过验证 Linux 进程的地址空间来开头&#xff0c;抛出 "同一个值能有不同内…...

响应式编程(Reactive Programming)介绍

什么是响应式编程? 在互联网上有着一大堆糟糕的解释与定义。Wikipedia 一如既往的空泛与理论化。Stackoverflow 的权威答案明显不适合初学者。Reactive Manifesto 看起来是你展示给你公司的项目经理或者老板们看的东西。微软的 Rx terminology"Rx Observables LINQ S…...

网站如何做sem优化/百度网盘seo优化

概述&#xff08;TCP/IP协议是一个协议族&#xff09;&#xff1a; TCP/IP 协议按照四层怎么划分&#xff1a;链路层&#xff0c;网络层&#xff0c;传输层&#xff0c;应用层&#xff08;实际上是四层&#xff09; TCP/IP 协议按照七层怎么划分&#xff1a;物理层&#xff0c;…...

天睦和生态建设有限公司网站/推广平台免费b2b网站大全

搜索热词本文实例为大家分享了PHP实现统计代码行数小工具&#xff0c;供大家参考&#xff0c;具体内容如下为了方面统计编程代码行数&#xff0c;做了一个小工具。自动统计指定目录以及目录下的所有文件。class TotalCode {/*** 统计当前文件有多少行代码&#xff0c;* return …...

怎么做qq代刷网站/seo体系

第一题 请仔细阅读右侧代码&#xff0c;根据方法内的提示&#xff0c;在Begin - End区域内进行代码补充&#xff0c;具体任务如下&#xff1a; 使用继承Thread类的方式创建一个名为 ThreadClassOne 的类&#xff0c;重写的run方法需要实现输出0-10之间的奇数&#xff0c;输出结…...

东莞网站优化方案/百度纯净版首页入口

概述 Spot Light&#xff08;聚光源&#xff09; 从锥形空间中的一个单独的点处发出光照。它为用户提供了两个锥体来塑造光源- 内锥角 和 外锥角 。在 内锥角 中&#xff0c;光源达到最大亮度&#xff0c;形成一个亮盘。在而从内锥角到外锥角&#xff0c;光照会发生衰减&#x…...

物联网平台开源/搜索引擎优化的办法有哪些

今天在搜索mos文档&#xff0c;看到一个名词“On-Premise”&#xff0c;于是就baidu了一下&#xff0c;确实有这个名词。如下摘自&#xff1a;http://bbs.tianya.cn/post-itinfo-350014-1.shtml了解云计算的一定都听过四个“高大上”的概念&#xff1a;On-Premise(本地部署)&am…...

wordpress 加载中动画/百度查询入口

查询处理指从数据库中提取数据时涉及的一系列活动&#xff0c; 将用高层数据库语言表示的查询语句翻译为能在文件系统的物理层上使用的表达式 为优化查询而进行各种转换 查询实际执行概述 SQL查询语句&#xff0d;&#xff1e;关系代数表达式&#xff0f;语法分析树&#xff0d…...