- Ingress 和 Ingress Controller 概述
- 在 k8s 中为什么会有 service 这个概念?
Pod 漂移问题
Kubernetes 具有强大的副本控制能力,能保证在任意副本(Pod)挂掉时自动从其他机器启动一个新的,还可以动态扩容等,通俗地说,这个 Pod 可能在任何时刻出现在任何节点上,也可能在任何时刻死在任何节点上;那么自然随着 Pod 的创建和销毁,Pod IP 肯定会动态变化;那么如何把这个动态的Pod IP 暴露出去?这里借助于 Kubernetes 的 Service 机制,Service 可以以标签的形式选定一组带有指定标签的 Pod,并监控和自动负载他们的 Pod IP,那么我们向外暴露只暴露 Service IP 就行了;这就是 NodePort 模式:即在每个节点上开起一个端口,然后转发到内部 Pod IP 上:
此时的访问方式:http://nodeip:nodeport/ ,即数据包流向如下:
客户端请求-->node 节点的 ip:端口--->service 的 ip:端口--->pod 的 ip:端口 - Service 存在哪些问题?
端口管理问题
采用 NodePort 方式暴露服务面临的问题是,服务一旦多起来,NodePort 在每个节点上开启的端口会及其庞大,而且难以维护;这时,我们能否使用一个 Nginx 直接对内进行转发呢?众所周知的是,Pod 与 Pod 之间是可以互相通信的,而 Pod 是可以共享宿主机的网络名称空间的,也就是说当在共享网络名称空间时,Pod 上所监听的就是 Node 上的端口。那么这又该如何实现呢?简单的实现就是使用DaemonSet 在每个 Node 上监听 80,然后写好规则,因为 Nginx 外面绑定了宿主机 80 端口(就像NodePort),本身又在集群内,那么向后直接转发到相应 Service IP 就行了,如下图所示: 域名分配及动态更新问题
从上面的方法,采用 Nginx-Pod 似乎已经解决了问题,但是其实这里面有一个很大缺陷:当每次有新服务加入又该如何修改 Nginx 配置呢?我们知道使用 Nginx 可以通过虚拟主机域名进行区分不同的服务,而每个服务通过 upstream 进行定义不同的负载均衡池,再加上 location 进行负载均衡的反向代理,在日常使用中只需要修改 nginx.conf 即可实现,那在 K8S 中又该如何实现这种方式的调度呢?假设后端的服务初始服务只有 ecshop,后面增加了 bbs 和 member 服务,那么又该如何将这 2 个服务加入到 Nginx-Pod 进行调度呢?总不能每次手动改或者 Rolling Update 前端 Nginx Pod 吧!此时Ingress 出现了,如果不算上面的 Nginx,Ingress 包含两大组件:Ingress Controller 和 Ingress。 - Ingress 介绍
-
Ingress 官网定义:Ingress 可以把进入到集群内部的请求转发到集群中的一些服务上,从而可以把服务映射到集群外部。Ingress 能把集群内 Service 配置成外网能够访问的 URL,流量负载均衡,提供基于域名访问的虚拟主机等。
Ingress 简单的理解就是你原来需要改 Nginx 配置,然后配置各种域名对应哪个 Service,现在把这个动作抽象出来,变成一个 Ingress 对象,你可以用 yaml 创建,每次不要去改 Nginx 了,直接改yaml 然后创建/更新就行了;
那么问题来了:”Nginx 该怎么处理?”
Ingress Controller 这东西就是解决 “Nginx 的处理方式” 的;
Ingress Controller 通过与Kubernetes API 交互,动态的去感知集群中 Ingress 规则变化,然后读取他,按照他自己模板生成一段 Nginx 配置,再写到 Nginx Pod 里,最后 reload 一下,工作流程如下图:实际上 Ingress 也是 Kubernetes API 的标准资源类型之一,它其实就是一组基于 DNS 名称(host)或 URL 路径把请求转发到指定的 Service 资源的规则。
用于将集群外部的请求流量转发到集群内部完成的服务发布。
需要明白的是,Ingress 资源自身不能进行“流量穿透”,仅仅是一组规则的集合,这些集合规则还需要其他功能的辅助,比如监听某套接字,然后根据这些规则的匹配进行路由转发,这些能够为 Ingress 资源监听套接字并将流量转发的组件就是 Ingress Controller。
注:Ingress 控制器不同于 Deployment 控制器的是,Ingress 控制器不直接运行为 kubecontroller-manager 的一部分,它仅仅是 Kubernetes 集群的一个附件,类似于 CoreDNS,需要在集群上单独部署。 -
Ingress Controller 介绍
-
扩展:Ingress controller 做成高可用
Ingress Controller 是一个七层负载均衡调度器,客户端的请求先到达这个七层负载均衡调度器,由七层负载均衡器在反向代理到后端 pod
常见的七层负载均衡器有 nginx、traefik,以我们熟悉的nginx 为例,假如请求到达 nginx,会通过 upstream 反向代理到后端 pod 应用,但是后端 pod 的 ip 地址是一直在变化的,因此在后端 pod 前需要加一个 service,这个 service 只是起到分组的作用,那么我们 upstream 只需要填写 service 地址即可 -
Ingress 和 Ingress Controller 总结
-
Ingress Controller 可以理解为控制器,它通过不断的跟 Kubernetes API 交互,实时获取后端Service、Pod 的变化,比如新增、删除等,结合 Ingress 定义的规则生成配置,然后动态更新上边的Nginx 或者 trafik 负载均衡器,并刷新使配置生效,来达到服务自动发现的作用。
-
Ingress 则是定义规则,通过它定义某个域名的请求过来之后转发到集群中指定的 Service。它可以通过 Yaml 文件定义,可以给一个或多个 Service 定义一个或多个 Ingress 规则。
-
Ingress Controller 代理 k8s 内部应用的流程
(1)部署 Ingress controller,这里 ingress controller 使用的是 nginx
(2)创建 Service,用来分组 pod
(3)创建 Pod 应用,可以通过控制器创建 pod
(4)创建 Ingress http,测试通过 http 访问应用
(5)创建 Ingress https,测试通过 https 访问应用
客户端通过七层调度器访问后端 pod 的方式
使用七层负载均衡调度器 ingress controller 时,当客户端访问 kubernetes 集群内部的应用时,数据包走向如下图流程所示:
-
安装 Nginx Ingress Controller
-
vim nginx-ingress-controller-rbac.yml
yml 文件可以在 github 上搜索
-
vim default-backend.yaml
注意这里的 nodeName
-
vim nginx-ingress-controller.yaml
注意:
default-backend.yaml 和 nginx-ingress-controller.yaml 文件指定了 nodeName:k8s-01,表示 default 和 nginx-ingress-controller 部署在 k8s-01 节点,需要自行修改成自己的主机名,这样才会调度成功,一定要让 defaulthttp-backend 和 nginx-ingress-controller 这两个 pod 在一个节点上。 -
更新文件
kubectl apply -f nginx-ingress-controller-rbac.yml
kubectl apply -f default-backend.yaml
kubectl apply -f nginx-ingress-controller.yaml
kubectl get po -n kube-system -
测试 Ingress HTTP 代理 tomcat
vim ingress-demo.yaml部署 ingress
(1)编写 ingress 的配置清单
vim ingress-myapp.yaml修改物理机本地的 host 文件,增加如下一行,下面的 ip 是 k8s 的 k8s-01 节点 ip
192.168.2.20 tomcat.lucky.com
浏览器访问 tomcat.lucky.com,出现如下:
把上面资源清单文件删除,防止干扰后面的实验
kubectl delete -f ingress-myapp.yaml -
测试 Ingress HTTPS 代理 tomcat
1、构建 TLS 站点
(1)准备证书,在控制节点操作
openssl genrsa -out tls.key 2048
openssl req -new -x509 -key tls.key -out tls.crt -subj /C=CN/ST=Beijing/L=Beijing/O=DevOps/CN=tomcat.lucky.com(2)生成 secret,在控制节点操作
kubectl create secret tls tomcat-ingress-secret --cert=tls.crt --key=tls.key
(3)查看 secret
kubectl get secret
显示如下:
(4)查看 tomcat-ingress-secret 详细信息
kubectl describe secret tomcat-ingress-secret -
创建 Ingress
Ingress 规则可以参考官方:
https://kubernetes.io/zh/docs/concepts/services-networking/ingress/
kubectl explain ingress.spec.rules.http.paths.backend.service
vim ingress-tomcat-tls.yaml浏览器访问 https://tomcat.lucky.com
删除 ingress 资源
kubectl delete -f ingress-tomcat-tls.yaml -
安装 harbor 请参考拙作
创建 docker 私有化仓库_高飞的博客-CSDN博客 -
安装和配置数据存储仓库 MySQL
yum install mysql* -y
yum install mariadb* -y
启动 MySQL
systemctl enable mariadb.service --now安装成功后,默认的 root 用户密码为空,你可以使用以下命令来创建 root 用户的密码,密码设置成 111111
mysqladmin -u root password "111111"登陆数据库
mysql -uroot -p111111
创建数据库 tb_order、tb_product、tb_stock
mysql> create database tb_product;
mysql> create database tb_stock;
mysql> create database tb_order;mysql> use tb_order
mysql> source /root/order.sql
mysql> use tb_stock
mysql> source /root/stock.sql
mysql> use tb_product
mysql> source /root/product.sqlmysql> grant all on *.* to 'root'@'10.244.%.%' identified by '111111';
mysql> grant all on *.* to 'root'@'192.168.%.%' identified by '111111';
mysql> grant all on *.* to 'root'@'%' identified by '111111';
mysql> flush privileges;
mysql> exit -
为什么要将 SpringCloud 项目迁移到 K8S 平台?
SpringCloud 只能用在 SpringBoot 的 java 环境中,而 kubernetes 可以适用于任何开发语言,只要能被放进 docker 的应用,都可以在 kubernetes 上运行,而且更轻量,更简单。
每个微服务可以部署多个,没有多少依赖,并且有负载均衡能力,比如一个服务部署一个副本或 5 个副本,通过 k8s 可以更好的去扩展我们的应用。
SpringCloud 很多功能都跟 kubernetes 重合,比如服务发现,负载均衡,配置管理,所以如果把SpringCloud 部署到 k8s,那么很多功能可以直接使用 k8s 原生的,减少复杂度。
SpringCloud 容易上手,是对开发者比较友好的平台;Kubernetes 是可以实现 DevOps 流程的,SpringCloud 和 kubernetes 各有优点,只有结合起来,才能发挥更大的作用,达到最佳的效果。
-
大型电商平台微服务架构解读
Xmind
Visio
https://www.processon.com
- 单体架构 vs 微服务解读
- 什么是微服务?
微服务是用于构建应用程序的架构风格,一个大的系统可由一个或者多个微服务组成,微服务架构可将应用拆分成多个核心功能,每个功能都被称为一项服务,可以单独构建和部署,这意味着各项服务在工作和出现故障的时候不会相互影响。 - 为什么要用微服务?
1、单体架构扩展性差、维护成本高、不可靠
什么是单体架构? 在单体架构下修改代码,需要把整个代码重新编译,重新部署,这个时间周期会很长;
单体架构下的所有代码模块都耦合在一起,代码量大,维护困难,想要更新一个模块的代码,也可能会影响其他模块,不能很好的定制化代码。
所有模块都用同一个数据库,存储方式比较单一。
2、微服务中可以有 java 编写、有 Python 编写的,他们都是靠 restful 架构风格统一成一个系统的,所以微服务本身与具体技术无关、扩展性强 - 微服务特性
1)灵活部署、独立扩展
传统的单体架构是以整个系统为单位进行部署,而微服务则是以每一个独立组件(例如订单服务,商品服务)为单位进行部署。
2)资源的有效隔离
每一个微服务拥有独立的数据源,假如微服务 A 想要读写微服务 B 的数据库,只能调用微服务 B 对外暴露的接口来完成。这样有效避免了服务之间争用数据库和缓存资源所带来的问题。另外微服务各模块部署在 k8s 中,可以进行 CPU、内存等资源的限制和隔离。
3)高度可扩展性
随着某些服务模块的不断扩展,可以跨多个服务器和基础架构进行部署,充分满足业务需求。
4)易于部署
相对于传统的单体式应用,基于微服务的应用更加模块化且小巧,且易于部署。
5)服务组件化
在微服务架构中,需要我们对服务进行组件化分解,服务是一种进程外的组件,它通过 HTTP 等通信协议进行协作,而不是像传统组件那样镶入式的方式协同工作,每一个服务都独立开发、部署、可以有效避免一个服务的修改引起整个系统的重新部署。
6)去中心化治理
在整个微服务架构,通过采用轻量级的契约定义接口,使得我们对服务本身的具体技术平台不再那么敏感,这样整个微服务架构系统中的各个组件就能针对不同的业务特点选择不同的技术平台。
7)容错设计
在微服务架构中,快速检测出故障源并尽可能地自动恢复服务是必须被设计考虑的,通常我们都希望在每个服务中实现监控和日志记录。比如对服务状态、断路器状态、吞吐量、网络延迟等关键数据进行可视化展示。
8)技术栈不受限
在微服务架构中,可以结合项目业务及团队的特点,合理地选择技术栈。
9)局部修改容易部署
单体应用只要有修改,就得重新部署整个应用,微服务解决了这样的问题。
10)易于开发和维护
一个微服务只会关注一个特定的业务功能,所以它业务清晰,代码量较少。 - 哪些项目适合微服务部署?
- 什么项目适合微服务?
在复杂度比较低的项目中,单体架构就可以满足需求,而且部署效率也会比较高,在复杂度比较高的项目中,单体架构就不能满足了,需要进行微服务化。
微服务可以按照业务功能本身的独立性来划分,如果系统提供的业务是非常底层的,如:操作系统内核、存储系统、网络系统、数据库系统等,这类系统都偏底层,功能和功能之间有着紧密的配合关系,如果强制拆分为较小的服务单元,会让集成工作量急剧上升,并且这种人为的切割无法带来业务上的真正的隔离,所以无法做到独立部署和运行,也就不适合做成微服务了。
那到底什么样的项目适合微服务呢?
1. 业务并发量大,项目复杂,访问流量高,为了将来更好的扩展,随时对代码更新维护,可以使用微服务
2. 代码依赖程度高,想要解耦合,交给多个开发团队维护
3. 业务初期,服务器数量少,可以使用微服务,能有效节省资源。
4. 从思想上: 对未来有清晰的认识,对技术更新要保持着一种自信,超前思维,知道这个东西在将来肯定会发展起来。
在学习技术的时候,适合自己的才是最好的,比方说很多人说我们公司单体架构用的也挺好的啊,为什么还要用微服务,其实他们再用单体可能适合他们业务需求,但是我们公司可能业务规模大,项目复杂,我就想要用微服务,或者我们在未来上有更大的远见,那我也会选择用微服务,不要说看别人用,我也用,而是我用是符合我们实际需求的,一切脱离实际业务的微服务都是耍流氓。 - 使用微服务需要考虑的问题
1、统一的配置管理中心
服务拆分以后,服务的数量非常多,如果所有的配置都以配置文件的方式放在应用本地的话,非常难以管理,可以想象当有几百上千个进程中有一个配置出现了问题,是很难将它找出来的,因而需要有统一的配置中心,来管理所有的配置,进行统一的配置下发。
在微服务中,配置往往分为几类,一类是几乎不变的配置,这种配置可以直接打在容器镜像里面,第二类是启动时就会确定的配置,这种配置往往通过环境变量,在容器启动的时候传进去,第三类就是统一的配置,需要通过配置中心进行下发,例如在大促的情况下,有些功能需要降级,哪些功能可以降级,哪些功能不能降级,都可以在配置文件中统一配置。
2、全链路监控
1)系统和应用的监控
监控系统和服务的健康状态和性能瓶颈,当系统出现异常的时候,监控系统可以配合告警系统,及时地发现,通知,干预,从而保障系统的顺利运行。
2)调用关系的监控
对代码调用关系进行监控
3、日志收集
业务层面、代码层面、系统层面
- SpringCloud 是什么?
官方解释:
官网: https://spring.io/projects/spring-cloud/ - SpringCloud 是一系列框架的有序集合。它利用 SpringBoot 的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用SpringBoot 的开发风格做到一键启动和部署。
SpringCloud 并没有重复制造轮子,它只是将各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过 SpringBoot 风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。 - SpringCloud 和 SpringBoot 什么关系?
-
SpringBoot 专注于快速方便的开发单个个体微服务。
-
SpringCloud 是关注全局的微服务协调整理治理框架,它将 SpringBoot 开发的一个个单体微服务整合并管理起来,SpringBoot 可以离开 SpringCloud 独立开发项目,但是 SpringCloud 离不开SpringBoot,属于依赖关系。
- SpringCloud 优缺点
1)SpringCloud 来源于 Spring,质量、稳定性、持续性都可以得到保证。
SpirngCloud 以 SpringBoot 为基础开发框架,可以给开发者大量的微服务开发经验,例如,只要极少量的标签,你就可以创建一个配置服务器,再加一些标签,你就可以得到一个客户端库来配置你的服务,更加便于业务落地。
2)SpringCloud 是 Java 领域最适合做微服务的框架,对 Java 开发者来说就很容易开发。
3)耦合度低,不影响其他模块
4)多个开发团队可以并行开发项目,提高开发效率
5)直接写自己的代码即可,然后暴露接口,通过组件进行服务通信。
缺点:
只能针对 Java 开发,部署麻烦、组件多,每个微服务都可以用一个数据库,导致数据管理复杂一套完整的微服务包括自动化部署,调度,资源管理,进程隔离,自愈,构建流水线等功能,单靠SpringCloud 是无法实现的,所以 SpringCloud+k8s 才是最好的方案 - 为何要将 SpringCloud 项目部署到 k8s 平台?
- SpringCloud 只能用在 SpringBoot 的 java 环境中,而 kubernetes 可以适用于任何开发语言,只要能被放进 docker 的应用,都可以在 kubernetes 上运行,而且更轻量,更简单。
每个微服务可以部署多个,没有多少依赖,并且有负载均衡能力,比如一个服务部署一个副本或 5 个副本,通过 k8s 可以更好的去扩展我们的应用。
Spring 提供应用的打包,Docker 和 Kubernetes 提供部署和调度。Spring 通过 Hystrix 线程池提供应用内的隔离,而 Kubernetes 通过资源,进程和命名空间来提供隔离。
Spring 为每个微服务提供健康终端,而 Kubernetes 执行健康检查,且把流量导到健康服务。Spring 外部化配置并更新它们,而Kubernetes 分发配置到每个微服务。
SpringCloud 很多功能都跟 kubernetes 重合,比如服务发现,负载均衡,配置管理,所以如果把
SpringCloud 部署到 k8s,那么很多功能可以直接使用 k8s 原生的,减少复杂度。
SpringCloud 容易上手,是对开发者比较友好的平台;Kubernetes 是可以实现 DevOps 流程的,
SpringCloud 和 kubernetes 各有优点,只有结合起来,才能发挥更大的作用,达到最佳的效果。 -
SpringCloud 项目部署到 k8s 的流程
-
制作镜像--->控制管理 pod--->暴露应用--->对外发布应用--->数据持久化---→日志/监控
1.制作镜像: 应用程序、运行环境、文件系统
2.控制器管理 pod:deployment 无状态部署、statefulset 有状态部署、Daemonset 守护进程部署、job & cronjob 批处理
3.暴露应用:服务发现、负载均衡
4.对外发布应用:service、Ingress HTTP/HTTPS 访问
5.pod 数据持久化:分布式存储-ceph 和 gluster
6.日志/监控:efk、prometheus、pinpoint 等 - SpringCloud 组件介绍
- 服务发现与注册组件 Eureka
- Eureka 是 Netflix 开发的服务发现框架, SpringCloud 将它集成在自己的子项目 spring-cloudnetflix 中,以实现 SpringCloud 中服务发现和注册功能。Eureka 包含两个组件:Eureka Server 和Eureka Client。
- Netflix 是什么?
Netflix 在 SpringCloud 项目中占着重要的作用,Netflix 公司提供了包括 Eureka、Hystrix、Zuul、Archaius 等在内的很多组件,在微服务架构中至关重要。 - 举个例子服务发现与注册
我们在买车的时候,需要找中介,如果不找中介,我们自己去找厂商或者个人车主,这是很麻烦的,也很浪费时间,所以为了方便,我们一般去找中介公司,把我们的需求说出来,他们就会按需给我们推荐车型,我们相当于微服务架构中的消费者 Consumer,中介相当于微服务架构中的提供者 Provider,Consumer 需要调用 Provider 提供的一些服务,就像是我们要买的车一样。 - Eureka 服务组成
- Eureka Server
Eureka Server 提供服务注册中心,各个节点启动后,会将自己的 IP 和端口等网络信息注册到Eureka Server 中,这样 Eureka Server 服务注册表中将会存储所有可用服务节点的信息,在 Eureka的图形化界面可以看到所有注册的节点信息。
Eureka Client
Eureka Client 是一个 java 客户端,在应用启动后,Eureka 客户端将会向 Eureka Server 端发送心跳,默认周期是 30s,如果 Eureka Server 在多个心跳周期内没有接收到某个节点的心跳,Eureka Server 将会从服务注册表中把这个服务节点移除(默认 90 秒)。
Eureka Client 分为两个角色,分别是 Application Service 和 Application Client
Application Service 是服务提供方,是注册到 Eureka Server 中的服务。
Application Client 是服务消费方,通过 Eureka Server 发现其他服务并消费。 - Register(服务注册):当 Eureka 客户端向 Eureka Server 注册时,会把自己的 IP、端口、运行状况等信息注册给 Eureka Server。
Renew(服务续约):Eureka 客户端会每隔 30s 发送一次心跳来续约,通过续约来告诉 Eureka Server 自己正常,没有出现问题。正常情况下,如果 Eureka Server 在 90 秒没有收到 Eureka 客户的续约,它会将实例从其注册表中删除。
Cancel(服务下线):Eureka 客户端在程序关闭时向 Eureka 服务器发送取消请求。 发送请求后,该客户端实例信息将从服务器的实例注册表中删除,防止 consumer 调用到不存在的服务。该下线请求不会自动完成,它需要调用以下内容:
DiscoveryManager.getInstance().shutdownComponent();
Get Registry(获取服务注册列表):获取其他服务列表。
Replicate(集群中数据同步):eureka 集群中的数据复制与同步。
Make Remote Call(远程调用):完成服务的远程调用。 -
客户端负载均衡之 Ribbon
- Ribbon 简介
- Ribbon 是一个基于 HTTP 和 TCP 的客户端负载均衡器,主要提供客户侧的软件负载均衡算法,运行在消费者端。客户端负载均衡是当浏览器向后台发出请求的时候,客户端会向 Eureka Server 读取注册到服务器的可用服务信息列表,然后根据设定的负载均衡策略,抉择出向哪台服务器发送请求。在客户端就进行负载均衡算法分配。Ribbon 客户端组件提供一系列完善的配置选项,比如连接超时、重试、重试算法等。
下面是用到的一些负载均衡策略:
随机策略---随机选择 server
轮询策略---轮询选择, 轮询 index,选择 index 对应位置的 Server
重试策略--在一个配置时间段内当选择 Server 不成功,则一直尝试使用 subRule 的方式选择一个可用的 server
最低并发策略--逐个考察 server,如果 server 断路器打开,则忽略,再选择其中并发链接最低的server
可用过滤策略--过滤掉一直失败并被标记为 circuit tripped 的 server,过滤掉那些高并发链接的server(active connections 超过配置的阈值)或者使用一个 AvailabilityPredicate 来包含过滤server 的逻辑,其实就就是检查 status 里记录的各个 Server 的运行状态;
响应时间加权重策略--根据 server 的响应时间分配权重,响应时间越长,权重越低,被选择到的概率也就越低。响应时间越短,权重越高,被选中的概率越高,这个策略很贴切,综合了各种因素,比如:网络,磁盘,io 等,都直接影响响应时间;
区域权重策略--综合判断 server 所在区域的性能,和 server 的可用性,轮询选择 server 并且判断一个 AWS Zone 的运行性能是否可用,剔除不可用的 Zone 中的所有 server。 - 举个列子说明 ribbon
比如我们设计了一个秒杀系统,但是为了整个系统的高可用,我们需要将这个系统做一个集群,而这个时候我们消费者就可以拥有多个秒杀系统的调用途径了,如下图。 如果这个时候我们没有进行一些均衡操作,如果我们对秒杀系统 1 进行大量的调用,而另外两个基本不请求,就会导致秒杀系统 1 崩溃,而另外两个就变成了傀儡,那么我们为什么还要做集群,我们高可用体现的意义又在哪呢?
所以 Ribbon 出现了,注意我们上面加粗的几个字——运行在消费者端。指的是,Ribbon 是运行在消费者端的负载均衡器,如下图。 其工作原理就是 Consumer 端获取到了所有的服务列表之后,在其内部使用负载均衡算法,进行对多个系统的调用。 - Ribbon 的功能
易于与服务发现组件(比如 Eureka)集成使用 Archaius 完成运行时配置
使用 JMX 暴露运维指标,使用 Servo 发布
多种可插拔的序列化选择
异步和批处理操作
自动 SLA 框架
系统管理/指标控制台 - Ribbon 和 nginx 对比分析
区别:
Ribbon 实现的是客户端负载均衡,它可以在客户端经过一系列算法来均衡调用服务。Ribbon 工作时分两步:
第一步:从 Eureka Server 中获取服务注册信息列表,它优先选择在同一个 Zone 且负载较少的Server。
第二步:根据用户指定的策略,在从 Server 取到的服务注册列表中选择一个地址,其中 Ribbon 提供了多种策略,例如轮询、随机等。 - 服务网关 Zuul
Zuul 是 SpringCloud 中的微服务网关,首先是一个微服务。也是会在 Eureka 注册中心中进行服务的注册和发现。也是一个网关,请求应该通过 Zuul 来进行路由。Zuul 网关不是必要的,是推荐使用的。
网关是什么?
是一个网络整体系统中的前置门户入口。请求首先通过网关,进行路径的路由,定位到具体的服务节点上。
Zuul 网关的作用:
统一入口:为服务提供一个唯一的入口,网关起到外部和内部隔离的作用,保障了后台服务的安全性。
鉴权校验:识别每个请求的权限,拒绝不符合要求的请求。
动态路由:动态的将请求路由到不同的后端集群中。
减少客户端与服务端的耦合:服务可以独立发展,通过网关层来做映射。 - 熔断器 Hystrix
Hystrix 的中文名字是“豪猪”,豪猪是满身长满了刺,能够保护自己不受天敌的伤害,代表了一种防御机制,Hystrix 在 SpringCloud 中负责服务熔断和服务降级的作用。
什么是服务熔断?(熔断可以保护服务):
在讲熔断之前先看个概念: 服务雪崩
假设有 A、B、C 三个服务,服务 A 调用服务 B 和 C,链路关系如下: - 接下来看下服务熔断:
举个生活中的例子
当电路发生故障或异常时,伴随着电流不断升高,并且升高的电流有可能能损坏电路中的某些重要器件,也有可能烧毁电路甚至造成火灾。若电路中正确地安置了保险丝,那么保险丝就会在电流异常升高到一定的高度和热度的时候,自身熔断切断电流,从而起到保护电路安全运行的作用。
在微服务架构中,在高并发情况下,如果请求数量达到一定极限(可以自己设置阈值),超出了设置的阈值,Hystrix 会自动开启服务保护功能,然后通过服务降级的方式返回一个友好的提示给客户端。假设当 10 个请求中,有 10%失败时,熔断器就会打开,此时再调用此服务,将会直接返回失败,不再调远程服务。直到 10s 钟之后,重新检测该触发条件,判断是否把熔断器关闭,或者继续打开。
服务降级(提高用户体验效果):
在高并发的场景下,当服务器的压力剧增时,根据当前业务以及流量的情况,对一些服务和页面进行策略控制,对这些请求做简单的处理或者不处理,来释放服务器资源用以保证核心业务不受影响,确保业务可以正常对外提供服务,比如电商平台,在针对 618、双 11 的时候会有一些秒杀场景,秒杀的时候请求量大,可能会返回报错标志“当前请求人数多,请稍后重试”等,如果使用服务降级,无法提供服务的时候,消费者会调用降级的操作,返回服务不可用等信息,或者返回提前准备好的静态页面写好的信息。 - API 网关 Springcloud Gateway
为什么学习了网关 Zuul,又要讲 Spring Cloud Gateway 呢?
原因很简单,就是 Spring Cloud 已经放弃 Zuul 了。现在 Spring Cloud 中引用的还是 Zuul 1.x版本,而这个版本是基于过滤器的,是阻塞 IO,不支持长连接,spring 官网上也已经没有 zuul 的组件了,所以给大家讲下 SpringCloud 原生的网关产品 Gateway。
Spring Cloud Gateway 是 Spring Cloud 新推出的网关框架,之前是 Netflix Zuul,由 spring官方基于 Spring5.0,Spring Boot2.0,Project Reactor 等技术开发的网关,该项目提供了一个构建在Spring Ecosystem 之上的 API 网关,旨在提供一种简单而有效的途径来发送 API,并向他们提供交叉关注点,例如:安全性,监控/指标和弹性.
SpringCloud Gateway 特征:
SpringCloud 官方对 SpringCloud Gateway 特征介绍如下:
(1)集成 Hystrix 断路器
(2)集成 Spring Cloud DiscoveryClient
(3)Predicates 和 Filters 作用于特定路由,易于编写的 Predicates 和 Filters
(4)具备一些网关的高级功能:动态路由、限流、路径重写
从以上的特征来说,和 Zuul 的特征差别不大。SpringCloud Gateway 和 Zuul 主要的区别,还是在底层的通信框架上。
简单说明一下上文中的三个术语:
1)Filter(过滤器):
和 Zuul 的过滤器在概念上类似,可以使用它拦截和修改请求,并且对上游的响应,进行二次处理。
过滤器为 org.springframework.cloud.gateway.filter.GatewayFilter 类的实例。
2)Route(路由):
网关配置的基本组成模块,和 Zuul 的路由配置模块类似。一个 Route 模块由一个 ID,一个目标URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配,目标 URI 会被访问。
3)Predicate(断言):
这是一个 Java8 的 Predicate,可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。断言的输入类型是一个 ServerWebExchange。 - 配置中心 SpringCloud Config
SpringCloud Config 是一个解决分布式系统的配置管理方案,它包含了 server 和 client 两个部分。server 用来获取远程的配置信息(默认为 Git 仓库),并且以接口的形式提供出去,client 根据server 提供的接口读取配置文件,以便于初始化自己的应用。如果配置中心出现了问题,将导致灾难性的后果,因此在生产环境下配置中心都会做集群,来保证高可用。此处配置高可用实际就是把多个配置中心(指定同一个 Git 远程仓库)注册到注册中心。
部署 SpringCloud 框架的电商项目:在线购物平台
安装 openjdk 和 maven
在 k8s 控制节点上操作
yum install java-1.8.0-openjdk maven-3.0.5* -y- 修改源代码,更改数据库连接地址
vim /root/microservic-test/stock-service/stock-service-biz/src/main/resources/application-fat.yml 修改产品服务 product 的数据库连接地址
vim /root/microservic-test/product-service/product-service-biz/src/main/resources/application-fat.yml 修改订单数据库
vim /root/microservic-test/order-service/order-service-biz/src/main/resources/application-fat.yml 通过 Maven 编译、构建、打包源代码
在 k8s 控制节点上操作
修改源代码数据库的地址之后回到/root/microservic-test 目录下执行如下命令:
# cd microservic-test
# mvn clean package -D maven.test.skip=true
清理缓存 /root/.m2/repository
编译完成大概需要 15-20 分钟,看到如下说明编译打包已经成功了:
在 k8s 中部署 Eureka 组件
修改 k8s 的控制节点和工作节点的上的 docker 的配置文件:
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors":["https://hxn0tro1.mirror.aliyuncs.com","https://registry.dockercn.com","https://docker.mirrors.ustc.edu.cn","https://dockerhub.azk8s.cn","http://hubmirror.c.163.com"],
"exec-opts": ["native.cgroupdriver=systemd"],
"insecure-registries":["192.168.2.50","harbor"]
}
EOF
注意:
daemon.json 中新增加了如下一行内容:
"insecure-registries":["192.168.2.50","harbor"],
这样才可以使用 harbor 私有镜像仓库- 重启 docker 使配置生效
systemctl daemon-reload && systemctl restart docker && systemctl status docker --no-pager创建拉取私有镜像仓库需要的 secret
kubectl create ns ms && kubectl create secret docker-registry registry-pull-secret --docker-server=192.168.2.50 --docker-username=admin --docker-password=Harbor12345 -n ms在 harbor 上创建一个项目 microservice
构建镜像
cd /root/microservic-test/eureka-servicedocker build -t 192.168.2.50/microservice/eureka:v1 .
docker login harbor
docker push 192.168.2.50/microservice/eureka:v12)部署服务
cd /root/microservic-test/k8s
修改 eureka.yaml 文件,把镜像变成 image: 192.168.2.50/microservice/eureka:v13)更新 yaml 文件
kubectl apply -f eureka.yaml上面运行没问题之后,在物理机的 hosts 文件,新加如下一行:
192.168.2.20 eureka.ctnrs.com
在浏览器访问 eureka.ctnrs.com 即可,可看到如下,说明 eureka 部署成功了:在 k8s 中部署网关 Gateway 服务
- 1)构建镜像
cd /root/microservic-test/gateway-service/
docker build -t 192.168.2.50/microservice/gateway:v1 .
docker push 192.168.2.50/microservice/gateway:v1 2)部署服务
cd /root/microservic-test/k8s
修改 gateway.yaml 文件,把镜像变成 image: 192.168.2.50/microservice/gateway:v1
3)更新 yaml 文件
kubectl apply -f gateway.yaml
4)查看 pod 状态
kubectl get pods -n ms 6)配置 hosts 文件
gateway 的域名是 gateway.ctnrs.com,需要在物理机找到 hosts 文件,再增加一行如下:
192.168.2.20 gateway.ctnrs.com
在浏览器访问 eureka.ctnrs.com
可看到 GATEWAY-SERVICE 已经注册到 eureka 了:
- 在 k8s 中部署前端 portal 服务
1)构建镜像
cd /root/microservic-test/portal-service
docker build -t 192.168.2.50/microservice/portal:v1 .
docker push 192.168.2.50/microservice/portal:v1 2)部署服务
cd /root/microservic-test/k8s
修改 portal.yaml 文件,把镜像变成 image: 192.168.2.50/microservice/portal:v1 3)更新 yaml 文件
kubectl apply -f portal.yaml
4)查看 pod 状态
kubectl get pods -n ms 在物理机的 hosts 文件中,再增加一行如下内容:
192.168.2.20 portal.ctnrs.com
6)查看 portal 是否注册到 eureka 中
在浏览器访问 eureka.ctnrs.com 可看到 portal 服务已经注册到 eureka 了
7)访问前端页面
在浏览器访问 portal.ctnrs.com
- 在 k8s 中部署订单 order 服务
1)构建镜像
cd /root/microservic-test/order-service/order-service-biz
docker build -t 192.168.2.50/microservice/order:v1 .
docker push 192.168.2.50/microservice/order:v1
2)部署服务
cd /root/microservic-test/k8s
修改 order.yaml 文件,把镜像变成 image: 192.168.2.50/microservice/order:v1 3)更新 yaml 文件
kubectl apply -f order.yaml
4)查看 pod 状态
kubectl get pods -n ms
- 在 k8s 中部署产品 product 服务
1)构建镜像
cd /root/microservic-test/product-service/product-service-biz
docker build -t 192.168.2.50/microservice/product:v1 .
docker push 192.168.2.50/microservice/product:v1
2)部署服务
cd /root/microservic-test/k8s
修改 product.yaml 文件,把镜像变成 image: 192.168.2.50/microservice/product:v1
3)更新 yaml 文件
kubectl apply -f product.yaml - 在 k8s 中部署库存 stock 服务
1)构建镜像
cd /root/microservic-test/stock-service/stock-service-biz
docker build -t 192.168.2.50/microservice/stock:v1 .
docker push 192.168.2.50/microservice/stock:v1
2)部署服务
cd /root/microservic-test/k8s
修改 stock.yaml 文件,把镜像变成 image: 192.168.2.50/microservice/stock:v1
3)更新 yaml 文件
kubectl apply -f stock.yaml
4)查看 pod 状态
kubectl get pods -n ms
上面都部署成功之后,在浏览器访问 eureka.ctnrs.com 可看到 gateway、portal、product、order、stock 等服务都已经注册到 eureka 了 在浏览器访问 portal.ctnrs.com 登陆前端页面,点击查询商品服务,出现如下:
选择手机,点击购买---确定,然后再点击查询订单服务,出现如下:
- 什么是全链路监控?
全链路性能监控从整体维度到局部维度展示各项指标,将跨应用的所有调用链性能信息集中展现,可方便度量整体和局部性能,并且方便找到故障产生的源头,生产上可极大缩短故障排除时间。 - 全链路监控跟传统的 prometheus 监控有何区别?
Prometheus 监控解决了基本指标和报警问题(cpu、内存、磁盘、网络流量等指标),全链路监控的解决链路追踪的问题,两者各司其职,是互相的补充。 - 为什么要进行全链路监控?
随着服务架构的流行,尤其是 k8s 的大量使用,导致各服务间的调用关系越来越复杂,一次请求往往需要涉及到多个服务,这些服务有可能是由不同的团队开发、可能使用不同的编程语言来实现、有可能分布在了几千台服务器,横跨多个不同的数据中心。分布式部署架构带来的问题就会迅速凸显出来。尤其线上出现问题,不知道如何排查,问题出现在哪个服务?如何快速定位问题?如何跟踪业务调用链路?于是就有了全链路监控 -
全链路监控系统概述
- 什么是全链路监控系统?
在分布式微服务架构中,系统为了接收并处理一个前端用户请求,需要让多个微服务应用协同工作,其中的每一个微服务应用都可以用不同的编程语言构建,由不同的团队开发,并可以通过多个对等的应用实例实现水平扩展,甚至分布在横跨多个数据中心的数千台服务器上。单个用户请求会引发不同应用之间产生一串顺序性的调用关系,如果要对这些调用关系进行监控,了解每个应用如何调用,这就产生了全链路监控。 - 为什么要进行全链路监控?
- 在微服务架构中,服务会被拆分成多个模块,这些模块可能由不同的开发团队开发、维护,也可能使用不同的编程语言来实现、也有可能分布在多台服务器上,由于服务的拆分,单个用户的请求会经过多个微服务,相互之间形成复杂的调用关系,传统的监控手段已经不能实现如此复杂的链路之间的监控了,因此,就需要一些可以帮助理解系统行为、用于分析性能问题的工具,以便发生故障的时候,能够快速定位和解决问题。
- 全链路监控系统可以解决哪些问题?
1. 请求链路追踪,故障快速定位:可以通过调用链结合业务日志快速定位错误信息。
2. 可视化: 各个阶段耗时,进行性能分析。
3. 依赖优化:各个调用环节的可用性、梳理服务依赖关系以及优化。
4. 数据分析,优化链路:可以得到用户的行为路径,汇总分析应用在很多业务场景。 - 全链路监控可监控哪些指标?
全链路监控的四部分:链路采集、指标采集、日志采集、深度分析 在微服务架构中,不同维度有不同的监控方式。
(1)健康检查。健康检查是对应用本身健康状况的监控,检查服务是否还正常存活。
(2)日志。日志是排查问题的主要方式,日志可以提供丰富的信息用于定位和解决问题。
(3)调用链监控。调用链监控可以完整的呈现出一次请求的全部信息,包括服务调用链路、所耗时间等。
(4)指标监控。指标是一些基于时间序列的离散数据点,通过聚合和计算后能反映出一些重要指标的趋势。
在上述 4 种监控方式中,健康检查是云平台等基础设施提供的能力,日志则一般有单独的日志中心进行日志的采集、存储、计算和查询,调用链监控一般也有独立的解决方案进行服务调用的埋点、采集、计算和查询。 - 指标监控选择 Prometheus 的主要原因:
(1)成熟的社区支撑。Prometheus 是一个开源的监控软件,拥有活跃的社区,能够很好地与云原生环境搭配。
(2) 易于部署和运维。Prometheus 核心只有一个二进制文件,没有其他的第三方依赖,部署运维均十分方便。
(3)采用 Pull 模型,通过 HTTP 的 Pull 方式从各个监控目标拉取监控数据。Push 模型一般通过Agent 方式去采集信息并推送到收集器中,每个服务的 Agent 都需要配置监控数据项与监控服务端的信息,在大量服务时会加大运维难度;另外,采用 Push 模型,在流量高峰期间监控服务端会同时接收到大量请求和数据,会给监控服务端造成很大压力,严重时甚至服务不可用。
(4)强大的数据模型。Prometheus 采集到的监控数据均以指标的形式存在于内置的时序数据库中,除了基本的指标名称外,还支持自定义的标签。通过标签可以定义出丰富的维度,方便进行监控数据的聚合和计算。
(5)强大的查询语言 PromQL。通过 PromQL 可以实现对监控数据的查询、聚合、可视化、告警。
(6)完善的生态。常见的操作系统、数据库、中间件、类库、编程语言,Prometheus 都提供了接入方案,并且提供了 Java/Golang/Ruby/Python 等语言的客户端 SDK,能够快速实现自定义的监控逻辑。
(7)高性能。Prometheus 单一实例即可处理数以百计的监控指标,每秒处理数十万的数据,在数据采集和查询方面有着优异的性能表现。
注意:查看干货 | 爱奇艺全链路自动化监控平台的探索与实践 - 常见的全链路监控工具有哪些?
-
Zipkin
github:https://github.com/openzipkin/zipkin - zipkin 是一个分布式的追踪系统,它能够帮助你收集服务架构中解决问题需要的时间数据,功能包括收集和查找这些数据。如果日志文件中有跟踪 ID,可以直接跳转到它。否则,可以根据服务、操作名称、标记和持续时间等属性进行查询。例如在服务中花费的时间百分比,以及哪些环节操作失败。特点是轻量,使用部署简单。
zipkin 还提供了一个 UI 界面,它能够显示通过每个应用程序的跟踪请求数。这有助于识别聚合行为,包括错误路径或对不推荐使用的服务的调用。 应用程序需要“检测”才能向 Zipkin 报告跟踪数据。这通常意味着需要配置一个用于追踪和检测的库。最流行的向 Zipkin 报告数据的方法是通过 http 或 Kafka,尽管还有许多其他选项,如 apache,activemq、gRPC 和 RabbitMQ。提供给 UI 存储数据的方法很多,如存储在内存中,或者使用受支持的后端(如 apachecassandra 或 Elasticsearch)持久存储。 -
Skywalking
- github: https://github.com/apache/incubator-skywalking
- skywalking 是本土开源的调用链追踪系统,包括监控、跟踪、诊断功能,目前已加入 Apache 孵化器,专门为微服务、云本地和基于容器(Docker、Kubernetes、Mesos)架构设计。
主要功能如下:
1)服务、服务实例、端点指标数据分析
2)根本原因分析,在运行时评测代码
3)服务拓扑图分析
4)服务、服务实例和端点依赖性分析
5)检测到慢速服务和终结点
6)性能优化
7)分布式跟踪和上下文传播
8)数据库访问度量。检测慢速数据库访问语句(包括 SQL 语句)。
9)报警
10)浏览器性能监视
-
Pinpoint
- github: https://github.com/naver/pinpoint
pinpoint 是韩国人开源的基于字节码注入的调用链分析,以及应用监控分析工具。Pinpoint 提供了一个解决方案,可以帮助分析系统的整体结构,以及通过跟踪分布式应用程序中的事务来分析其中的组件是如何相互连接的。
功能如下:
1)一目了然地了解应用程序拓扑
2)实时监视应用程序
3)获得每个事务的代码级可见性
4)安装 APM 代理程序,无需更改一行代码
5)对性能的影响最小(资源使用量增加约 3%)
全链路监控工具对比分析
- 市面上的全链路监控理论模型大多都是借鉴 Google Dapper 论文,下面重点关注以下三种 APM 组件:APM = ApplicationPerformance Management,中文即应用性能管理
1)Zipkin:由 Twitter 公司开源,开放源代码分布式的跟踪系统,用于收集服务的定时数据,以解决微服务架构中的延迟问题,包括:数据的收集、存储、查找和展现。
2)Pinpoint:一款对 Java 编写的大规模分布式系统的 APM 工具,由韩国人开源的分布式跟踪组件。
3)Skywalking:国产的优秀 APM 组件,是一个对 JAVA 分布式应用程序集群的业务运行情况进行追踪、告警和分析的系统。- 全面的调用链路数据分析,提供代码级别的可见性以便轻松定位失败点和瓶颈。
1.zipkin
zipkin 的链路监控粒度相对没有那么细,调用链中具体到接口级别,再进一步的调用信息未普及。
2.skywalking
skywalking 支持 20+的中间件、框架、类库,比如:主流的 dubbo、Okhttp,还有 DB 和消息中间件。skywalking 链路调用分析截取的比较简单,网关调用 user 服务,由于支持众多的中间件,所以 skywalking 链路调用分析比 zipkin 完备些。
3.pinpoint
pinpoint 应该是这三种 APM 组件中,数据分析最为完备的组件。提供代码级别的可见性以便轻松定位失败点和瓶颈,上图可以看到对于执行的 sql 语句,都进行了记录。还可以配置报警规则等,设置每个应用对应的负责人,根据配置的规则报警,支持的中间件和框架也比较完备。
pinpoint 和 zipkin 对比分析
- 差异性:
1. Pinpoint 是一个完整的性能监控解决方案,有从探针、收集器、存储到 Web 界面等全套体系,而 Zipkin 只侧重收集器和存储服务,虽然也有用户界面,但其功能与 Pinpoint 不可同日而语。反而 pinpoint 提供有 Query 接口,更强大的用户界面和系统集成能力,可以基于该接口二次开发实现。
2. Zipkin 官方提供有基于 Finagle 框架(Scala 语言)的接口,而其他框架的接口由社区贡献,目前可以支持 Java、Scala、Node、Go、Python、Ruby 和 C# 等主流开发语言和框架;但是Pinpoint 目前只有官方提供的 Java Agent 探针,其他的都在请求社区支援中。
3. Pinpoint 提供有 Java Agent 探针,通过字节码注入的方式实现调用拦截和数据收集,可以做到真正的代码无侵入,只需要在启动服务器的时候添加一些参数,就可以完成探针的部署,而 Zipkin 的Java 接口实现 Brave(zipkin 的 java 客户端),只提供了基本的操作 API,如果需要与框架或者项目集成的话,就需要手动添加配置文件或增加代码。
4. Pinpoint 的后端存储基于 Hbase,而 Zipkin 基于 Cassandra(Cassandra 是一套开源分布式 NoSQL 数据库系统)。
相似性:
pinpoint 与 zipkin 都是基于 Google Dapper(google 的分布式追踪系统 dapper)的那篇论文,因此理论基础大致相同。两者都是将服务调用拆分成若干有级联关系的 Span,通过 SpanId 和ParentSpanId 来进行调用关系的级联,最后再将整个调用链流经的所有的 Span 汇聚成一个 Trace,报告给服务端的 collector 进行收集和存储。
Pinpoint 所采用的概念也不完全与那篇论文一致。比如他采用 TransactionId 来取代 TraceId,而真正的 TraceId 是一个结构,里面包含了 TransactionId, SpanId 和 ParentSpanId。而且Pinpoint 在 Span 下面又增加了一个 SpanEvent 结构,用来记录一个 Span 内部的调用细节(比如具体的方法调用等等),因此 Pinpoint 默认会比 Zipkin 记录更多的跟踪数据。但是理论上并没有限定Span 的粒度大小,所以一个服务调用可以是一个 Span,那么每个服务中的方法调用也可以是个Span,这样的话,其实 Brave 也可以跟踪到方法调用级别,只是具体实现并没有这样做而已。- span 是什么?
基本工作单元,一次链路调用(可以是 RPC,DB 等没有特定的限制)创建一个 span,通过一个 64位 ID 标识它,uuid 较为方便,span 中还有其他的数据,例如描述信息,时间戳,key-value 对的(Annotation)tag 信息,parent_id 等,其中 parent-id 可以表示 span 调用链路来源。 上图说明了 span 在一次大的跟踪过程中是什么样的。Dapper 记录了 span 名称,以及每个 span的 ID 和父 ID,以重建在一次追踪过程中不同 span 之间的关系。如果一个 span 没有父 ID 被称为 root span。所有 span 都挂在一个特定的跟踪上,也共用一个跟踪 id。
Span 数据结构:
type Span struct {
TraceID int64 #用于标示一次完整的请求 id
Name string
ID int64 #当前这次调用 span_id
ParentID int64 #上层服务的调用 span_id 最上层服务 parent_id 为 null
Annotation []Annotation #用于标记的时间戳
Debug bool
}- Trace 是什么?
类似于树结构的 Span 集合,表示一次完整的跟踪,从请求到服务器开始,服务器返回 response 结束,跟踪每次 rpc 调用的耗时,存在唯一标识 trace_id。比如:你运行的分布式大数据存储一次 Trace就由你的一次请求组成。 每种颜色的 note 标注了一个 span,一条链路通过 TraceId 唯一标识,Span 标识发起的请求信息。树节点是整个架构的基本单元,而每一个节点又是对 span 的引用。节点之间的连线表示的 span 和它的父 span 直接的关系。虽然 span 在日志文件中只是简单的代表 span 的开始和结束时间,他们在整个树形结构中却是相对独立的。初始化实验环境,新创建一台虚拟机安装 pinpoint
- 安装 pinpoint 服务
- unzip pinpoint-docker-2.0.1.zip
cd pinpoint-docker-2.0.1
修改 docker-compose.yml 文件的 version 版本,变成自己支持的版本
version: "3.6" 变成 version: "2.2"
#通过下面命令在线安装 pinpoint 需要的镜像(镜像较大,拉取需要时间)
docker-compose pull
#启动服务
docker-compose up -d
#查看对应的服务是否启动
docker ps | grep pinpoint
#找到 pinpoint-web,可看到在宿主机绑定的端口是 8079,
在浏览器访问 ip:8079 即可访问 pinpoint 的 web ui 界面- 部署电商项目:带 pinpoint agent 客户端
- unzip microservic-test-dev1.zip
修改源代码,更改数据库连接地址
1)修改库存数据库
vim /root/microservic-test-dev1/stock-service/stock-service-biz/src/main/resources/application-fat.yml
jdbc:mysql://192.168.2.10:3306/tb_stock?characterEncoding=utf-8
#变成自己的 mysql 数据库所在机器的地址 2)修改产品数据库
vim /root/microservic-test-dev1/product-service/product-service-biz/src/main/resources/application-fat.yml
jdbc:mysql://192.168.2.10:3306/tb_product?characterEncoding=utf-8 3)修改订单数据库
vim /root/microservic-test-dev1/order-service/order-service-biz/src/main/resources/application-fat.yml
url: jdbc:mysql://192.168.2.10:3306/tb_order?characterEncoding=utf-8 #修改配置,指定 pinpoint 服务端
vim /root/microservic-test-dev1/product-service/product-service-biz/pinpoint/pinpoint.config
profiler.collector.ip=192.168.2.60
#这个是安装 pinpoint 服务的 ip 地址
vim /root/microservic-test-dev1/order-service/order-service-biz/pinpoint/pinpoint.config
profiler.collector.ip=192.168.2.60
vim /root/microservic-test-dev1/stock-service/stock-service-biz/pinpoint/pinpoint.config
profiler.collector.ip=192.168.2.60
vim /root/microservic-test-dev1/portal-service/pinpoint/pinpoint.config
profiler.collector.ip=192.168.2.60
vim /root/microservic-test-dev1/gateway-service/pinpoint/pinpoint.config
profiler.collector.ip=192.168.2.60
vim /root/microservic-test-dev1/eureka-service/pinpoint/pinpoint.config
profiler.collector.ip=192.168.2.60
#上面修改的 ip 是部署 pinpoint 的机器的 ip 地址,也就是 pinpoint 的服务端- 通过 Maven 编译、打包、构建代码
在 k8s 的控制节点操作
修改源代码之后回到/root/microservic-test-dev1 目录下执行如下命令:
cd /root/microservic-test-dev1
mvn clean package -D maven.test.skip=true
#看到如下,说明代码已经打包完成
- 部署带 pinpoint agent 端的产品服务
- cd /root/microservic-test-dev1/product-service/product-service-biz
docker build -t 192.168.2.50/microservice/product:v2 .
docker push 192.168.2.50/microservice/product:v2
cd /root/microservic-test-dev1/k8s
修改 product.yaml 文件,把镜像变成 image: 192.168.2.50/microservice/product:v2
更新 yaml 文件
kubectl delete -f product.yaml
kubectl apply -f product.yaml 上面部署成功之后,登陆 pinpoint web 界面,可看到有个新的应用是 ms-product
- 部署带 pinpoint agent 端的订单服务
cd /root/microservic-test-dev1/order-service/order-service-biz
docker build -t 192.168.2.50/microservice/order:v2 .
docker push 192.168.2.50/microservice/order:v2
cd /root/microservic-test-dev1/k8s
修改 order.yaml 文件,把镜像变成 image: 192.168.2.50/microservice/order:v2
更新 yaml 文件
kubectl delete -f order.yaml
kubectl apply -f order.yaml
上面部署成功之后,登陆 pinpoint web 界面,可看到有个新的应用是 ms-order
- 部署带 pinpoint agent 端的 stock 服务
cd /root/microservic-test-dev1/stock-service/stock-service-biz
docker build -t 192.168.2.50/microservice/stock:v2 .
docker push 192.168.2.50/microservice/stock:v2
cd /root/microservic-test-dev1/k8s
修改 stock.yaml 文件,把镜像变成 image: 192.168.2.50/microservice/stock:v2
更新 yaml 文件
kubectl delete -f stock.yaml
kubectl apply -f stock.yaml
上面部署成功之后,登陆 pinpoint web 界面,可看到有个新的应用是 ms-stock
- 部署带 pinpoint agent 端的 portal 服务
cd /root/microservic-test-dev1/portal-service/
docker build -t 192.168.2.50/microservice/portal:v2 .
docker push 192.168.2.50/microservice/portal:v2
cd /root/microservic-test-dev1/k8s
修改 portal.yaml 文件,把镜像变成 image: 192.168.2.50/microservice/portal:v2
更新 yaml 文件
kubectl delete -f portal.yaml
kubectl apply -f portal.yaml
上面部署成功之后,登陆 pinpoint web 界面,可看到有个新的应用是 ms-portal
- 部署带 pinpoint agent 端的网关服务
1)构建镜像
cd /root/microservic-test-dev1/gateway-service/
docker build -t 192.168.2.50/microservice/gateway:v2 .
docker push 192.168.2.50/microservice/gateway:v2
2)部署服务
cd /root/microservic-test-dev1/k8s
修改 gateway.yaml 文件,把镜像变成 image: 192.168.2.50/microservice/gateway:v2
3)更新 yaml 文件
kubectl delete -f gateway.yaml
kubectl apply -f gateway.yaml
4)配置 hosts 文件
gateway 的域名是 gateway.ctnrs.com,找到 hosts 文件,再增加一行如下:
192.168.2.20 gateway.ctnrs.com
在浏览器访问 eureka.ctnrs.com
可看到 GATEWAY-SERVICE 已经注册到 eureka 了: #访问前端页面
http://portal.ctnrs.com/- Pinpoint web 界面使用说明
上面都部署好之后,可以在 pinpoint 的 web 页面查看服务之间的调用关系: 在上图可看到右侧有绿色的点,我们把鼠标放上去,把绿色点的圈住 点击上面的 Path,就可以看到具体的代码之间的调用了