Após modificar os pesos das instâncias no console do Microservices Engine (MSE), o tráfego pode não seguir a nova distribuição. Os pesos do Nacos são propriedades de metadados; portanto, o framework da aplicação deve oferecer suporte explícito ao roteamento ponderado para que as alterações afetem o tráfego.
Como funcionam os pesos do Nacos
Os pesos das instâncias no Nacos são valores relativos. Ao atualizar um peso no console do MSE, o sistema envia o novo valor a todos os clientes Nacos conectados como parte dos metadados da instância. No entanto, o Nacos não impõe a distribuição de tráfego. O framework no lado do cliente lê o peso e o aplica durante o balanceamento de carga.
Um peso igual a 0 remove a instância do tráfego. Para pesos diferentes de zero, a probabilidade esperada de roteamento para uma instância é:
instance weight / sum of all instance weights
Por exemplo, duas instâncias com pesos 3 e 1 recebem 75% e 25% do tráfego, respectivamente, mas apenas se o framework implementar a seleção ponderada.
Identifique a causa
|
Causa |
Sintomas |
Frameworks afetados |
|
Framework trata o peso como binário |
Tráfego distribuído uniformemente entre todas as instâncias com peso diferente de zero |
Spring Cloud Alibaba (configuração padrão) |
|
Framework usa balanceamento de carga próprio |
Alterações de peso ignoradas; aplicam-se regras de balanceamento específicas do framework |
Dubbo, Spring Cloud Alibaba + LoadBalancer |
|
Aplicação não lê o campo de peso |
Código personalizado de descoberta de serviços ignora a propriedade de peso |
Implementações personalizadas de cliente Nacos |
Solução por framework
Spring Cloud Alibaba
Por padrão, o Spring Cloud Alibaba trata os pesos do Nacos como binários: zero significa nenhum tráfego; qualquer outro valor indica tráfego igualitário. Para ative o balanceamento de carga ponderado, ative o balanceador compatível com Nacos.
Adicione o seguinte ao arquivo application.properties ou application.yml:
spring.cloud.loadbalancer.nacos.enabled=true
Se você usar o Spring Cloud LoadBalancer diretamente, ative o WeightedServiceInstanceListSupplier:
spring.cloud.loadbalancer.configurations=weighted
Ou configure programaticamente:
public class CustomLoadBalancerConfiguration {
@Bean
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder()
.withDiscoveryClient()
.withCaching()
.withWeighted()
.build(context);
}
}
Dubbo
O Dubbo possui configuração própria de balanceamento de carga e não lê os pesos das instâncias do Nacos por padrão. Configure o balanceamento baseado em peso nos níveis global, de interface ou de método.
Configuração global (application.yml):
dubbo:
consumer:
loadbalance: roundrobin
Configuração no nível da interface (lado do provedor):
@DubboService(loadbalance = "roundrobin")
public class DemoServiceImpl implements DemoService {}
Configuração no nível da interface (lado do consumidor, tem prioridade):
@DubboReference(loadbalance = "roundrobin")
private DemoService demoService;
O Dubbo oferece suporte aos seguintes algoritmos de balanceamento de carga:
|
Algoritmo |
Valor de configuração |
Suporte a peso |
|
Aleatório ponderado |
|
Sim |
|
Round robin ponderado |
|
Sim |
|
Menos ativo + aleatório ponderado |
|
Sim |
|
Resposta mais curta + aleatório ponderado |
|
Sim |
|
Hash consistente |
|
Não |
Com random ou roundrobin, o Dubbo utiliza seu próprio sistema de pesos. Para usar os pesos das instâncias do Nacos, implemente uma extensão personalizada de LoadBalance que leia o campo weight do Nacos.
Implementações personalizadas de cliente Nacos
Se sua aplicação chamar a API do Nacos diretamente, confirme se a lógica de endereçamento lê o campo weight.
**Opção 1: Usar selectOneHealthyInstance (recomendado)**
O método selectOneHealthyInstance do cliente Nacos executa uma seleção aleatória ponderada com base nos pesos das instâncias:
NamingService namingService = NacosFactory.createNamingService(properties);
// Returns a single instance selected by weighted random
Instance instance = namingService.selectOneHealthyInstance("your-service-name");
Opção 2: Implementar seleção ponderada personalizada
Ao recuperar a lista completa de instâncias, aplique a seleção baseada em peso manualmente:
NamingService namingService = NacosFactory.createNamingService(properties);
List<Instance> instances = namingService.getAllInstances("your-service-name");
// Filter healthy instances and apply weighted random selection
List<Instance> healthy = instances.stream()
.filter(Instance::isHealthy)
.filter(i -> i.getWeight() > 0)
.collect(Collectors.toList());
// Calculate total weight
double totalWeight = healthy.stream()
.mapToDouble(Instance::getWeight)
.sum();
// Weighted random selection
double random = ThreadLocalRandom.current().nextDouble() * totalWeight;
double cumulative = 0;
for (Instance inst : healthy) {
cumulative += inst.getWeight();
if (random < cumulative) {
// Use this instance
break;
}
}
Para obter a referência completa da API, consulte Nacos Java SDK.
Verifique o roteamento baseado em peso
Após aplicar a correção, verifique se os pesos entraram em vigor:
Defina o peso da instância A como 1 e o da instância B como 9.
Envie 100 solicitações para o serviço.
Verifique os logs de acesso de cada instância. A instância B deve receber aproximadamente 90% das solicitações.
Se o tráfego ainda apresentar distribuição uniforme, verifique os seguintes pontos:
A alteração na configuração do balanceador de carga foi implantada e a aplicação reiniciada.
Nenhuma outra regra de balanceamento de carga (como políticas de service mesh ou roteamento no nível de gateway) substitui a configuração no nível do framework.
Os pesos das instâncias são diferentes de zero e refletem corretamente no console do Nacos.