config.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. package config
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "io/ioutil"
  7. "os"
  8. "strings"
  9. "time"
  10. "github.com/fsnotify/fsnotify"
  11. "go.etcd.io/etcd/client"
  12. )
  13. var Conf *Configure
  14. const ConfigPath = "conf/common.json"
  15. // mysql 配置
  16. type MysqlConfig struct {
  17. User string `json:"user"`
  18. Password string `json:"password"`
  19. Addr string `json:"addr"`
  20. DefaultDB string `json:"default_db"`
  21. Charset string `json:"charset"`
  22. MaxIdle json.Number `json:"max_idle"`
  23. MaxConn json.Number `json:"max_conn"`
  24. }
  25. // redis 配置
  26. type RedisConfig struct {
  27. Addrs string `json:"addrs"`
  28. Password string `json:"password"`
  29. DefaultDB json.Number `json:"default_db"`
  30. PoolSize json.Number `json:"pool_size"`
  31. MinIdleConns json.Number `json:"min_idle_conns"`
  32. MaxRetries json.Number `json:"max_retries"`
  33. IsCluster string `json:"is_cluster"`
  34. }
  35. type ElasticConfig struct {
  36. Addr string `json:"addr"`
  37. Sniff string `json:"sniff"`
  38. }
  39. type LogConfig struct {
  40. MaxSize json.Number `json:"max_size"`
  41. MaxBackups json.Number `json:"max_backups"`
  42. MaxAge json.Number `json:"max_age"`
  43. DisableStacktrace string `json:"disable_stacktrace"`
  44. }
  45. type RPCNode struct {
  46. Scheme string `json:"scheme"`
  47. Name string `json:"name"`
  48. UpdateInterval json.Number `json:"update_interval"`
  49. MysqlDB string `json:"mysql_db"`
  50. RedisDB json.Number `json:"redis_db"`
  51. Log LogConfig `json:"log"`
  52. ServiceName string `json:"service_name"`
  53. ServicePort json.Number `json:"service_port"`
  54. }
  55. type RPCConfig struct {
  56. BasePath string `json:"base_path"`
  57. AuthCheck RPCNode `json:"gd_auth_check"`
  58. Crontab RPCNode `json:"gd_crontab"`
  59. }
  60. type RateLimitConf struct {
  61. RateLimitChannel string `json:"rate_limit_channel"`
  62. RescueTickerTime json.Number `json:"rescue_ticker_time"`
  63. }
  64. type DingDingConfig struct {
  65. AccessToken string `json:"access_token"`
  66. Secret string `json:"secret"`
  67. }
  68. type ThirdPartConfig struct {
  69. ZjcAppKey string `json:"zjc_app_key"`
  70. ZjcAppSecret string `json:"zjc_app_secret"`
  71. ZcrkEngineUserName string `json:"zcrk_engine_user_name"`
  72. ZcrkEnginePasswrod string `json:"zcrk_engine_passwrod"`
  73. ZcrkUserName string `json:"zcrk_user_name"`
  74. ZcrkPasswrod string `json:"zcrk_passwrod"`
  75. ZcrkUserNameOne string `json:"zcrk_user_name_one"`
  76. ZcrkPasswrodOne string `json:"zcrk_passwrod_one"`
  77. HttpProxyUrl string `json:"http_proxy_url" description:"数据源正向代理url"`
  78. EdAppId string `json:"ed_app_id"` // eds16787f343c1676853
  79. EdAppSecret string `json:"ed_app_secret"` // 3d3f47bef850c5a2b0c15d4b94b6b3a3
  80. C300Token string `json:"c_300_token"` // be318b5cf56c65e9172b8636699fcf17
  81. ArcbangAppId string `json:"arcbang_app_id"` // 476795160986910721
  82. ArcbangAppKey string `json:"arcbang_app_key"` // 897c86f2779341e88e38b3eb9acb384f
  83. NjKey string `json:"nj_key"` // E78E1F76-A9FE-4687-A3EB-198B7628D959
  84. DbDwkey string `json:"db_dwkey"` // chejinjia
  85. DbToken string `json:"db_token"` // chejinjia2017030
  86. DbEncKey string `json:"db_enc_key"` // 91724890
  87. ScViolationDwkey string `json:"sc_violation_dwkey"` // be2hjdeii1f90c5c55bfa0af7
  88. ScViolationToken string `json:"sc_violation_token"` // be2hjdeii1f90c5c55bfa0af7
  89. ScViolationEncKey string `json:"sc_violation_enc_key"` // 33725169
  90. MojiAppKey string `json:"moji_app_key"` // 25270402
  91. MojiAppSecret string `json:"moji_app_secret"` // bc1ec844f9a516919c85c09b1c75d682
  92. MojiAppCode string `json:"moji_app_code"` // fd4df24553a04d08a71a2566203a37db
  93. LcbAppCode string `json:"lcb_app_code"` // 3101
  94. LcbSecret string `json:"lcb_secret"` // b9b548a34220f097e6c22ca933f76a8e
  95. JhAppKey string `json:"jh_app_key"` // 1ef0aa20c3d4cbe71f4a799122625bb9
  96. ZxCompanyKey string `json:"zx_company_key"` // 001061808271603202J1I3Q1H0T2L
  97. ZxCompanyCode string `json:"zx_company_code"` // 65db6e13ecef31a54642df747986472a
  98. MsToken string `json:"ms_token"` // 81ed9993bcad8cd0d1f55f9565104b76
  99. ZqyKey string `json:"zqy_key"` // CETRo4r-KIkk05-uoyiE-20V7NU-Ab36
  100. ZhUser string `json:"zh_user"` // tangmimi
  101. ZhPwd string `json:"zh_pwd"` // E37A41FE3B1843E1AC46E6589CD76412
  102. ZzxAppKey string `json:"zzx_app_key"`
  103. ZzxUser string `json:"zzx_user"`
  104. ZjtAuthorizationCode string `json:"zjt_authorization_code"` // LkPw8252672h4NmF
  105. ZjtCryptoKey string `json:"zjt_crypto_key"` // Wuz2162IF9O60X58
  106. ZjtUserNo string `json:"zjt_user_no"` // SYZNCQCAR
  107. DjDwkey string `json:"dj_dwkey"` // wdhyiylhotoabycqtq
  108. DjToken string `json:"dj_token"` // MIYYKOUKIYKKKYWH081YOIYLIOJ
  109. DjEncKey string `json:"dj_enc_key"` // 91724890
  110. DjScDwkey string `json:"dj_sc_dwkey"` // whsc00081890080870
  111. DjScToken string `json:"dj_sc_token"` // MIYYKOUKIYKKKYWH081YOIYLIOJ
  112. DjScEncKey string `json:"dj_sc_enc_key"` // 91724890
  113. DjAppid string `json:"dj_appid"` // 9225417112424
  114. DjSecrtkey string `json:"dj_secrtkey"` // IYYTOKYLHBTLIYKYQUYLHYLIY
  115. DjScAppid string `json:"dj_sc_appid"` // 5524892445452455145
  116. DjScSecrtkey string `json:"dj_sc_secrtkey"` // YUOUIYOIYKHMJHUYUIOYLIYIKYIKYIJU
  117. SpyUserName string `json:"spy_user_name"`
  118. SpyPassWord string `json:"spy_pass_word"`
  119. JisuAppkey string `json:"jisu_appkey"`
  120. BjcUserName string `json:"bjc_user_name"`
  121. BjcPwd string `json:"bjc_pwd"`
  122. BjcLoginUrl string `json:"bjc_login_url"`
  123. DjVinAppid string `json:"dj_vin_appid"` // 9225417112424
  124. DjVinSecrtkey string `json:"dj_vin_secrtkey"` // IYYTOKYLHBTLIYKYQUYLHYLIY
  125. C003AppCode string `json:"c003_app_code"`
  126. DingTalkWebhook string `json:"ding_talk_webhook"`
  127. HystrixLoopTime json.Number `json:"hystrix_loop_time"`
  128. AdmAppkey string `json:"adm_appkey"`
  129. HystrixPublishChannel string `json:"hystrix_publish_channel"`
  130. DingDing DingDingConfig `json:"ding_ding"`
  131. RobotUrl string `json:"robot_url"`
  132. }
  133. type Configure struct {
  134. RunMode string `json:"run_mode"`
  135. AppKey string `json:"app_key"`
  136. AppSecret string `json:"app_secret"`
  137. Mysql MysqlConfig `json:"mysql"`
  138. Redis RedisConfig `json:"redis"`
  139. Elastic ElasticConfig `json:"elastic"`
  140. Rpc RPCConfig `json:"rpc"`
  141. GdInnerAccount string `json:"gd_inner_account"`
  142. RateLimit RateLimitConf `json:"rate_limit"`
  143. ThirdPart ThirdPartConfig `json:"third_part"`
  144. }
  145. func watchEtcd(keysAPI client.KeysAPI, index uint64, runmode, key string, cli client.Client) {
  146. basePath := fmt.Sprintf("/%s/config", runmode)
  147. watcherOptions := &client.WatcherOptions{
  148. AfterIndex: index,
  149. Recursive: true,
  150. }
  151. watcher := keysAPI.Watcher(basePath, watcherOptions)
  152. for {
  153. r, err := watcher.Next(context.Background())
  154. if err != nil || r == nil {
  155. break
  156. }
  157. if r.Node != nil && r.PrevNode != nil {
  158. if r.Node.Key == r.PrevNode.Key && (r.Node.Value != r.PrevNode.Value) {
  159. reloadEtcd(runmode, key, cli)
  160. }
  161. }
  162. if r.Node != nil && r.PrevNode == nil {
  163. reloadEtcd(runmode, key, cli)
  164. }
  165. }
  166. }
  167. func reloadEtcd(runmode, key string, cli client.Client) {
  168. keysAPI := client.NewKeysAPI(cli)
  169. basePath := fmt.Sprintf("/%s/config", runmode)
  170. if resp, err := keysAPI.Get(context.Background(), basePath, &client.GetOptions{
  171. Recursive: true,
  172. }); err == nil && resp != nil && resp.Node != nil {
  173. conf := &Configure{}
  174. value := getNodeData(key, resp.Node)
  175. if jsonStr, err := json.Marshal(value); err == nil {
  176. if err := json.Unmarshal(jsonStr, &conf); err == nil {
  177. *Conf = *conf
  178. return
  179. } else {
  180. fmt.Printf("json Unmarshal failed. error:%s", err)
  181. }
  182. } else {
  183. fmt.Printf("json Marshal failed. error:%s", err)
  184. }
  185. } else {
  186. fmt.Printf("get %s failed. error:%s", basePath, err)
  187. }
  188. }
  189. // key 为加密密钥
  190. func GetConfig(runmode, key string, cli client.Client) *Configure {
  191. keysAPI := client.NewKeysAPI(cli)
  192. basePath := fmt.Sprintf("/%s/config", runmode)
  193. if resp, err := keysAPI.Get(context.Background(), basePath, &client.GetOptions{
  194. Recursive: true,
  195. }); err == nil && resp != nil && resp.Node != nil {
  196. Conf = &Configure{}
  197. value := getNodeData(key, resp.Node)
  198. if jsonStr, err := json.Marshal(value); err == nil {
  199. if err := json.Unmarshal(jsonStr, &Conf); err == nil {
  200. go watchEtcd(keysAPI, resp.Index, runmode, key, cli)
  201. return Conf
  202. } else {
  203. fmt.Printf("json Unmarshal failed. error:%s", err)
  204. }
  205. } else {
  206. fmt.Printf("json Marshal failed. error:%s", err)
  207. }
  208. } else {
  209. fmt.Printf("get %s failed. error:%s", basePath, err)
  210. os.Exit(1)
  211. }
  212. return nil
  213. }
  214. // 递归取出node的叶子节点值
  215. func getNodeData(key string, head *client.Node) (value interface{}) {
  216. s0 := strings.Split(head.Key, "/")
  217. len0 := len(s0)
  218. if len0 == 0 {
  219. return
  220. }
  221. if head.Dir {
  222. mapData := map[string]interface{}{}
  223. for _, node := range head.Nodes {
  224. s1 := strings.Split(node.Key, "/")
  225. len1 := len(s1)
  226. if len1 == 0 {
  227. break
  228. }
  229. mapData[s1[len1-1]] = getNodeData(key, node)
  230. }
  231. value = mapData
  232. } else {
  233. if key != "" && head.Value != "" {
  234. if bytesData, err := Base64URLDecode(head.Value); err != nil {
  235. fmt.Printf("Base64URLDecode(%s) failed. error:%s", head.Value, err)
  236. os.Exit(1)
  237. } else {
  238. if data, err := AesDecrypt(bytesData, []byte(key)); err != nil {
  239. fmt.Printf("AesDecrypt failed. error:%s", err)
  240. os.Exit(1)
  241. } else {
  242. value = string(data)
  243. }
  244. }
  245. } else {
  246. // 无加密,直接取值
  247. value = head.Value
  248. }
  249. }
  250. return
  251. }
  252. // 适配k8s 方式
  253. // 公共配置会以configmap的方式映射到容器的conf/common.json中
  254. func GetConfigForK8s() *Configure {
  255. buffer, err := ioutil.ReadFile(ConfigPath)
  256. if err != nil {
  257. fmt.Printf("get %s failed. error:%s", ConfigPath, err)
  258. return nil
  259. }
  260. Conf = &Configure{}
  261. if err := json.Unmarshal(buffer, Conf); err != nil {
  262. fmt.Printf("json Unmarshal failed. error:%s", err)
  263. return nil
  264. }
  265. go watchConfigFileForK8s()
  266. return Conf
  267. }
  268. func ReloadConfigForK8s() {
  269. buffer, err := ioutil.ReadFile(ConfigPath)
  270. if err != nil {
  271. fmt.Printf("get %s failed. error:%s", ConfigPath, err)
  272. }
  273. confTmp := &Configure{}
  274. if err := json.Unmarshal(buffer, confTmp); err != nil {
  275. fmt.Printf("json Unmarshal failed. error:%s", err)
  276. }
  277. Conf = confTmp
  278. }
  279. // 判断路径文件/文件夹是否存在
  280. func Exists(path string) bool {
  281. _, err := os.Stat(path)
  282. if err != nil {
  283. if os.IsExist(err) {
  284. return true
  285. }
  286. return false
  287. }
  288. return true
  289. }
  290. func watchConfigFileForK8s() {
  291. fileExist := true
  292. watch, err := fsnotify.NewWatcher()
  293. if err != nil {
  294. fmt.Printf("new file watcher failed\n\n")
  295. os.Exit(1)
  296. }
  297. defer watch.Close()
  298. /*err = watch.Add(ConfigPath)
  299. if err != nil {
  300. fmt.Printf("add file watcher failed\n\n")
  301. os.Exit(1)
  302. }*/
  303. for {
  304. // 判断文件是否存在
  305. if !Exists(ConfigPath) {
  306. time.Sleep(10 * time.Second)
  307. fileExist = false
  308. continue
  309. } else {
  310. watch.Remove(ConfigPath)
  311. watch.Add(ConfigPath)
  312. if !fileExist { // 文件重新创建
  313. ReloadConfigForK8s()
  314. }
  315. fileExist = true
  316. }
  317. select {
  318. case ev := <-watch.Events:
  319. {
  320. fmt.Println("op : ", ev.Op)
  321. ReloadConfigForK8s()
  322. }
  323. case err := <-watch.Errors:
  324. {
  325. fmt.Println("error : ", err)
  326. continue
  327. }
  328. }
  329. }
  330. }