前面的理论点已经讲了很多了,从分布式过度到微服务,一点一点把微服务的思想渗透给大家。接着又宏观的角度概述了下微服务的星星点点。好了,东风已到,开始实战。
源码托管地址:https://github.com/cddofficial/SpringCloudRepo
目录
1 Eureka
1.1 简介
Eureka是Netflix公司的一个服务治理框架,Spring Cloud对Eureka有很好的支持。
Eureka分为两部分,一种基于REST(Representational State Transfer)的服务,主要用于AWS云,用于定位服务,以实现中间层服务器的负载平衡和故障转移。 我们将此服务称为Eureka Server。 Eureka还附带了一个基于Java的客户端组件Eureka Client,它使与服务的交互变得更加容易。 客户端还有一个内置的负载均衡器,可以进行基本的循环负载均衡。 在Netflix,一个更复杂的负载均衡器包含Eureka基于流量,资源使用,错误条件等多种因素提供加权负载平衡,以提供卓越的弹性。
整个微服务都是由Eureka Server和Eureka Client支持的,如图所示:
Eureka Server:主要提供服务注册(也可以说是服务发现),这些其他所有的服务都可以注册上去。
Eureka Client:当然是上面的提到哪些”其他服务“了,要注册到服务发现服务上的服务。通常包括:
gateway服务,其他业务功能微服务,Spring Cloud Config配置中心(不是必须有的)。
1.2 原理
先来看下Eureka高层架构
上面的架构描述了Eureka在Netflix上的部署方式,这就是通常运行它的方式。这里要提下eureka中的region和zone的概念。
这部分知识点eureka官网几乎没有提到,我们在这里说下。
region和zone(或者Availability Zone)均是AWS的概念。在非AWS环境下,我们可以简单地将region理解为Eureka集群,zone理解成机房。看一下区域(Region)概念。AWS云服务在全球不同的地方都有数据中心,比如北美、南美、欧洲和亚洲等。与此对应,根据地理位置我们把某个地区的基础设施服务集合称为一个区域。现在可能会有9个或10个这样的区域,下面是一些区域机器编码对照图:
好了就说到这,不理解这部分几乎对学习spring cloud微服务架构没有影像。不扯远了,如果大家还想了解eureka中的zone和region,可以直接到文末,查看一些参考资料。接下来我们继续说eureka。
Eureka提供服务注册服务,每个节点启动后,会在eureka server中进行注册,这样eureka Server中的服务注册表 中将会存储所有可用服务节点的信息,服务节点的信息可以在界面直观的看到。
Eureka server之间将会通过复制的方式完成数据的同步。
Eureka client 是一个java客户端,用于简化与eureka server之间的交互,客户端同时也具备一个内置的,使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向eureka server发送心跳(默认周期是30秒)。如果eureka server在多个周期内没有接收到某个节点的心跳,eureka server就会从服务注册表中把这个服务节点移除(默认90秒)。
综上,eureka通过心跳检查,健康检查,客户端缓存机制,确保的系统的高可用性,灵活性和可伸缩性。
1.3 服务提供者和消费者
在实战之前我们先要明白服务的提供者和消费者这样的概念和思想。
服务提供者:服务的被调用方(即,为其他服务提供服务的服务)
服务消费者:服务的调用方(即,调用其他服务的服务)
如果有两个服务,一个是用户微小服务,一个是可乐微服务服务。有个业务,正好用户微服务调用了可乐微服务,那么这时候用户微服务就是服务消费者,可乐微服务就是服务提供者了。如下图:
2.开始实战
2.1 环境准备
IDE工具:sts(Spring Tool Suit),当然eclipse也可以,安装sts插件就行了。
Spring Boot版本:2.0.7
Spring Cloud版本:Finchley.SR2
maven版本:3.6.1
jdk版本:1.8
2.2 场景
话说有这样一个情况,小明要去商店买可乐,这个业务需要一个用户服务管理小明的信息,需要一个可乐服务,用来管理可乐(减少库存等)。
2.3 eureka server
我们要创建一个eureka server服务用来注册其他微服务,即,其他的微服务都可以注册到这个服务上。接下来开始创建一个Spring Boot项目,项目名称为:eureka-server-service-discover,名称前半部分表示这是一个eureka server,后半部分表示作用是服务发现(或者服务注册)。
2.3.1. 先创建项目
1. 如下图所示,点击1处或2处,再依次点击3、4处,很简单。
2.接下来会弹出下面这个页面,注意我们的项目名称。点击next。
3.在接下来弹出的页面中,其他都可以不选,版本暂时用当前最新版2.2.1。点击“finished",如下图:】
4. 到这里项目就算创建好了,项目结构如下图:
附加:
除了这种方式创建spring boot项目外,我们还可以通过:https://start.spring.io/ 去创建spring boot项目,下载下来解压后再导入到我们的IDE工具中也是可以的。
2.3.2 项目配置
1.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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.cdd.cloud</groupId>
<artifactId>eureka-server-service-discover</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eureka-server-service-discover</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- eureka server依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!-- 引入spring cloud的依赖,不能少,主要用来管理Spring Cloud生态各组件的版本 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 添加spring-boot的maven插件,不能少,打jar包时得用 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2. yml文件配置,在静态文件资源目录resource创建application.yml文件,该文件配置内容如下:
server:
port: 8761
eureka:
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://localhost:8761/eureka/
3. 启动类上打上注解@EnableEurekaServer,如下图:
package com.cdd.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer //eureka server注解
public class EurekaServerServiceDiscoverApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerServiceDiscoverApplication.class, args);
}
}
2.3.3 测试
1. 启动该项目,启动成功后,可以看到控制台日志输出,服务器端口是我们配置的 8761,如下图:
2 .在浏览器中输入: localhost:8761 ,响应页面如下图就说明我们的服务注册(服务发现)服务创建好了。
2.4 eureka client
好了,现在服务注册服务已经创建好了。根据我们的场景和计划,还要创建两个eureka client微服务,一个是用户微服务,一个是可乐微服务。接下来就开始吧!
2.4.1 创建可乐微服务
微服务名称为:eureka-client-coke,前半部表示这是一个eureka-client,后半部分表示业务可乐微服务。
我们这个微服务打算连接本机mysql数据库。如果你没有可连接的mysql,也可以采用内存数据库H2,连接方式可参照下面创建用户微服务的方式。
我们已经有一个服务注册服务eureka-server-service-discover了,可以不用再像上面那样重新再创建项目了,我们直接找到
eureka-server-service-discover代码,赋值一份并且重命名。
当然也可以你自己再重新创建了,都是可以的。接下来看,复我们采用复制这种方式的时候都要干些什么
1. 复制得到eureka-client-coke
(1) 复制eureka-server-service-discover
(2). 重命名为eureka-client-coke
(3).进入eureka-client-coke文件,只留下src文件夹、.gitignore、pom.xml,删掉其他文件,如下图:
(4),打开pom文件,进行修改,修改内容(只修改这一个地方)如下图:
(5).导入到STS中,如下:
这种方式,后面就不再详细赘述,后面说的复制xxxx服务重命名为yyyy服务,就是这里描述的操作。
2. 接下来开始配置
(1)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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.7.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.cdd.cloud</groupId>
<artifactId>eureka-client-coke</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eureka-server-service-discover</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- eureka client依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- web依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 连接mysql所需依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 测试需要依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!-- 引入spring cloud的依赖,不能少,主要用来管理Spring Cloud生态各组件的版本 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 添加spring-boot的maven插件,不能少,打jar包时得用 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
(2)yml文件进行配置,配置好代码如下:
server:
port: 9001
spring:
application:
name: eureka-client-coke #服务名称
datasource:
url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8
driver-class-name: com.mysql.jdbc.Driver
username: root
password: root
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true #显示真实ip,不是必须的
(3)修改启启动类
修改启动类名称为EurekaClientCokeApplication、删掉@EnableEurekaServer注解,添加@EableEurekaClient注解,代码如下:
package com.cdd.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient //eureka client 注解
public class EurekaClientCokeApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientCokeApplication.class, args);
}
}
3 测试
(1)启动eureka-client-coke服务,可以看到控制台打印信息,以我们刚才配置的9001端口启动成功了
(2)刷新localhost:8761页面,这个就是页面可以查看有哪些服务注册上了,后文说到的查看服务注册页面,就是这个页面。
现在可以看到eureka-client-coke服务已经注册到eureka-server-serivce-discover上了,如下:
到这里我们的可乐微服务就创建好了。
2.4.2 创建用户微服务
现在可乐微服务eureka-client-coke已经创建好了,需要再创建一个用户微服务。
用户微服务名称为:eureka-client-user,前半部分表示这是一个eureka client,后半部分表示业务功能是用户微服务。
我们这个用户微服务采用内存数据库H2。当然大家也可以仿照上面的可乐微服务eureka-client-coke连接mysql数据库方式,那种方便就采用哪种。
1. 复制eureka-client-coke服务重命名为eureka-client-user(详细操作可参照创建可乐微服务的第1步)。
导入后如下图:
2.修改配置
(1)修改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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.7.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.cdd</groupId>
<artifactId>eureka-client-user</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>service-discover</name>
<description>Demo project for Spring Boot</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- eureka client依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- web依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- H2 数据库依赖 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 访问数据用 spring data jpa -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!-- 引入spring cloud的依赖,不能少,主要用来管理Spring Cloud生态各组件的版本 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 添加spring-boot的maven插件,不能少,打jar包时得用 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
(2)修改yml文件配置,修改后代码如下:
server:
port: 9002
spring:
application:
name: eureka-client-user #应用程序名称
jpa:
generate-ddl: false
show-sql: true
hibernate:
ddl-auto: none
datasource:
platform: h2
schema: classpath:schema.sql #一般是创建表结构的sql
data: classpath:data.sql #一般是处理表数据的sql
logging:
level:
root: INFO
org.hibernate: INFO
org.hibernate.type.descriptor.sql.BasicBinder: TRANCE
org.hibernate.type.descriptor.sql.BasicExtractor: TRANCE
com.cdd: DEBUG
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
(3)修改启动类,修改后代码如下:
package com.cdd.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class EurekaClientUserApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientUserApplication.class, args);
}
}
(4)添加数据sql文件(采用H2数据库时用到)
在resources目录下添加两个文件data.sql和schema.sql,位置如下:
a. schema.sql文件,内容如下:
drop table user if exists;
create table user(
id bigint generated by default as identity,
name varchar(20),
age int(3),
primary key (id)
);
b. data.sql文件内容如下:
insert into user(id,name,age) values(1,'亚瑟', 20);
insert into user(id,name,age) values(2,'鲁班', 20);
insert into user(id,name,age) values(3,'兰陵王', 20);
insert into user(id,name,age) values(4,'庄周', 20);
3.服务注册测试
到这里我们一个很基础的用户微服务就创建好了,接下来启动eureka-client-user服务(前提是
eureka-server-serivce-discover、eureka-client-coke都已经启动了)。
(1)可以看到控制台输出日志,是以刚才配置的9002启动成功的,如下图:
(2)刷新服务注册页面: localhost:8761,可以看到用户微服务eureka-client-user已经注册上去了,如下图:
4 测试访问数据库
现在我们来编写代码,测试下连接的H2数据库,能不能访问。
(1)在用户微服务启动类所在包下,新建一个entity包,在该包下创建一个User类。代码如下:
package com.cdd.demo.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column
private String name;
@Column
private Short age;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Short getAge() {
return age;
}
public void setAge(Short age) {
this.age = age;
}
}
(2)在用户微服务启动类所在包下,新建一个repository包,在该包下创建一个UserRepository接口。代码如下:
package com.cdd.demo.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.cdd.demo.entity.User;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}
(3)在用户微服务启动类所在包下,新建一个controller包,在该包下创建一个UserController类。代码如下:
package com.cdd.demo.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import com.cdd.demo.entity.User;
import com.cdd.demo.repository.UserRepository;
@RestController
public class UserController {
@Autowired
private UserRepository userRepository;
@GetMapping("/user/{id}")
public User findById(@PathVariable long id) {
return this.userRepository.findById(id).get();
}
}
现在重新启动eureka-client-user服务,启动成功后在浏览其中输入:http://localhost:9002/user/1
查看用户id为1的用户信息,响应页面如下图:
到这里我们的:
eureka server服务,有一个是服务注册服务eureka-server-service-discover微服务创建好了。
eureka client服务,有两个分别是可乐微服务eureka-client-coke和用户微服务eureka-client-user都创建好了。
哪里我没有写详细或有问题的,欢迎大家发声啊。这才是spring cloud微服务的开始,后面还有很多呢,go on!
3 参考资料
eureka在github上wiki里面的介绍:https://github.com/Netflix/eureka/wiki/Eureka-at-a-glance
eureka中的zone和region: https://blog.csdn.net/awschina/article/details/17639191