Open kazegusuri opened 5 years ago
@dfawley How do you think of this? Not everyone use ServiceConfig with discovery, so it would be easier if we have another way to specify configs without specifying raw json.
The main reason to deprecate WithBalancerName
is to avoid having two ways to do the same thing.
Reason for json
is that it's the service config format agreed upon by all the grpc languages.
It is reasonable to support specifying service using a format other than json, maybe a native go struct.
For now, please try WithDefaultServiceConfig
. To set balancer to roundrobin, you can set
grpc.WithDefaultServiceConfig(`{"loadBalancingPolicy":"round_robin"}`)
Accepting JSON config does not provide more backwards compatibility guarantees than accepting a config struct. Passing string configs like this is pretty weird, I would recommend code-first API, and if someone wants to drive the config from JSON or any other format, it can be done with a factory function, like ServiceConfigFromJSON() (which is still a poor API considering that there are many ways to source the JSON).
What's the status on this?
any update?
This is unfortunately not something the team has resources to spend on right now. This will require us to evaluate the existing grpc.ServiceConfig
to determine if we should just keep using it, or finish removing it and replace it with something more appropriate.
One reason this is not a priority is that the JSON form should be completely functional to use. Note that there is a proto representation for service config, and it's possible to serialize that to JSON and inject it, so there already technically is a native Go struct for service config.
I've been on a bit of a wild ride with this this evening. I've seen quite a few conflicting pieces of documentation about service config, and I've seen various deprecation notices too. I'm honestly completely unsure about what I have to specify in this magic JSON string, but I'm just going to try some things and see if they work I suppose. If JSON is the service format agreed upon by all languages, then it must be documented somewhere in full, right? I've just really struggled to find that place currently (I may just be being completely blind though!)
The current solution of passing JSON is indeed quite weird. Not only weird though, as above, it's really difficult to see what you're meant to pass to this function. If it was a struct then it could have comments, deprecation warnings, etc. Right now I'm putting a magic string in that I don't even know is actually right. Significantly worse than that though, I can put anything in there and it'll still compile, and still pass static analysis. Regular Go code with deprecations or removed fields would fail one of those checks and point out exactly what is wrong.
From the above response, is ServiceConfig being deprecated too?
From the above response, is ServiceConfig being deprecated too?
The grpc.ServiceConfig
type is already deprecated, but service configs themselves are not.
For documentation, which is admittedly not ideal, the best sources would be:
Note that we are happy to accept external contributions, so if you feel the documentation is lacking and you think you can help improve it, let us know and we can work with you.
I agree with the sentiments of wanting compile-time failures, but note that you can actually get that if you use the protobuf form and serialize it to JSON to input it to grpc.
I'm just going to try some things and see if they work I suppose.
What are you actually trying to do?
I agree with the sentiments of wanting compile-time failures, but note that you can actually get that if you use the protobuf form and serialize it to JSON to input it to grpc.
That's a fair point! I'm assuming you have to use the protojson
package to encode it in the correct format (similar to what that documentation is saying about field name formatting, etc.)?
Note that we are happy to accept external contributions, so if you feel the documentation is lacking and you think you can help improve it, let us know and we can work with you.
I have contributed before, and would love to do so again, but my time is really constrained right now. If I do find the time though I'll see what I can do. In the meantime I can only offer some observations based on my experience tonight in case someone else beats me to it. So here's my thoughts:
What are you actually trying to do?
I've been deploying a gRPC into Kubernetes and looking into the various options for load balancing in that environment. I found this https://github.com/sercand/kuberesolver, and they say to use the round robin balancer strategy, so was just trying to get that in place. I used the WithBalancer dial option but saw it was deprecated which led me here. I've given it a try now and the snippet from that markdown document is what I'm using and it seems to be working well.
I don't mean to have come off the wrong way with this by the way, I just want to be constructive here! I appreciate you taking the time to respond and answer those questions, and for working on gRPC in the first place.
That's a fair point! I'm assuming you have to use the protojson package to encode it in the correct format (similar to what that documentation is saying about field name formatting, etc.)?
Yes, you'd want to use protojson
, and ideally we should also export our .pb.go
s for service config since OSS Go proto really needs a single source of truth.
Also, it being a markdown file on GitHub made me wonder if it was actually maintained at first
Perhaps we should link to it from our godoc comments on the WithDefaultServiceConfig
function, and then it would be more discoverable and a testament to its freshness, while also improving our documentation. What do you think?
When you do look at that Godoc, you're also told that it's an experimental API.
We should probably remove this. We try to do this by default for all new APIs we add, in case they turn out to not work in practice. The one has been there long enough without being changed, so it seems to be fine to make it stable.
they say to use the round robin balancer strategy, so was just trying to get that in place
FWIW we do have an example of setting exactly this here:
Thank you for the feedback.
Perhaps we should link to it from our godoc comments on the WithDefaultServiceConfig function, and then it would be more discoverable and a testament to its freshness, while also improving our documentation. What do you think?
Yeah, that's a good shout. Removing that experimental comment would also help too, I agree.
FWIW we do have an example of setting exactly this here:
If I'm understanding correctly, that actually is a deprecated approach (though the solution you've posted there is the one I found most people using on GitHub from doing a search of the function name). The one I landed on was this:
grpc.WithDefaultServiceConfig(`{"loadBalancingConfig": [{"round_robin":{}}]}`)
If I'm understanding correctly, that actually is a deprecated approach
Argh, I didn't even look closely at it, but you are right. What you have is the preferred form, and we should update our example. Note that, in this case, "deprecated" means "there's another way, which we recommend using instead", not "it will be removed", since we intend to keep backward compatibility forever (for anything not originally marked w/experimental).
Use case(s) - what problem will this feature solve?
It seems WithBalancerName is deprecated in https://github.com/grpc/grpc-go/pull/2900 in favor of WithDefaultServiceConfig. WithDefaultServiceConfig accepts only raw JSON, so if we want to use specific balancer statically, we need to use JSON to specify that.
Proposed Solution
Please keep WithBalancerName as is, or another way to specify the configurations instead of using JSON.
Alternatives Considered
Additional Context