github.com/isyscore/isc-gobase@v1.5.3-0.20231218061332-cbc7451899e9/debug/README.md (about)

     1  # 调试包
     2  调试包用于为应用提供在线上时候的一些观察和调试能力,目前分为两个部分
     3  - 单实例配置调试功能
     4  - 集群化配置变更功能
     5  
     6  配置
     7  ```yaml
     8  base:
     9    debug:
    10      # 线上调试功能开启,默认开启
    11      enable: true
    12  ```
    13  
    14  # 一、单实例配置调试功能
    15  通过提供restful的方式,给业务提供诸多功能用于单实例的线上调试功能<br/>
    16  
    17  - 动态修改日志级别
    18  - 动态打印接口出入参
    19  - 动态查看管理的bean
    20  - 动态启用pprof
    21  
    22  ## 1. 帮助手册
    23  命令很多,提供帮助手册
    24  ```shell
    25  curl http://localhost:xxx/{api-prefix}/{api-module}/debug/help
    26  ```
    27  
    28  示例:<br/>
    29  ```json
    30  {
    31    "-============================================================================================================================================================================================": "",
    32    "1.-【帮助】": "---------------------: curl http://localhost:8080/api/demo/debug/help",
    33    "2.-": "========================【日志】===========================================================================================================================================================",
    34    "2.1 动态修改日志": "-----------------: curl -X PUT http://localhost:8080/api/demo/config/update -d '{\"key\":\"base.logger.level\", \"value\":\"debug\"}'",
    35    "3.-": "===================【接口出入参】===========================================================================================================================================================",
    36    "3.1 指定url打印请求": "--------------: curl -X PUT http://localhost:8080/api/demo/config/update -d '{\"key\":\"base.server.request.print.include-uri[0]\", \"value\":\"/api/xx/xxx\"}'",
    37    "3.2 指定url不打印请求": "------------: curl -X PUT http://localhost:8080/api/demo/config/update -d '{\"key\":\"base.server.request.print.exclude-uri[0]\", \"value\":\"/api/xx/xxx\"}'",
    38    "3.3 指定url打印请求和响应": "---------: curl -X PUT http://localhost:8080/api/demo/config/update -d '{\"key\":\"base.server.response.print.include-uri[0]\", \"value\":\"/api/xx/xxx\"}'",
    39    "3.4 指定url不打印请求和响应": "-------: curl -X PUT http://localhost:8080/api/demo/config/update -d '{\"key\":\"base.server.response.print.exclude-uri[0]\", \"value\":\"/api/xx/xxx\"}'",
    40    "4.-": "===================【bean管理】============================================================================================================================================================",
    41    "4.1 获取注册的所有bean": "-----------: curl http://localhost:8080/api/demo/bean/name/all",
    42    "4.2 查询注册的bean": "--------------: curl http://localhost:8080/api/demo/bean/name/list/{name}",
    43    "4.3 查询bean的属性值": "-------------: curl -X POST http://localhost:8080/api/demo/bean/field/get' -d '{\"bean\": \"xx\", \"field\":\"xxx\"}'",
    44    "4.4 修改bean的属性值": "-------------: curl -X POST http://localhost:8080/api/demo/bean/field/set' -d '{\"bean\": \"xx\", \"field\": \"xxx\", \"value\": \"xxx\"}'",
    45    "4.5 调用bean的函数": "--------------: curl -X POST http://localhost:8080/api/demo/bean/fun/call' -d '{\"bean\": \"xx\", \"fun\": \"xxx\", \"parameter\": {\"p1\":\"xx\", \"p2\": \"xxx\"}}'",
    46    "5.-": "=====================【pprof】============================================================================================================================================================",
    47    "5.1 动态启用pprof": "---------------: curl -X PUT http://localhost:8080/api/demo/config/update -d '{\"key\":\"base.server.gin.pprof.enable\", \"value\":\"true\"}'",
    48    "6.-": "===================【配置处理】=============================================================================================================================================================",
    49    "6.1 服务所有配置": "----------------: curl http://localhost:8080/api/demo/config/values",
    50    "6.2 服务所有配置(yaml结构)": "-------: curl http://localhost:8080/api/demo/config/values/yaml",
    51    "6.3 服务某个配置": "----------------: curl http://localhost:8080/api/demo/config/value/{key}",
    52    "6.4 修改服务的配置": "--------------: curl -X PUT http://localhost:8080/api/demo/config/update -d '{\"key\":\"xxx\", \"value\":\"yyy\"}'",
    53    "===============================================================================================================================================================================================": ""
    54  }
    55  ```
    56  
    57  ## 2. 动态修改日志
    58  在出现问题时候,希望开启debug日志,这里提供了动态修改的功能,如下
    59  ```shell
    60  curl -X PUT http://localhost:xxx/{api-prefix}/{api-module}/config/update -d '{"key":"base.logger.level", "value":"debug"}'
    61  ```
    62  
    63  提示:<br/>
    64  目前日志级别粒度比较粗,比如修改了级别为debug后,则大于等于debug的级别都会打印,粒度还是比较粗,建议后续增加日志分组概念
    65  
    66  
    67  ## 3. 接口动态打印
    68  在出现问题时候如何确定接口是否正常,要开启请求和响应的话,就方便多了,这里提供了该功能
    69  
    70  ### 指定uri
    71  如果不指定uri则会默认打印所有的请求
    72  ```shell
    73  # 指定要打印的请求的uri
    74  curl -X PUT http://localhost:xxx/{api-prefix}/{api-module}/config/update -d '{"key":"base.server.request.print.include-uri[0]", "value":"/api/xx/xxx"}'
    75  # 指定不要打印的请求uri
    76  curl -X PUT http://localhost:xxx/{api-prefix}/{api-module}/config/update -d '{"key":"base.server.request.print.exclude-uri[0]", "value":"/api/xx/xxx"}'
    77  
    78  # 指定要打印的响应的uri
    79  curl -X PUT http://localhost:xxx/{api-prefix}/{api-module}/config/update -d '{"key":"base.server.response.print.include-uri[0]", "value":"/api/xx/xxx"}'
    80  # 指定不要打印的响应uri
    81  curl -X PUT http://localhost:xxx/{api-prefix}/{api-module}/config/update -d '{"key":"base.server.response.print.exclude-uri[0]", "value":"/api/xx/xxx"}'
    82  ```
    83  
    84  提示:<br/>
    85  - 如果"请求"和"响应"都开启打印,则只会打印"响应",因为响应中已经包括了"请求"
    86  - 指定多个uri的话,如下,配置其实是按照properties的方式进行指定的
    87  ```shell
    88  curl -X PUT http://localhost:xxx/{api-prefix}/{api-module}/config/update -d '{"key":"base.server.request.print.include-uri[0]", "value":"/api/xx/xxx"}'
    89  curl -X PUT http://localhost:xxx/{api-prefix}/{api-module}/config/update -d '{"key":"base.server.request.print.include-uri[1]", "value":"/api/xx/xxy"}'
    90  curl -X PUT http://localhost:xxx/{api-prefix}/{api-module}/config/update -d '{"key":"base.server.request.print.include-uri[2]", "value":"/api/xx/xxz"}'
    91  ...
    92  ```
    93  ### 开启打印
    94  注意:开启打印的话,所有的接口都会打印,所以建议请先指定uri
    95  ```shell
    96  # 开启请求的打印
    97  curl -X PUT http://localhost:xxx/{api-prefix}/{api-module}/config/update -d '{"key":"base.server.request.print.enable", "value":"true"}'
    98  # 开启响应的打印
    99  curl -X PUT http://localhost:xxx/{api-prefix}/{api-module}/config/update -d '{"key":"base.server.request.print.enable", "value":"true"}'
   100  # 开启异常的打印
   101  curl -X PUT http://localhost:xxx/{api-prefix}/{api-module}/config/update -d '{"key":"base.server.exception.print.enable", "value":"true"}'
   102  ```
   103  ## 4. 动态管理bean
   104  在运行中如果出现问题,需要查看某个对象的属性和函数的时候,就可以使用该功能,进行动态的查看、修改对应属性,以及动态的执行对应的函数
   105  
   106  ### 注意:
   107  要使用该功能,前提是要先将对象注册到bean管理里面才行,否则是查询不到的,目前还需要手动添加到bean包管理里面<br/>
   108  示例:
   109  ```shell
   110    tt := TestEntity{Name: "hello", Age: 12}
   111    // 请使用指针
   112    bean.AddBean("test", &tt)
   113  ```
   114  
   115  ```shell
   116  # 获取注册的所有bean
   117  curl http://localhost:xxx/{api-prefix}/{api-module}/bean/name/all'
   118  # 查询注册的某些bean 
   119  curl http://localhost:xxx/{api-prefix}/{api-module}/bean/name/list/:name'
   120  # 查询某个bean的属性值
   121  curl -X POST http://localhost:xxx/{api-prefix}/{api-module}/bean/field/get' -d '{"bean": "xx", "field": "xxx"}'
   122  # 修改某个bean的属性的值
   123  curl -X PUT http://localhost:xxx/{api-prefix}/{api-module}/bean/field/set' -d '{"bean": "xx", "field": "xxx", "value": "xxx"}'
   124  # 调用bean的某个函数
   125  curl -X POST http://localhost:xxx/{api-prefix}/{api-module}/bean/fun/call' -d '{"bean": "xx", "fun": "xxx", "parameter": {"p1":"xx", "p2": "xxx"}}'
   126  ```
   127  
   128  注意:<br/>
   129  - 调用bean函数中,parameter的对应的map中的key只能是p1、p2、p3...这种表示的是第一个、第二个、第三个参数的值
   130  - 调用bean函数中,参数值暂时只适用于基本结构,对于实体类或者map类的暂时不支持,后续可以考虑支持
   131  
   132  ## 5. 动态启用pprof
   133  在线上出现性能问题后,本地如果要排查则很有可能复现不了,如果可以直接在线上开启pprof功能的话,就非常好了,这里提供了动态开启pprof的功能
   134  ```shell
   135  # 开启pprof
   136  curl -X PUT http://localhost:xxx/{api-prefix}/{api-module}/config/update -d '{"key":"base.server.gin.pprof.enable", "value":"true"}'
   137  ```
   138  
   139  注意:<br/>
   140  启用pprof对业务性能会产生一定的影响,不过影响不大,对于正式业务不是长久之计,因此如果想要业务恢复过来,只有重启
   141  
   142  
   143  ### 示例:
   144  然后就可以基于web端口xxx来使用pprof了,具体pprof用法这里不做介绍,这里举一个简单例子。开启开关后,我们执行如下pprof命令即可排查相关问题
   145  ```shell
   146  # 其中18080是新开的一个网页端口用于在该端口内查看信息,默认30秒
   147  go tool pprof -http=:18080 http://localhost:xxx/debug/pprof/goroutine
   148  ```
   149  然后自动打开网页,如下
   150  ![pprof.png](./pic/pprof.png)
   151  
   152  # 二、集群化配置变更功能
   153  
   154  集群化的配置变更功能目前底层使用的是etcd,因此需要接入如下
   155  ```yaml
   156  debug:
   157    # 线上调试功能开启,默认:true-开启
   158    enable: true
   159    etcd:
   160      # 多个域名配置,中间逗号分隔
   161      endpoints: {ip}:{port},{ip}:{port},{ip}:{port}
   162      # 用户名
   163      user: xxx
   164      # 密码
   165      password: xxx
   166  ```
   167  
   168  提供如下三个api
   169  ```go
   170  // 初始化相关信息
   171  func Init() {}
   172  
   173  // 添加对某个key的监听
   174  func AddWatcher(key string, keyListener KeyListener) {}
   175  
   176  // 开始监听
   177  func StartWatch() {}
   178  
   179  // 更新某个key
   180  func Update(key, value string) {}
   181  ```
   182  
   183  示例
   184  ```go
   185  // 测试监听
   186  func TestWatcher(t *testing.T) {
   187      debug.Init()
   188      debug.AddWatcher("test", func(key string, value string) {
   189          fmt.Println("有变化 key=", key, ", value=", value)
   190      })
   191      debug.StartWatch()
   192      t0.Sleep(1000000000000)
   193  }
   194  
   195  // 测试推送
   196  func TestWatcher(t *testing.T) {
   197      debug.Init()
   198      debug.Update("test", time.TimeToStringYmdHmsS(time.Now()))
   199  }
   200  ```
   201  
   202  #### 说明:debug包和etcd包区别
   203  可能有人会问题了,debug功能与etcd的watch差不多,为什么还需要再提供一个debug包,etcd本身提供的watch功能比较强大,在业务使用时候还需要做一些适配和改造,比如如下功能
   204  - 集群中某个节点宕机,这个时候配置变化了,该节点并没有watch到结果,重启后也获取不到最新的值,就会造成集群中所有节点数据不一致的问题
   205  
   206  debug对etcd的watch功能做了简单的封装