微服务(或微服务架构)是一种云原生架构方法,其中单个应用程序由许多松散耦合且可独立部署的较小组件或服务组成。
Spring Cloud 是一系列框架的有序集合
,它利用 Spring Boot 的开发便利性简化了分布式系统的开发,比如服务发现、服务网关、服务路由、链路追踪等。百度百科
技术栈关系如下:
Spring cloud中文网
微服务的概念源于2014年3月Martin Fowler所写的一篇文章“Microservices”,微服务架构是一种架构模式,他提倡将单一应用程序划分成一组小的服务,服务之间互相互相协调、互相配合,为用户提供最终价值,每个服务运行在其独立的进程中,服务与服务间采用器轻量级的通信机制互相沟通(通常是基于HTTP的RESTFUL API)。每个服务都围绕着具体业务进行构建,并且能够被独立的部署到生产环境、类生产环境等,另外,应尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建。微服务是一种架构风格
,一个大型复杂软件应用由一个或多个微服务组成。系统中的各个微服务可被独立部署,各个微服务之间是松耦合的(可以相互调用)。每个微服务仅关注于完成一件任务并很好的完成该任务,在所有的情况下,每个任务代表着一个小的业务能力。
耦合:两个东西的关联度,根据关联度的高低来分耦合的程度,
分为:
✔ 完全耦合:关联紧密,不能分开,下一步以上一步为基础
✔ 松耦合:关联度不高
✔ 完全解耦:没有任何关联
微服务可以放在容器里跑,容器需要给微服务提供环境,容器里跑的就是微服务,容器跟微服务没有关系。
为什么叫微服务架构?
整个架构里只要有微服务层,就可以叫做微服务架构。
容易混淆的概念
Spring boot:spring boot是一个框架,一种全新的编程规范,他的产生简化了框架的使用,所谓简化是指简化了spring众多框架中所需的大量且繁琐的配置文件,所以springboot是一个服务于框架的框架,服务范围是简化配置文件!
Spring cloud:spring cloud基于spring boot提供了一整套服务的解决方案,包括服务注册与发现,配置中心,全链路监控,服务网关,负载均衡,熔断器等组件
Spring cloud利用spring boot的开发便利性巧妙的简化了分布式系统的基础设施开发,spring cloud为开发人员提供了快速构建分布式系统的一些工具,包扣配置管理、服务发现、断路器、路由、微代理、事件总线,他们都可以用spring boot的开发风格做到一键启动和部署!
Spring boot: 专注于快速方便的开发单个个体微服务(关注微观,简化配置);
Spring cloud:关注全局的微服务协调治理框架,将spring boot开发的一个个单体微服务组合并管理起来(关注宏观);
Spring boot可以离开spring cloud独立使用,但是spring cloud不可以离开spring boot,属于依赖关系。
1.Fegin(接口调用)
:微服务之间通过rest接口通讯,springcloud提供fegin框架来支持rest的调用,fegin使得不同进程的rest接口调用得以用优雅的方式进行,这种优雅表现的就像同一个进程调用一样(简化微服务的通信过程)
2.Eureka(注册发现)
:微服务模式下,一个大的web应用通常都被拆分为很多比较小的web应用(服务),这个时候就需要有一个地方保存这些服务的相关信息,才能让各个小的应用彼此知道对方,这个时候就需要在注册中心进行注册。每个应用启动时向配置的注册中心注册自己的信息(IP地址、端口号、服务名称等信息),注册中心将他们保存起来,服务间相互调用的时候,通过服务名称就可以到注册中心找到对应的服务信息,从而进行通讯,注测与发现服务为微服务之间的调用带来了方便,解决了硬编码的问题,服务间只通过对方的服务id,而无需知道其IP和端口即可,以获取对方服务
硬编码:代码写死,调用谁就写谁才能查找出来
3.Ribbon(负载均衡)
:ribbon是Netflix发布的负载均衡器,他有助于控制http和TCP客户端的行为,为ribbon配置服务提供者的地址列表后,ribbon就可基于某种负载均衡算法,自动的帮助服务消费者去请求。Ribbon默认为我们提供了很多的负载均衡算法,例如轮询、随机等,当然,我们也可为ribbon实现自定义的负载均衡算法,在spring cloud中,当ribbon与eureka配合使用时,ribbon可自动从eurekaserver获取服务提供者的地址列表,并基于负载均衡算法,请求其中一个服务提供者的实例(为了服务的可靠性,一个微服务可能部署多个实例)
4.Hystrix(熔断器)
:当服务提供者响应非常缓慢,那么消费者对提供者的请求就会被强制等待,直到提供者响应超时。在高负载场景下,如果不做任何处理,此类问题可能会导致服务提供者的资源耗竭甚至整个系统的崩溃(雪崩效应)。Hystrix正是为了防止此类问题发生。Hystirx是由Netflix开源的一个延迟和容错库,用于隔离访问远程系统、服务或第三方库,防止级联失败,从而提升系统的可用性与容错性。
5.Zuul(微服务网关)
:不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,例如一个电影购票的手机app。可能调用多个微服务的接口才能完成一次购票的业务流程,如果让客户端直接与各个微服务通信,会有以下的问题:
01.客户端会多次请求不同的微服务,增加了客户端的复杂性
02.存在跨域请求,在一定场景下处理相对复杂
03.认证复杂,每个服务都需要独立认证
04.某些微服务可能使用了对防火墙、浏览器不友好的协议,直接访问时会有一定的困难
以上问题可借助微服务网关解决。
微服务网关是介于客户端和服务器端之间的中间层,所有的外部请求都会先经过微服务网关。是由微服务网关后,微服务网关将封装应用程序的内部结构,客户端只用跟网关交互,而无须直接调用特定微服务的接口,这样,开发就可以得到简化,不仅如此,使用微服务网关还有以下优点:
1)易于监控:可在微服务网关收集监控数据并将其送到外部系统进行分析
2)易于认证:可在微服务网关上进行认证,然后再将请求转发到后端的微服务,而无需在每个微服务中进行认证
3)减少了客户端与各个微服务之间的交互次数
Spring Cloud Bus用轻量级消息代理链接分布式系统的节点。然后可以使用此代理来广播状态更改(例如配置更改)或其他管理指令。一个关键的想法是,该总线就像用于Spring Boot应用的分布式致动器,可以横向扩展。但是它也可以用作应用之间的通信渠道。该项目为AMQP经纪人或Kafka作为传输者提供了入门者。
对于传统的单体应用,常使用配置文件管理所有配置。例如一个springboot开发的单体应用,可将配置内容放在application.Yml文件中,如果需要切换环境,可设置多个profile,并在启动应用时指定spring.profiles.active={profile}
。然而,在微服务架构中,微服务的配置管理一般有以下需求:
01.集中管理配置:一个使用微服务架构的应用系统可能会包含成百上千个微服务,因此集中管理配置是非常有必要的
02.不同环境、不同配置:例如数据源配置在不同的环境(开发、测试、预发布、生产等)中是不同的。
03.运行期间可动态调整:例如可根据各个微服务的负载情况,动态调整数据源连接池大小或熔断阈值,并且在调整配置时不停止微服务
04.配置修改后可自动更新:如配置内容发生变化,微服务能够自动更新配置
综上所述,对于微服务架构而言,一个通用的配置管理机制是必不可少的,常见做法是使用配置服务器管理配置,spring cloudbus利用GIT或SVN等管理配置、采用Kafka或rabbit MQ等信息总线通知所有应用,从而实现配置的自动更新并且刷新所有微服务实例的配置。
实验环境
第一台 192.168.235.10
第二台 192.168.235.11
firewall-cmd --zone=public --add-port=8000/tcp --permanent
firewall-cmd --zone=public --add-port=8761/tcp --permanent
firewall-cmd --zone=public --add-port=8888/tcp --permanent
firewall-cmd --zone=public --add-port=9000/tcp --permanent
firewall-cmd --zone=public --add-port=9001/tcp --permanent
firewall-cmd --reload
【注册中心的集群】
[root@localhost ~]# unzip spring-cloud-examples.zip
[root@localhost ~]# cd spring-cloud-examples/
[root@localhost spring-cloud-examples]# cd eureka-producer-consumer/spring-cloud-eureka/
[root@localhost spring-cloud-eureka]# ls
pom.xml src
[root@localhost spring-cloud-eureka]# vim src/main/resources/application.properties
spring.application.name=spring-cloud-eureka
server.port=8000
eureka.client.register-with-eureka=true #表示是否将自己注册到Eureka Server
eureka.client.fetch-registry=true #表示是否从Eureka Server中获取注册的服务信息
eureka.client.serviceUrl.defaultZone=http://192.168.235.10:8000/eureka/,http://192.168.235.11:8000/eureka/
[root@localhost spring-cloud-eureka]# mvn clean package "清除由项目编译创建的target,并打包"
[root@localhost spring-cloud-eureka]# java -jar target/spring-cloud-eureka-0.0.1-SNAPSHOT.jar "运行jar包命令"
···会阻塞终端
[root@localhost ~]# cd spring-cloud-examples/eureka-producer-consumer/spring-cloud-eureka/
[root@localhost spring-cloud-eureka]# vim src/main/resources/application.properties
spring.application.name=spring-cloud-eureka
server.port=8000
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
eureka.client.serviceUrl.defaultZone=http://192.168.235.10:8000/eureka/,http://192.168.235.11:8000/eureka/
[root@localhost spring-cloud-eureka]# mvn clean package
[root@localhost spring-cloud-eureka]# java -jar target/spring-cloud-eureka-0.0.1-SNAPSHOT.jar
第一台另开终端
[root@localhost ~]# firefox 192.168.235.10:8000
【启动producer】
另开终端
[root@localhost ~]# cd /root/spring-cloud-examples/eureka-producer-consumer/spring-cloud-producer/
[root@localhost spring-cloud-producer]# vim src/main/resources/application.properties
spring.application.name=spring-cloud-producer
server.port=9000
eureka.client.serviceUrl.defaultZone=http://192.168.235.10:8000/eureka/,http://192.168..235.11:8000/eureka/
[root@localhost spring-cloud-producer]# mvn spring-boot:run
···
负载均衡的组件:
[root@localhost spring-cloud-producer]# vim src/main/java/com/neo/controller/HelloController.java
@RestController
public class HelloController {
@RequestMapping("/hello")
public String index(@RequestParam String name) {
return "hello "+name+",this is zhaohuaizhe";
}
}
[root@localhost spring-cloud-producer]# mvn spring-boot:run
[root@localhost ~]# cd /root/spring-cloud-examples/eureka-producer-consumer/spring-cloud-consumer/
[root@localhost spring-cloud-consumer]# vim src/main/resources/application.properties
spring.application.name=spring-cloud-consumer
server.port=9001
eureka.client.serviceUrl.defaultZone=http://192.168.235.10:8000/eureka/,http://1
92.168.235.11:8000/eureka/
[root@localhost spring-cloud-consumer]# source /etc/profile
[root@localhost spring-cloud-consumer]# mvn spring-boot:run
另开终端 访问的是consumer的ip和端口 反馈的信息是produce上的
[root@localhost ~]# curl 192.168.235.10:9001/hello/aa
hello aa,this is first messge[root@localhost ~]# curl 192.168.235.10:9001/hello/aa
hello aa,this is zhaohuaizhe
[root@localhost ~]# firefox 192.168.235.10:8000
【微服务的熔断器,健康检查的作用】
运行带熔断器的consumer
[root@localhost ~]# cd /root/spring-cloud-examples/spring-cloud-hystrix/spring-cloud-consumer-hystrix/
[root@localhost spring-cloud-consumer-hystrix]# vim src/main/resources/application.properties
spring.application.name=spring-cloud-consumer-hystrix
server.port=9001
feign.hystrix.enabled=true
eureka.client.serviceUrl.defaultZone=http://192.168.235.10:8000/eureka/,http://192.168.235.11:8000/eureka/
[root@localhost spring-cloud-consumer-hystrix]# mvn spring-boot:run
另开终端
[root@localhost ~]# curl 192.168.235.10:9001/hello/aa
hello aa,this is first messge
[root@localhost ~]# curl 192.168.235.10:9001/hello/aa
hello aa,this is zhaohuaizhe
第一台上的producer停止
[root@localhost ~]# curl 192.168.235.10:9001/hello/aa
hello aa,this is zhaohuaizhe
[root@localhost ~]# firefox 192.168.235.10:8000
运行网关
[root@localhost ~]# cd /root/spring-cloud-examples/spring-cloud-zuul/spring-cloud-zuul/
[root@localhost spring-cloud-zuul]# vim src/main/resources/application.properties
spring.application.name=gateway-service-zuul
server.port=8888
eureka.client.service-url.defaultZone=http://192.168.235.10:8000/eureka/,http://192.168.235.11:8000/eureka/
#是否开启重试功能
zuul.retryable=true
#对当前服务的重试次数
ribbon.MaxAutoRetries=2
#切换相同Server的次数
ribbon.MaxAutoRetriesNextServer=0
[root@localhost spring-cloud-zuul]# mvn spring-boot:run
另开终端
[root@localhost ~]# curl 'http://192.168.235.10:8888/spring-cloud-producer/hello?name=haha&token=123'
hello haha,this is zhaohuaizhe
[root@localhost ~]# firefox 192.168.235.10:8000
Spring Cloud Sleuth实现了一种分布式的服务链路跟踪
解决方案,通过使用Sleuth可以让我们快速定位某个服务的问题。
✔ Sleuth和zipkin结合使用可以通过图形化的界面
查看微服务请求的延迟情况及各个微服务的依赖情况,可以描绘出微服务系统的拓扑图,也可以根据耗时分析来做对某个微服务的优化!
✔ Sleuth是Spring Cloud的组件之一,它为Spring Cloud实现了一种分布式追踪
解决方案,兼容Zipkin,HTrace和其他基于日志的追踪系统,例如 ELK(Elasticsearch 、Logstash、 Kibana)
✔ Zipkin是一个分布式系统的APM工具(Application Performance Management),基于Google Dapper 实现。它帮助收集解决微服务架构中延迟问题
所需的时间数据,并管理这些数据。和Sleuth结合可以提供可视化Web界面分析调用链路耗时情况。
第一台主机
–>上面所有的终端都结束,因为有个固定的目录专门做链路追踪
内存 3G
[root@localhost ~]# cd /root/spring-cloud-examples/spring-cloud-sleuth-zipkin/
[root@localhost spring-cloud-sleuth-zipkin]# ls
pom.xml spring-cloud-producer zipkin-server
spring-cloud-eureka spring-cloud-zuul
# 注册中心
[root@localhost spring-cloud-sleuth-zipkin]# cd spring-cloud-eureka/
[root@localhost spring-cloud-eureka]# vim src/main/resources/application.yml
server:
port: 8761
spring:
application:
name: eureka
eureka:
client:
serviceUrl:
defaultZone: http://192.168.235.10:8761/eureka/
[root@localhost spring-cloud-eureka]# mvn spring-boot:run
–>链路追踪 另开终端 [source /etc/profile]
[root@localhost ~]# cd /root/spring-cloud-examples/spring-cloud-sleuth-zipkin/zipkin-server/
[root@localhost zipkin-server]# vim src/main/resources/application.yml
defaultZone: http://192.168.235.10:8761/eureka/
[root@localhost zipkin-server]# mvn spring-boot:run
producer 生产者 [Ctrl+Shift+T]
[root@localhost zipkin-server]# cd ..
[root@localhost spring-cloud-sleuth-zipkin]# cd spring-cloud-producer/
[root@localhost spring-cloud-producer]# vim src/main/resources/application.yml
server:
port: 9001
spring:
application:
name: producer
zipkin:
base-url: http://192.168.235.10:9000
sleuth:
sampler:
percentage: 1.0
eureka:
client:
serviceUrl:
defaultZone: http://192.168.235.10:8761/eureka/
[root@localhost spring-cloud-producer]# mvn spring-boot:run
–>Zuul 网关
[root@localhost ~]# cd /root/spring-cloud-examples/spring-cloud-sleuth-zipkin/spring-cloud-zuul/
[root@localhost spring-cloud-zuul]# vim src/main/resources/application.yml
server:
port: 8888
spring:
application:
name: zuul
zipkin:
base-url: http://192.168.235.10:9000
sleuth:
sampler:
percentage: 1.0
eureka:
client:
serviceUrl:
defaultZone: http://192.168.235.10:8761/eureka/
[root@localhost spring-cloud-zuul]# mvn spring-boot:run
–>另开终端访问
[root@localhost ~]# curl 'http://192.168.235.10:8888/producer/hello?name=aa&token=123'
hello aa,this is first messge
[root@localhost ~]# firefox 192.168.235.10:9000
把之前的链路追踪停止掉
[root@localhost ~]# cd /root/spring-cloud-examples/spring-boot-admin-eureka/
[root@localhost spring-boot-admin-eureka]# ls
pom.xml spring-cloud-producer
spring-boot-admin-server spring-cloud-producer-2
spring-cloud-eureka
–>注册中心
[root@localhost spring-boot-admin-eureka]# cd spring-cloud-eureka/
[root@localhost spring-cloud-eureka]# mvn spring-boot:run
–>另开终端
运行生产者1
[root@localhost ~]# cd /root/spring-cloud-examples/spring-boot-admin-eureka/spring-cloud-producer
[root@localhost spring-cloud-producer]# mvn spring-boot:run
Updating port to 9000
2021-09-27 11:40:48.035 INFO 54084 --- [ main] com.neo.ProducerApplication : Started ProducerApplication in 11.475 seconds (JVM running for 35.568)
运行生产者2
[root@localhost ~]# cd /root/spring-cloud-examples/spring-boot-admin-eureka/spring-cloud-producer-2/
[root@localhost spring-cloud-producer-2]# mvn spring-boot:run
Updating port to 9001
2021-09-27 11:42:16.187 INFO 54263 --- [ main] com.neo.Producer2Application : Started Producer2Application in 10.92 seconds (JVM running for 18.074)
–>运行配置邮件的服务
[root@localhost ~]# cd /root/spring-cloud-examples/spring-boot-admin-eureka/spring-boot-admin-server/
[root@localhost spring-boot-admin-server]# vim src/main/resources/application.yml
1 server:
2 port: 8000
3 spring:
4 application:
5 name: admin-server
6 mail:
7 host: smtp.qq.com
8 username: 1684629789@qq.com
9 password: xxx(授权密码)
10 properties:
11 mail:
12 smtp:
13 auth: true
14 starttls:
15 enable: true
16 required: true
17 boot:
18 admin:
19 notify:
20 mail:
21 from: 1684629789@qq.com
22 to: 1684629789@qq.com
[root@localhost spring-boot-admin-server]# mvn spring-boot:run
随意停止一个producer,查看是否发送邮件!
Rather than envy, as their own efforts to catch up!