一、简述
随着云应用和容器技术的发展成熟,微服务技术架构应用于实际项目的场景越来越多,有关微服务的技术架构分析、原理等介绍,网上资料非常多,我们主要从入门实战的角度出发,让大家深入了解怎么开发或改造一个微服务应用,掌握Eureka、Zuul、Feign、Ribbon、Hystrix等在微服务项目中各自的职责,能够在开发得心应手。
二、微服务技术架构比较
一提到微服务大家第一个想到的就是Spring cloud,但Spring cloud本身其实只是一套微服务规范,并不是一个拿来即可用的框架,很多组织或者公司为开发者提供了这套规范的实现方式,我们通过一个表格对比如下:
| Spring Cloud | Netflix | 官方 | Alibaba | Consul | Kubernetes |
|---|---|---|---|---|---|
| 分布式配置 | Archaius | spring cloud config | Nacos | Consul | ConfigMap |
| 服务注册/发现 | Eureka | -- | Nacos | Consul | Api Server |
| 服务熔断 | Hystrix | -- | Sentinel | -- | -- |
| 服务调用 | Feign | OpenFeign | Dubbo RPC | -- | -- |
| 服务路由 | Zuul | Gateway | Dubbo PROXY | -- | -- |
| 分布式消息 | -- | SCS RabbitMQ | SCS RocketMQ | -- | -- |
| 负载均衡 | Ribbon | -- | Dubbo LB | -- | -- |
| 分布式事务 | -- | -- | Seata | -- | -- |
三、需求背景
两个项目app-server和app-client,假定app-server对外提供服务接口,app-client消费接口服务(当前假设只是为了示例简单清晰,项目中请根据实际情况设计),可以使用Eureka做服务注册中心,自动发现微服务接口、管理查看服务、接口状态;使用Zuul做微服务网关,进行日志记录或者鉴权处理,配合Ribbon进行微服务负载均衡,Histrix对异常业务熔断、降级处理,Feign进行服务调用。
四、Eureka服务注册中心
1、创建项目
在IDEA中,点击File->New->Project...,选择Spring Initializr创建项目(也可选择Maven创建项目),如下图所示:
【注意】:如果上图中的Server URL无法正常加载,可将spring的项目初始化地址修改为:
https://start.aliyun.com/
2、修改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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.nandy.eureka_001</groupId>
<artifactId>eureka_001</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2021.0.4</spring-cloud.version>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<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>
<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>
3、application.yml配置
server:
port: 8081
spring:
application:
# 应用名称
name: Eureka_Server
eureka:
client:
# 由于该应用为注册中心,所以设置为false,代表不向注册中心注册自己
#一定要配置为false,不然启动时会把自己当作客户端向自己注册,会报错
register-with-eureka: false
# 由于注册中心的职责就是维护服务实例,它并不需要去检索服务,所以也设置为 false
fetch-registry: false
service-url:
# 客户端服务注册的位置说明
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
instance:
hostname: 127.0.0.1
lease-renewal-interval-in-seconds: 30
server:
renewal-percent-threshold: 0.49
【注意】renewal-percent-threshold该参数配置为0.49,主要是为了解决: EUREKA服务注册中心搭建好后页面有如下误信息,该参数默认值为0.8
# 为解决该问题,有人建议将application.yml中的配置项目改为false,我个人不推荐
# server:
# enable-self-preservation: false # 关闭自我保护
EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT
具体为什么是0.49,请参看博文
4、启动类
package com.nandy.eureka_001;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class Eureka001Application {
public static void main(String[] args) {
SpringApplication.run(Eureka001Application.class, args);
}
}
Eureka项目结构如下图所示
三、Eureka服务中心测试
在浏览器中输入:http://localhost:8081 后,打开如下图的Eureka服务监控页面,8081是Eureka服务在application.yml中配置的端口。
四、Eureka高可用方案
1、hosts中配置域名信息
在操作系统中,使用相关命令在hosts中增加域名,sudo vim /etc/hosts
127.0.0.1 euk1.com
127.0.0.1 euk2.com
2、application-dev.yml
server:
# 指定该Eureka实例的端口
port: 8081
spring:
application:
# 应用名称
name: Eureka_Server
eureka:
instance:
# 指定该Eureka实例的主机名
hostname: euk1.com
ip-address: 127.0.0.1
# 优先使用IP
prefer-ip-address: false
client:
# 由于该应用为注册中心,所以设置为false,代表不向注册中心注册自己
#一定要配置为false,不然启动时会把自己当作客户端向自己注册,会报错
register-with-eureka: true
# 由于注册中心的职责就是维护服务实例,它并不需要去检索服务,所以也设置为 false
fetch-registry: true
service-url:
# 客户端服务注册的位置说明
defaultZone: http://euk2.com:8082/eureka/
3、application-pro.yml
server:
# 指定该Eureka实例的端口
port: 8082
spring:
application:
# 应用名称
name: Eureka_Server
eureka:
instance:
# 指定该Eureka实例的主机名
hostname: euk2.com
ip-address: 127.0.0.1
# 优先使用IP
prefer-ip-address: false
client:
# 由于该应用为注册中心,所以设置为false,代表不向注册中心注册自己
#一定要配置为false,不然启动时会把自己当作客户端向自己注册,会报错
register-with-eureka: true
# 由于注册中心的职责就是维护服务实例,它并不需要去检索服务,所以也设置为 false
fetch-registry: true
service-url:
# 客户端服务注册的位置说明
defaultZone: http://euk1.com:8081/eureka/
经查阅资料,总结出以下几点:
- defaultZone 后面的eureka注册中心的地址要写成域名;
- eureka.client.register-with-eureka的值要写为true
- eureka.client.fetch-registry的值要写为true
- eureka集群中多个eureka服务的spring.application.name的值要一致
- eureka.instance.prefer-ip-address的值必须设置为false;prefer-ip-address:true代表使用ip地址的形式来定义注册中心的地址,而不使用主机名,而defaultZone中是以域名的方式向注册中心注册的,最终导致分片节点不能识别匹配(ip地址和域名),而认为分片均处于不可达状态;
- 各个eureka server节点要配置自己的hostname,各节点的hostname必须是各自的域名;
4、查看http://localhost:8081
5、查看http://localhost:8082
6、控制台信息说明
- DS Replicas: 代表集群信息,当有多个Eureka Server组成集群时,DS Replicas 会展示集群中的其他节点。比如:EurekaServer1中展示的是ek2.com,EurekaServer2中展示的是ek1.com
- total-avail-memory:总共可用的内存,540 mb
- num-of-cpus:CPU 的个数,8 核
- current-memory-usage:当前已经使用内存的百分比,使用了 276 mb,使用率69%
- server-uptime:服务已启动时间
- registered-replicas:当前Eureka Server是往哪个Eureka Server进行注册的。本案例是Eureka Server1和Eureka Server2互为客户端
- unavailable-replicas:不可用的集群节点
- available-replicas:可用的相邻集群节点