-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: support Nacos v2 as ServiceRegistry (1/n) #703
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #703 +/- ##
==========================================
- Coverage 88.47% 88.06% -0.41%
==========================================
Files 121 128 +7
Lines 5995 6378 +383
==========================================
+ Hits 5304 5617 +313
- Misses 492 548 +56
- Partials 199 213 +14 ☔ View full report in Codecov by Sentry. |
|
||
option go_package = "mosn.io/htnn/types/registries/nacos/v2"; | ||
|
||
message Config { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How many differences between Nacos v1 & v2? If the Nacos v2 shares the most options with the v1, we can just add a new field to indicate if v2 or v1 is used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are not many differences between Nacos v1 and v2 in terms of configuration options. Both versions share the same fields
) | ||
|
||
func init() { | ||
registry.AddRegistryFactory(nacos.Name, func(store registry.ServiceEntryStore, om metav1.ObjectMeta) (registry.Registry, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the Nacos v1 & v2 uses the same Nacos registry, we should not register a new registry, but add the v2 support in the existing Nacos implementation.
fix license update nacos docs add nacos param add nacos param add nacos param add nacos param add nacos param add nacos param fix license fix license update nacos docs add nacos param add nacos param add nacos param add nacos param add nacos param feat: support Nacos v2 as ServiceRegistry
} | ||
if len(config.Groups) == 0 { | ||
config.Groups = []string{"DEFAULT_GROUP"} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code above is almost copied from the config.go
. Could we share as much as possible?
For example, we can construct the project like this:
nacos/
client/
v1/
v2/
the package v1 implements v1 client, and v2 implements v2 client. The client is an interface that provides the methods which are different in v1/v2. The common part will be outside of the client interface.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The use of nacos api is different.
v1 use "github.com/nacos-group/nacos-sdk-go"
v2 use "github.com/nacos-group/nacos-sdk-go/v2"
So the shared code is little.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lyt122
Thanks for your explanation. What a pity!
What about writing code like this:
func (reg *Nacos) Start(c registrytype.RegistryConfig) error {
config := c.(*nacos.Config)
reg.version = config.Version
// this method returns a client interface
client, err := reg.newClient(config)
if err != nil {
return err
}
// call client's fetchAllServices inside
fetchedServices, err := reg.fetchAllServices(client)
if err != nil {
return fmt.Errorf("fetch all services error: %v", err)
}
reg.client = client
for key := range fetchedServices {
// // call client's subscribe inside
err = reg.subscribe(key.GroupName, key.ServiceName)
if err != nil {
reg.logger.Errorf("failed to subscribe service, err: %v, service: %v", err, key)
// the service will be resubscribed after refresh interval
delete(fetchedServices, key)
}
}
reg.watchingServices = fetchedServices
dur := 30 * time.Second
refreshInteval := config.GetServiceRefreshInterval()
if refreshInteval != nil {
dur = refreshInteval.AsDuration()
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@spacewander
The subscribe function need the getSubscribeCallback
function, which need store
in Nacos to update serviceEntry.
And other params also is needed, such as stopped
, logger
.
Should I write like this
subscribe(groupName string, serviceName string, stopped atomic.Bool, logger log.RegistryLogger, store registry.ServiceEntryStore)
or add these params in Client struct?like this
type nacosClient struct {
Groups []string
Namespace string
namingClient *Client
logger log.RegistryLogger
stopped atomic.Bool
store registry.ServiceEntryStore
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about passing the result of getSubscribeCallback? In this way only one param is needed.
We can define our own model.SubscribeService, which is the common part between Nacos v1 & v2's models. Then we can add an adapter to wrap the result of getSubscribeCallback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
v1's callback use model.SubscribeService
type SubscribeService struct {
ClusterName string `json:"clusterName"`
Enable bool `json:"enable"`
InstanceId string `json:"instanceId"`
Ip string `json:"ip"`
Metadata map[string]string `json:"metadata"`
Port uint64 `json:"port"`
ServiceName string `json:"serviceName"`
Valid bool `json:"valid"`
Weight float64 `json:"weight"`
Healthy bool `json:"healthy"`
}
but v2's callback use model.Instance
type Instance struct {
InstanceId string `json:"instanceId"`
Ip string `json:"ip"`
Port uint64 `json:"port"`
Weight float64 `json:"weight"`
Healthy bool `json:"healthy"`
Enable bool `json:"enabled"`
Ephemeral bool `json:"ephemeral"`
ClusterName string `json:"clusterName"`
ServiceName string `json:"serviceName"`
Metadata map[string]string `json:"metadata"`
InstanceHeartBeatInterval int `json:"instanceHeartBeatInterval"`
IpDeleteTimeout int `json:"ipDeleteTimeout"`
InstanceHeartBeatTimeOut int `json:"instanceHeartBeatTimeOut"`
}
we can't define the common part
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We only use Ip, Port and Metadata in getSubscribeCallback. These fields exits both in v1 and v2, so it is possible to define the common part
reg.version = config.Version | ||
if reg.version == "v1" { | ||
cli, err := v1.NewClient(config) | ||
if err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can move the part after if err != nil {
outside the current block.
reg.client = cli | ||
} else if reg.version == "v2" { | ||
cli, err := v2.NewClient(config) | ||
if err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
if err != nil { | ||
return err | ||
if reg.version == "v1" { | ||
cli, err := v1.NewClient(config) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto. We can wrap the version handling in a new method
} | ||
|
||
func (c *NacosClient) unsubscribe(groupName string, serviceName string, callback func(services []model.SubscribeService, err error)) error { | ||
err := c.client.Subscribe(&vo.SubscribeParam{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrong method?
@lyt122 BTW, you can use main branch to sync the upstream, and use a separate branch to develop feature. Therefore, previous commits won't be in the PR. |
ref #258
It's about start and stop the Nacos