
大家好,我是小悟。
Hera是一款由美团点评开源的分布式应用监控与追踪系统,专注于解决微服务架构下的性能监控、故障诊断和链路追踪问题。它借鉴了Google Dapper的设计理念,并结合了互联网企业的实际需求进行了优化和改进。
<!-- pom.xml 添加依赖管理 -->
<properties>
<spring-boot.version>2.7.14</spring-boot.version>
<hera.version>2.0.0</hera.version>
</properties>从GitHub下载最新版本:
# Hera仓库地址:https://github.com/Meituan-Dianping/Hera
wget https://github.com/Meituan-Dianping/Hera/releases/download/v2.0.0/hera-distribution-2.0.0.tar.gz
tar -zxvf hera-distribution-2.0.0.tar.gz# hera-collector/config/application.yml
server:
port: 8081
storage:
type: elasticsearch
elasticsearch:
cluster-nodes: localhost:9200
index-prefix: hera
# hera-web/config/application.yml
server:
port: 8080
query:
service-url: http://localhost:8082# 启动Collector
cd hera-collector/bin
./startup.sh
# 启动Query
cd hera-query/bin
./startup.sh
# 启动Web
cd hera-web/bin
./startup.sh<!-- pom.xml -->
<dependencies>
<!-- SpringBoot基础依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<!-- Hera Agent Core -->
<dependency>
<groupId>com.meituan.hera</groupId>
<artifactId>hera-agent-core</artifactId>
<version>${hera.version}</version>
</dependency>
<!-- Hera SpringBoot Starter -->
<dependency>
<groupId>com.meituan.hera</groupId>
<artifactId>hera-spring-boot-starter</artifactId>
<version>${hera.version}</version>
</dependency>
<!-- 其他依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies># application.yml
server:
port: 8080
spring:
application:
name: demo-service
# Hera配置
hera:
enabled: true
app-name: ${spring.application.name}
env: dev
collector:
host: localhost
port: 8081
trace:
enable: true
sample-rate: 1.0 # 采样率
metrics:
enable: true
interval: 60s # 上报间隔// DemoApplication.java
import com.meituan.hera.spring.boot.autoconfigure.EnableHera;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableHera // 启用Hera监控
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}// UserController.java
import com.meituan.hera.trace.annotation.Trace;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/{id}")
@Trace // 添加追踪注解
public User getUser(@PathVariable Long id) {
// 模拟业务逻辑
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new User(id, "User" + id);
}
@PostMapping
@Trace(name = "createUser") // 自定义Span名称
public User createUser(@RequestBody User user) {
// 业务处理
return user;
}
@GetMapping("/list")
public List<User> listUsers(@RequestParam int page,
@RequestParam int size) {
// 分页查询
return userService.getUsers(page, size);
}
}
// User.java
public class User {
private Long id;
private String name;
// 构造方法、getter、setter省略
}// UserService.java
import com.meituan.hera.trace.annotation.Trace;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Trace
public User getUserById(Long id) {
// 模拟数据库查询
simulateDatabaseQuery();
return new User(id, "User" + id);
}
@Trace(name = "batchQuery")
public List<User> getUsers(int page, int size) {
List<User> users = new ArrayList<>();
for (int i = 0; i < size; i++) {
users.add(new User((long) i, "User" + i));
}
return users;
}
private void simulateDatabaseQuery() {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}// UserFeignClient.java
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(name = "user-service", url = "${user.service.url}")
public interface UserFeignClient {
@GetMapping("/users/{id}")
User getUser(@PathVariable("id") Long id);
}
// 配置类
@Configuration
public class FeignConfig {
@Bean
public feign.okhttp.OkHttpClient okHttpClient() {
return new feign.okhttp.OkHttpClient();
}
}// CustomMetrics.java
import com.meituan.hera.metrics.api.MetricRegistry;
import com.meituan.hera.metrics.api.Counter;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class CustomMetrics {
private Counter userLoginCounter;
private Counter apiErrorCounter;
@PostConstruct
public void init() {
userLoginCounter = MetricRegistry.getCounter("user.login.count");
apiErrorCounter = MetricRegistry.getCounter("api.error.count");
}
public void recordLogin() {
userLoginCounter.inc();
}
public void recordApiError() {
apiErrorCounter.inc();
}
}// MonitorAspect.java
import com.meituan.hera.trace.TraceContext;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class MonitorAspect {
private final CustomMetrics customMetrics;
public MonitorAspect(CustomMetrics customMetrics) {
this.customMetrics = customMetrics;
}
@Around("@annotation(org.springframework.web.bind.annotation.GetMapping) || " +
"@annotation(org.springframework.web.bind.annotation.PostMapping)")
public Object monitorApi(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
String traceId = TraceContext.getTraceId();
try {
Object result = joinPoint.proceed();
long duration = System.currentTimeMillis() - startTime;
// 记录成功指标
recordSuccessMetrics(joinPoint, duration);
return result;
} catch (Exception e) {
customMetrics.recordApiError();
throw e;
}
}
private void recordSuccessMetrics(ProceedingJoinPoint joinPoint, long duration) {
String methodName = joinPoint.getSignature().getName();
// 记录到监控系统
}
}// TraceFilter.java
import com.meituan.hera.trace.TraceContext;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@Component
@Order(1)
public class TraceFilter implements Filter {
@Override
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
// 从请求头获取Trace信息
String traceId = httpRequest.getHeader("X-Trace-ID");
String spanId = httpRequest.getHeader("X-Span-ID");
if (traceId != null) {
TraceContext.setTraceId(traceId);
}
if (spanId != null) {
TraceContext.setSpanId(spanId);
}
try {
chain.doFilter(request, response);
} finally {
TraceContext.clear();
}
}
}// ThreadPoolConfig.java
import com.meituan.hera.trace.instrument.async.TraceableExecutorService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Configuration
public class ThreadPoolConfig {
@Bean("traceableExecutor")
public ExecutorService traceableExecutor() {
ExecutorService executor = Executors.newFixedThreadPool(10);
return new TraceableExecutorService(executor);
}
}# 启动SpringBoot应用
mvn spring-boot:run
# 测试API
curl http://localhost:8080/api/users/1
curl -X POST http://localhost:8080/api/users \
-H "Content-Type: application/json" \
-d '{"id": 2, "name": "Test User"}'http://localhost:8080 (Hera Web界面)# application.yml 追加日志配置
logging:
level:
com.meituan.hera: DEBUG
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} [TraceID:%X{traceId}] - %msg%n"# application-prod.yml
hera:
enabled: true
app-name: ${spring.application.name}
env: prod
collector:
host: hera-collector.prod.svc.cluster.local
port: 8081
trace:
enable: true
sample-rate: 0.1 # 生产环境降低采样率
metrics:
enable: true
interval: 30s
buffer:
size: 10000
flush-interval: 5s# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-service
spec:
replicas: 3
template:
spec:
containers:
- name: app
image: demo-service:latest
env:
- name: HERA_AGENT_OPTS
value: "-javaagent:/app/agent/hera-agent.jar"
- name: HERA_APP_NAME
value: "demo-service"
- name: HERA_ENV
value: "prod"
volumeMounts:
- name: hera-agent
mountPath: /app/agent
volumes:
- name: hera-agent
configMap:
name: hera-agent-config通过集成Hera,企业可以构建完整的可观测性体系,显著提升微服务架构下的运维效率和故障处理能力,为业务稳定运行提供有力保障。

谢谢你看我的文章,既然看到这里了,如果觉得不错,随手点个赞、转发、在看三连吧,感谢感谢。那我们,下次再见。
您的一键三连,是我更新的最大动力,谢谢
山水有相逢,来日皆可期,谢谢阅读,我们再会
我手中的金箍棒,上能通天,下能探海
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。