最近闲来无事,准备把自己学习经历写几篇博客,水平有限,在学习Springcloud之前,你首先得知道,集群/分布式/微服务/SOA是什么?下面我就简单说说
我刚接触这几个名词的时候,感觉高端得不得了,当你真正接触的时候,就会发现没那么简单,也没那么难,话不多说,上才艺!!
同一个业务,运行在不同的服务器上面,它们干的是同一件事情。
简单来说就是在二个或者更多的服务器上面部署一个相同的项目,如果其中一台服务器挂掉,另外一台服务器还能使用,保证可用性。
一个完整地业务,拆分成多个不同的子业务,部署在不同的服务器上面。
本来一个系统是一个大模块,但是有些模块的访问量比较大,有些模块的访问量比较低,通过功能拆分之后,模块之间独立,各做各的事情。
高吞吐量,像之前一个流程可能需要30分钟,通过分布式拆分后只需要10分钟或者更低(前提是多个服务器的情况下)
集群和分布式并不冲突,可以有分布式集群
例如:有一个公司,有5个小伙子写Java,4个小伙子写前端,2个小伙子做测试,1个小伙子做DBA。
看完不少资料其实,分布式/微服务/SOA,它们的概念都差不多,基本上了解其中一个,没必要细分具体的每个概念。
读完这里之后,你对分布式/微服务也有一定的了解了,单从概念来说,是非常容易理解的。
从分布式/微服务的角度,当我们的一个大系统拆分成多个小的模块后。这些小的模块组合起来,完成功能。
如图
模块拆分完之后,肯定会有各种各样的问题,SpringCloud就是一套完整地解决方案。
SpringCloud的基础功能:
当我们的功能进行拆分后,首当其冲的就是各种子系统直接得通信问题,子系统与子系统之间不是在同一个环境下,那就需要远程调用。远程调用可能就会想到httpClient,WebService等等这些技术来实现。
但是远程调用,就必须得知道ip地址,在服务多的情况下,手动来维护这些静态配置就是噩梦!
为了解决微服务架构中的服务实例维护问题(ip地址), 产生了大量的服务治理框架和产品。这些框架和产品的实现都围绕着服务注册与服务发现机制来完成对微服务应用实例的自动化管理。
在SpringCloud中我们的服务治理框架一般使用的就是Eureka。
首先创建一个主Maven工程,在其pom文件引入依赖,spring Boot版本为2.0.3.RELEASE,Spring
Cloud版本为Finchley.RELEASE。这个pom文件作为父pom文件,起到依赖版本控制的作用,其他module工程继承该pom。
主pom.xml如下:
<?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>
<groupId>com.forezp</groupId>
<artifactId>sc-f-chapter1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>sc-f-chapter1</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/>
</parent>
<modules>
<module>eureka-server</module>
<module>service-hi</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
然后创建二个model工程:一个model工程作为服务注册中心,即Eureka Server,另一个作为Eureka Client。
创建完后的工程,其pom.xml继承了父pom文件,并引入spring-cloud-starter-netflix-eureka-server的依赖,代码如下:
<?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>
<groupId>com.forezp</groupId>
<artifactId>eureka-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>eureka-server</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>com.forezp</groupId>
<artifactId>sc-f-chapter1</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
启动一个服务注册中心,只需要一个注解@EnableEurekaServer,这个注解需要在springboot工程的启动application类上加:
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run( EurekaServerApplication.class, args );
}
}
eureka是一个高可用的组件,它没有后端缓存,每一个实例注册之后需要向注册中心发送心跳(因此可以在内存中完成),在默认情况下erureka
server也是一个eureka client ,必须要指定一个 server。
eureka server的配置文件appication.yml:
server:
port: 8761
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
spring:
application:
name: eurka-server
在Eureka Server一般我们会这样配置:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
eureka server 是有界面的,启动工程,打开浏览器访问: http://localhost:8761 ,界面如下:
No application available 没有服务被发现 ……_ 因为没有注册服务当然不可能有服务被发现了。
Eureka Client分为服务提供者和服务消费者。
创建过程同server类似,创建完pom.xml如下:
<?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>
<groupId>com.forezp</groupId>
<artifactId>service-hi</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>service-hi</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>com.forezp</groupId>
<artifactId>sc-f-chapter1</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
<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>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
通过注解@EnableEurekaClient 表明自己是一个eurekaclient
@SpringBootApplication
@EnableEurekaClient
@RestController
public class ServiceHiApplication {
public static void main(String[] args) {
SpringApplication.run( ServiceHiApplication.class, args );
}
@Value("${server.port}")
String port;
@RequestMapping("/hi")
public String home(@RequestParam(value = "name", defaultValue = "forezp") String name) {
return "hi " + name + " ,i am from port:" + port;
}
}
还需要在配置文件中注明自己的服务注册中心的地址,application.yml配置文件:
server:
port: 8762
spring:
application:
name: service-hi
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
需要指明spring.application.name,这个很重要,这在以后的服务与服务之间相互调用一般都是根据这个name 。 启动工程,打开http://localhost:8761 ,即eureka server 的网址:
你会发现一个服务已经注册在服务中了,服务名为SERVICE-HI ,端口为7862
服务注册:启动的时候会通过发送REST请求的方式将自己注册到Eureka Server上,同时带上了自身服务的一些元数据信息。
服务续约:在注册完服务之后,服务提供者会维护一个心跳用来持续告诉Eureka Server: "我还活着 ”
服务下线:当服务实例进行正常的关闭操作时,它会触发一个服务下线的REST请求给Eureka Server, 告诉服务注册中心:“我要下线了 ”。
获取服务:当我们启动服务消费者的时候,它会发送一个REST请求给服务注册中心,来获取上面注册的服务清单
服务调用:服务消费者在获取服务清单后,通过服务名可以获得具体提供服务的实例名和该实例的元数据信息。在进行服务调用的时候,优先访问同处一个Zone中的服务提供方。
失效剔除:默认每隔一段时间(默认为60秒) 将当前清单中超时(默认为90秒)没有续约的服务剔除出去。
自我保护:EurekaServer 在运行期间,会统计心跳失败的比例在15分钟之内是否低于85%(通常由于网络不稳定导致)。Eureka Server会将当前的实例注册信息保护起来, 让这些实例不会过期,尽可能保护这些注册信息。
本文参考链接:
https://www.fangzhipeng.com/springcloud/2018/08/01/sc-f1-eureka.html
https://mp.weixin.qq.com/s/MJrahcDXwxgDr5zBdO3XWw