(五)SpringCloud-Ribbon负载均衡

2023-11-03

目录

1、Spring Cloud Ribbon简介

Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。它有助于控制Http和Tcp客户端的行为。通过SpringCloud的封装,可以让我们轻松的将面向服务的REST模板请求自动转换成客户端负载均衡的服务调用

官网参考地址:
官网:https://www.springcloud.cc/spring-cloud-greenwich.html#spring-cloud-ribbon

中文:http://docs.springcloud.cn/user-guide/ribbon/


2、Ribbon提供了七种负载均衡策略

名称 解释
RoundRobinRule 轮训策略
RandomRule 随机策略
BestAvailableRule 过滤出故障服务器后,选择一个并发量最小的
WeightedResponseTimeRule 针对响应时间加权轮询
AvailabilityFilteringRule 可用过滤策略,先过滤出故障的或并发请求大于阈值的一部分服务实例,然后再以线性轮询的方式从过滤后的实例清单中选出一个
ZoneAvoidanceRule 从最佳区域实例集合中选择一个最优性能的服务实例
RetryRule 选择一个Server,如果失败,重新选择一个Server重试

3、微服务架构下如何使用Ribbon

3.1 使用Eureka作为注册中心时使用Ribbon

3.1.1 引入ribbon依赖

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

3.1.2 往容器中注入RestTemplate

使用@LoadBalanced注解赋予RestTemplate负载均衡的能力

@Bean
@LoadBalanced
public RestTemplate createRestTemplate(){
    return new RestTemplate();
}

3.1.3 配置RibbonClient

例如:注入负载均衡规则,默认是轮询,更多配置以及配置实现类参见本文档的 Ribbon的相关配置

@Configuration
public class MyRibbonRuleConfig {
	// 为指定轮询规则为随机
    @Bean
    public IRule myRule(){
        return new RandomRule();
    }
}

注:这个配置类MyRibbonRuleConfig 必须使用@Configuration注解标识,并且每一个配置都要用@Bean注解

如果我们将这个配置类放在@ComponentScan注解的扫描包下,则会对所有的@RibbonClients客户端生效,但是有时候,我们想要针对不同的客户端,使用不同的配置(例如不同的负载均衡规则),就需要排除该配置类,可以通过@ComponentScan@SpringBootApplication限定扫包范围(@ComponentScan配置排除:@ComponentScan(excludeFilters = { @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = MyRibbonRuleConfig.class)}))或者将这个类不与启动类放在同一个包下。

3.1.4 为服务指定ribbon配置

// 启动类为某个服务指定负载均衡规则
@SpringBootApplication
@EnableEurekaClient
// 修改针对PROVIDER-PAYMENT-8001-3服务的轮训规则,多个不同的服务使用不同的规则,则在@RibbonClients中配置多个@RibbonClient
@RibbonClients(value = {@RibbonClient(name="PROVIDER-PAYMENT-8001-3",configuration = MyRibbonRuleConfig.class)})
public class EurekaOrder80Start {
    public static void main(String[] args) {
        SpringApplication.run(EurekaOrder80Start.class,args);
    }
}

3.1.5 使用RestTemplate调用服务

 // 通过在eureka上注册过的微服务名称调用
public static final String PAYMENT_SRV = "http://PROVIDER-PAYMENT-8001-3/study";

@Resource
private RestTemplate restTemplate;

// 127.0.0.1/study/consumer/payment/create?serial=xiaohong
@GetMapping("/consumer/payment/create")
public CommonResult create(Payment payment)
{
    return restTemplate.postForObject(PAYMENT_SRV + "/provider/payment/insertPayment",payment,CommonResult.class);
}

3.1.6 Demo示例

gitee地址中的cloud-eureka-consumer-order80和cloud-eureka-provider-payment8001-3模块


3.2 在没有Eureka的情况下使用Ribbon

官网教程:
在这里插入图片描述


3.2.1 调用方式一:使用Ribbon的Api

这地方需要注意的是loadBalancer.choose()方法返回的已经是服务的真实地址了。调用的时候需要使用不带负载均衡的RestTemplate去调用。

@Autowired
private LoadBalancerClient loadBalancer;

// 没有负载均衡的restTemplate,如果这里也使用负载均衡的restTemplate,那么在调用getForObject的时候,则会将uri中的域名地址作为服务名称,再去查询对应的IP地址。
// 这当然就会找不到啦,因为loadBalancer.choose()返回的已经是服务真实的ip地址了
@Resource(name = "restTemplate")
private RestTemplate restTemplate;

// 127.0.0.1/study/consumer/payment/get2/1
@GetMapping("/consumer/payment/get2/{id}")
public CommonResult getPayment2(@PathVariable Long id) {
    ServiceInstance instance = loadBalancer.choose("PROVIDER-PAYMENT-8001-3");
    URI uri = UriComponentsBuilder.fromUriString(String.format("http://%s:%s/study/provider/payment/get/{id}", instance.getHost(), instance.getPort()))
            .build()
            .expand(id) // 替换url中的模板参数
            .encode(StandardCharsets.UTF_8) // 设置编码
            .toUri();
   return restTemplate.getForObject(uri,CommonResult.class);
}

3.2.2 调用方式二:使用带负载均衡的RestTemplate

// 通过在eureka上注册过的微服务名称调用
public static final String PAYMENT_SRV = "http://PROVIDER-PAYMENT-8001-3/study";

// 带有负载均衡的RestTemplate
@Resource(name = "restTemplateLoadBalanced")
private RestTemplate restTemplateLoadBalanced;

// 127.0.0.1/study/consumer/payment/get/1
@GetMapping("/consumer/payment/get/{id}")
public CommonResult getPayment(@PathVariable Long id)
{
    return restTemplateLoadBalanced.getForObject(PAYMENT_SRV + "/provider/payment/get/"+id, CommonResult.class, id);
}

3.2.3 通过listOfServers配置的服务器列表

禁用 Eureka 后(ribbon.eureka.enabled=false,也可以不引入Eureka的包)手动配置PROVIDER-PAYMENT-8001-3服务的地址

# 通过配置的方式为PROVIDER-PAYMENT-8001-3服务配置负载均衡的规则
PROVIDER-PAYMENT-8001-3:
  ribbon:
    listOfServers: localhost:8001,localhost:8002

3.2.4 完整demo

gitee地址中的cloud-ribbon-consumer-order80模块


4、如何使用RestTemplate

4.1 GET请求

4.1.1 getForObject

getForObject有以下3种重载方法

  • public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables)
    该方法提供了三个参数,其中url为请求的地址,responseType为请求响应体body的包装类型,urlVariables为url中的参数绑定

  • public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables)
    该方法与上面的相似,只是用map来封装参数。

  • public <T> T getForObject(URI url, Class<T> responseType)
    使用统一资源标识符来封装请求地址和参数

/**
 * 对于getForObject的三种重载方法调用demo
 * 127.0.0.1/study/restTemplateTestOrder/payment/getObject_1/1
 * @param id
 * @return
 */
@GetMapping("/restTemplateTestOrder/payment/getObject_1/{id}")
public CommonResult getPayment(@PathVariable Long id)
{
	CommonResult commonResult = new CommonResult();
	Map<String,CommonResult> resultMap = new HashMap<>();
	// getForObject(String url, Class<T> responseType, Object... uriVariables)
	CommonResult result1 = restTemplate.getForObject(PAYMENT_SRV + "/restTemplateTestPayment/payment/get_1/" + id, CommonResult.class, id);
	CommonResult result2 = restTemplate.getForObject(PAYMENT_SRV + "/restTemplateTestPayment/payment/{1}/{2}", CommonResult.class, "get_1",id);

	CommonResult result3 = restTemplate.getForObject(PAYMENT_SRV + "/restTemplateTestPayment/payment/get_2?id=" + id, CommonResult.class, id);
	CommonResult result4 = restTemplate.getForObject(PAYMENT_SRV + "/restTemplateTestPayment/payment/get_2?id={1}&serial={2}", CommonResult.class, id,"小明");
	resultMap.put("result1",result1);
	resultMap.put("result2",result2);
	resultMap.put("result3",result3);
	resultMap.put("result4",result4);

	// getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables)
	Map<String, Object> param = new HashMap<>();
	param.put("id",id);
	param.put("get_1","get_1");
	param.put("serial","小王");
	CommonResult result5 = restTemplate.getForObject(PAYMENT_SRV + "/restTemplateTestPayment/payment/{get_1}/{id}", CommonResult.class, param);
	CommonResult result6 = restTemplate.getForObject(PAYMENT_SRV + "/restTemplateTestPayment/payment/get_2?id={id}&serial={serial}", CommonResult.class, param);
	resultMap.put("result5",result5);
	resultMap.put("result6",result6);

	// getForObject(URI url, Class<T> responseType)
	MultiValueMap<String,String> mapParam = new LinkedMultiValueMap();
	mapParam.add("serial","小王1");
	mapParam.add("serial","小王2");
	URI uri = UriComponentsBuilder.fromUriString(PAYMENT_SRV + "/restTemplateTestPayment/payment/get_2?id={id}")
			.queryParams(mapParam) // 设置查询参数
			.build()
			.expand(id) // 替换url中的模板参数
			.encode(StandardCharsets.UTF_8) // 设置编码
			.toUri();
	CommonResult result7 = restTemplate.getForObject(uri, CommonResult.class);
	resultMap.put("result7",result7);

	commonResult.setData(resultMap);
	return commonResult;
}

4.1.2 getForEntity

  • public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables)
  • public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables)
  • public <T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType)

这3个方法和4.1.1中的3个方法对应。只是返回的是ResponseEntity
可通过responseEntity获取响应头,响应状态,响应体等信息。
// 状态信息
HttpStatus statusCode = responseEntity.getStatusCode();
int statusCodeValue = responseEntity.getStatusCodeValue();

// 请求头信息
HttpHeaders headers = responseEntity.getHeaders();

// 响应体
T body = responseEntity.getBody();

4.2 POST请求(使用demo参考4.1的Get请求)

关于post请求中第二个参数Object request说明:
在这里插入图片描述
从源码可以看到,如果我们传入的是一个非HttpEntity,则封装为一个HttpEntity。我们在实际调用过程中,可以使用传递一个Object类型的参数,这个参数会被放在请求体body中,这就和前端发送post请求一样。我们就可以调用服务提供者方的post接口。

4.2.1 postForObject

  • public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType,Object... uriVariables)
  • public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType,Map<String, ?> uriVariables)
  • public <T> T postForObject(URI url, @Nullable Object request, Class<T> responseType)

4.2.2 postForObject

  • public <T> ResponseEntity<T> postForEntity(String url, @Nullable Object request,Class<T> responseType, Object... uriVariables)
  • public <T> ResponseEntity<T> postForEntity(String url, @Nullable Object request,Class<T> responseType, Map<String, ?> uriVariables)
  • public <T> ResponseEntity<T> postForEntity(URI url, @Nullable Object request, Class<T> responseType)

4.2.3 postForLocation

  • public URI postForLocation(String url, @Nullable Object request, Object... uriVariables)
  • public URI postForLocation(String url, @Nullable Object request, Map<String, ?> uriVariables)
  • public URI postForLocation(URI url, @Nullable Object request)
    该方法实现了以POST请求提交资源,并返回新的资源的URI。这样我们就可以将返回的URI作为参数去调用public <T> ResponseEntity<T> postForObject/postForEntity(URI url, @Nullable Object request, Class<T> responseType)public <T> T getForObject/getForEntity/(URI url, Class<T> responseType) 方法。这实现了重定向的功能。

5、@LoadBalanced 注解作用原理简单讲解

为什么在 RestTemplate 上加了一个 @LoadBalanced 之后,RestTemplate 就能够跟 Eureka整合,让我们不但可以使用服务名称去调用接口,还能够自动通过注册中心的实例集群实现负载均衡,应该归功于 Spring Cloud 给大量的底层适配工作,将这些复杂都封装好了,用起来才会那么简单。

主要的逻辑就是@LoadBalanced修饰的 RestTemplate 会注册一个拦截器,在请求之前在拦截器中对请求的地址进行替换,或者根据具体的负载策略选择服务地址,然后再去调用真实的服务地址,这就是 @LoadBalanced 的原理

LoadBalancerAutoConfiguration类中:

public RestTemplateCustomizer restTemplateCustomizer(final LoadBalancerInterceptor loadBalancerInterceptor) {
	// 实现RestTemplateCustomizer中customize方法的对象,实现逻辑是为restTemplate添加LoadBalancerInterceptor拦截器
	return restTemplate -> {
		List<ClientHttpRequestInterceptor> list = new ArrayList<>(
				restTemplate.getInterceptors());
		list.add(loadBalancerInterceptor);
		restTemplate.setInterceptors(list);
	};
}

@Bean
public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(
		final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) {
	return () -> restTemplateCustomizers.ifAvailable(customizers -> {
		for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {
			for (RestTemplateCustomizer customizer : customizers) {
				// 调用RestTemplateCustomizer中customize方法,为restTemplate添加LoadBalancerInterceptor拦截器
				customizer.customize(restTemplate);
			}
		}
	});
}

8.1、负载均衡

RibbonLoadBalancerClient类:

public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint)
		throws IOException {
	// 获取负载均衡器,里面包含serviceId下存活的实例
	ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
	
	// 从负载均衡器中根据轮询规则获取一个实例的地址
	Server server = getServer(loadBalancer, hint);
	if (server == null) {
		throw new IllegalStateException("No instances available for " + serviceId);
	}
	RibbonServer ribbonServer = new RibbonServer(serviceId, server,
			isSecure(server, serviceId),
			serverIntrospector(serviceId).getMetadata(server));

	return execute(serviceId, ribbonServer, request);
}

在这里插入图片描述

8.2、地址替换

InterceptingClientHttpRequest类中的request.getURI()实际调用ServiceRequestWrapper类的getURI()方法,从instance中获取实例的IP地址。
在这里插入图片描述

ServiceRequestWrapperpublic URI getURI() {
	URI uri = this.loadBalancer.reconstructURI(this.instance, getRequest().getURI());
	return uri;
}

6、Ribbon的相关配置

锚点
Spring Cloud Netflix默认为Ribbon提供了以下的beans:

Bean类型 Bean名称 类名称 功能
IClientConfig ribbonClientConfig DefaultClientConfigImpl ribbon相关配置
IRule ribbonRule ZoneAvoidanceRule 根据区域和可用性过滤服务器的规则
IPing ribbonPing DummyPing IPing在Ribbon 框架中,负责检查服务实例是否存活(UP),DummyPing是IPing实现,永远返回true
ServerList ribbonServerList ConfigurationBasedServerList 加载服务列表。ConfigurationBasedServerList则是从配置文件加载服务列表
ServerListFilter ribbonServerListFilter ZonePreferenceServerListFilter 过滤服务列表,过滤掉所有和客户端环境里的配置的zone的不同的服务,如果和客户端相同的zone不存在,才不进行过滤
ILoadBalancer ribbonLoadBalancer ZoneAwareLoadBalancer 负载均衡器
ServerListUpdater ribbonServerListUpdater PollingServerListUpdater 动态服务器列表更新器更新的策略

注:当Ribbon与Eureka一起使用时

  • 则DiscoveryEnabledNIWSServerList作为ribbonServerList的实现类
  • NIWSDiscoveryPing则是作为IPing接口的实现,该接口会委托给Eureka用于确定服务器是否启动

6.1 IRule

功能:根据特定算法从服务列表选取一个服务进行访问。

RoundRobinRule:轮询规则,默认规则
AvailabilityFilteringRule:负载均衡器规则,过滤掉1。由于多次访问故障而处于断路状态的服务,2。并发的连接数量超过阈值的服务。然后对剩余的服务列表按照RoundRobinRule策略进行访问。
WeightedResponseTimeRule:根据平均响应时间计算所有服务的权重,响应时间越快,服务权重越重,优先被选中
RetryRule:按照RoundRobinRule的策略获取服务。如果获取服务失败。在指定时间内进行重试,获取可用的服务
BestAvailableRule:此负载均衡器会过滤由于多次访问故障而处于断路状态的服务,然后选择一个并发量最小的服务
RandomRule:随意获取一个服务

6.2 IPing

功能:在后台运行的一个组件,用于检测服务器列表是否运行正常

NIWSDiscoveryPing:不执行真正的ping,如果DiscoveryClient认为是在线,则程序认为本次心跳成功,服务正常运行
PingUrl:此组件会使用HttpClient调用一个服务,如果调用成功,则认为本次心跳成功,表示服务正常运行
NoOpPing:永远返回true,表示服务永远正常
DummyPing:默认实现,默认返回true,表示服务永远正常

6.3 ServerList

功能:存储服务列表。分为静态和动态,如果为动态,后台有一个县城会定时刷新和过滤服务列表

ConfigurationBasedServerList:从配置文件中获取所有服务列表。(静态)
DiscoveryEnabledNIWSServerList:从EurekaClient中获取服务列表。(动态)
DomainExtractingServerList:代理类,根据ServerList的值实现具体的逻辑

6.4 ServerListFilter

该接口允许过滤配置或动态获取的具有所需特性的服务器列表

ZoneAffinityServerListFilter:过滤掉所有的不和客户端在相同zone的服务,如果和客户端相同的zone不存在,才不过滤不同zone服务
ZonePreferenceServerListFilter:ZoneAffinityServerListFilter的子类。和ZoneAffinityServerListFilter相似,但是比较的zone是发布环境里面的zone。过滤掉所有和客户端环境里的配置的zone的不同的服务,如果和客户端相同的zone不存在,才不进行过滤。
ServerListSubsetFilter:ZoneAffinityServerListFilter的子类。此过滤器确保客户端仅看到由ServerList实现返回的整个服务器的固定子集。它还可以定期用新服务器替代可用性差的子集中的服务器。

6.5 ServerListUpdater

功能:被DynamicServerListLoadBalancer用于动态的更新服务列表

PollingServerListUpdater:默认的实现策略,此对象会启动一个定时线程池,定时执行更新策略
EurekaNotificationServerListUpdater:当收到缓存刷新的通知梦回更新服务列表。

6.6 IClientConfig

功能:定义配置信息,用来初始化ribbon客户端和负载均衡器

DefaultClientConfigImpl:IClientConfig的默认实现,配置文件里的部分值为ribbon。

6.7 ILoadBalancer

功能:定义软件负载平衡器操作的接口。动态更新一组服务列表及根据指定算法从现有服务器列表中选择一个服务

DynamicServerListLoadBalancer:DynamicServerListLoadBalancer组合Rule、IPing、ServerList、ServerListFilter、ServerListUpdater实现类,实现动态更新和过滤更新服务列表
ZoneAwareLoadBalancer:这是DynamicServerListLoadBalancer的子类,主要加入zone的因素。统计每个zone的平均请求的情况,保证从所有zone选取对当前客户端服务最好的服务组列表

7、如何通过设置Properties配置文件自定义Ribbon客户端

支持的属性:

配置项 对应的配置接口
.ribbon.NFLoadBalancerClassName ILoadBalancer
.ribbon.NFLoadBalancerRuleClassName IRule
.ribbon.NFLoadBalancerPingClassName IPing
.ribbon.NIWSServerListClassName ServerList
.ribbon.NIWSServerListFilterClassName ServerListFilter

例如为PROVIDER-PAYMENT-8001-3服务配置负载均衡规则:

PROVIDER-PAYMENT-8001-3:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule

这里有个问题:
在这里插入图片描述
官网描述的优先级是:配置文件是高于@RibbonClient(configuration=MyRibbonConfig.class)定义的beans和默认值,但是经过我试验,优先级是@RibbonClient(configuration=MyRibbonConfig.class)>配置文件>默认值。

ps: 这个地方可能是这样,如果你在@RibbonClient注解的属性或者是配置文件配置了和默认值一样的配置,那么就等同于你没有配置。未在ribbon验证,因为我再使用feign的时候也遇到类似的问题。

情况如下:
decode404默认值是false。
当在@FeignClient注解配置decode404=false,配置文件decode404=true时,decode404的功能是开启的
当在@FeignClient注解配置decode404=true,配置文件decode404=false时,decode404的功能也是开启的


8、Ribbon的其他配置

8.1 超时时间

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


ribbon:	
  ConnectTimeout: 2000 # 请求连接的超时时间
  ReadTimeout: 5000 # 请求处理的超时时间

# 也可以为每个Ribbon客户端设置不同的超时时间, 通过服务名称进行指定:
PROVIDER-PAYMENT-8001-3: 
  ribbon:
    ReadTimeout: 5000
    ConnectTimeout: 2000

8.2 并发参数

ribbon:
	MaxTotalConnections: 500 # 最大连接数
	MaxConnectionsPerHost: 500 # 每个host最大连接数
	
PROVIDER-PAYMENT-8001-3: 
  ribbon:
    MaxTotalConnections: 500
    MaxConnectionsPerHost: 500

9、使用RetryRule配置重试

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

PROVIDER-PAYMENT-8001-3:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RetryRule

或者是针对所有客户端生效:
ribbon:
  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RetryRule

当然也可是改用配置类的方式

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

(五)SpringCloud-Ribbon负载均衡 的相关文章

随机推荐

  • 小白怎么入门网络安全,学这两类证书就够了NISP或CISP

    其实网络安全这个门槛 对于当代的年轻人来说 不高也不低 其中NISP证书分为一级 二级 三级 专项 证书由中国信息安全测评中心颁发 持NISP二级证书可与免考兑换CISP证书 因为CISP报考需要工作经验 NISP填补了在校大学生无法考取C
  • SVN 安装与使用教程总结

    转载 http www cnblogs com armyfai p 3985660 html SVN简介 为什么要使用SVN 程序员在编写程序的过程中 每个程序员都会生成很多不同的版本 这就需要程序员有效的管理代码 在需要的时候可以迅速 准
  • Error:在安装elasticsearch和logstash程序出现的报错

    开启logstash服务出现 Failed to start logstash service Unit not found root localhost systemctl start logstash Failed to start l
  • ALAssetsLibrary获取所有图片

    通过创建ALAssetsLibrary 的实例可以访问系统Photos里的图片与视频 这个库包括了保存的图片 从iTunes导入的和从其他设备里面导入的图片 你可以访问所有的分类和保存图片视频 用普通的alloc和init就可以创建ALAs
  • word给公式自动编号、交叉引用

    利用域给公式自动编号 鼠标定位在公式末尾 如下图 注意是蓝框的末尾 在红框的末尾会无法识别 在公式末尾输入一个 号 作用是让编号右对齐 前不要有空格 插入 文档部件 域 如图指示 点击确定 这里的equaltion是自己添加的 后面再说 公
  • 【解释】对用户透明=对用户隐蔽:关系模型的存取路径对用户透明

    在计算机中 从某个角度看不到的特性称该特性是透明的 这个意义上的 透明 与社会生活中的透明含义恰好相反 例如计算机组织对程序员是透明的 就是说计算机组织对程序员来说是看不到的 也不需要看到的 和汉语字典里面的意思不一样 举个栗子 比如数据库
  • 网络安全之sql注入-less1

    less 1 是字符注入 union注入的步骤一般有以下几步 1 判断注入点 2 判断是整型还是字符型 3 判断查询列数 4 判断显示位 5 获取敏感信息 1 判断注入点 我们再Less1中看到 id将作为参数来使用 因此我们输入 http
  • python moviepy学习系列(一)安装及功能模板简介

    Moviepy简介 Moviepy是一个用于视频编辑的Python模块 它可被用于一些基本操作 如剪切 拼接 插入标题 视频合成 即非线性编辑 视频处理和创建高级特效 它可对大多数常见视频格式进行读写 包括GIF 安装方式 Pip安装方式
  • 闻达搭建paddingpadding

    项目地址wenda LLM wenda 闻达 一个LLM调用平台 为小模型外挂知识库查找和设计自动执行动作 实现不亚于于大模型的生成能力 github com git clone https github com wenda LLM wen
  • STM32定时器学习 hal库PWM输入捕获实验

    实验原理 输入捕获实验目的是为了获得脉宽和频率 首先是脉宽的获得 在实际捕获实验中 有两个通道 一个负责捕获上升沿 一个负责下降沿 从上图可以看出 t1 t2 时间就是我们需要测量的高电平时间 假如定时器工作在向上计数模式 测量方法是 首先
  • 特殊的IP地址127.x.x.x的含义

    特殊的IP地址127 x x x的含义 127 0 0 1 127 0 0 1是最常用的一种 表示本地计算机的IP地址 也可以用localhost表示 最常见的用法是 在 Windows 平台下使用快捷键 Win R 打开运行对话框 接着输
  • 十--nodejs原理(buffer)

    1 Buffer 1 Arraybuffer对象是用表示通用的 固定长度的二进制数据缓冲区 Arraybuffer不能直接操作 而是要通过类型数组对象或DataView对象来操作 它们会将缓冲区数据表示为特定格式的数据 并通过这类格式来读写
  • 冲流量显示与服务器通讯异常,科来:如何分析网络异常流量突发

    概述 网络异常流量突发是经常困扰运维管理人员的问题之一 突发流量可能会造成网络的拥塞 从而产生丢包 延时和抖动 导致网络服务质量下降 不仅如此 突发流量还可能存在安全风险 例如 DoS攻击 蠕虫 窃密等 会对网络和业务系统造成更大的危害 常
  • 学习C++项目——数据库知识学习(主从原理,分离配置,远程工具只是了解,都没有实现)

    学习数据库知识 一 思路和学习方法 本文学习于 B站平台UP主 IT 小当家 学习 MySQL 数据库 如里面加以自己的一些学习复现和理解 如有侵权会进行删除 学习Oracle以后也可以参考之前学习的UP主 C语言技术网 www freec
  • Java作用域与生命周期

    基本数据类型的作用域 作用域决定了在其内的变量名的可用性和生命周期 与c c 一样 作用域由花括号的位置决定 int x 5 x y都可用 int y 6 只有x可用 尽管下列代码在c c 中合法 但在Java中不能使用 c c 中将一个较
  • 《我的眼睛--图灵识别》第一章:起源

    我的眼睛 图灵识别 第一章 起源 账号登录 相信经常上网的你对上面这张图肯定不会陌生 特别是在注册新账号 账号登录或发表新文章之类的时候 它们都有可能出现要求我们输入 那么肯定会有人提出疑问 这些所谓的验证图形码跟我要做的事情毫无任何关系
  • Ubuntu开机后卡在登陆界面进去不

    系统 Ubuntu18 03 系统跑代码卡死了 导致鼠标键盘都用不了 直接强制关机后 卡在登陆界面进不去 步骤 1 系统启动后 在BIOS引导界面按 ESC 键进入选择菜单 选择第一个 Ubuntu 按 e 键进入编辑模式 2 在 hand
  • linux-ubuntu-bash切换zsh问题

    bash切换zsh问题记录 简单切换 sudo chsh s zsh 如果该命令没有生效 则可以直接修改配置文件 sudo gedit etc passwd 将 bin zsh改为 bin zsh
  • 【Linux系统编程】20.程序、进程、CPU和MMU、PCB

    目录 程序 进程 CPU和MMU PCB 程序 编译好的二进制文件 存在磁盘上 只占用磁盘资源 进程 进程是活跃的程序 占用系统资源 在内存中执行 程序运行起来 产生一个进程 程序类似于剧本 进程类似于一场戏 一场戏需要舞台 演员 灯光 道
  • (五)SpringCloud-Ribbon负载均衡

    目录 1 Spring Cloud Ribbon简介 2 Ribbon提供了七种负载均衡策略 3 微服务架构下如何使用Ribbon 3 1 使用Eureka作为注册中心时使用Ribbon 3 1 1 引入ribbon依赖 3 1 2 往容器