SpringCloud是什么
SpringCloud是一系列框架的有序集合。它利用SpringBoot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等等,都可以用SpringBoot的开发风格做到一键启动和部署。
SpringCloud并没有重复造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过SpringBoot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。
这里,我们需要注意,SpringCloud其实是一套规范,是一套用于构建微服务架构的规范,而不是一个可以拿来即用的框架。在这个规范之下第三方公司的Netflix公司开发了一些组件(SCN)、spring官方开发了一些框架/组件,包括第三方的阿里巴巴开发了一套框架/组件集合SpringCloud Alibaba(SCA),这些才是SpringCloud规范的实现。
SpringCloud体系结构(组件协同工作机制)
SpringCloud中的各组件协同工作,才能够支持一个完整的微服务架构。比如:
- 注册中心负责服务的注册与发现,很好将各服务连接起来
- API网关负责转发所有外来的请求
- 断路器负责监控服务之间的调用情况,连续多次失败进行熔断保护
- 配置中心提供了统一的配置信息管理服务,可以实时的通知各个服务获取最新的配置信息
Eureka服务注册中心
关于服务注册中心
对于任何一个微服务,原则上都应存在或者支持多个提供者,这是由微服务的分布式属性决定的。更进一步,为了支持弹性扩缩容特性,一个微服务的提供者的数量和分布往往是动态变化的,也是无法预先确定的。因此,原本是在单体应用阶段常用的静态LB机制就不再适用了,需要引入额外的组件来管理微服务提供者的注册与发现,而这个组件就是服务注册中心。
注册中心的一般原理如下图所示:
分布式微服务架构中,服务注册中心用于存储服务提供者地址信息、服务发布相关的属性信息,消费者通过主动查询和被动通知的方式获取服务提供者的地址信息,而不再需要通过硬编码方式得到提供者的地址信息。消费者只需要知道当前系统发布了哪些服务,而不需要知道服务具体存在于什么位置,这就是透明化路由。
以下是几种主流注册中心的对比:
组件名 | 语言 | CAP | 对外暴露接口 |
Eureka | Java | AP(自我保护机制,保证可用) | HTTP |
Consul | Go | CP | HTTP/DNS |
ZooKeeper | Java | CP | 客户端 |
Nacos | Java | 支持AP/CP切换 | HTTP |
搭建单例Eureka Server
由于我们要搭建一个SpringCloud体系框架,所以我们先创建一个spring-cloud-demo的父工程,其Maven的pom文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--spring boot 父启动器依赖-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
</parent>
<groupId>com.rubin</groupId>
<artifactId>spring-cloud-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<dependencies>
<!--日志依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<!--测试依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--lombok⼯具-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
<scope>provided</scope>
</dependency>
<!-- Actuator可以帮助你监控和管理Spring Boot应⽤-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<!--编译插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
<!--打包插件-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
创建子模块scn,其pom结构如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-demo</artifactId>
<groupId>com.rubin</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<artifactId>scn</artifactId>
<dependencies>
<!--web依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
在scn模块下创建我们的Eureka Server单例服务模块:scn-eureka-8761,其pom结构如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>scn</artifactId>
<groupId>com.rubin</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>scn-eureka-8761</artifactId>
<dependencies>
<!--Eureka server依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
由于是SpringBoot项目,我们编写SpringBoot的启动类如下:
package com.rubin.scn.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class Eureka8761Bootstrap {
public static void main(String[] args) {
SpringApplication.run(Eureka8761Bootstrap.class, args);
}
}
由上述代码可知,我们使用@EnableEurekaServer
注解来标明我们该服务是一个Eureka Server服务器。接下来便写我们的配置文件:application.yml。内容如下:
server:
port: 8761
spring:
application:
name: scn-eureka
eureka:
instance:
hostname: 127.0.0.1
prefer-ip-address: true
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@
# 租约续约间隔时间,默认30秒
lease-renewal-interval-in-seconds: 30
# 租约到期,服务时效时间,默认值90秒,服务超过90秒没有发生心跳,EurekaServer会将服务从列表移除
lease-expiration-duration-in-seconds: 90
client:
service-url:
defaultZone: http://127.0.0.1:8761/eureka/
register-with-eureka: false
fetch-registry: false
server:
# EurekaServer每隔多少秒检查服务列表是否全部有效
eviction-interval-timer-in-ms: 6000
# 打开自动进入自我保护模式
enable-self-preservation: true
# Eureka缓存更新时间间隔
response-cache-update-interval-ms: 3000
# 关闭只读缓存来提高服务上下线的响应速度
use-read-only-response-cache: false
启动我们的服务,我们访问:http://127.0.0.1:8761,会看到如下页面:
至此,我们的单实例Eureka Server注册中心就搭建完成。
搭建Eureka Server集群
单实例在我们开发测试阶段比较常见,在生产环境下,我们还是要搭建一个Eureka Server集群来保证注册中心的可用性。下面我们就来在单例的基础上改造成集群方式。
首先,我们要在scn模块下再新建一个名称为scn-eureka-8762的子模块,其pom如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>scn</artifactId>
<groupId>com.rubin</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>scn-eureka-8762</artifactId>
<dependencies>
<!--Eureka server依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
编写其启动类:
package com.rubin.scn.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class Eureka8762Bootstrap {
public static void main(String[] args) {
SpringApplication.run(Eureka8762Bootstrap.class, args);
}
}
编写其配置文件如下:
server:
port: 8762
spring:
application:
name: scn-eureka
eureka:
instance:
hostname: 127.0.0.1
prefer-ip-address: true
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@
# 租约续约间隔时间,默认30秒
lease-renewal-interval-in-seconds: 30
# 租约到期,服务时效时间,默认值90秒,服务超过90秒没有发生心跳,EurekaServer会将服务从列表移除
lease-expiration-duration-in-seconds: 90
client:
service-url:
defaultZone: http://127.0.0.1:8761/eureka/
register-with-eureka: true
fetch-registry: true
# 配制了该项 回阻止将该实例注册为一个eureka client 默认是true 默认自动加入一个Maker类标记 所以引入eureka-client依赖之后 加不加@EnableEurekaClient都会默认注册进EurekaServer
# enabled: false
# 每隔多久拉取一次服务列表
registry-fetch-interval-seconds: 30
server:
# EurekaServer每隔多少秒检查服务列表是否全部有效
eviction-interval-timer-in-ms: 6000
# 打开自动进入自我保护模式
enable-self-preservation: true
# Eureka缓存更新时间间隔
response-cache-update-interval-ms: 3000
# 关闭只读缓存来提高服务上下线的响应速度
use-read-only-response-cache: false
修改我们原来单例的scn-eureka-8761服务的配置文件如下:
server:
port: 8761
spring:
application:
name: scn-eureka
eureka:
instance:
hostname: 127.0.0.1
prefer-ip-address: true
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@
# 租约续约间隔时间,默认30秒
lease-renewal-interval-in-seconds: 30
# 租约到期,服务时效时间,默认值90秒,服务超过90秒没有发生心跳,EurekaServer会将服务从列表移除
lease-expiration-duration-in-seconds: 90
client:
service-url:
defaultZone: http://127.0.0.1:8762/eureka/
register-with-eureka: true
# 每隔多久拉取一次服务列表
registry-fetch-interval-seconds: 30
fetch-registry: true
# 配制了该项 回阻止将该实例注册为一个eureka client 默认是true 默认自动加入一个Maker类标记 所以引入eureka-client依赖之后 加不加@EnableEurekaClient都会默认注册进EurekaServer
# enabled: false
server:
# EurekaServer每隔多少秒检查服务列表是否全部有效
eviction-interval-timer-in-ms: 6000
# 打开自动进入自我保护模式
enable-self-preservation: true
# Eureka缓存更新时间间隔
response-cache-update-interval-ms: 3000
# 关闭只读缓存来提高服务上下线的响应速度
use-read-only-response-cache: false
依次启动两个项目,打开http://127.0.0.1:8761和http://127.0.0.1:8762会看到我们的两个Eureka Server实例已经启动成功并且成功注册进了彼此的注册表中:
至此,我们的Eureka Server集群就搭建完成了。欢迎小伙伴积极留言交流~~~
文章评论