This is an automated email from the ASF dual-hosted git repository.
xuetaoli pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/dubbo-go-samples.git
The following commit(s) were added to refs/heads/main by this push:
new 8af31d88 feat: samples for k8s probe (#1033)
8af31d88 is described below
commit 8af31d88afd2bffc9b31ec9d5af67936d44cd04a
Author: Xuetao Li <[email protected]>
AuthorDate: Mon Mar 16 16:40:24 2026 +0800
feat: samples for k8s probe (#1033)
* feat: samples for k8s probe
* import format
* add integrate test for probe
* fix comment
---
README.md | 4 +-
README_CN.md | 4 +-
metrics/probe/README.md | 166 +++++++++++++++++++
metrics/probe/README_CN.md | 177 +++++++++++++++++++++
metrics/probe/deploy/server-deployment.yml | 43 +++++
metrics/probe/go-client/cmd/main.go | 161 +++++++++++++++++++
metrics/probe/go-server/Dockerfile | 6 +
metrics/{ => probe}/go-server/build.sh | 21 ++-
metrics/probe/go-server/cmd/main.go | 142 +++++++++++++++++
metrics/{ => prometheus_grafana}/Deployment.yml | 0
metrics/{ => prometheus_grafana}/README.md | 4 +-
metrics/{ => prometheus_grafana}/README_CN.md | 4 +-
.../{ => prometheus_grafana}/assert/grafana.png | Bin
.../{ => prometheus_grafana}/docker-compose.yml | 0
.../{ => prometheus_grafana}/go-client/Dockerfile | 0
.../{ => prometheus_grafana}/go-client/build.sh | 0
.../{ => prometheus_grafana}/go-client/cmd/main.go | 0
.../{ => prometheus_grafana}/go-server/Dockerfile | 0
.../{ => prometheus_grafana}/go-server/build.sh | 0
.../{ => prometheus_grafana}/go-server/cmd/main.go | 0
metrics/{ => prometheus_grafana}/grafana.json | 0
.../{ => prometheus_grafana}/prometheus_pull.yml | 0
.../{ => prometheus_grafana}/prometheus_push.yml | 0
metrics/{ => prometheus_grafana}/proto/greet.pb.go | 2 +-
metrics/{ => prometheus_grafana}/proto/greet.proto | 2 +-
.../{ => prometheus_grafana}/proto/greet.triple.go | 0
start_integrate_test.sh | 3 +
27 files changed, 727 insertions(+), 12 deletions(-)
diff --git a/README.md b/README.md
index 88903866..94fd2f16 100644
--- a/README.md
+++ b/README.md
@@ -36,7 +36,9 @@ Please refer to [HOWTO.md](HOWTO.md) for detailed
instructions on running the sa
* `service_discovery/service`: Java/Go interoperability with Nacos using
application-level service discovery (Dubbo3 model).
* `llm`: Example of integrating Large Language Models (LLMs) with Dubbo-go.
* `logger`: Logging examples for Dubbo-go applications.
-* `metrics`: Shows how to collect and expose metrics from Dubbo-go services,
supporting both Prometheus Push and Pull modes. Also includes the `pgw-cleaner`
tool for cleaning zombie metrics in Push mode.
+* `metrics`: Observability-related samples.
+ * `metrics/prometheus_grafana`: Shows how to collect and expose metrics from
Dubbo-go services, supporting both Prometheus Push and Pull modes. Also
includes the `pgw-cleaner` tool for cleaning zombie metrics in Push mode.
+ * `metrics/probe`: Demonstrates Dubbo-go Kubernetes probe endpoints
(`/live`, `/ready`, `/startup`) and deployment usage.
* `mesh`: Proxy-based service mesh example showing how to deploy Dubbo-go
services with Envoy on Kubernetes.
* `online_boutique`: Microservices “online boutique” demo built with Dubbo-go.
* `otel/tracing`: Distributed tracing examples using OpenTelemetry.
diff --git a/README_CN.md b/README_CN.md
index 1c0940a1..f6250068 100644
--- a/README_CN.md
+++ b/README_CN.md
@@ -36,7 +36,9 @@
* `service_discovery/service`:基于 Nacos 的应用级服务发现(Dubbo3 模型)Java/Go 互操作示例。
* `llm`:将大模型(LLM)集成到 Dubbo-go 中的示例。
* `logger`:Dubbo-go 应用的日志使用示例。
-* `metrics`:展示如何采集并暴露 Dubbo-go 服务的指标,支持 Prometheus Push 和 Pull 两种模式;同时包含用于清理
Push 模式僵尸指标的 `pgw-cleaner` 工具。
+* `metrics`:可观测性相关示例。
+ * `metrics/prometheus_grafana`:展示如何采集并暴露 Dubbo-go 服务指标,支持 Prometheus Push 和
Pull 两种模式;同时包含用于清理 Push 模式僵尸指标的 `pgw-cleaner` 工具。
+ * `metrics/probe`:演示 Dubbo-go 在 Kubernetes
场景下的探针端点(`/live`、`/ready`、`/startup`)及部署方式。
* `mesh`:基于代理的服务网格示例,展示如何在 Kubernetes 上结合 Envoy 部署 Dubbo-go 服务。
* `online_boutique`:基于 Dubbo-go 构建的微服务 “在线商城” 演示项目。
* `otel/tracing`:使用 OpenTelemetry 的分布式链路追踪示例。
diff --git a/metrics/probe/README.md b/metrics/probe/README.md
new file mode 100644
index 00000000..fc7d43ca
--- /dev/null
+++ b/metrics/probe/README.md
@@ -0,0 +1,166 @@
+
+# Dubbo-Go Kubernetes Probe Sample
+
+English | [中文](README_CN.md)
+
+This example demonstrates how to integrate **Kubernetes liveness, readiness,
and startup probes** with a Dubbo-Go Triple service.
+
+It showcases how to expose dedicated probe endpoints and how Kubernetes reacts
during application startup and warm-up.
+
+
+## Project Layout
+
+```
+metrics/probe/
+├── go-client/
+│ └── cmd/main.go # Integration checker for ports/probes/RPC
+├── go-server/
+│ ├── cmd/main.go # Application entrypoint
+│ ├── build.sh # Docker build script
+│ └── Dockerfile # Container image definition
+└── deploy/
+ └── server-deployment.yml # Kubernetes deployment
+```
+
+
+## Default Configuration
+
+| Item | Value |
+| ------------------- | ----------------------------- |
+| Triple service port | `20000` |
+| Probe HTTP port | `22222` |
+| Probe endpoints | `/live`, `/ready`, `/startup` |
+| Client target | `tri://127.0.0.1:20000` |
+
+### Probe Semantics
+
+* `GET /live`
+ Indicates whether the process is alive.
+
+* `GET /ready`
+ Indicates whether the service is ready to receive traffic.
+
+* `GET /startup`
+ Indicates whether the application startup phase has completed.
+
+
+## Run Locally
+
+### 1️Start the server
+
+```bash
+go run ./metrics/probe/go-server/cmd/main.go
+```
+
+### 2️Run the go-client integration checks
+
+```bash
+go run ./metrics/probe/go-client/cmd/main.go
+```
+
+The `go-client` validates:
+
+* Triple port `20000` is reachable.
+* Probe port `22222` is reachable.
+* `/live` returns `200`.
+* `/ready` and `/startup` eventually return `200` after warm-up.
+* One `Greet` RPC call succeeds.
+
+### 3️Monitor probe endpoints
+
+```bash
+watch -n 1 '
+for p in live ready startup; do
+ url="http://127.0.0.1:22222/$p"
+
+ body=$(curl -sS --max-time 2 "$url" 2>&1)
+ code=$(curl -s -o /dev/null --max-time 2 -w "%{http_code}" "$url"
2>/dev/null)
+
+ printf "%-8s [%s] %s\n" "$p" "$code" "$body"
+done
+'
+```
+
+### Expected Behavior
+
+| Phase | /live | /ready | /startup |
+| -------------------- | ----- | ------ | -------- |
+| Process started | 200 | 503 | 503 |
+| During warm-up | 200 | 503 | 503 |
+| After warm-up (~15s) | 200 | 200 | 200 |
+
+
+## Kubernetes Probe Configuration
+
+Example probe configuration:
+
+```yaml
+livenessProbe:
+ httpGet:
+ path: /live
+ port: 22222
+
+readinessProbe:
+ httpGet:
+ path: /ready
+ port: 22222
+
+startupProbe:
+ httpGet:
+ path: /startup
+ port: 22222
+```
+
+
+## Run on Kubernetes
+
+### Build the image
+
+From the repository root:
+
+```bash
+./metrics/probe/go-server/build.sh
+```
+
+
+### Load image into local cluster (if needed)
+
+For example, with Minikube:
+
+```bash
+minikube image load dubbo-go-probe-server:latest
+```
+
+
+### Deploy to Kubernetes
+
+```bash
+kubectl apply -f metrics/probe/deploy/server-deployment.yml
+kubectl rollout status deploy/dubbo-go-probe-server
+kubectl get pod -l app=dubbo-go-probe-server
+```
+
+
+### Inspect probe status
+
+```bash
+kubectl describe pod -l app=dubbo-go-probe-server
+```
+
+### Expected Kubernetes Behavior
+
+* Immediately after deployment:
+
+ * `Ready` = `False`
+ * `ContainersReady` = `False`
+
+* After ~15 seconds (warm-up completed):
+
+ * `Ready` = `True`
+ * `ContainersReady` = `True`
+
+This demonstrates proper separation of:
+
+* Process liveness
+* Service readiness
+* Startup lifecycle completion
diff --git a/metrics/probe/README_CN.md b/metrics/probe/README_CN.md
new file mode 100644
index 00000000..2678bc06
--- /dev/null
+++ b/metrics/probe/README_CN.md
@@ -0,0 +1,177 @@
+
+# Dubbo-Go Kubernetes 探针示例
+
+[English](README.md) | 中文
+
+
+本示例演示如何在 Dubbo-Go Triple 服务中集成 **Kubernetes 的 liveness、readiness 和 startup
探针**。
+
+通过暴露独立的探针端点,可以清晰地观察应用启动、预热以及就绪阶段在 Kubernetes 中的行为。
+
+
+## 项目结构
+
+```
+metrics/probe/
+├── go-client/
+│ └── cmd/main.go # 集成测试客户端(端口/探针/RPC 校验)
+├── go-server/
+│ ├── cmd/main.go # 程序入口
+│ ├── build.sh # Docker 构建脚本
+│ └── Dockerfile # 镜像定义文件
+└── deploy/
+ └── server-deployment.yml # Kubernetes 部署文件
+```
+
+
+## 默认配置
+
+| 项目 | 默认值 |
+| ----------- | ----------------------------- |
+| Triple 服务端口 | `20000` |
+| 探针 HTTP 端口 | `22222` |
+| 探针路径 | `/live`, `/ready`, `/startup` |
+| 客户端目标地址 | `tri://127.0.0.1:20000` |
+
+
+## 探针语义说明
+
+* `GET /live`
+ 表示进程是否存活(进程级健康检查)。
+
+* `GET /ready`
+ 表示服务是否已准备好接收流量。
+
+* `GET /startup`
+ 表示应用是否完成启动阶段。
+
+
+## 本地运行
+
+### 启动服务
+
+```bash
+go run ./metrics/probe/go-server/cmd/main.go
+```
+
+### 运行 go-client 做集成检查
+
+```bash
+go run ./metrics/probe/go-client/cmd/main.go
+```
+
+`go-client` 会依次检查:
+
+* Triple 端口 `20000` 可连接。
+* 探针端口 `22222` 可连接。
+* `/live` 返回 `200`。
+* `/ready`、`/startup` 在预热完成后返回 `200`。
+* 发起一次 `Greet` RPC,确认 Triple 服务可用。
+
+
+### 观察探针状态
+
+```bash
+watch -n 1 '
+for p in live ready startup; do
+ url="http://127.0.0.1:22222/$p"
+
+ body=$(curl -sS --max-time 2 "$url" 2>&1)
+ code=$(curl -s -o /dev/null --max-time 2 -w "%{http_code}" "$url"
2>/dev/null)
+
+ printf "%-8s [%s] %s\n" "$p" "$code" "$body"
+done
+'
+```
+
+
+### 预期行为
+
+| 阶段 | /live | /ready | /startup |
+| ------------ | ----- | ------ | -------- |
+| 进程刚启动 | 200 | 503 | 503 |
+| 预热阶段 | 200 | 503 | 503 |
+| 预热完成(约 15 秒) | 200 | 200 | 200 |
+
+说明:
+
+* `/live` 只要进程未崩溃就返回 200。
+* `/ready` 与 `/startup` 在应用完成预热前返回 503。
+* 预热完成后,三个端点均返回 200。
+
+
+## Kubernetes 探针配置示例
+
+```yaml
+livenessProbe:
+ httpGet:
+ path: /live
+ port: 22222
+
+readinessProbe:
+ httpGet:
+ path: /ready
+ port: 22222
+
+startupProbe:
+ httpGet:
+ path: /startup
+ port: 22222
+```
+
+
+## 在 Kubernetes 中运行
+
+### 构建镜像
+
+在仓库根目录执行:
+
+```bash
+./metrics/probe/go-server/build.sh
+```
+
+
+### 将镜像加载到本地集群
+
+例如使用 Minikube:
+
+```bash
+minikube image load dubbo-go-probe-server:latest
+```
+
+
+### 部署到 Kubernetes
+
+```bash
+kubectl apply -f metrics/probe/deploy/server-deployment.yml
+kubectl rollout status deploy/dubbo-go-probe-server
+kubectl get pod -l app=dubbo-go-probe-server
+```
+
+
+### 查看探针状态
+
+```bash
+kubectl describe pod -l app=dubbo-go-probe-server
+```
+
+
+### 预期 Kubernetes 行为
+
+* 刚部署时:
+
+ * `Ready` = `False`
+ * `ContainersReady` = `False`
+
+* 约 15 秒后(预热完成):
+
+ * `Ready` = `True`
+ * `ContainersReady` = `True`
+
+这体现了:
+
+* 进程存活检查(Liveness)
+* 服务可用性检查(Readiness)
+* 启动阶段控制(Startup)
+
+三者的职责分离。
diff --git a/metrics/probe/deploy/server-deployment.yml
b/metrics/probe/deploy/server-deployment.yml
new file mode 100644
index 00000000..62281fe1
--- /dev/null
+++ b/metrics/probe/deploy/server-deployment.yml
@@ -0,0 +1,43 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: dubbo-go-probe-server
+ labels:
+ app: dubbo-go-probe-server
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: dubbo-go-probe-server
+ template:
+ metadata:
+ labels:
+ app: dubbo-go-probe-server
+ spec:
+ containers:
+ - name: server
+ image: dubbo-go-probe-server:latest
+ imagePullPolicy: IfNotPresent
+ ports:
+ - containerPort: 20000
+ name: triple
+ - containerPort: 22222
+ name: probe
+ livenessProbe:
+ httpGet:
+ path: /live
+ port: probe
+ initialDelaySeconds: 5
+ periodSeconds: 10
+ readinessProbe:
+ httpGet:
+ path: /ready
+ port: probe
+ initialDelaySeconds: 5
+ periodSeconds: 5
+ startupProbe:
+ httpGet:
+ path: /startup
+ port: probe
+ failureThreshold: 30
+ periodSeconds: 1
diff --git a/metrics/probe/go-client/cmd/main.go
b/metrics/probe/go-client/cmd/main.go
new file mode 100644
index 00000000..07249480
--- /dev/null
+++ b/metrics/probe/go-client/cmd/main.go
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package main
+
+import (
+ "context"
+ "fmt"
+ "io"
+ "net"
+ "net/http"
+ "strings"
+ "time"
+)
+
+import (
+ "dubbo.apache.org/dubbo-go/v3/client"
+ _ "dubbo.apache.org/dubbo-go/v3/imports"
+
+ "github.com/dubbogo/gost/log/logger"
+)
+
+import (
+ greet "github.com/apache/dubbo-go-samples/direct/proto"
+)
+
+const (
+ tripleAddr = "127.0.0.1:20000"
+ probeBaseURL = "http://127.0.0.1:22222"
+
+ tcpReadyTimeout = 20 * time.Second
+ probeReadyTimeout = 40 * time.Second
+ requestTimeout = 2 * time.Second
+)
+
+func main() {
+ ctx := context.Background()
+
+ if err := waitTCPReady(tripleAddr, tcpReadyTimeout); err != nil {
+ logger.Fatalf("triple port is not ready: %v", err)
+ panic("triple port is not ready")
+ }
+ logger.Infof("triple port is ready: %s", tripleAddr)
+
+ if err := waitTCPReady("127.0.0.1:22222", tcpReadyTimeout); err != nil {
+ logger.Fatalf("probe port is not ready: %v", err)
+ panic("probe port is not ready")
+ }
+ logger.Info("probe port is ready: 127.0.0.1:22222")
+
+ if err := expectHTTPStatus(probeBaseURL+"/live", http.StatusOK,
requestTimeout); err != nil {
+ logger.Fatalf("/live check failed: %v", err)
+ panic("/live check failed")
+ }
+ logger.Info("/live is healthy")
+
+ if err := waitHTTPStatus(probeBaseURL+"/ready", http.StatusOK,
probeReadyTimeout, requestTimeout); err != nil {
+ logger.Fatalf("/ready did not become healthy: %v", err)
+ panic("/ready did not become healthy")
+ }
+ logger.Info("/ready is healthy")
+
+ if err := waitHTTPStatus(probeBaseURL+"/startup", http.StatusOK,
probeReadyTimeout, requestTimeout); err != nil {
+ logger.Fatalf("/startup did not become healthy: %v", err)
+ panic("/startup did not become healthy")
+ }
+ logger.Info("/startup is healthy")
+
+ if err := callGreet(ctx); err != nil {
+ logger.Fatalf("greet rpc check failed: %v", err)
+ panic("greet rpc check failed")
+ }
+ logger.Info("probe sample integration checks passed")
+}
+
+func callGreet(ctx context.Context) error {
+ cli, err := client.NewClient(
+ client.WithClientURL("tri://" + tripleAddr),
+ )
+ if err != nil {
+ return fmt.Errorf("create client: %w", err)
+ }
+
+ svc, err := greet.NewGreetService(cli)
+ if err != nil {
+ return fmt.Errorf("create greet service: %w", err)
+ }
+
+ rpcCtx, cancel := context.WithTimeout(ctx, 3*time.Second)
+ defer cancel()
+
+ resp, err := svc.Greet(rpcCtx, &greet.GreetRequest{Name: "probe-check"})
+ if err != nil {
+ return fmt.Errorf("invoke greet: %w", err)
+ }
+ if strings.TrimSpace(resp.Greeting) == "" {
+ return fmt.Errorf("empty greet response")
+ }
+ logger.Infof("greet rpc succeeded: %s", resp.Greeting)
+ return nil
+}
+
+func waitTCPReady(addr string, timeout time.Duration) error {
+ deadline := time.Now().Add(timeout)
+ for {
+ conn, err := net.DialTimeout("tcp", addr, 1*time.Second)
+ if err == nil {
+ _ = conn.Close()
+ return nil
+ }
+ if time.Now().After(deadline) {
+ return fmt.Errorf("tcp %s not ready within %s: %w",
addr, timeout, err)
+ }
+ time.Sleep(300 * time.Millisecond)
+ }
+}
+
+func waitHTTPStatus(url string, expected int, timeout, reqTimeout
time.Duration) error {
+ deadline := time.Now().Add(timeout)
+ var lastErr error
+ for {
+ err := expectHTTPStatus(url, expected, reqTimeout)
+ if err == nil {
+ return nil
+ }
+ lastErr = err
+ if time.Now().After(deadline) {
+ return fmt.Errorf("url %s not ready within %s: %w",
url, timeout, lastErr)
+ }
+ time.Sleep(500 * time.Millisecond)
+ }
+}
+
+func expectHTTPStatus(url string, expected int, reqTimeout time.Duration)
error {
+ client := http.Client{Timeout: reqTimeout}
+ resp, err := client.Get(url)
+ if err != nil {
+ return err
+ }
+ defer func() { _ = resp.Body.Close() }()
+
+ body, _ := io.ReadAll(resp.Body)
+ if resp.StatusCode != expected {
+ return fmt.Errorf("expect status %d but got %d, body=%s",
expected, resp.StatusCode, strings.TrimSpace(string(body)))
+ }
+ return nil
+}
diff --git a/metrics/probe/go-server/Dockerfile
b/metrics/probe/go-server/Dockerfile
new file mode 100644
index 00000000..c58271e5
--- /dev/null
+++ b/metrics/probe/go-server/Dockerfile
@@ -0,0 +1,6 @@
+FROM alpine:3.19
+WORKDIR /app
+COPY metrics/probe/go-server/probeApp /app/server
+
+EXPOSE 20000 22222
+ENTRYPOINT ["/app/server"]
diff --git a/metrics/go-server/build.sh b/metrics/probe/go-server/build.sh
similarity index 60%
copy from metrics/go-server/build.sh
copy to metrics/probe/go-server/build.sh
index 8b6c7bc1..d21e9afe 100644
--- a/metrics/go-server/build.sh
+++ b/metrics/probe/go-server/build.sh
@@ -1,3 +1,5 @@
+#!/bin/bash
+
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
@@ -14,7 +16,18 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# if run on linux server use this
-#GOOS=linux GOARCH=arm64
-go build -o metricsApp cmd/main.go
-docker build . -t metrics-app:latest
\ No newline at end of file
+set -e
+
+echo "Building probe server image..."
+
+# Build from repository root.
+cd "$(dirname "$0")/../../.."
+
+# Build linux binary first. This uses local `replace => ../dubbo-go` if
present.
+TARGET_OS=${TARGET_OS:-linux}
+TARGET_ARCH=${TARGET_ARCH:-amd64}
+
+CGO_ENABLED=0 GOOS="$TARGET_OS" GOARCH="$TARGET_ARCH" go build -o
metrics/probe/go-server/probeApp ./metrics/probe/go-server/cmd/main.go
+docker build -f metrics/probe/go-server/Dockerfile -t
dubbo-go-probe-server:latest .
+
+echo "Build completed successfully."
diff --git a/metrics/probe/go-server/cmd/main.go
b/metrics/probe/go-server/cmd/main.go
new file mode 100644
index 00000000..9c907fdc
--- /dev/null
+++ b/metrics/probe/go-server/cmd/main.go
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package main
+
+import (
+ "context"
+ "os"
+ "os/signal"
+ "sync/atomic"
+ "syscall"
+ "time"
+)
+
+import (
+ "dubbo.apache.org/dubbo-go/v3"
+ _ "dubbo.apache.org/dubbo-go/v3/imports"
+ "dubbo.apache.org/dubbo-go/v3/metrics"
+ "dubbo.apache.org/dubbo-go/v3/metrics/probe"
+ "dubbo.apache.org/dubbo-go/v3/protocol"
+ "dubbo.apache.org/dubbo-go/v3/server"
+
+ "github.com/dubbogo/gost/log/logger"
+
+ "github.com/pkg/errors"
+)
+
+import (
+ greet "github.com/apache/dubbo-go-samples/direct/proto"
+)
+
+const (
+ triplePort = 20000
+ probePort = 22222
+ probeLivenessPath = "/live"
+ probeReadinessPath = "/ready"
+ probeStartupPath = "/startup"
+ warmupSeconds = 15
+)
+
+type ProbeGreetServer struct{}
+
+func (srv *ProbeGreetServer) Greet(_ context.Context, req *greet.GreetRequest)
(*greet.GreetResponse, error) {
+ return &greet.GreetResponse{Greeting: "hello " + req.Name}, nil
+}
+
+func main() {
+ var warmupDone atomic.Bool
+ var dependencyReady atomic.Bool
+ dependencyReady.Store(true)
+
+ go func() {
+ logger.Infof("Warmup started, readiness/startup will fail for
%ds", warmupSeconds)
+ time.Sleep(warmupSeconds * time.Second)
+ warmupDone.Store(true)
+ logger.Info("Warmup completed, readiness/startup should be
healthy")
+ }()
+
+ probe.RegisterLiveness("process", func(ctx context.Context) error {
+ return nil
+ })
+ probe.RegisterReadiness("dependency", func(ctx context.Context) error {
+ if !dependencyReady.Load() {
+ return errors.New("dependency not ready")
+ }
+ return nil
+ })
+ probe.RegisterReadiness("warmup", func(ctx context.Context) error {
+ if !warmupDone.Load() {
+ return errors.New("warmup not complete")
+ }
+ return nil
+ })
+ probe.RegisterStartup("warmup", func(ctx context.Context) error {
+ if !warmupDone.Load() {
+ return errors.New("startup warmup not complete")
+ }
+ return nil
+ })
+
+ ins, err := dubbo.NewInstance(
+ dubbo.WithMetrics(
+ metrics.WithEnabled(),
+ metrics.WithProbeEnabled(),
+ metrics.WithProbePort(probePort),
+ metrics.WithProbeLivenessPath(probeLivenessPath),
+ metrics.WithProbeReadinessPath(probeReadinessPath),
+ metrics.WithProbeStartupPath(probeStartupPath),
+ metrics.WithProbeUseInternalState(true),
+ ),
+ )
+ if err != nil {
+ panic(err)
+ }
+
+ srv, err := ins.NewServer(
+ server.WithServerProtocol(
+ protocol.WithTriple(),
+ protocol.WithPort(triplePort),
+ ),
+ )
+ if err != nil {
+ panic(err)
+ }
+
+ if err := greet.RegisterGreetServiceHandler(srv, &ProbeGreetServer{});
err != nil {
+ panic(err)
+ }
+
+ stopCh := make(chan os.Signal, 1)
+ signal.Notify(stopCh, syscall.SIGINT, syscall.SIGTERM)
+
+ go func() {
+ logger.Infof("Probe sample server started, triple=%d probe=%d",
triplePort, probePort)
+ if err := srv.Serve(); err != nil {
+ logger.Error("Server error:", err)
+ }
+ }()
+
+ <-stopCh
+ logger.Info("Received shutdown signal, mark probe states to not ready")
+ dependencyReady.Store(false)
+ probe.SetReady(false)
+ probe.SetStartupComplete(false)
+
+ // Wait for test to complete
+ time.Sleep(3 * time.Second)
+}
diff --git a/metrics/Deployment.yml b/metrics/prometheus_grafana/Deployment.yml
similarity index 100%
rename from metrics/Deployment.yml
rename to metrics/prometheus_grafana/Deployment.yml
diff --git a/metrics/README.md b/metrics/prometheus_grafana/README.md
similarity index 98%
rename from metrics/README.md
rename to metrics/prometheus_grafana/README.md
index 7b09479b..fc8c0847 100644
--- a/metrics/README.md
+++ b/metrics/prometheus_grafana/README.md
@@ -76,7 +76,7 @@ First, start the Grafana, Prometheus, and Pushgateway
services. We use `docker-c
```bash
# Enter the metrics directory
-cd metrics
+cd metrics/prometheus_grafana
# Start all monitoring services in the background
docker-compose up -d
```
@@ -168,7 +168,7 @@ For
details:[tools/pgw-cleaner](../tools/pgw-cleaner/README.md)
- **Cannot connect to `host.docker.internal`**
- - `host.docker.internal` is a built-in feature of Docker. If this address
is not accessible, replace the IP address in `metrics/prometheus.yml` and the
Grafana data source address with your actual IP address.
+ - `host.docker.internal` is a built-in feature of Docker. If this address
is not accessible, replace the IP address in
`metrics/prometheus_grafana/prometheus_pull.yml` and the Grafana data source
address with your actual IP address.
-----
diff --git a/metrics/README_CN.md b/metrics/prometheus_grafana/README_CN.md
similarity index 98%
rename from metrics/README_CN.md
rename to metrics/prometheus_grafana/README_CN.md
index 8bb2d5fb..9b7d8332 100644
--- a/metrics/README_CN.md
+++ b/metrics/prometheus_grafana/README_CN.md
@@ -79,7 +79,7 @@ go run ./go-server/cmd/main.go --push=false
```bash
# 进入 metrics 目录
-cd metrics
+cd metrics/prometheus_grafana
# 以后台模式启动所有监控服务
docker-compose up -d
```
@@ -170,7 +170,7 @@ Pushgateway 设计初衷:为短生命周期进程(batch job、cron job)提
- 在 Prometheus 的查询栏中输入 `dubbo_consumer_requests_succeed_total`,确认能查询到数据。
- **`host.docker.internal` 无法连接**
- - `host.docker.internal` 是 Docker 的内置功能,如果该地址无法访问,请将
`metrics/prometheus.yml`
+ - `host.docker.internal` 是 Docker 的内置功能,如果该地址无法访问,请将
`metrics/prometheus_grafana/prometheus_pull.yml`
中的Ip地址以及Grafana的数据源地址换为实际的Ip地址。
-----
diff --git a/metrics/assert/grafana.png
b/metrics/prometheus_grafana/assert/grafana.png
similarity index 100%
rename from metrics/assert/grafana.png
rename to metrics/prometheus_grafana/assert/grafana.png
diff --git a/metrics/docker-compose.yml
b/metrics/prometheus_grafana/docker-compose.yml
similarity index 100%
rename from metrics/docker-compose.yml
rename to metrics/prometheus_grafana/docker-compose.yml
diff --git a/metrics/go-client/Dockerfile
b/metrics/prometheus_grafana/go-client/Dockerfile
similarity index 100%
rename from metrics/go-client/Dockerfile
rename to metrics/prometheus_grafana/go-client/Dockerfile
diff --git a/metrics/go-client/build.sh
b/metrics/prometheus_grafana/go-client/build.sh
similarity index 100%
rename from metrics/go-client/build.sh
rename to metrics/prometheus_grafana/go-client/build.sh
diff --git a/metrics/go-client/cmd/main.go
b/metrics/prometheus_grafana/go-client/cmd/main.go
similarity index 100%
rename from metrics/go-client/cmd/main.go
rename to metrics/prometheus_grafana/go-client/cmd/main.go
diff --git a/metrics/go-server/Dockerfile
b/metrics/prometheus_grafana/go-server/Dockerfile
similarity index 100%
rename from metrics/go-server/Dockerfile
rename to metrics/prometheus_grafana/go-server/Dockerfile
diff --git a/metrics/go-server/build.sh
b/metrics/prometheus_grafana/go-server/build.sh
similarity index 100%
rename from metrics/go-server/build.sh
rename to metrics/prometheus_grafana/go-server/build.sh
diff --git a/metrics/go-server/cmd/main.go
b/metrics/prometheus_grafana/go-server/cmd/main.go
similarity index 100%
rename from metrics/go-server/cmd/main.go
rename to metrics/prometheus_grafana/go-server/cmd/main.go
diff --git a/metrics/grafana.json b/metrics/prometheus_grafana/grafana.json
similarity index 100%
rename from metrics/grafana.json
rename to metrics/prometheus_grafana/grafana.json
diff --git a/metrics/prometheus_pull.yml
b/metrics/prometheus_grafana/prometheus_pull.yml
similarity index 100%
rename from metrics/prometheus_pull.yml
rename to metrics/prometheus_grafana/prometheus_pull.yml
diff --git a/metrics/prometheus_push.yml
b/metrics/prometheus_grafana/prometheus_push.yml
similarity index 100%
rename from metrics/prometheus_push.yml
rename to metrics/prometheus_grafana/prometheus_push.yml
diff --git a/metrics/proto/greet.pb.go
b/metrics/prometheus_grafana/proto/greet.pb.go
similarity index 98%
rename from metrics/proto/greet.pb.go
rename to metrics/prometheus_grafana/proto/greet.pb.go
index 4b9d164e..e1102c03 100644
--- a/metrics/proto/greet.pb.go
+++ b/metrics/prometheus_grafana/proto/greet.pb.go
@@ -139,7 +139,7 @@ const file_greet_proto_rawDesc = "" +
"\rGreetResponse\x12\x1a\n" +
"\bgreeting\x18\x01 \x01(\tR\bgreeting2D\n" +
"\fGreetService\x124\n" +
-
"\x05Greet\x12\x13.greet.GreetRequest\x1a\x14.greet.GreetResponse\"\x00B8Z6github.com/apache/dubbo-go-samples/metrics/proto;greetb\x06proto3"
+
"\x05Greet\x12\x13.greet.GreetRequest\x1a\x14.greet.GreetResponse\"\x00B8Z6github.com/apache/dubbo-go-samples/metrics/prometheus_grafana/proto;greetb\x06proto3"
var (
file_greet_proto_rawDescOnce sync.Once
diff --git a/metrics/proto/greet.proto
b/metrics/prometheus_grafana/proto/greet.proto
similarity index 96%
rename from metrics/proto/greet.proto
rename to metrics/prometheus_grafana/proto/greet.proto
index cb4df81a..9546a73e 100644
--- a/metrics/proto/greet.proto
+++ b/metrics/prometheus_grafana/proto/greet.proto
@@ -19,7 +19,7 @@ syntax = "proto3";
package greet;
-option go_package = "github.com/apache/dubbo-go-samples/metrics/proto;greet";
+option go_package =
"github.com/apache/dubbo-go-samples/metrics/prometheus_grafana/proto;greet";
message GreetRequest {
string name = 1;
diff --git a/metrics/proto/greet.triple.go
b/metrics/prometheus_grafana/proto/greet.triple.go
similarity index 100%
rename from metrics/proto/greet.triple.go
rename to metrics/prometheus_grafana/proto/greet.triple.go
diff --git a/start_integrate_test.sh b/start_integrate_test.sh
index ac59d5bc..6666f31e 100755
--- a/start_integrate_test.sh
+++ b/start_integrate_test.sh
@@ -73,6 +73,9 @@ array+=("async")
# error
array+=("error")
+# metrics
+array+=("metrics/probe")
+
# config_center
array+=("config_center/nacos")
# array+=("config_center/apollo")