一.为微服务应用增加健康监控

1.在 build.gradle 文件 dependencies 属性中增加

compile('org.springframework.boot:spring-boot-starter-actuator')

2.启动程序后在地址栏输入127.0.0.1:8801/actuator/health即可查看当前服务的状态

status有UP(正常运行)、DOWN、OUT_OF_SERVICE、UN_KNOWN等

3.在application中我们可以公开一些信息供外部访问,例如

开放信息

info:

app:

name: 提供用户查询服务

version: 1.0

4.注:在springboot2.x版本中默认只暴露/info和/health,可以使用如下配置增加入口:

 endpoints:
web:
exposure:
include: bus-refresh,refresh``` ##二.微服务间直接调用api 1.不推荐直接调用,一般使用@RestTemplate调用其他服务的api,在启动类实例化对象,使用@Bean作用是实例化一个Bean并使用该方法的名称命名
示例代码:
``` @Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}

2.在controller中调用

示例代码:

public class UserController {

 @Autowired
private RestTemplate restTemplate; @GetMapping("/getUser")
public String getUser(){
return restTemplate.getForObject("http://127.0.0.1:8801/user/get", String.class);
}
}```
##三.微服务的注册与发现 0.通过注册与发现可以实时的获取服务的配置,而不需要去手动修改
1.新建项目添加依赖
compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-server')
2.在application.yml文件中添加配置
#Eureka 服务端信息
eureka:
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://localhost:8808/eureka 各配置的作用详解:
register-with-eureka 表示是否把自己注册到Eureka Server,默认true;
fetch-registry表示是否从其他Eureka Server获取注册信息,默认true;
service-url.defaultZone设置与Enreka Server交互的地址,多个地址用逗号隔开(英文逗号) 3.在启动类加注解@EnableEurekaServer标识是Eureka Server
4.在需要被注册的微服务工程上添加依赖
compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
5.application.yml信息
application.name用于指定注册到Eureka Server上的应用名称;
instance.prefer-ip-adress表示将自己的ip注册到EurekaServer,若不配置该属性,或者设置为false,则表示注册所在操作系统的hostname到Eureka Server。
6.在需要被注册的启动类上添加注解@EnableDiscoveryClient注解,声明这是一个Eureka Client。
7.调用其他服务可以通过DiscoveryClient寻找其他服务
示例代码:
@GetMapping("/getUser")
public String getUser() {
List<ServiceInstance> list = discoveryClient.getInstances("service-user");
if (list.size() > 0) {
String url = list.get(0).getUri().toString();
return restTemplate.getForObject(url + "/user/get", String.class);
} else {
return null;
}
}
}
##四.使用Ribbon实现负载均衡## 0.注册一个微服务后启动多个实例就相当于用同一个服务名称启动了多个服务节点,达到了集群的目的,这时消费端与服务端之间的的调用就应该采用Ribbon
1.添加依赖
compile('org.springframework.cloud:spring-cloud-starter-netflix-ribbon')
2.启动类添加@LoadBanlanced开启负载均衡能力
代码示例:
@SpringBootApplication
public class LearnConsumerUserApplication { @Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
} public static void main(String[] args) {
SpringApplication.run(LearnConsumerUserApplication.class, args);
}
}
3.修改调用服务端的代码
示例代码:
@RestController
public class UserController { @Autowired
private RestTemplate restTemplate; @GetMapping("/getUser")
public String getUser() {
return restTemplate.getForObject("http://service-user/user/get", String.class);
}
}
##五.使用Feign实现声明式REST调用 1.在消费端添加依赖
compile('org.springframework.cloud:spring-cloud-starter-openfeign')
官网M2和M6资源有差异,阿里云的M2和官网的M2也有差异,有点奇怪,保险起见增加如下2个依赖:
compile('org.springframework.cloud:spring-cloud-openfeign-core')
compile('io.github.openfeign:feign-java8')
2.修改消费端启动类,增加注解@ EnableFeignClients,去掉之前的@restTemplate和负载均衡,Feign做了整合
3.创建接口Feign,增加@Feign(name=“service-user”)注解适应Eureka和Ribbon
@FeignClient("service-user")
public interface UserFeignClient { @GetMapping("/user/get")
public String getUser(); @GetMapping("/user/type1/{id}")
public String getUserById1(@PathVariable(value="id") String id); @GetMapping("/user/type2")
public String getUserById2(@RequestParam("id") String id); @PostMapping("/user/type3")
public String getUserById3(@RequestParam Map<String, Object> reqMap); @PostMapping("/user/type4")
public String getUserById4(@RequestBody String jsonObj);
}
4.修改消费端的controller,使用上面的接口
@RestController
public class UserController { @Autowired
private UserFeignClient userFeignClient; @GetMapping("/getUser")
public String getUser() {
return userFeignClient.getUser();
} @GetMapping("/getUser1/{id}")
public String getUserById1(@PathVariable String id) {
return userFeignClient.getUserById1(id);
} @GetMapping("/getUser2")
public String getUserById2(@RequestParam("id") String id) {
return userFeignClient.getUserById2(id);
} @PostMapping("/getUser3")
public String getUserById3(@RequestParam Map<String, Object> reqMap) {
return userFeignClient.getUserById3(reqMap);
} @PostMapping("/getUser4")
public String getUserById4(@RequestBody String jsonObj) {
return userFeignClient.getUserById4(jsonObj);
}
} ##六.使用Hystrix实现微服务的容错处理 0. Hystrix 能使你的系统在出现依赖服务失效的时候,通过隔离系统所依赖的服务,防止服务级联失败,同时提供失败回退机制,更优雅地应对失效,并使你的系统能更快地从异常中恢复。 都能做什么?
1、防止单个依赖耗尽容器(例如 Tomcat)内所有用户线程
2、降低系统负载,对无法及时处理的请求快速失败(fail fast)而不是排队
3、提供失败回退,以在必要时让失效对用户透明化
4、使用隔离机制(例如『舱壁』/『泳道』模式,熔断器模式等)降低依赖服务对整个系统的影响
5、针对系统服务的度量、监控和报警,提供优化以满足近实时性的要求
6、在 Hystrix 绝大部分需要动态调整配置并快速部署到所有应用方面,提供优化以满足快速恢复的要求
7、能保护应用不受依赖服务的整个执行过程中失败的影响,而不仅仅是网络请求
1.消费端增加依赖
compile('org.springframework.cloud:spring-cloud-starter-netflix-hystrix')
2. 增加一个 UserFeignClientFallback 实现 FallbackFactory
@Component
public class UserFeignClientFallback implements FallbackFactory<UserFeignClient> { @Override
public UserFeignClient create(Throwable cause) {
return new UserFeignClient() { @Override
public String getUser() {
//可把日志记录到其他地方
System.out.println("失败原因:" + cause.getMessage()); return "调取用户信息异常";
} @Override
public String getUserById1(String id) {
return "调取用户信息异常";
} @Override
public String getUserById2(String id) {
return "调取用户信息异常";
} @Override
public String getUserById3(Map<String, Object> reqMap) {
return "调取用户信息异常";
} @Override
public String getUserById4(String jsonObj) {
return "调取用户信息异常";
}
}; } }
3. UserFeignClient 增加 fallbackFactory配置
@FeignClient(name = "service-user", fallbackFactory = UserFeignClientFallback.class)
public interface UserFeignClient { @GetMapping("/user/get")
public String getUser(); @GetMapping("/user/type1/{id}")
public String getUserById1(@PathVariable(value = "id") String id); @GetMapping("/user/type2")
public String getUserById2(@RequestParam("id") String id); @PostMapping("/user/type3")
public String getUserById3(@RequestParam Map<String, Object> reqMap); @PostMapping("/user/type4")
public String getUserById4(@RequestBody String jsonObj);
}
4.application.yml文件中开启hystrix
feign: hystrix: enabled: true
##七.使用Zuul构建为服务网关 1. 为什么要使用微服务网关? 1、客户端会多次请求不同的微服务,增加了客户端的复杂性。
2、存在跨域请求,在一定场景下处理相对复杂。
3、认证复杂,每个服务都需要独立认证。
4、难以重构,随着项目迭代可能需要重新划分微服务,如果客户端直接与微服务通信,那么重构也会很难实施。
5、某些微服务可能使用了防火墙,直接访问会有一定的困难。 以上问题借助微服务网关既可以解决。 Zuul简介
Zuul是Netflix开源的微服务网关,它可以和Eureka、Ribbon、Hystrix等组件配合使用。Zuul的核心是一系列的过滤器,这些过滤器可以完成一下功能:
1、验证与安全保障: 识别面向各类资源的验证要求并拒绝那些与要求不符的请求。
2、审查与监控: 在边缘位置追踪有意义数据及统计结果,从而为我们带来准确的生产状态结论。
3、动态路由: 以动态方式根据需要将请求路由至不同后端集群处。
4、压力测试: 逐渐增加指向集群的负载流量,从而计算性能水平。
5、负载分配: 为每一种负载类型分配对应容量,并弃用超出限定值的请求。
6、静态响应处理: 在边缘位置直接建立部分响应,从而避免其流入内部集群。
7、多区域弹性: 跨越AWS区域进行请求路由,旨在实现ELB使用多样化并保证边缘位置与使用者尽可能接近。
1.开始构建一个微服务网关,新建工程,引入依赖
compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
compile('org.springframework.cloud:spring-cloud-starter-netflix-zuul')
2.修改启动类,增加@EnableZuulProxy注解,代表这是一个网关代理服务,该代理使用Ribbon来定位注册在Eureka上的服务,同时整合了Hystrix
3.填写application.yml配置类
#服务端口
server:
port: 8888 #Eureka配置信息
spring:
application:
name: gateway-zuul
eureka:
client:
service-url:
defaultZone: http://localhost:8808/eureka
instance:
prefer-ip-address: true
4.注:一些实用的配置
#只路由指定服务,忽略其他服务,并忽略路径中含有admin的请求, 映射路径(含已注册的服务和外部服务)
zuul:
ignored-services: '*'
ignored-patterns: /**/admin/**
routes:
service-user: /userSer/**
consumer-user: /userCon/**
demo-rooter:
url: http://10.2.6.33:8100/
path: /demo/** a、ignored-services: '*' 代表忽略所有微服务, 只路由routes中的配置 b、ignored-patterns: /**/admin/** 代表忽略含有admin的路径 c、service-user: /userSer/** 把原来的用户服务端映射到 /userSer 上, 类似取了一个别名
这样原来访问 http://127.0.0.1:8888/service-user/user/get 就变成了 http://127.0.0.1:8888/suserSer/user/get d、demo-rooter: 这个自定义的路由,名字可以随便取, 配置指定的路径和目标地址
例子中 http://127.0.0.1:8888/demo/getSome 相当于访问了 http://10.2.6.33:8100/getSome
##八.使用spring Cloud Config统一配置微服务配置## 0. 在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件。在Spring Cloud中,有分布式配置中心组件spring cloud config为服务端和客户端提供了分布式系统的外部化配置支持。配置服务中心采用Git的方式存储配置文件,因此我们很容易部署修改,有助于对环境配置进行版本管理。
1.创建server工程,增加依赖
compile('org.springframework.cloud:spring-cloud-config-server')
compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
2.启动类增加注解@EnableConfigServer注解
3.application.yml配置
服务端口
server:
port: 8099 配置信息所在git仓库信息
spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: https://gitee.com/seley6/test
search-paths: config
username:
password: eureka:
client:
service-url:
defaultZone: http://localhost:8808/eureka
instance:
prefer-ip-address: true
3.创建一个配置的客户端,添加依赖
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.cloud:spring-cloud-starter-config')
compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client') 注:增加actuator是为了实现客户端通过 /actuator/refresh 实现配置动态更新。
4.创建bootstrap.yml配置文件
配置配置服务端
spring:
application:
name: config-client
cloud:
config:
discovery:
enabled: true
service-id: config-server
profile: dev
label: master eureka:
client:
service-url:
defaultZone: http://localhost:8808/eureka
instance:
prefer-ip-address: true 开放刷新入口
management:
endpoints:
web:
exposure:
include: refresh
5.向远程git仓库提交文件 config-client-dev.yml
服务端口
server:
port: 9901 info:
app:
version: 1.0 配置服务的路劲规则:
/{label}/{application}-{profile}.yml
label相当于git分支,application是应用名,profile是属性名, 所以对应步骤2 我们应该增加一个config-client-dev.yml文件并提交到master。
6.创建一个api获得version信息
@RestController
public class TestController { @Value("${info.app.version}")
private String version; @GetMapping("/getVersion")
public String getUser() {
return this.version;
} }
7.依次启动服务
①、启动 learn-discover-eureka (8808)
②、启动 learn-config-server (8099)
③、启动 learn-config-client (端口我们在远程git中配置的是9901) ④、访问如下链接即可查到对应远程git中的配置信息
http://127.0.0.1:8099/config-client/dev ⑤、访问如下链接我们 可以查到版本结果
http://127.0.0.1:9901/getVersion ⑥、修改 config-client-dev.yml 中version信息,再次提交到git ⑦、访问步骤④中的地址,发现配置已经修改, 但访问步骤⑤还是返回之前的配置信息, 这时我们要POST方式请求 http://127.0.0.1:9901/actuator/refresh, 之后再次访问步骤④,发现配置信息已经更新。 注意:刷新并不是重启服务,所以端口信息还有其他需要启动时才生效的配置是无法通过此方式动态更新的, 需要手动重启服务。
8.自动刷新配置
前文我们讨论了使用/refresh 端点手动刷新配置,但是如果所有微服务节点的配置都需要手动去刷新的话,那必然是一个繁琐的工作,并且随着系统的不断扩张,会变得越来越难以维护。因此,实现配置的自动刷新是很有必要的,本节我们讨论使用Spring Cloud Bus实现配置的自动刷新。 Spring Cloud Bus提供了批量刷新配置的机制,它使用轻量级的消息代理(例如RabbitMQ、Kafka等)连接分布式系统的节点,这样就可以通过Spring Cloud Bus广播配置的变化或者其他的管理指令。 下面我们以RabbitMQ为例,为大家讲解如何使用Spring Cloud Bus实现配置的自动刷新。
①、 安装RabbitMQ。 去另一篇文章中去看 Windows下安装RabbitMQ ②、服务端 learn-config-server 增加依赖
compile('org.springframework.cloud:spring-cloud-starter-bus-amqp') ③、application.yml 中增加 rabbitmq配置
(事实上我们可以不配置服务端信息,我们通过任一客户端都可以刷新其他微服务配置,但为了均衡客户端职责,同时服务端也是高可靠的,所以我们用服务端 /bus/refresh 来更新其他客户端)
#服务端口
server:
port: 8099 #配置信息所在git仓库信息
spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: https://gitee.com/seley6/test
search-paths: config
username:
password:
rabbitmq:
host: 10.2.6.33
port: 5672
username: gaojinliang
password: [密码] eureka:
client:
service-url:
defaultZone: http://localhost:8808/eureka
instance:
prefer-ip-address: true #开放全局配置刷新入口
management:
endpoints:
web:
exposure:
include: bus-refresh
④、客户端 learn-config-client 增加依赖
compile('org.springframework.cloud:spring-cloud-starter-bus-amqp') ⑤、bootstrap.yml 中增加对rabbitmq的配置
#配置配置服务端
spring:
application:
name: config-client
cloud:
config:
discovery:
enabled: true
service-id: config-server
profile: dev
label: master
rabbitmq:
host: 127.0.0.1
port: 5672
username: gaojinliang
password: [] eureka:
client:
service-url:
defaultZone: http://localhost:8808/eureka
instance:
prefer-ip-address: true #开放刷新入口
management:
endpoints:
web:
exposure:
include: refresh
⑥、测试类中增加 @RefreshScope 注解代表需要动态刷新配置
@RestController
@RefreshScope
public class TestController { @Value("${info.app.version}")
private String version; @GetMapping("/getVersion")
public String getUser() {
return this.version;
} }
依次服务启动: a、启动 learn-discover-eureka (8808)
b、启动 learn-config-server (8099)
c、启动 learn-config-client
(可以启动多个,以了解更新过程。 可以去掉远程仓库中的端口配置,本地区分端口启动, 也可以远程多建几个配置文件,本地使用 spring.cloud.config.profile 区分) d、访问如下链接我们 可以查到版本结果
http://127.0.0.1:9901/getVersion e、修改 config-client-dev.yml 中version信息,再次提交到git f、 这时我们要POST方式请求 http://127.0.0.1:8099/actuator/bus-refresh, 之后再次访问步骤4,发现配置信息已经更新, 如果启动了多个客户端实例,则会发现它们都已经更新。 一般Git服务都提供 WebHook 功能,可以在提交变更后触发指定地址,这样就更自动化了, 由于我们的Git仓库在外网上,无法触发内网地址,所以就不尝试了,有兴趣的同学可以去试试,另外也可以在公司内网搭建一个Gitblit尝试。 局部刷新 某些场景下(例如灰度发布),我们可能只想刷新部分微服务的配置,此时可通过/bus/refresh端点的destination参数来定位要刷新的应用程序。 例如: /actuator/bus-refresh?destination=config-client:9901 ,这样消息总线上的微服务实例就会根据destination参数的值来判断是否需要要刷新。其中 config-client:9901 指的是各个微服务的ApplicationContext ID。 destination参数也可以用来定位特定的微服务。例如:/actuator/bus-refresh?destination=config-client:** ,这样就可以触发config-client微服务所有实例的配置刷新。 ##九.使用HystrixDashboard + Turbine实现可视化监控数据## 0. 了解了Hystrix实现微服务的容错处理,除此之外Hystrix还实现了近乎实时的监控。 接下来我们来给多个客户端做监控,并使用 Turbine 做聚合,并在 HystrixDashboard 中显示。
1.建多个客户端工程,分别增加依赖
compile('org.springframework.cloud:spring-cloud-starter-netflix-hystrix')
2.启动类增加注解@EnableCircuitBreaker
3.application.yml文件开放hystrix.stream入口
#开启监控入口
management:
endpoints:
web:
exposure:
include: hystrix.stream
注:上面的三步即在各自的服务中开启监控,当服务启动后我们可以从地址 http://ip:port/hystrix.stream 看到各自的监控信息,但显示的只是文本信息。
4.聚合监控信息并显示
①增加工程,添加依赖
compile('org.springframework.cloud:spring-cloud-starter-netflix-turbine')
compile('org.springframework.cloud:spring-cloud-starter-netflix-hystrix-dashboard')
compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
② 启动类增加 @EnableTurbine 和 @EnableHystrixDashboard
③application.yml配置
#服务端口
server:
port: 8765 #Eureka配置信息
spring:
application:
name: service-trubine
eureka:
client:
service-url:
defaultZone: http://localhost:8808/eureka
instance:
prefer-ip-address: true #聚合服务监控数据
turbine:
app-config: consumer-user,consumer-user2
cluster-name-expression: "'default'"
注:注册到eureka服务,并通过 turbine.app-config 配置哪些服务需要被聚合监控
5.依次启动服务
①、启动 learn-discover-eureka (8808)
②、启动 learn-service-user (8801)
③、启动 learn-consumer-user (8802)
④、启动 learn-consumer-user2 (8812)
⑤、启动 learn-service-turbine (8765) ⑥、访问 http://127.0.0.1:8765/hystrix 可看到如下界面 (1)URL地址, 可以录入单个服务的监控地址 http://ip:port/actuator/hystrix.stream,我们这里主要是看聚合数据所以录入 http://127.0.0.1:8765/turbine.stream
(2)Delay:延迟可以不填
(3)Title: 标题随便写一个
(4)点击 Monitor Stream 既可看到如下监控界面 (需要多次刷新2个工程中的接口)

spring微服务(顺序由简入难易于理解)的更多相关文章

  1. Docker-compose编排微服务顺序启动

    一.概述 docker-compose可以方便组合多个 docker 容器服务, 但是, 当容器服务之间存在依赖关系时, docker-compose 并不能保证服务的启动顺序.docker-comp ...

  2. spring微服务架构-脑图

    spring团队对新一代软件开发的思索.为什么软件开发是spring boot?为什么软件开发是spring cloud?如何使用spring cloud搭建微服务. 清晰脑图查看

  3. 关于微服务、SOA、以及API的理解

    现在微服务.SOA.RESTful API设计等在各大公司很流行.微服务(micro services)这个概念不是新概念,很多公司已经在实践了,例如亚马逊.Google.FaceBook,Aliba ...

  4. 一张图了解Spring Cloud微服务架构

    Spring Cloud作为当下主流的微服务框架,可以让我们更简单快捷地实现微服务架构.Spring Cloud并没有重复制造轮子,它只是将目前各家公司开发的比较成熟.经得起实际考验的服务框架组合起来 ...

  5. Spring Cloud Turbine微服务集群实时监控

    本文代码下载地址: https://gitlab.com/mySpringCloud/turbine SpringBoot版本:1.5.9.RELEASE (稳定版) SpringCloud版本:Ed ...

  6. 【微服务】使用spring cloud搭建微服务框架,整理学习资料

    写在前面 使用spring cloud搭建微服务框架,是我最近最主要的工作之一,一开始我使用bubbo加zookeeper制作了一个基于dubbo的微服务框架,然后被架构师否了,架构师曰:此物过时.随 ...

  7. 7个点说清楚spring cloud微服务架构

    前言 spring cloud作为当下主流的微服务框架,让我们实现微服务架构简单快捷,spring cloud中各个组件在微服务架构中扮演的角色如下图所示,黑线表示注释说明,蓝线由A指向B,表示B从A ...

  8. Spring Cloud微服务架构升级总结

    ↵ [编者的话]微服务的概念源于 2014 年 3 月 Martin Fowler 所写的一篇文章“Microservices”.文中内容提到:微服务架构是一种架构模式,它提倡将单一应用程序划分成一组 ...

  9. SpringCloud(9)使用Spring Cloud OAuth2保护微服务系统

    一.简介 OAth2是一个标准的授权协议. 在认证与授权的过程中,主要包含以下3种角色. 服务提供方 Authorization Server. 资源持有者 Resource Server. 客户端 ...

随机推荐

  1. Flask学习 4 http方法

    服务端端 #!/usr/bin/env python # encoding: utf-8 """ @version: v1.0 @author: cxa @file: f ...

  2. (转)jupyter常用快捷键

    转:http://www.mamicode.com/info-detail-2395285.html Jupyter Notebook 有两种键盘输入模式.即命令模式和编辑模式,这与 vim有些类似. ...

  3. Advanced search keywords

    Advanced search options Find what you're looking for in less time. Use the following symbols to quic ...

  4. day22—一个AngularJS框架应用toDoList

    转行学开发,代码100天——2018-04-07 今天用AngularJS照着课程写了一个案例,即toDoList,记事清单效果. 主要实现以下效果: 1.通过文本框添加内容,同时添加事件列表.主要用 ...

  5. Eclipse报内存溢出

    (1)在配置tomcat的JDK里面设置.Window-->proference->Myeclipse-->servers-->Tomcat5-->JDK里面设置: -X ...

  6. jmeter之JDBC请求

    jmeter不仅可以测试http请求,也可以执行JDBC请求的测试.本次以mysql为例,介绍JDBC请求如何完成发送 目录 1.环境配置 2.数据库连接配置 3.添加一个JDBC请求 1.环境配置 ...

  7. 第 4 章 前端基础之jquery

    一.jQuery是什么? 1. jQuery由美国人John Resig创建,至今已吸引了来自世界各地的众多 javascript高手加入其team. 2. jQuery是继prototype之后又一 ...

  8. JNI-java native interface(java本地接口)

    什么是JNI java native interface(java本地接口) ABI: application binary interface (应用程序二进制接口) 为什么要使用JNI * 复用很 ...

  9. 在没有iis的情况下,webApi自托管(转自momo314)

    第一步 新建一个控制台应用程序 并添加WebApi相关引用,注意,添加之后会默认帮你添加 System.Web.Http.WebHost 的引用,不过,折并没有什么鸟用,干掉他,然后手动添加引用 Sy ...

  10. APM-全链路追踪

    1.故障快速定位 跨语言实现开发中在业务日志中添加调用链ID,可以通过调用链结合业务日志快速定位错误信息. 2.各个调用环节的性能分析 分析调用链的各个环节耗时,分析系统的性能瓶颈,找到系统的薄弱环节 ...