in server/action.go [135:250]
func (svcOpts *ServiceOptions) export(info *common.ServiceInfo) error {
svc := svcOpts.Service
if info != nil {
if svc.Interface == "" {
svc.Interface = info.InterfaceName
}
svcOpts.Id = common.GetReference(svcOpts.rpcService)
svcOpts.info = info
}
// TODO: delay needExport
if svcOpts.unexported != nil && svcOpts.unexported.Load() {
err := perrors.Errorf("The service %v has already unexported!", svc.Interface)
logger.Errorf(err.Error())
return err
}
if svcOpts.exported != nil && svcOpts.exported.Load() {
logger.Warnf("The service %v has already exported!", svc.Interface)
return nil
}
regUrls := make([]*common.URL, 0)
if !svc.NotRegister {
regUrls = config.LoadRegistries(svc.RegistryIDs, svcOpts.registriesCompat, common.PROVIDER)
}
urlMap := svcOpts.getUrlMap()
protocolConfigs := loadProtocol(svc.ProtocolIDs, svcOpts.protocolsCompat)
if len(protocolConfigs) == 0 {
logger.Warnf("The service %v'svcOpts '%v' protocols don't has right protocolConfigs, Please check your configuration center and transfer protocol ", svc.Interface, svc.ProtocolIDs)
return nil
}
var invoker protocol.Invoker
ports := getRandomPort(protocolConfigs)
nextPort := ports.Front()
for _, proto := range protocolConfigs {
// *important* Register should have been replaced by processing of ServiceInfo.
// but many modules like metadata need to make use of information from ServiceMap.
// todo(DMwangnimg): finish replacing procedure
// registry the service reflect
methods, err := common.ServiceMap.Register(svc.Interface, proto.Name, svc.Group, svc.Version, svcOpts.rpcService)
if err != nil {
formatErr := perrors.Errorf("The service %v needExport the protocol %v error! Error message is %v.",
svc.Interface, proto.Name, err.Error())
logger.Errorf(formatErr.Error())
return formatErr
}
port := proto.Port
if len(proto.Port) == 0 {
port = nextPort.Value.(string)
nextPort = nextPort.Next()
}
ivkURL := common.NewURLWithOptions(
common.WithPath(svc.Interface),
common.WithProtocol(proto.Name),
common.WithIp(proto.Ip),
common.WithPort(port),
common.WithParams(urlMap),
common.WithParamsValue(constant.BeanNameKey, svcOpts.Id),
common.WithParamsValue(constant.ApplicationTagKey, svcOpts.Application.Tag),
//common.WithParamsValue(constant.SslEnabledKey, strconv.FormatBool(config.GetSslEnabled())),
common.WithMethods(strings.Split(methods, ",")),
// todo(DMwangnima): remove this
common.WithAttribute(constant.ServiceInfoKey, info),
common.WithToken(svc.Token),
common.WithParamsValue(constant.MetadataTypeKey, svcOpts.metadataType),
// fix https://github.com/apache/dubbo-go/issues/2176
common.WithParamsValue(constant.MaxServerSendMsgSize, proto.MaxServerSendMsgSize),
common.WithParamsValue(constant.MaxServerRecvMsgSize, proto.MaxServerRecvMsgSize),
)
if len(svc.Tag) > 0 {
ivkURL.AddParam(constant.Tagkey, svc.Tag)
}
// post process the URL to be exported
svcOpts.postProcessConfig(ivkURL)
// config post processor may set "needExport" to false
if !ivkURL.GetParamBool(constant.ExportKey, true) {
return nil
}
if len(regUrls) > 0 {
svcOpts.cacheMutex.Lock()
if svcOpts.cacheProtocol == nil {
logger.Debugf(fmt.Sprintf("First load the registry protocol, url is {%v}!", ivkURL))
svcOpts.cacheProtocol = extension.GetProtocol(constant.RegistryProtocol)
}
svcOpts.cacheMutex.Unlock()
for _, regUrl := range regUrls {
setRegistrySubURL(ivkURL, regUrl)
invoker = svcOpts.generatorInvoker(regUrl, info)
exporter := svcOpts.cacheProtocol.Export(invoker)
if exporter == nil {
return perrors.New(fmt.Sprintf("Registry protocol new exporter error, registry is {%v}, url is {%v}", regUrl, ivkURL))
}
svcOpts.exporters = append(svcOpts.exporters, exporter)
}
} else {
invoker = svcOpts.generatorInvoker(ivkURL, info)
exporter := extension.GetProtocol(protocolwrapper.FILTER).Export(invoker)
if exporter == nil {
return perrors.New(fmt.Sprintf("Filter protocol without registry new exporter error, url is {%v}", ivkURL))
}
svcOpts.exporters = append(svcOpts.exporters, exporter)
}
// this protocol would be destroyed in graceful_shutdown
// please refer to (https://github.com/apache/dubbo-go/issues/2429)
graceful_shutdown.RegisterProtocol(proto.Name)
}
svcOpts.exported.Store(true)
return nil
}