Configuration

go-doudou supports dotenv and yaml format local configuration file, and Alibaba Nacos configuration center and Ctrip Apollo configuration center out-of-box. go-doudou loads configuration from these sources to environment variables.

Comparing with remote configuration center local configuration files have higher priority, so value of each environment variable loaded from local files won't be overridden by configuration from remote center.

Local Configuration File

The usage of dotenv and yaml files are the same, only naming rules are different. They will be explained separately below.

TIP

Files with different format can be used together, or you can use only one kind of format. If used together, yaml files have higher priority. After all yaml files loaded, dotenv files loads.

Dotenv File

If you have multiple .env files, such as .env.test, .env.prod to configure different environment, you can set GDD_ENV environment variable to test or prod by terminal, Dockerfile or k8s file to load corresponding file.

Configuration Loading Rule:

  1. For one environment variable, no matter where be configured, first value has highest priority, won't be overridden by later values
  2. Using prod as example, loading order is:
    1. Load .env.prod.local
    2. If GDD_ENV != test, load .env.local
    3. Load .env.prod
    4. Load .env

Note:file name must be prefixed with .env

Yaml File

Support both .yml suffixed and .yaml suffixed files. If you have multiple yaml files, such as app-test.yml, app-prod.yml to configure different environment, you can set GDD_ENV environment variable to test or prod by terminal, Dockerfile or k8s file to load corresponding file.

Configuration Loading Rule:

  1. For one environment variable, no matter where be configured, first value has highest priority, won't be overridden by later values
  2. Using prod as example, loading order is:
    1. Load app-prod-local.yml
    2. If GDD_ENV != test, load app-local.yml
    3. Load app-prod.yml
    4. Load app.yml

Note:file name must be prefixed with app

Remote Configuration Solution

go-doudou has built-in support for two remote configuration solution: Nacos from Alibaba and Apollo from Ctrip to load configuration when start and customize listener to react to config change event.

To enable remote configuration support, you should configure below environment variable in local configuration file:

  • GDD_CONFIG_REMOTE_TYPE: remote configuration center name,options:nacosapollo

TIP

There are some go-doudou native configuration (GDD_ prefixed) in Service Configuration and Memberlist Configuration supporting be configured in runtime by reacting to change event from remote configuration center. Dynamic configuration have highest priority, can override old configuration from any other sources.

Nacos Configuration Center

go-doudou will load configuration from Nacos server when service start out-of-box. You just need to add some configuration in local configuration files.

  • GDD_NACOS_NAMESPACE_ID: Nacos namespaceId, not required
  • GDD_NACOS_SERVER_ADDR: Nacos server connection url, required
  • GDD_NACOS_CONFIG_FORMAT: configuration data format, options: dotenv(default), yaml
  • GDD_NACOS_CONFIG_GROUP: Nacos group, default is DEFAULT_GROUP
  • GDD_NACOS_CONFIG_DATAID: Nacos dataId, required, multiple dataId should be separated by comma. Loading order is the same as configuration order, so first loaded value has highest priority.

There is exported singleton NacosClient from configmgr for communicating with Nacos configuration center, you can call AddChangeListener method to add custom event listener. For example:

func main() {

	...

	if configmgr.NacosClient != nil {
		configmgr.NacosClient.AddChangeListener(configmgr.NacosConfigListenerParam{
			DataId: "statsvc-dev",
			OnChange: func(event *configmgr.NacosChangeEvent) {
				fmt.Println("group:" + event.Group + ", dataId:" + event.DataId + fmt.Sprintf(", changes: %+v\n", event.Changes))
			},
		})
	}

	...

	srv.Run()
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Apollo Configuration Center

go-doudou will load configuration from Apollo server when service start out-of-box. You just need to add some configuration in local configuration files.

  • GDD_SERVICE_NAME: Apollo AppId
  • GDD_APOLLO_CLUSTER: Apollo cluster, default is default
  • GDD_APOLLO_ADDR: Apollo server connection url, required
  • GDD_APOLLO_NAMESPACE: Apollo namespace, just like dataId for Nacos, default is application.properties, multiple dataId should be separated by comma. Loading order is the same as configuration order, so first loaded value has highest priority.
  • GDD_APOLLO_SECRET: Apollo secret, not required

There is exported singleton ApolloClient from configmgr for communicating with Nacos configuration center, you can call AddChangeListener method to add custom event listener. For example:

type ConfigChangeListener struct {
	configmgr.BaseApolloListener
}

func (c *ConfigChangeListener) OnChange(event *storage.ChangeEvent) {
	c.Lock.Lock()
	defer c.Lock.Unlock()
	if !c.SkippedFirstEvent {
		c.SkippedFirstEvent = true
		return
	}
	logger.Info("from OnChange")
	fmt.Println(event.Changes)
	for key, value := range event.Changes {
		fmt.Println("change key : ", key, ", value :", value)
	}
	fmt.Println(event.Namespace)
	logger.Info("from OnChange end")
}

func main() {

    ...

	var listener ConfigChangeListener

	configmgr.ApolloClient.AddChangeListener(&listener)

    ...

	srv.Run()
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

Here is additional note: custom event listener will also react to the very first configuration loading event when service start, if you need to skip it, you should "extend" BaseApolloListener struct from configmgr package, then add below code to the beginning of OnChange function

c.Lock.Lock()
defer c.Lock.Unlock()
if !c.SkippedFirstEvent {
  c.SkippedFirstEvent = true
  return
}
1
2
3
4
5
6

Service Configuration

Red asterisk marked configuration can be dynamically changed in runtime by go-doudou listening to change events from remote configuration center.

Environment VariableDescriptionDefaultRequired
GDD_BANNERwhether output banner to stdout or not to consoletrue
GDD_BANNER_TEXTgo-doudou
GDD_LOG_LEVELpossible values are panic, fatal, error, warn, warning, info, debug, traceinfo
GDD_LOG_FORMATset log format to text or json, possible values are text and jsontext
GDD_LOG_REQ_ENABLEenable request and response loggingfalse
GDD_GRACE_TIMEOUTgraceful shutdown timeout for http server15s
GDD_WRITE_TIMEOUThttp server connection write timeout15s
GDD_READ_TIMEOUThttp server connection read timeout15s
GDD_IDLE_TIMEOUThttp server connection idle timeout60s
GDD_ROUTE_ROOT_PATHprefix string to each of http api routes
GDD_SERVICE_NAMEservice nameYes
GDD_HOSThost for the http server to listen on
GDD_PORTport for the http server to listen on6060
GDD_GRPC_PORTport for the gRPC server to listen50051
GDD_RETRY_COUNTclient retry count0
GDD_MANAGE_ENABLEenable built-in api endpoints such as /go-doudou/doc, /go-doudou/openapi.json, /go-doudou/prometheus, /go-doudou/registry and /go-doudou/configtrue
*GDD_MANAGE_USERhttp basic username for built-in api endpointsadmin
*GDD_MANAGE_PASShttp basic password for built-in api endpointsadmin
GDD_TRACING_METRICS_ROOTmetrics root for jaeger tracinggo-doudou
GDD_WEIGHTservice instance weight1
GDD_SERVICE_DISCOVERY_MODEservice discovery mode, available options: memberlist and nacosmemberlist
GDD_ENABLE_RESPONSE_GZIPenable http response gzip compressiontrue
GDD_SQL_LOG_ENABLEenable sql loggingfalse

Memberlist Configuration

Red asterisk marked configuration can be dynamically changed in runtime by go-doudou listening to change events from remote configuration center. These configuration can be used to adjust gossip message convergence speed, in other words, how fast service list cached in each service instance memory become consistent.

Environment VariableDescriptionDefaultRequired
GDD_MEM_SEEDseed address for join memberlist cluster. If empty or not set, this node will create a new cluster for other nodes to join
GDD_MEM_NAMEfor dev and test purpose only. unique name of this node in cluster. if empty or not set, hostname will be used instead
GDD_MEM_HOSTspecify AdvertiseAddr attribute of memberlist config struct. if GDD_MEM_HOST starts with dot such as .seed-svc-headless.default.svc.cluster.local, it will be prefixed with hostname to be seed-2.seed-svc-headless.default.svc.cluster.local for supporting k8s statefulset service. By default, private ip is used
GDD_MEM_PORTTCP and UDP port for memberlist instance to listen on7946
*GDD_MEM_DEAD_TIMEOUTdead node will be removed from node map if not received refute messages from it in GDD_MEM_DEAD_TIMEOUT duration60s
*GDD_MEM_SYNC_INTERVALlocal node will synchronize states from other random node every GDD_MEM_SYNC_INTERVAL duration60s
*GDD_MEM_RECLAIM_TIMEOUTdead node will be replaced with new node with the same name but different full address in GDD_MEM_RECLAIM_TIMEOUT duration3s
*GDD_MEM_PROBE_INTERVALping remote nodes for failure detection every GDD_MEM_PROBE_INTERVAL duration5s
*GDD_MEM_PROBE_TIMEOUTprobe fail if not receive ack message in GDD_MEM_PROBE_TIMEOUT duration3s
*GDD_MEM_SUSPICION_MULTThe multiplier for determining the time an inaccessible node is considered suspect before declaring it dead6
*GDD_MEM_RETRANSMIT_MULTThe multiplier for the number of retransmissions that are attempted for messages broadcasted over gossip4
*GDD_MEM_GOSSIP_NODEShow many remote nodes you want to send gossip messages4
*GDD_MEM_GOSSIP_INTERVALgossip messages in queue every GDD_MEM_GOSSIP_INTERVAL duration500ms
*GDD_MEM_INDIRECT_CHECKSthe number of nodes that will be asked to perform an indirect probe of a node in the case a direct probe fails3
GDD_MEM_TCP_TIMEOUTTCP request will timeout in GDD_MEM_TCP_TIMEOUT duration30s
GDD_MEM_WEIGHTDeprecated node weight for smooth weighted round-robin balancing0
GDD_MEM_WEIGHT_INTERVALnode weight will be calculated every GDD_MEM_WEIGHT_INTERVAL0s
GDD_MEM_LOG_DISABLEwhether disable memberlist loggingfalse
GDD_MEM_CIDRS_ALLOWEDIf not set, allow any connection (default), otherwise specify all networks allowed connecting (you must specify IPv6/IPv4 separately). Example: GDD_MEM_CIDRS_ALLOWED=172.28.0.0/16

Nacos Configuration

Environment VariableDescriptionDefaultRequired
GDD_NACOS_NAMESPACE_IDthe namespaceId of Nacospublic
GDD_NACOS_TIMEOUT_MStimeout for requesting Nacos server in milliseconds10000
GDD_NACOS_NOT_LOAD_CACHE_AT_STARTnot to load persistent nacos service info in CacheDir at start timefalse
GDD_NACOS_LOG_DIRthe directory for log/tmp/nacos/log
GDD_NACOS_CACHE_DIRthe directory for persist nacos service info/tmp/nacos/cache
GDD_NACOS_LOG_LEVELthe level of log, it's must be debug,info,warn,errorinfo
GDD_NACOS_SERVER_ADDRnacos server connection url, multiple urls are joined by comma
GDD_NACOS_REGISTER_HOSTservice instance host to be registered to nacos server, if not set, private ip is used by default
GDD_NACOS_CONFIG_FORMATconfiguration data format, options: dotenv, yamldotenv
GDD_NACOS_CONFIG_GROUPconfiguration groupDEFAULT_GROUP
GDD_NACOS_CONFIG_DATAIDconfiguration dataIdYes

Apollo Configuration

Environment VariableDescriptionDefaultRequired
GDD_APOLLO_CLUSTERapollo clusterdefault
GDD_APOLLO_ADDRapollo config service addressYes
GDD_APOLLO_NAMESPACEapollo namespaceapplication.properties
GDD_APOLLO_BACKUP_ENABLEenable local disk cache of configurationtrue
GDD_APOLLO_BACKUP_PATHthe directory for local disk cache of configuration
GDD_APOLLO_MUSTSTARTif failed to connect to apollo config service, return error immediatelyfalse
GDD_APOLLO_SECRETapollo configuration secret
GDD_APOLLO_LOG_ENABLEenable print apollo logfalse