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实现的一套客户端负载均衡的工具。 简单的说,Ribbon是Netflix发布的开源项目,主…...

大数据第一轮复习笔记(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…...
LeetCode 2108. 找出数组中的第一个回文字符串
给你一个字符串数组 words ,找出并返回数组中的 第一个回文字符串 。如果不存在满足要求的字符串,返回一个 空字符串 “” 。 回文字符串 的定义为:如果一个字符串正着读和反着读一样,那么该字符串就是一个 回文字符串 。 示例 …...
第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.类型 有监督:分类、回归 无监督:聚类、降维 2.挑战: 过拟合:泛化能力弱 欠拟合:模型过于简单 二、 1.开发流程 数据收集->数据清洗->特征工程->数据建模 2.选择性能指标: 回归问题 均方根…...

L1-072 刮刮彩票
“刮刮彩票”是一款网络游戏里面的一个小游戏。如图所示: 每次游戏玩家会拿到一张彩票,上面会有 9 个数字,分别为数字 1 到数字 9,数字各不重复,并以 33 的“九宫格”形式排布在彩票上。 在游戏开始时能看见一个位置上…...
互联网摸鱼日报(2023-02-18)
互联网摸鱼日报(2023-02-18) InfoQ 热门话题 从用云焦虑到“深度云化”,新云原生时代带给我们哪些思考? 数据治理之需求层次 GitHub 更新 Copilot 以阻止不安全代码,并称其支持了超 60% 的 Java 开发者 数据库隔离…...

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

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

SpringBoot3集成TDengine自适应裂变存储
前言 首先很遗憾的告诉大家,今天这篇分享要关注才可以看了。原因是穷啊,现在基本都是要人民币玩家了,就比如chatGPT、copilot,这些AI虽然都是可以很好的辅助编码,但是都是要钱。入驻CSDN有些年头了,中间有几…...
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在应用当中有时会导致输出的文件在某些电脑正常显示,在某些电脑乱码显示。这个固然是由于各个电脑系统配置有差异,但是我们可以在应用该函数时就排除该差异来保证任意台电脑正常显示输出的文件。 如下…...

接口和抽象类
接口(Interface)和抽象类(Abstract Class)是支持抽象类定义的两种机制。 1.抽象类 (1)说明 在Java中被abstract关键字修饰的类称为抽象类,被abstract关键字修饰的方法称为抽象方法,抽象方法只有方法的声明,没有方法体。抽象类是用来捕捉子…...
ES7新特性
1. ES7 新特性 1.1. Array.prototype.includes includes 方法用来检测是否包含某个数组,返回布尔类型值 其他检测包含字符串的方法: indexOf(),返回的是下标值,如果没有则返回-1 1.2 指数操作符 指数…...

【软件测试】资深测试总结的几个自动化测试点,提升跨越一大步......
目录:导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜)前言 自动化的软件测试与…...
GEE:时间序列分析1——认识arraySlice()
本文是记录时间序列分析系列教程的开篇之作,教程由浅入深介绍在GEE平台上进行时间序列分析的方法和代码。本教程会从操作时间序列的基本函数开始讲解,到后续更新会加入一些成熟的时间序列分析方法。随着本教程文章数量增加到一定数量,本专栏会适当涨价。欢迎乐多们订阅。 文…...

【react实战小项目:笔记】用React 16写了个订单页面
视频地址 React 16 实现订单列表及评价功能 简介:React 以其组件化的思想在前端领域大放异彩,但其革命化的前端开发理念对很多 React 初学者来说, 却很难真正理解和应用到真实项目中。本课程面向掌握了 React 基础知识但缺乏实战经验的开发…...
30岁+的人如何进行自我提升和职场规划
今天非常忙一天开了N个会,一堆头疼的事情要解决,一晃就加班到现在,刚打到了的士开始想今天分享点什么。 实在不知道写什么了,突然想起下午部门茶话会小伙伴问的问题:“30岁的人如何进行自我提升和职场规划”。 这是个…...

创建基于Vue2.0开发项目的两种方式
前天开始接触基于Vue2.0的前端项目,实际操作中肯定会遇到一些问题,慢慢摸索和总结。 其实,作为开发一般企事业单位应用的小项目,前端的懂一点HTMLCSSJavaScroptJQueryJson(或者Xml),后端懂一…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...
OD 算法题 B卷【正整数到Excel编号之间的转换】
文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的:a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...

若依项目部署--传统架构--未完待续
若依项目介绍 项目源码获取 #Git工具下载 dnf -y install git #若依项目获取 git clone https://gitee.com/y_project/RuoYi-Vue.git项目背景 随着企业信息化需求的增加,传统开发模式存在效率低,重复劳动多等问题。若依项目通过整合主流技术框架&…...
Vuex:Vue.js 应用程序的状态管理模式
什么是Vuex? Vuex 是专门为 Vue.js 应用程序开发的状态管理模式 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。 在大型单页应用中,当多个组件共享状态时,简单的单向数据流…...
CMake系统学习笔记
CMake系统学习笔记 基础操作 最基本的案例 // code #include <iostream>int main() {std::cout << "hello world " << std::endl;return 0; }// CMakeLists.txt cmake_minimum_required(VERSION 3.0)# 定义当前工程名称 project(demo)add_execu…...