概念
微服务的概念源于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的开发风格做到一键启动和部署!
Springboot与Springcloud的区别
Spring boot: 专注于快速方便的开发单个个体微服务(关注微观,简化配置);
Spring cloud:关注全局的微服务协调治理框架,将spring boot开发的一个个单体微服务组合并管理起来(关注宏观);
Spring boot可以离开spring cloud独立使用,但是spring cloud不可以离开spring boot,属于依赖关系。
Spring cloud全部组件的解析
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可自动从eureka server获取服务提供者的地址列表,并基于负载均衡算法,请求其中一个服务提供者的实例(为了服务的可靠性,一个微服务可能部署多个实例)
4.Hystrix(熔断器)
:当服务提供者响应非常缓慢,那么消费者对提供者的请求就会被强制等待,直到提供者响应超时。在高负载场景下,如果不做任何处理,此类问题可能会导致服务提供者的资源耗竭甚至整个系统的崩溃(雪崩效应)。Hystrix正是为了防止此类问题发生。Hystirx是由Netflix开源的一个延迟和容错库,用于隔离访问远程系统、服务或第三方库,防止级联失败,从而提升系统的可用性与容错性。
5.Zuul(微服务网关)
:不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,例如一个电影购票的手机app。可能调用多个微服务的接口才能完成一次购票的业务流程,如果让客户端直接与各个微服务通信,会有以下的问题:
01.客户端会多次请求不同的微服务,增加了客户端的复杂性
02.存在跨域请求,在一定场景下处理相对复杂
03.认证复杂,每个服务都需要独立认证
04.某些微服务可能使用了对防火墙、浏览器不友好的协议,直接访问时会有一定的困难
以上问题可借助微服务网关解决。
微服务网关是介于客户端和服务器端之间的中间层,所有的外部请求都会先经过微服务网关。是由微服务网关后,微服务网关将封装应用程序的内部结构,客户端只用跟网关交互,而无须直接调用特定微服务的接口,这样,开发就可以得到简化,不仅如此,使用微服务网关还有以下优点:
1)易于监控:可在微服务网关收集监控数据并将其送到外部系统进行分析
2)易于认证:可在微服务网关上进行认证,然后再将请求转发到后端的微服务,而无需在每个微服务中进行认证
3)减少了客户端与各个微服务之间的交互次数
Spring cloud bus(统一配置服务)
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
Eureka
【注册中心的集群】
第一台
- [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
【启动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
第一台运行consumer
- [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
另开终端 访问的是consumer的ip和端口 反馈的信息是produce上的
- [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 ~]# firefox 192.168.235.10:8000
Hystrix
【微服务的熔断器,健康检查的作用】
第一台上的consumer(消费者)结束
运行带熔断器的consumer
- [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
Zuul
第一台上带监控的cosumer停止
运行网关
- [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
另开终端
- [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
[root@localhost ~]# firefox 192.168.235.10:8000
Sleuth+zipkin(跟踪服务)
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
Spring Boot
把之前的链路追踪停止掉
- [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
- server:
- port: 8000
- spring:
- application:
- name: admin-server
- mail:
- host: smtp.qq.com
- username: 1684629789@qq.com
- password: xxx(授权密码)
- properties:
- mail:
- smtp:
- auth: true
- starttls:
- enable: true
- required: true
- boot:
- admin:
- notify:
- mail:
- from: 1684629789@qq.com
- to: 1684629789@qq.com
[root@localhost spring-boot-admin-server]# mvn spring-boot:run
随意停止一个producer,查看是否发送邮件!