Docker系列——Grafana+Prometheus+Node-exporter釘釘推送(四)

溫一壺清酒發表於2021-06-18

近期搭建的伺服器監控平臺,來進行一個總結。主要分為監控平臺的搭建、告警中心的配置以及訊息的推送。推送的話,支援多種終端。具體詳細可檢視之前的博文,在這裡羅列下,方便檢視。

Docker系列——Grafana+Prometheus+Node-exporter伺服器監控平臺(一)

Docker系列——Grafana+Prometheus+Node-exporter伺服器告警中心(二)

Docker系列——Grafana+Prometheus+Node-exporter微信推送(三)

釘釘推送

今天在之前的基礎上,再來寫一篇釘釘推送。其實,在此之前,也寫過了,只不過是結合jenkins推送訊息,Jenkins環境搭建(7)-整合釘釘訊息推送。操作配置也類似,具體我們來看。

新增機器人

新增機器人,具體步驟可參考jenkins那篇博文,裡面有詳細介紹。配置機器人也簡單,所以就不重複講的,直接去看就行。

新增webhook

結合Prometheus實現釘釘訊息推送,需要使用到webhook,webhook直接使用docker部署即可,開源地址

拉取映象

使用命令docker pull timonwong/prometheus-webhook-dingtalk 即可。

配置檔案

配置檔案不知道怎麼配,可以先啟動服務,不指定配置檔案,啟動後,到容器內檢視預設的配置檔案,然後對應修改即可。

進入目錄/prometheus/webhook-dingtalk,使用命令 vim config.yml,新增如下內容:

## Request timeout
# timeout: 5s

## Customizable templates path

## You can also override default template using `default_message`
## The following example to use the 'legacy' template from v0.3.0
# default_message:
#   title: '{{ template "legacy.title" . }}'
#   text: '{{ template "legacy.content" . }}'

## Targets, previously was known as "profiles"
targets:
  webhook1:
    url: https://oapi.dingtalk.com/robot/send?access_token=XXX
    message:                                                           
      # Use legacy template                                            
      title: {{ template "ding.link.title" . }}                 
   webhook_mention_all:
     url: https://oapi.dingtalk.com/robot/send?access_token=XXX
     mention:
       all: false

啟動服務

啟動服務,使用如下命令:

docker run -d --name webhook \
-p 8060:8060 \
-v /prometheus/webhook-dingtalk/config.yml:/prometheus/config.yml \
timonwong/prometheus-webhook-dingtalk:latest \
--ding.profile="webhook1=https://oapi.dingtalk.com/robot/send?access_token=XXX" \
--web.enable-ui

注意:博文中的access_token=XXX都是自己的釘釘機器人token。

告警配置

修改檔案alertmanager.yml,新增webhook_configs配置,配置如下:

global:
  resolve_timeout: 5m
  smtp_from: '{{ template "email.from" . }}'
  smtp_smarthost: 'smtp.qq.com:465'
  smtp_auth_username: '{{ template "email.from" . }}'
  smtp_auth_password: ''
  smtp_hello: 'qq.com'
  smtp_require_tls: false
  wechat_api_url: 'https://qyapi.weixin.qq.com/cgi-bin/'
  wechat_api_secret: ''
  wechat_api_corp_id: ''
templates:
  - '/etc/alertmanager/*.tmpl'
route:
  group_by: ['alertname']
  group_wait: 5s
  group_interval: 5s
  repeat_interval: 5m
  receiver: 'email'
receivers:
- name: 'email'
  email_configs:
  - to: '{{ template "email.to" . }}'
    html: '{{ template "email.html" . }}'
    send_resolved: true
    headers: { Subject: "{{ .CommonAnnotations.summary }}" }
    #insecure_skip_verify: true
  webhook_configs:
  - url: 'http://ip:8060/dingtalk/webhook1/send' # webhook1啟動服務配置
    send_resolved: true # 傳送已解決通知
  wechat_configs:
  - send_resolved: true
    to_party: '8'
    to_user: '@all'
    agent_id: ''
    corp_id: ''
    api_secret: ''
    api_url: 'https://qyapi.weixin.qq.com/cgi-bin/'
    message: '{{ template "wechat.html" . }}'
inhibit_rules:
  - source_match:
      severity: 'critical'
    target_match:
      severity: 'warning'
    equal: ['alertname', 'dev', 'instance']

配置好後,需要重啟alertmanager服務,使配置生效。

訊息推送

同樣的,將node服務停掉,檢視觸發後的訊息推送,檢測配置是否生效。推送如下

收到了如上訊息,說明配置是成功了的,但內容也是過多,不簡潔。老套路,我們來優化一下。

訊息模板

進入目錄/prometheus/webhook-dingtalk/templates,可以將原有的模板備份下,使用命令 vim default.tmpl,新增如下內容:

{{ define "__subject" }}[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .GroupLabels.SortedPairs.Values | join " " }} {{ if gt (len .CommonLabels) (len .GroupLabels
) }}({{ with .CommonLabels.Remove .GroupLabels.Names }}{{ .Values | join " " }}{{ end }}){{ end }}{{ end }}{{ define "__alertmanagerURL" }}{{ .ExternalURL }}/#/alerts?receiver={{ .Receiver }}{{ end }}

{{ define "__text_alert_list" }}{{ range . }}
**Labels**
{{ range .Labels.SortedPairs }}> - {{ .Name }}: {{ .Value | markdown | html }}
{{ end }}
**Annotations**
{{ range .Annotations.SortedPairs }}> - {{ .Name }}: {{ .Value | markdown | html }}
{{ end }}
**Source:** [{{ .GeneratorURL }}]({{ .GeneratorURL }})
{{ end }}{{ end }}

{{ define "default.__text_alert_list" }}{{ range . }}
---
**告警級別:** {{ .Labels.severity | upper }}

**運營團隊:** {{ .Labels.team | upper }}

**觸發時間:** {{ dateInZone "2006.01.02 15:04:05" (.StartsAt) "Asia/Shanghai" }}

**事件資訊:** 
{{ range .Annotations.SortedPairs }}> - {{ .Name }}: {{ .Value | markdown | html }}


{{ end }}

**事件標籤:**
{{ range .Labels.SortedPairs }}{{ if and (ne (.Name) "severity") (ne (.Name) "summary") (ne (.Name) "team") }}> - {{ .Name }}: {{ .Value | markdown | html }}
{{ end }}{{ end }}
{{ end }}
{{ end }}
{{ define "default.__text_alertresovle_list" }}{{ range . }}
---
**告警級別:** {{ .Labels.severity | upper }}

**運營團隊:** {{ .Labels.team | upper }}

**觸發時間:** {{ dateInZone "2006.01.02 15:04:05" (.StartsAt) "Asia/Shanghai" }}

**結束時間:** {{ dateInZone "2006.01.02 15:04:05" (.EndsAt) "Asia/Shanghai" }}

**事件資訊:**
{{ range .Annotations.SortedPairs }}> - {{ .Name }}: {{ .Value | markdown | html }}


{{ end }}

**事件標籤:**
{{ range .Labels.SortedPairs }}{{ if and (ne (.Name) "severity") (ne (.Name) "summary") (ne (.Name) "team") }}> - {{ .Name }}: {{ .Value | markdown | html }}
{{ end }}{{ end }}
{{ end }}
{{ end }}

{{/* Default */}}
{{ define "default.title" }}{{ template "__subject" . }}{{ end }}
{{ define "default.content" }}#### \[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}\] **[{{ index .GroupLabels "alertname" }}]({{ template "__alertmanagerURL" . }})**
{{ if gt (len .Alerts.Firing) 0 -}}

![警報 圖示](https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=3626076420,1196179712&fm=15&gp=0.jpg)

**====偵測到故障====**
{{ template "default.__text_alert_list" .Alerts.Firing }}


{{- end }}

{{ if gt (len .Alerts.Resolved) 0 -}}
{{ template "default.__text_alertresovle_list" .Alerts.Resolved }}


{{- end }}
{{- end }}

{{/* Legacy */}}
{{ define "legacy.title" }}{{ template "__subject" . }}{{ end }}
{{ define "legacy.content" }}#### \[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}\] **[{{ index .GroupLabels "alertname" }}]({{ template "__alertmanagerURL" . }})**
{{ template "__text_alert_list" .Alerts.Firing }}
{{- end }}

{{/* Following names for compatibility */}}
{{ define "ding.link.title" }}{{ template "default.title" . }}{{ end }}
{{ define "ding.link.content" }}{{ template "default.content" . }}{{ end }}

配置後,重新啟動webhook服務,需要將模板掛載到容器中,使用命令:

docker run -d --name webhook \
-p 8060:8060 \
-v /prometheus/webhook-dingtalk/templates/default.tmpl:/prometheus/templates/default.tmpl  \
-v /prometheus/webhook-dingtalk/config.yml:/prometheus/config.yml \
timonwong/prometheus-webhook-dingtalk:latest \
--ding.profile="webhook1=https://oapi.dingtalk.com/robot/send?access_token=XXX" \
--web.enable-ui

服務啟動成功後,我們可以訪問ui頁面,因為我們啟動服務時,開啟了ui頁面,http://ip:8060/ui/ ,可以檢視模板是否引用生效,如下所示:

我們可以看到,模板配置是生效了。

再次將對應服務停用,檢視收到的推送,如下所示:

模板引用,優化到這,就成功了。

prometheus-alert

在使用webhook時,嘗試了艾特人員功能,沒能成功,無意中找到另一個專案prometheus-alert,部署下試試,專案使用說明地址

拉取映象

使用命令 docker pull feiyu563/prometheus-alert:latest

配置檔案

配置檔案不知道怎麼配,可以先啟動服務,不指定配置檔案,啟動後,到容器內檢視預設的配置檔案,然後對應修改即可。

進入目錄 /prometheus/prometheusalert,使用命令 vim app.conf,新增如下內容:

#---------------------↓全域性配置-----------------------
appname = PrometheusAlert
#登入使用者名稱
login_user=XXX
#登入密碼
login_password=XXX
#監聽地址
httpaddr = "0.0.0.0"
#監聽埠
httpport = 8080
runmode = dev
#設定代理 proxy = http://123.123.123.123:8080
proxy =
#開啟JSON請求
copyrequestbody = true
#告警訊息標題
title=PrometheusAlert
#連結到告警平臺地址
GraylogAlerturl=http://graylog.org
#釘釘告警 告警logo圖示地址
logourl=https://raw.githubusercontent.com/feiyu563/PrometheusAlert/master/doc/alert-center.png
#釘釘告警 恢復logo圖示地址
rlogourl=https://raw.githubusercontent.com/feiyu563/PrometheusAlert/master/doc/alert-center.png
#簡訊告警級別(等於3就進行簡訊告警) 告警級別定義 0 資訊,1 警告,2 一般嚴重,3 嚴重,4 災難
messagelevel=3
#電話告警級別(等於4就進行語音告警) 告警級別定義 0 資訊,1 警告,2 一般嚴重,3 嚴重,4 災難
phonecalllevel=4
#預設撥打號碼(頁面測試簡訊和電話功能需要配置此項)
defaultphone=xxxxxxxx
#故障恢復是否啟用電話通知0為關閉,1為開啟
phonecallresolved=0
#自動告警抑制(自動告警抑制是預設同一個告警源的告警資訊只傳送告警級別最高的第一條告警資訊,其他訊息預設遮蔽,這麼做的目的是為了減少相同告警來源的訊息數量,防止告警炸彈,0為關閉,1為開啟)
silent=0
#是否前臺輸出file or console
logtype=file
#日誌檔案路徑
logpath=logs/prometheusalertcenter.log
#轉換Prometheus,graylog告警訊息的時區為CST時區(如預設已經是CST時區,請勿開啟)
prometheus_cst_time=0
#資料庫驅動,支援sqlite3,mysql,postgres如使用mysql或postgres,請開啟db_host,db_port,db_user,db_password,db_name的註釋
db_driver=sqlite3
#db_host=127.0.0.1
#db_port=3306
#db_user=root
#db_password=root
#db_name=prometheusalert

#---------------------↓webhook-----------------------
#是否開啟釘釘告警通道,可同時開始多個通道0為關閉,1為開啟
open-dingding=1
#預設釘釘機器人地址
ddurl=https://oapi.dingtalk.com/robot/send?access_token=XXX
#是否開啟 @所有人(0為關閉,1為開啟)
dd_isatall=1

#是否開啟微信告警通道,可同時開始多個通道0為關閉,1為開啟
open-weixin=1
#預設企業微信機器人地址
wxurl=https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxx

#是否開啟飛書告警通道,可同時開始多個通道0為關閉,1為開啟
open-feishu=0
#預設飛書機器人地址
fsurl=https://open.feishu.cn/open-apis/bot/hook/xxxxxxxxx

#---------------------↓騰訊雲介面-----------------------
#是否開啟騰訊雲簡訊告警通道,可同時開始多個通道0為關閉,1為開啟
open-txdx=0
#騰訊雲簡訊介面key
TXY_DX_appkey=xxxxx
#騰訊雲簡訊模版ID 騰訊雲簡訊模版配置可參考 prometheus告警:{1}
TXY_DX_tpl_id=xxxxx
#騰訊雲簡訊sdk app id
TXY_DX_sdkappid=xxxxx
#騰訊雲簡訊簽名 根據自己稽核通過的簽名來填寫
TXY_DX_sign=騰訊雲

#是否開啟騰訊雲電話告警通道,可同時開始多個通道0為關閉,1為開啟
open-txdh=0
#騰訊雲電話介面key
TXY_DH_phonecallappkey=xxxxx
#騰訊雲電話模版ID
TXY_DH_phonecalltpl_id=xxxxx
#騰訊雲電話sdk app id
TXY_DH_phonecallsdkappid=xxxxx

#---------------------↓華為雲介面-----------------------
#是否開啟華為雲簡訊告警通道,可同時開始多個通道0為關閉,1為開啟
open-hwdx=0
#華為雲簡訊介面key
HWY_DX_APP_Key=xxxxxxxxxxxxxxxxxxxxxx
#華為雲簡訊介面Secret
HWY_DX_APP_Secret=xxxxxxxxxxxxxxxxxxxxxx
#華為雲APP接入地址(埠介面地址)
HWY_DX_APP_Url=https://rtcsms.cn-north-1.myhuaweicloud.com:10743
#華為雲簡訊模板ID
HWY_DX_Templateid=xxxxxxxxxxxxxxxxxxxxxx
#華為雲簽名名稱,必須是已稽核通過的,與模板型別一致的簽名名稱,按照自己的實際簽名填寫
HWY_DX_Signature=華為雲
#華為雲簽名通道號
HWY_DX_Sender=xxxxxxxxxx

#---------------------↓阿里雲介面-----------------------
#是否開啟阿里雲簡訊告警通道,可同時開始多個通道0為關閉,1為開啟
open-alydx=0
#阿里雲簡訊主賬號AccessKey的ID
ALY_DX_AccessKeyId=xxxxxxxxxxxxxxxxxxxxxx
#阿里雲簡訊介面金鑰
ALY_DX_AccessSecret=xxxxxxxxxxxxxxxxxxxxxx
#阿里雲簡訊簽名名稱
ALY_DX_SignName=阿里雲
#阿里雲簡訊模板ID
ALY_DX_Template=xxxxxxxxxxxxxxxxxxxxxx

#是否開啟阿里雲電話告警通道,可同時開始多個通道0為關閉,1為開啟
open-alydh=0
#阿里雲電話主賬號AccessKey的ID
ALY_DH_AccessKeyId=xxxxxxxxxxxxxxxxxxxxxx
#阿里雲電話介面金鑰
ALY_DH_AccessSecret=xxxxxxxxxxxxxxxxxxxxxx
#阿里雲電話被叫顯號,必須是已購買的號碼
ALY_DX_CalledShowNumber=xxxxxxxxx
#阿里雲電話文字轉語音(TTS)模板ID
ALY_DH_TtsCode=xxxxxxxx

#---------------------↓容聯雲介面-----------------------
#是否開啟容聯雲電話告警通道,可同時開始多個通道0為關閉,1為開啟
RLY_DH_open-rlydh=0
#容聯雲基礎介面地址
RLY_URL=https://app.cloopen.com:8883/2013-12-26/Accounts/
#容聯雲後臺SID
RLY_ACCOUNT_SID=xxxxxxxxxxx
#容聯雲api-token
RLY_ACCOUNT_TOKEN=xxxxxxxxxx
#容聯雲app_id
RLY_APP_ID=xxxxxxxxxxxxx

#---------------------↓郵件配置-----------------------
#是否開啟郵件
open-email=0
#郵件發件伺服器地址
Email_host=smtp.qq.com
#郵件發件伺服器埠
Email_port=465
#郵件帳號
Email_user=xxxxxxx@qq.com
#郵件密碼
Email_password=xxxxxx
#郵件標題
Email_title=運維告警
#預設傳送郵箱
Default_emails=xxxxx@qq.com,xxxxx@qq.com

#---------------------↓七陌雲介面-----------------------
#是否開啟七陌簡訊告警通道,可同時開始多個通道0為關閉,1為開啟
open-7moordx=0
#七陌賬戶ID
7MOOR_ACCOUNT_ID=Nxxx
#七陌賬戶APISecret
7MOOR_ACCOUNT_APISECRET=xxx
#七陌賬戶簡訊模板編號
7MOOR_DX_TEMPLATENUM=n
#注意:七陌簡訊變數這裡只用一個var1,在程式碼裡寫死了。
#-----------
#是否開啟七陌webcall語音通知告警通道,可同時開始多個通道0為關閉,1為開啟
open-7moordh=0
#請在七陌平臺新增虛擬服務號、文字節點
#七陌賬戶webcall的虛擬服務號
7MOOR_WEBCALL_SERVICENO=xxx
# 文字節點裡被替換的變數,我配置的是text。如果被替換的變數不是text,請修改此配置
7MOOR_WEBCALL_VOICE_VAR=text

#---------------------↓telegram介面-----------------------
#是否開啟telegram告警通道,可同時開始多個通道0為關閉,1為開啟
open-tg=0
#tg機器人token
TG_TOKEN=xxxxx
#tg訊息模式 個人訊息或者頻道訊息 0為關閉(推送給個人),1為開啟(推送給頻道)
TG_MODE_CHAN=0
#tg使用者ID
TG_USERID=xxxxx
#tg頻道name
TG_CHANNAME=xxxxx
#tg api地址, 可以配置為代理地址
#TG_API_PROXY="https://api.telegram.org/bot%s/%s"

#---------------------↓workwechat介面-----------------------
#是否開啟workwechat告警通道,可同時開始多個通道0為關閉,1為開啟
open-workwechat=0
# 企業ID
WorkWechat_CropID=xxxxx
# 應用ID
WorkWechat_AgentID=xxxx
# 應用secret
WorkWechat_AgentSecret=xxxx
# 接受使用者
WorkWechat_ToUser="zhangsan|lisi"
# 接受部門
WorkWechat_ToParty="ops|dev"
# 接受標籤
WorkWechat_ToTag=""
# 訊息型別, 暫時只支援markdown
# WorkWechat_Msgtype = "markdown"

#---------------------↓百度雲介面-----------------------
#是否開啟百度雲簡訊告警通道,可同時開始多個通道0為關閉,1為開啟
open-baidudx=0
#百度雲簡訊介面AK(ACCESS_KEY_ID)
BDY_DX_AK=xxxxx
#百度雲簡訊介面SK(SECRET_ACCESS_KEY)
BDY_DX_SK=xxxxx
#百度雲簡訊ENDPOINT(ENDPOINT引數需要用指定區域的域名來進行定義,如服務所在區域為北京,則為)
BDY_DX_ENDPOINT=http://smsv3.bj.baidubce.com
#百度雲簡訊模版ID,根據自己稽核通過的模版來填寫(模版支援一個引數code:如prometheus告警:{code})
BDY_DX_TEMPLATE_ID=xxxxx
#百度雲簡訊簽名ID,根據自己稽核通過的簽名來填寫
TXY_DX_SIGNATURE_ID=xxxxx

#---------------------↓百度Hi(如流)-----------------------
#是否開啟百度Hi(如流)告警通道,可同時開始多個通道0為關閉,1為開啟
open-ruliu=0
#預設百度Hi(如流)機器人地址
BDRL_URL=https://api.im.baidu.com/api/msg/groupmsgsend?access_token=xxxxxxxxxxxxxx
#百度Hi(如流)群ID
BDRL_ID=123456

上述這麼多配置項,但我們這裡是結合釘釘使用,所以只配置webhook即可。

啟動服務

使用如下命令:

docker run -d -p 10:8080 --name prometheusalert-center \
-v /prometheus/prometheusalert/:/app/conf \
feiyu563/prometheus-alert:latest

啟動後,就可以通過ip+埠的方式訪問了,介面如下:

CPU監控

在之前說過記憶體監控,今天再來說下CPU監控,CPU是重點關注指標,具體配置我們來看。我們在原先的告警規則中,新增CPU監控規則,如下所示:

groups:
 - name: hostStatsAlert
   rules:
   - alert: hostCpuUsageAlert
     expr: 100 * (1 - avg(irate(node_cpu_seconds_total{mode="idle"}[2m])) by(instance)) > 85
     for: 1m
     labels:
       severity: page
     annotations:
       summary: "Instance {{ $labels.instance }} CPU usgae high"
       description: "{{ $labels.instance }} CPU usage above 85% (current value: {{ $value }})"
   - alert: hostMemUsageAlert
     expr: (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100 > 85
     for: 1m
     labels:
       severity: page
     annotations:
       summary: "Instance {{ $labels.instance }} MEM usgae high"
       description: "{{ $labels.instance }} MEM usage above 85% (current value: {{ $value }})"
   - alert: node-up
     expr: up{job="linux"} == 0
     for: 15s
     labels:
       severity: page
       team: node
     annotations:
       summary: "{{ $labels.instance }} 已停止執行超過 15s!"
       description: "{{ $labels.instance }} 檢測到異常停止!請重點關注!!!"

上述示例 hostCpuUsageAlert 規則,新增到/prometheus/rules目錄下的規則中,並重啟Prometheus服務,使配置生效。

重啟後,通過Prometheus服務檢視規則,如下所示:

注意:規則配置CPU使用率超過85%則會出發警報,正常情況下,不會輕易觸發,但又想檢測下規則是否能正常觸發,將85降低即可;也可以使用命令 cat /dev/zero>/dev/null 手動拉高CPU。

訊息推送

講到這,服務已經好了,規則也配置好了,但如何跟altermanager關聯起來呢,接著來看。

修改配置檔案alertmanager.yml,將webhook的url修改成如下內容:

- url: 'http://ip:10/prometheusalert?type=dd&tpl=prometheus-dd&ddurl=https://oapi.dingtalk.com/robot/send?access_token=XXX'

重啟alertmanager服務,檢視prometheusalert如下所示:

{{ $var := .externalURL}}{{ range $k,$v:=.alerts }}
{{if eq $v.status "resolved"}}
## [prometheus恢復資訊]({{$v.generatorURL}})
#### [{{$v.labels.alertname}}]({{$var}})
###### 告警級別:{{$v.labels.level}}
###### 開始時間:{{GetCSTtime $v.startsAt}}
###### 結束時間:{{GetCSTtime $v.endsAt}}
###### 故障主機IP:{{$v.labels.instance}}
##### {{$v.annotations.description}}
![Prometheus](https://raw.githubusercontent.com/feiyu563/PrometheusAlert/master/doc/alert-center.png)
{{else}}
## [prometheus告警資訊]({{$v.generatorURL}})
#### [{{$v.labels.alertname}}]({{$var}})
###### 告警級別:{{$v.labels.level}}
###### 開始時間:{{GetCSTtime $v.startsAt}}
###### 故障主機IP:{{$v.labels.instance}}
##### {{$v.annotations.description}}
![Prometheus](https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=3626076420,1196179712&fm=15&gp=0.jpg)
{{end}}
{{ end }}

一切就緒,我們來看最終效果,觸發CPU高於85%,在釘釘上查收訊息推送,告警訊息如下所示:

當CPU低於這個配置值時,釘釘同樣會收到恢復推送,如下所示:

伺服器監控,就暫時告一段落了,自己實踐一次,也收穫頗多,再接再厲。

相關文章