架构的演变
单体 -> 集群(负载均衡) -> 分布式 -> SOA -> 微服务 -> 服务网格 -> 云原生
SpringCloud最核心的几大组件如如下:
1、Netflix Eureka:
Eureka就是用来管理微服务的通信地址清单的,有了Eureka之后我们通过服务的名字就能实现服务的调用
2、Spring Cloud Config:分布式配置:
分布式配置管理中心,用来统一的管理服务的配置文件
3、Netflix Ribbon\Feign : 客户端负载均衡:
Ribbon和Feign都是客户端负载均衡器,它的作用是在服务发生调用的时候帮我们将请求按照某种规则分发到多个目标服务器上,简单理解就是用来解决微服务之间的通信问题。
4、Netflix Hystrix :断路器
Hystrix是用来解决微服务故障,保护微服务安全的组件,避免因为服务器故障,导致整个调用链上的微服务全都出现异常
5、Netflix Zuul : 服务网关
我们可以把它看作是微服务的大门,所有的请求都需要经过zuul之后才能到达目标服务,根据这一特性,我们可以把微服务公共的是事情交给zuul统一处理
6、Spring Cloud Bus:消息总线
消息总线是在微服务中给各个微服务广播消息的一个组件,我们使用消息总线构建一个消息中心,其他微服务来接入到消息中心,当消息总线发起消息,接入的微服务都可以收到消息从而进行消费
7、Spring Cloud Sleuth:微服务链路追踪
链路追踪的作用就是来监控维护之间的调用关系,让程序员方便直观的感受到一个请求经历了哪些微服务,以及服务的请求时间,是否有异常等
Eureka
微服务的其中一个特点是服务之间需要进行网络通信,服务器之间发起调用时调用服务得知道被调用服务的通信地址,试问当微服务数量成百上千之多,程序员该如何管理众多的服务通信地址,对于随时新增加的微服务和下线的微服务,又应该如何去动态添加和删除这些微服务的通信地址呢?所以手工管理服务的通信地址是一件遥不可及的事情,我们需要借助一个强大的工具帮我们实现这一功能 - Eureka,同类型的组件还有 zookeeper,consul等
Eureka的工作原理
1、服务注册
2、服务发现
3、心跳续约
4、服务下线
Eureka的工作流程
spring cloud netflix 下的一个开源项目 - Eureka , 服务注册与发现组件
springboot整合springcloud实战
项目搭建
1、搭建父项目
管理:springboot ; springcloud依赖
导入:公共依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<!--1. SpringBoot的jar包-->
<!--SpringBoot-->
<parent>
<groupId> org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
<!--2.管理 SpringCloud的jar包
-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!--3.这里是所有子项目都可以用的jar包-->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--lobok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
2、搭建子项目
service-eureka
1.导入依赖:spring-cloud-starter-netflix-eureka-server
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2.启动类:启动服务 : @EnableEureakServer
3.YML配置
端口
主机名
禁用注册和拉取注册表的功能
注册地址
关闭和我保护
server:
port: 10010 #端口
eureka:
instance:
hostname: localhost #主机
client: #客户端配置
#EurekaServer自己不要注册到EurekaServer自己 ,只有EurekaClient才注册
registerWithEureka: false
#EurekaServer不要拉取服务的通信地址列表 ,只有EurekaClient才拉取地址列表
fetchRegistry: false
serviceUrl: #注册中心的注册地址
#http://${eureka.instance.hostname}:${server.port}/eureka/
defaultZone: http://localhost:10010/eureka/
server:
enable-self-preservation: false #关闭自我保护警告
测试服务开启
启动springcloud-eureka-server-10010工程,浏览器访问 http://localhost:10010 ,出现如下界面代码EurekaServer集成成功:
service-order
1.导入依赖:eureka-client ; web包
2.启动类
3.yml配置
端口
服务名
注册地址
使用IP注册
实例ID
service-user - ---- 同上
3、服务通信Ribbon
1.创建公共模块
创建User实体类
2.修改用户服务
1.导入公共模块的依赖
2.编写controller,返回User实体类
3.使用@Value("${server.port}")读取端口,设置给User
4.用户集群
3.修改订单服务
1.使用RestTemplate通信
1.导入公共模块的依赖
2.启动类:注册一个RestTemplate的Bean
3.编写controller,注入RestTemplate调用用户服务
使用IP:端口调用
2.使用Ribbon通信
1.导入ribbon的基础依赖
<!--Ribbon依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
开启负载均衡
@SpringBootApplication
@EnableEurekaClient
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class);
}
//配置一个RestTemplate ,Spring封装的一个机遇Restful风格的http客户端 工具
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
2.给RestTemplate的Bean方法加上@LoadBalanced
3.修改:RestTemplate调用用户服务,使用服务名调用
把: IP:端口 改成服务名
3、测试
分别启动EurekaServer注册中心 ,启动两个UserServer用户服务,启动OrderServer订单消费者服务,浏览器访问订单服务:http://localhost:10020/order/1 ,发送多次请求。
观察响应的结果中的端口变化 - 端口会交替出现10030,10031我们可以推断出Ribbon默认使用的是轮询策略。
Ribbon
Ribbon的概述:
Ribbon是Netflix发布的云中间层服务开源项目,主要功能是提供客户端负载均衡算法
。Ribbon客户端组件提供一系列完善的配置项,如,连接超时,重试
等。简单的说,Ribbon是一个客户端负载均衡器,Ribbon可以按照负载均衡算法(如简单轮询,随机连接等)向多个服务发起调用
(正好可以解决上面的问题),我们也很容易使用Ribbon实现自定义的负载均衡算法
。
Ribbon的工作机制:
如下图,我们将user-server(用户服务)做集群处理,增加到2个节点(注意:两个user-server(用户服务)的服务名要一样,ip和端口不一样),在注册中心的服务通信地址清单中user-server(用户服务)这个服务下面会挂载两个通信地址 。 order-server(订单服务)会定时把服务通信地址清单拉取到本地进行缓存
, 那么当order-server(订单服务)在向user-server(用户服务)发起调用时,需要指定服务名为 user-server(用户服务)
;那么这个时候,ribbon会根据user-server(用户服务)这个服务名找到两个order-server的通信地址
, 然后ribbon会按照负载均衡算法(默认轮询)选择其中的某一个通信地址,发起http请求实现服务的调用
,如下图:
负载均衡算法:
Ribbon内置7种负载均衡算法,每种算法对应了一个算法类如下:
Ribbon综述
Ribbon的使用相对比较简单,配合RestTemplate使用注解@LoadBalanced即可完成负载均衡配置,但是再我们的订单服务Controller中向用户服务发起请求的代码就显得不简单了。我们需要手动去拼接目标服务的URL,以及参数,可能参数比较简单的时候你没什么感觉,当地址比较复杂,参数比较多的时候,拼接URL就会得特别麻烦,而且显得好傻,在下一章节我们会学习另外一个客户端负载均衡Feign,它在Ribbon的基础上进行了封装,让服务的调用方式显得更简答和高级。相关Ribbon的调优可以自行搜索