grafana / k6

A modern load testing tool, using Go and JavaScript - https://k6.io
GNU Affero General Public License v3.0
25.58k stars 1.26k forks source link

Load balancing "roundRobin" strategy doesn't work in gRPC tests #2758

Open gcfabri opened 1 year ago

gcfabri commented 1 year ago

Brief summary

Using DNS option (select="roundRobin") to load balancing with round robin strategy is not working in gRPC tests.

k6 version

v0.40.0

OS

Linux

Docker version and image (if applicable)

No response

Steps to reproduce the problem

Set the option to use load balancing strategy:

export const options = {
    dns: {
        ttl: "5m",
        select: "roundRobin",
        policy: "preferIPv4",
    },
};

or --dns "ttl=5m,select=roundRobin,policy=preferIPv4" or K6_DNS="ttl=5m,select=roundRobin,policy=preferIPv4"

Expected behaviour

Channel switches to load balancing policy accordingly and then iterate sequentially over the resolved IPs.

2022/11/07 16:27:06 INFO: [core] Channel switches to new LB policy "round_robin"

Actual behaviour

Channel switches to new LB policy "pick_first".

          /\      |‾‾| /‾‾/   /‾‾/   
     /\  /  \     |  |/  /   /  /    
    /  \/    \    |     (   /   ‾‾\  
   /          \   |  |\  \ |  (‾)  | 
  / __________ \  |__| \__\ \_____/ .io

  execution: local
     script: benchmark/k6/grpc_script.js
     output: -

  scenarios: (100.00%) 1 scenario, 1 max VUs, 10m30s max duration (incl. graceful stop):
           * default: 10 iterations shared among 1 VUs (maxDuration: 10m0s, gracefulStop: 30s)

2022/11/07 16:14:42 INFO: [core] [Channel #1] Channel created
2022/11/07 16:14:42 INFO: [core] [Channel #1] original dial target is: "dns:///grpc-west-poc-dev.grpc-east-west-poc-dev.svc.cluster.local:50051"
2022/11/07 16:14:42 INFO: [core] [Channel #1] parsed dial target is: {Scheme:dns Authority: Endpoint:grpc-west-poc-dev.grpc-east-west-poc-dev.svc.cluster.local:50051 URL:{Scheme:dns Opaque: User: Host: Path:/grpc-west-poc-dev.grpc-east-west-poc-dev.svc.cluster.local:50051 RawPath: ForceQuery:false RawQuery: Fragment: RawFragment:}}
2022/11/07 16:14:42 INFO: [core] [Channel #1] Channel authority set to "grpc-west-poc-dev.grpc-east-west-poc-dev.svc.cluster.local:50051"
2022/11/07 16:14:42 INFO: [core] [Channel #1] Resolver state updated: {
  "Addresses": [
    {
      "Addr": "10.90.7.196:50051",
      "ServerName": "",
      "Attributes": null,
      "BalancerAttributes": null,
      "Type": 0,
      "Metadata": null
    },
    {
      "Addr": "10.90.9.94:50051",
      "ServerName": "",
      "Attributes": null,
      "BalancerAttributes": null,
      "Type": 0,
      "Metadata": null
    }
  ],
  "ServiceConfig": null,
  "Attributes": null
} (resolver returned new addresses)
2022/11/07 16:14:42 INFO: [core] [Channel #1] Channel switches to new LB policy "pick_first"
na-- commented 1 year ago

Thanks for reporting this! :bow: I am not sure this has to be handled with k6's global DNS setting though, that's why I added evaluation needed. gRPC has its own internal way of load balancing:

So it makes some sense to me to be able to be able to configure it differently on the gRPC Client level or, more likely, on the Client.connect() level :thinking: For example, a user might want to have 2 different scenarios and compare different load balancing strategies, or something like that :man_shrugging: Or have 2 separate gRPC connections to potentially 2 different services, one with load balancing enabled and another without.

The default value of such a per-connect() setting might be influenced by the global dns k6 option, but it seems to me that it should be its own thing, assuming it can co-exist with the global option.