(五)SpringCloud-Ribbon负载均衡

九、Ribbon负载均衡 使用Ribbon做负载均衡,并配置轮询策略,默认为轮询 阅读详情

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地址。
在这里插入图片描述

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

6、Ribbon的相关配置

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

Bean类型Bean名称类名称功能
IClientConfigribbonClientConfigDefaultClientConfigImplribbon相关配置
IRuleribbonRuleZoneAvoidanceRule根据区域和可用性过滤服务器的规则
IPingribbonPingDummyPingIPing在Ribbon 框架中,负责检查服务实例是否存活(UP),DummyPing是IPing实现,永远返回true
ServerListribbonServerListConfigurationBasedServerList加载服务列表。ConfigurationBasedServerList则是从配置文件加载服务列表
ServerListFilterribbonServerListFilterZonePreferenceServerListFilter过滤服务列表,过滤掉所有和客户端环境里的配置的zone的不同的服务,如果和客户端相同的zone不存在,才不进行过滤
ILoadBalancerribbonLoadBalancerZoneAwareLoadBalancer负载均衡器
ServerListUpdaterribbonServerListUpdaterPollingServerListUpdater动态服务器列表更新器更新的策略

注:当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.NFLoadBalancerClassNameILoadBalancer
.ribbon.NFLoadBalancerRuleClassNameIRule
.ribbon.NFLoadBalancerPingClassNameIPing
.ribbon.NIWSServerListClassNameServerList
.ribbon.NIWSServerListFilterClassNameServerListFilter

例如为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

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

Spring Cloud - Ribbon 负载均衡原理、负载策略、懒加载 ps:案例是上一章所讲的 “根据订单id查询订单的同时,把订单所属的用户信息一起返回”。上一章我们讲到 order-service(订单服务) 使用 RestTemplate 发送 Http 请求到 user-service(用户服务),同时我们使用 @LoadBalanced 注解增加负载均衡,通过负载均衡算法分配到 user-service 集群,那么中间这个负载均衡到底是什么东西在起作用?负载均衡算法到底是什么?接下来我们就一起来了解一下吧~ 阅读详情

相关推荐

【springcloud 微服务】Spring Cloud Ribbon 负载均衡使用策略详解

springcloud中ribbon负载均衡策略总结

congge_study的博客 7685

SpringCloud中Ribbon负载均衡配置

在启动类配置,使用此配置方法,对应全部服务都会进行该规则的负载均衡。在对应yml文件配置,使用这种方法可以对某一个服务单独配置。

znq123127的博客 448

Android存储方案对比(SharedPreferences 、 MMKV 、 DataStore)

简介:本文介绍了Android开发中常用的键值对存储方案,包括SharedPreferences、MMKV和DataStore,并且对比了它们在性能、并发处理、易用性和稳定性上的特点。通过实际代码示例,帮助开发者根据项目需求选择最适合的存储方案,提升应用性能和用户体验。

LiuYong_01的博客 1794

SpringCloud 第三讲 Ribbon负载均衡策略(相关配置)

代码方式:配置灵活,但修改时需要重新打包@Bean配置方式:直观,方便,无需重新打包发布,但是无法做全局配置userserver: #你的服务名称ribbon:NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #负载均衡规则为何要开启饥饿加载,因为在我们第一次加载时候,响应时间比较慢,原因是第一次加服务需要从服务注册列表中拉取服务实例,以及初始化相关的组件到Spring中。

ggjklncffd的博客 694

Ubuntu登录界面黑屏?手把手教你排查和修复LightDM启动失败(附debug命令详解)

本文详细介绍了Ubuntu系统中LightDM(Light Display Manager)启动失败导致登录界面黑屏的排查与修复方法。通过系统状态检查、调试模式分析、常见故障解决方案及高级调试技巧,帮助用户快速定位并解决LightDM相关问题,恢复正常的图形登录环境。

weixin_34005090的博客 316

避坑指南:Windows下OpenCV摄像头索引混乱问题的3种解决之道

本文详细解析了Windows下OpenCV摄像头索引混乱问题的3种解决方案,包括GUID查询法、DirectShow接口集成和注册表固化技术。针对工业视觉和智能监控场景,提供实战代码和性能优化建议,帮助开发者稳定识别多路摄像头设备,有效解决VideoCapture接口的索引漂移问题。

weixin_30836759的博客 406

SpringCloud - Spring Cloud Netflix 之 Ribbon负载均衡(五)

Spring Cloud Ribbon 是一套基于 Netflix Ribbon 实现的客户端负载均衡和服务调用工具Ribbon 是 Netflix 公司发布的开源组件,其主要功能是提供客户端的负载均衡算法和服务调用。Spring Cloud 将其与 Netflix 中的其他开源服务组件(例如 Eureka、Feign 以及 Hystrix 等)一起整合进 Spring Cloud Netflix 模块中,整合后全称为 Spring Cloud Netflix RibbonRibbon 是 Spring C

MinggeQingchun的博客 871

工作中SVN的使用,保姆级教程!

SVN是一款集中式版本控制系统,采用客户端-服务器模式管理代码版本。与Git相比,SVN在目录权限控制、大型二进制文件处理等方面具有优势,适合特定场景使用。本文介绍了SVN的安装方法、基本操作(检出、提交、更新、回滚等)以及分支管理(创建、合并、切换)。同时讲解了文件冲突的解决方法,并演示了如何在IDEA中集成SVN工具。SVN虽然逐渐被Git取代,但在某些特定场景下仍是可靠选择,工具选择应基于团队和项目需求。

胜人者有力,自胜者强! 1854

【Spring Cloud】分布式必学springcloud(五)——Ribbon自定义负载均衡策略

这里我借鉴上一篇博客的框架,对ribbon模块进行修改假定这次修改为随机访问RandomRule。##3.1修改配置文件eurekaclienthttpserverport7000springnameclient1ribbon在配置文件中,我们指明了client1服务要使用策略。client1ribbon。...

哈士奇 4652

如何用Hugo Stack主题打造极简技术博客?3个必改配置与5个高级美化技巧

本文详细解析了如何深度定制Hugo Stack主题,打造个性化技术博客。文章提供了3个必改配置与5个高级美化技巧,涵盖字体美学、布局重构、代码块视觉强化及细节打磨,帮助开发者超越基础部署,实现从功能到美学的进阶,提升博客质感与用户体验。

carrot的博客 569

【机器人技术基础】MATLAB Robotics Toolbox PUMA560 运动学正逆解

机器人技术基础实验2报告 1. 实验目的和要求 2. 实验手段 2.1 实验原理 2.2 函数详解 3. 实验主要内容 4. 实验结果和分析 4.1 正运动学求解 例1 例2 4.2 逆运动学求解 例1 例2 1. 实验目的和要求 掌握常见形式的机器人的D-H坐标系建立方法、运动学建模; 正逆运动学分析与求解; 使用Robotics Toolbox对直角坐标机器人、圆柱坐标机器人、球坐标机器人、PUMA560其中之一建立运动学模型,正逆求解和仿真。 2. 实验手段 2.1

【人工智障 | 计算鸡视觉 | 机器孩】 1万+

SpringCloud(五)负载均衡之Ribbon

SpringCloud(五)负载均衡之Ribbon 关于负载均衡 负载均衡一般分为服务器端负载均衡和客户端负载均衡 所谓服务器端负载均衡,比如Nginx、F5这些,请求到达服务器之后由这些负载均衡器根据一定的算法将请求路由到目标服务器处理。 所谓客户端负载均衡,比如我们要说的Ribbon,服务消费者客户端会有一个服务器地址列表,调用方在请求前通过一定的负载均衡算法选择一个服务器进行访问,负载均衡算法的执行是在请求客户端进行。 Ribbon是Netflix发布的负载均衡器。Eureka一般配合Ribbon进行

weixin_49741990的博客 283

uniapp:在map地图组件上添加控件,在地图上添加浮层展示自定义按钮或元素,uniApp如何在Map组件地图上添加悬浮在上面的图标/图片(全平台兼容安卓苹果app、H5网页、微信小程序、nvue)

uni-app的map添加控件问题,uniapp实现地图展示控件,uniapp小程序如何在map组件上增加按钮,uni-app,h5移动端网页,微信小程序,支付宝小程序,Android安卓,苹果ios,app,nvue,Uniapp腾讯地图添加控件,uniapp百度地图添加控件,地图上展示控件并可以点击,在地图上展示控件信息,uniapp map地图怎么向地图上增加工具栏,使用cover-view将控件在地图上展示,解决uniapp map上添加浮层无法显示问题,不显示怎么办,css样式不生效,地图等最高层

✅ 精选推荐文章 3231

springcloud(五)Ribbon 负载均衡

一、概述 前面一节已经通过 RestTemplate 实现了服务消费者对服务提供者的调用,这只是实现了最基本的需求,如果在某个具体的业务场景下,对于某服务的调用需求激增,这时候我们就需要为该服务实现负载均衡以满足高并发访问,在一个大型的分布式应用系统中,负载均衡(Load Balancing)是必备的。 二、Spring Cloud Ribbon Spring Cloud 提供了实现负载均衡...

ByteSea数海拾光 443

Qt Creator配置MSVC编译环境、调试环境

获取和安装:cdb.exe 在 Debugging tools for Windows 中,而现在已经不单独提供下载,只在Windows SDK 或者Windows Driver Kit里面包含 所以需要下载微软的调试工具,最少需要下载 Windows SDK。在windows上开发,一般使用Qt Creator自带mingw编译器,编译和调试都很方便,安装Qt时勾选后,自动配置完毕。但是有时候我们需要使用MSVC的编译器,这个时候我们没法直接使用,需要配置环境才能使用,以下是配置方案。

希望能帮助大家,希望大家多多支持,你们的支持是我前进的动力。 6988

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

SpringCloud学习笔记(五)Ribbon负载均衡

概述 Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。 简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ri...

huangpf_vcx 277

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

SpringCloud全家桶(五)——Ribbon负载均衡

文章目录五、Ribbon客户端负载均衡1、基本概念2、调用关系3、用户服务集群配置4、消费者Order-server集成Ribbon5、测试结果 五、Ribbon客户端负载均衡 1、基本概念 为什么要使用Ribbon:为防止应用出现单节点故障,为服务集群得时候,会出现一个服务在注册中心有两个通讯地址,当我们在调用这个服务得时候应该如何选择,这时候我们就要用到 Ribbon,也就是负载均衡器,他的功能就是帮助我们做请求得转发。Ribbon可以按照负载均衡算法(如简单轮询,随机连接等)向多个服务发起调用(正好可

WLK0423的博客 398

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

SpringCloud入门实战(五)-Ribbon负载均衡集成

SpringCloud从0到1系列-集成ribbon

一个喜欢诗和远方的程序媛 1853

springcloud 简单示例之负载均衡feign、ribbon(五)

1.Spring cloud 服务间调用一般有两种方式,第一种:ribbon+restTemplate、第二种:fegin(Feign默认集成了ribbon),两种方式都支持负载均衡。 2.两种方式中,被调用的服务代码和配置不需要做任何修改,改改启动端口,启动两个服务就可以了。 server: port: 7001 spring: application: name: spri...

玩火的稻草人的博客 335

SpringCloud Ribbon实战之自定义负载均衡策略(五)

下面我们继续讲Ribbon自定义的负载均衡策略 在启动微服务的时候就能去加载我们自定义的Ribbon配置类,从而使配置生效, 例如使用新的注解@RibbonClient:@RibbonClient(name="MICROSERVICECLOUD-DEPT",configuration=MySelfRule.class) 下面我们就开始吧 1,修改消费者客户端的主启动类,在主启动类上加上新的...

ywl470812087的博客 11万+

spring cloud Alibaba 实现负载均衡 Ribbon学习笔记五

Ribbon实现负载均衡一、实现方式二、手写客户端侧负载均衡器三、使用Ribbon实现负载均衡四、Ribbon 组成五、Ribbon 配置 一、实现方式 服务器端负载均衡(单体架构) 客户端侧负载均衡(内容中心相对用户中心,属于客户端,可在内容中心集群中配置负载均衡规则) 二、手写客户端侧负载均衡器 随机负载均衡算法 三、使用Ribbon实现负载均衡 1、定义:Netfix开源的客户端侧负载均衡器,即提供了负载均衡算法 2、架构演进: 3、整合Ribbon 加依赖:不需要,spri

lzf2284466的博客 977

SpringCloud(五):Ribbon负载均衡服务调用

目录 概述 是什么 官网资料 能干嘛 LB(负载均衡) Ribbon本地负载均衡客户端和Nginx服务客服端负载均衡的区别 Ribbon负载均衡演示 Ribbon核心组件IRule Ribbon负载均衡算法 概述 是什么 Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端,负载均衡的工具。 简单来说,ribbon是Netflix发布的开源项目,主要功能是提供客户端软件负载均衡的算法和服务调用。 Ribbon客户端组件提供一系列完善的配置如

Clawww的学习笔记 265

SpringCloud 入门教程(五): Ribbon实现客户端的负载均衡

接上节,假如我们的Hello world服务的访问量剧增,用一个服务已经无法承载, 我们可以把Hello World服务做成一个集群。 很简单,我们只需要复制Hello world服务,同时将原来的端口8762修改为8763。然后启动这两个Spring Boot应用, 就可以得到两个Hello World服务。这两个Hello world都注册到了eureka服务中心。这时候再访问http:/...

ywl470812087的博客 10万+

搭建springcloud的demo之Ribbon负载均衡(五)

Ribbon的负载均衡算法 简单轮询算法:一台服务器一次 Ribbon在工作时分成两步 第一步先选择EurekaServer,它优先选择在同一个区域内负载较少的server; 第二步再根据用户指定的策略,在从server取到的服务注册列表中选择一个地址; ...

yuanting_的博客 424

SpringCloud系列之五: Ribbon客户端负载均衡

1.Ribbon 是什么? 一套客户端负载均衡工具. 举例:窗口点餐,点餐时会分好几个窗口,就是为了让人员分摊到不同的窗口,来避免人员堆积,我们点餐的时候,作为客户消费者会主动地选择人员最少的窗口的去点餐. 2.能做什么? 负载均衡的工具,将用户的请求分摊到多个服务器上,从而达到高可用.,负载均衡算法可以自定义. LB集成到消费方,消费方通过Ribbon,从服务注册中西获知哪些服务可用,然后根据算...

努力发光呀 324

SpringCloud(五)——Ribbon负载均衡服务调用

文章目录一、Ribbon概述1.是什么?2.官网资料3.能干嘛二、Ribbon负载均衡演示1.架构说明2.POM文件3.RestTemplate的使用三、Ribbon核心组件IRule1.IRule:根据特定算法从服务列表中选取一个要访问的服务2.如何替换算法?三、Ribbon负载均衡算法 一、Ribbon概述 1.是什么? 2.官网资料 https://github.com/Netflix/ribbon/wiki/Getting-Started Ribbon目前也进入维护模式 未来替换方案 3.

筱筱攻程师的博客 381
上一篇: mybatis遇见的问题(持续更新)
下一篇: 查看Linux日志
村口老师傅
博客等级 码龄9年 67粉丝 107原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值