gsvc_service.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
  2. //
  3. // This Source Code Form is subject to the terms of the MIT License.
  4. // If a copy of the MIT was not distributed with this file,
  5. // You can obtain one at https://github.com/gogf/gf.
  6. package gsvc
  7. import (
  8. "context"
  9. "github.com/gogf/gf/v2/encoding/gjson"
  10. "github.com/gogf/gf/v2/errors/gcode"
  11. "github.com/gogf/gf/v2/errors/gerror"
  12. "github.com/gogf/gf/v2/internal/intlog"
  13. "github.com/gogf/gf/v2/os/gcmd"
  14. "github.com/gogf/gf/v2/text/gstr"
  15. )
  16. // LocalService provides a default implements for interface Service.
  17. type LocalService struct {
  18. Head string // Service custom head string in service key.
  19. Deployment string // Service deployment name, eg: dev, qa, staging, prod, etc.
  20. Namespace string // Service Namespace, to indicate different services in the same environment with the same Name.
  21. Name string // Name for the service.
  22. Version string // Service version, eg: v1.0.0, v2.1.1, etc.
  23. Endpoints Endpoints // Service Endpoints, pattern: IP:port, eg: 192.168.1.2:8000.
  24. Metadata Metadata // Custom data for this service, which can be set using JSON by environment or command-line.
  25. }
  26. // NewServiceWithName creates and returns a default implements for interface Service by service name.
  27. func NewServiceWithName(name string) Service {
  28. s := &LocalService{
  29. Name: name,
  30. Metadata: make(Metadata),
  31. }
  32. s.autoFillDefaultAttributes()
  33. return s
  34. }
  35. // NewServiceWithKV creates and returns a default implements for interface Service by key-value pair string.
  36. func NewServiceWithKV(key, value string) (Service, error) {
  37. var (
  38. err error
  39. array = gstr.Split(gstr.Trim(key, DefaultSeparator), DefaultSeparator)
  40. )
  41. if len(array) < 6 {
  42. err = gerror.NewCodef(gcode.CodeInvalidParameter, `invalid service key "%s"`, key)
  43. return nil, err
  44. }
  45. s := &LocalService{
  46. Head: array[0],
  47. Deployment: array[1],
  48. Namespace: array[2],
  49. Name: array[3],
  50. Version: array[4],
  51. Endpoints: NewEndpoints(array[5]),
  52. Metadata: make(Metadata),
  53. }
  54. s.autoFillDefaultAttributes()
  55. if len(value) > 0 {
  56. if err = gjson.Unmarshal([]byte(value), &s.Metadata); err != nil {
  57. err = gerror.WrapCodef(gcode.CodeInvalidParameter, err, `invalid service value "%s"`, value)
  58. return nil, err
  59. }
  60. }
  61. return s, nil
  62. }
  63. // GetName returns the name of the service.
  64. // The name is necessary for a service, and should be unique among services.
  65. func (s *LocalService) GetName() string {
  66. return s.Name
  67. }
  68. // GetVersion returns the version of the service.
  69. // It is suggested using GNU version naming like: v1.0.0, v2.0.1, v2.1.0-rc.
  70. // A service can have multiple versions deployed at once.
  71. // If no version set in service, the default version of service is "latest".
  72. func (s *LocalService) GetVersion() string {
  73. return s.Version
  74. }
  75. // GetKey formats and returns a unique key string for service.
  76. // The result key is commonly used for key-value registrar server.
  77. func (s *LocalService) GetKey() string {
  78. serviceNameUnique := s.GetPrefix()
  79. serviceNameUnique += DefaultSeparator + s.Endpoints.String()
  80. return serviceNameUnique
  81. }
  82. // GetValue formats and returns the value of the service.
  83. // The result value is commonly used for key-value registrar server.
  84. func (s *LocalService) GetValue() string {
  85. b, err := gjson.Marshal(s.Metadata)
  86. if err != nil {
  87. intlog.Errorf(context.TODO(), `%+v`, err)
  88. }
  89. return string(b)
  90. }
  91. // GetPrefix formats and returns the key prefix string.
  92. // The result prefix string is commonly used in key-value registrar server
  93. // for service searching.
  94. //
  95. // Take etcd server for example, the prefix string is used like:
  96. // `etcdctl get /services/prod/hello.svc --prefix`
  97. func (s *LocalService) GetPrefix() string {
  98. s.autoFillDefaultAttributes()
  99. return DefaultSeparator + gstr.Join(
  100. []string{
  101. s.Head,
  102. s.Deployment,
  103. s.Namespace,
  104. s.Name,
  105. s.Version,
  106. },
  107. DefaultSeparator,
  108. )
  109. }
  110. // GetMetadata returns the Metadata map of service.
  111. // The Metadata is key-value pair map specifying extra attributes of a service.
  112. func (s *LocalService) GetMetadata() Metadata {
  113. return s.Metadata
  114. }
  115. // GetEndpoints returns the Endpoints of service.
  116. // The Endpoints contain multiple host/port information of service.
  117. func (s *LocalService) GetEndpoints() Endpoints {
  118. return s.Endpoints
  119. }
  120. func (s *LocalService) autoFillDefaultAttributes() {
  121. if s.Head == "" {
  122. s.Head = gcmd.GetOptWithEnv(EnvPrefix, DefaultHead).String()
  123. }
  124. if s.Deployment == "" {
  125. s.Deployment = gcmd.GetOptWithEnv(EnvDeployment, DefaultDeployment).String()
  126. }
  127. if s.Namespace == "" {
  128. s.Namespace = gcmd.GetOptWithEnv(EnvNamespace, DefaultNamespace).String()
  129. }
  130. if s.Version == "" {
  131. s.Version = gcmd.GetOptWithEnv(EnvVersion, DefaultVersion).String()
  132. }
  133. if s.Name == "" {
  134. s.Name = gcmd.GetOptWithEnv(EnvName).String()
  135. }
  136. }