管理微服务的利器,构建分布式系统的工具。 是基于Spring Boot构建的(Cloud的版本与Boot的版本不一样会发生什么?)。 版本命名规则:伦敦地铁站名字
- 配置管理,例如相同的服务,不同的配置。
- 服务注册,管理每一个启动的微服务状态。
- 服务发现,微服务直接的互相发现。
- 断路器?熔断机制。
- 智能路由
- 负载均衡
- 微代理
- 一次性令牌
- 等等等
Spring Cloud 配置
- 版本
Spring Cloud Config
微服务多配置多,节点多,手工管理复杂。这时就需要微服务的集中化配置。
Config Server
配置中心,利用git来集中管理程序的配置。
- 依赖
implementation 'org.springframework.cloud:spring-cloud-config-server:4.0.4'
- 注解
package cn.duchaoqun.config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.config.server.EnableConfigServer;
// 添加Client注解
@SpringBootApplication
@EnableDiscoveryClient
@EnableConfigServer
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- 配置
spring.application.name=eureka-config-server
eureka.client.service-url.defaultZong = http://localhost:8761/eureka/
server.port=8082
spring.cloud.config.server.git.uri=https://github.com/duchaoqun/spring-cloud-config
spring.cloud.config.server.git.search-paths=config-repo
-
注意先准备git仓库
-
验证 访问 http://localhost:8082/auther/dev 返回如下内容代表启动成功
配置文件命名规则
Config Client
Spring Cloud Netflix
集成 Netflix的开源软件。
Spring Cloud Bus
消息总线,利用分布式消息将服务和服务实力链接在一起,用于在一个集群
Spring Cloud for Cloud Foundry
很少用到
Spring Cloud Foundry Service Broker
很少用到
Spring Cloud Cluster
基于Zookeeper实现集群
Spring Cloud Consul
服务发现,配置管理
Spring Cloud Security
安全管理
Spring Cloud Sleuth
分布式跟踪,例如日志收集。
Spring Cloud Data Flow
Spring Cloud Stream
Spring Cloud Stream App Starters
Spring Cloud Task App Starters
Spring Cloud for Amazon Web Services
Spring Cloud Connectors
Spring Cloud Starters
Spring Cloud CLI
Spring Cloud Contract
http://cloud.spring.io/spring-cloud-static/Finchley.M2/
spring-cloud-starter-netflix-eureka-server
单体架构
整体所有的业务逻辑都包含在一个大的单体的项目内,从0到1来完成所有内容。
优点
-
功能划分非常清楚。
-
层次关系好,例如MVC,每一层相互独立。
-
部署简单。
-
技术单一,例如仅仅使用单一一种编程语言。
-
用人成本低。
缺点
-
功能逐渐增多,升级风险高,维护成本越来越高,交付周期越来越长,伸缩性扩展性差,监控某个功能困难。
微服务架构
SOA(Service-Oriented Architecture),将系统拆分出独立的部分,跨域。
**如何进行服务的拆分?**
- 拆分足够微小。
- 尽量采用轻量级的通信,例如Rest方式,http来进行交互。
- 领域驱动原则,深刻理解业务,有些情况需要根据业务领域和边界进行拆分。
- 单一职责原则,高内聚低耦合,对其他的服务依赖必须低。
- 不限于技术栈(不能滥用),针对不同的业务,场景,存储,算力来使用不同的技术来实现。
- 横向拆分:例如MVC中的某一层中的某一个功能。
- 纵向拆分:业务上整体从上到下的某一个业务逻辑的拆分。
- 领域边界拆分:业务模块的整体拆除来。
**如何设计微服务?**
- 服务拆分
- 服务注册
- 服务发现
- 服务消费
- 统一的入口
- 配置管理,同一个服务,不同的机器问题。
- 熔断机制,保护系统本身。
- 自动扩展,根据当前负荷情况自动扩展。
**优点**
- 易于理解和实现单一的功能,更少的业务逻辑,易于维护和部署和更新。
如何发现服务?你发布的微服务,需要让其他的微服务能找得到?
- 单一的微服务需要通过URI来访问服务(直连模式),IP地址与主机绑定,IP地址比较难记,很难做负载均衡。这时候就需要一个注册中心来管理所有的微服务。
- 客户端发现模式,微服务启动后将自己的信息提交注册中心,客户端去中心查询可用微服务,客户端计算均衡使用那个微服务。
- 服务端发现模式,微服务启动后将自己的信息提交注册中心,客户端去中心查询可用微服务,中心均衡分配使用那个微服务。
Eureka 服务的注册
Eureka Server
https://start.spring.io/ 生成项目基础代码,用IDEA打开,然后添加eureka-server依赖。
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.3'
id 'io.spring.dependency-management' version '1.1.3'
}
group = 'cn.duchaoqun'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '17'
}
repositories {
mavenCentral()
}
// 第一步
ext {
set('springCloudVersion', "2022.0.4")
}
dependencies {
// 第二步
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
// https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-eureka-server
implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-netflix-eureka-server', version: '4.0.3'
}
// 第一部
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
tasks.named('test') {
useJUnitPlatform()
}
- application.properties 配置
server.port=8761
eureka.instance.hostname=localhost
# 单纯的服务端,不启用客户端功能
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.client.service-url.defaultZong = http://${eureka.instance.hostname}:${server.port}/eureka/
- 最后在Application上面加上注解 EnableEurekaServer
package cn.duchaoqun.demospringcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class DemoSpringCloudApplication {
public static void main(String[] args) {
SpringApplication.run(DemoSpringCloudApplication.class, args);
}
}
- 启动项目,访问配置好的端口即可。
Eureka Client
// spring cloud 依赖管理
ext {
set('springCloudVersion', "2022.0.4")
}
dependencies {
// eureka client dependence
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client:4.0.2'
implementation 'org.springframework.boot:spring-boot-starter-web:2.3.12.RELEASE'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
// spring cloud 版本
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
- Application add annotation
// 添加Client注解
@SpringBootApplication
@EnableDiscoveryClient
public class DemoSpringCloudApplication {
public static void main(String[] args) {
SpringApplication.run(DemoSpringCloudApplication.class, args);
}
}
Feign消费微服务
Ribbon:通常配合Eureka来使用,通过服务名称来找对应的资源,内部实现负载均衡。
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-ribbon:2.2.8.RELEASE'
Feign
-
准备Eureka注册中心
-
准备Eureka客户端,用于提供数据微服务
-
准备Eureka-Feign客户端,访问其他微服务来获取数据
代码实例
-
application.properties
// eureka client dependence
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client:4.0.2'
// add openfeign
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign:2.2.8.RELEASE'
- Application.java
package cn.duchaoqun.feign;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
// 添加Client注解
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients // add annotation
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- Service Interface
package cn.duchaoqun.feign.service;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
// 第一步,添加注解指定其他微服务的名称
@FeignClient("spring-cloud-eureka-client-china")
public interface ProvinceClient {
// 第二部,指定其他微服务提供的服务地址
@GetMapping("/listProvinces")
String listProvinces();
}
- Controller
package cn.duchaoqun.feign.controller;
import cn.duchaoqun.feign.service.ProvinceClient;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ProvinceController {
// 第三步,注入客户端
@Resource
private ProvinceClient provinceClient;
// 第四步,定义本服务的方法,通过feign来调用其他微服务返回数据
@GetMapping("/provinces")
public String listProvinces() {
// 通过Feign客户端方法其他微服务来返回数据
return provinceClient.listProvinces();
}
}
注册中心是单体?如何高可用?
API 网关
统一的API入口,可以集合多个API(单点故障)。 避免将内部数据服务暴露给外部。 混合内部的不同服务的通讯协议。 降低构建微服务的复杂性。
nginx
Spring Cloud Zuul
-
有注册中心
-
有目标微服务
-
添加依赖
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-zuul:2.2.10.RELEASE'
- 添加启动注解
package cn.duchaoqun.zuul;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
// 添加Client注解
@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulProxy
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- 配置文件application.yml
[[eureka]].client.service-url.defaultZong = http://localhost:8761/eureka/
# # config zuul
[[zuul]].routes.china.path=/province/**
[[zuul]].routes.china.url=http://localhost:8081/province
##zuul.strip-prefix=false
##zuul.routes.china.url=spring-cloud-eureka-client-china
server:
port: 8484
spring:
application:
name: eureka-client-zuul-server
zuul:
routes:
spring-cloud-eureka-client-china:
path: /province/**
service-id: spring-cloud-eureka-client-china
strip-prefix: false
prefix: /api
这个配置有问题,不能转发请求,待研究。
spring-cloud-starter-netflix-hystrix
熔断机制
熔断机制,对系统本身的防护,例如超量的请求,为避免服务垮掉,响应一个提示。
断路器 断路器模式, Microsoft Azure:Closed(正常),Open(超载),Half-Open(有限制)
优点:可以让系统更加稳定,减少性能损耗,及时的响应(明确告知客户端超载了),可以日志记录异常数据。对后期优化提供帮助。
手动关闭熔断功能。 熔断器也需要并发。
熔断与降级的区别?
- 目的一直,都是为了保护系统,提供默认的响应内容。
- 触发条件不一样,熔断针对单一一个服务的超负荷,降级针对整体的服务性能进行考量。
- 管理目标层次不同,熔断针对每一个微服务,降级针对整个服务。
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-hystrix:2.2.8.RELEASE'
EnableCircuitBreaker
自动扩展
垂直扩展:增加单台主机的配置 水平扩展:增加主机数量
就是使用 eureka-server 来实现水平扩展。 监控机器的状态,然后自动创建新的并启动新的(虚拟机)实例。