Spring Cloud 官方文档说了,它是一个完整的微服务体系,用户能够经过使用 Spring Cloud 快速搭建一个本身的微服务系统。那么 Spring Cloud 到底是如何使用的呢?他到底有哪些组件?java
spring-cloud-commons
组件里面,就有 Spring Cloud 默认提供的全部组件功能的抽象接口,有的还有默认实现。目前的 2020.0.x (按照以前的命名规则应该是 iiford),也就是spring-cloud-commons-3.0.x
包括:git
DiscoveryClient
,从注册中心发现微服务。ServiceRegistry
,注册微服务到注册中心。LoadBalancerClient
,客户端调用负载均衡。其中,重试策略从spring-cloud-commons-2.2.6
加入了负载均衡的抽象中。CircuitBreaker
,负责什么状况下将服务断路并降级而后,通常一个完整的微服务系统还包括:github
在以前的系列中,咱们将 Spring cloud 升级到了 Hoxton 版本,组件体系是:web
而且实现了以下的功能:算法
注册中心相关:spring
微服务实例相关:数据库
metamap
中的zone
配置,来区分不一样集群的实例。只有实例的metamap
中的zone
配置同样的实例才能互相调用。网关相关:apache
metamap
中的zone
配置鉴别所处集群,仅把请求转发到相同集群的微服务实例在后续的使用,开发,线上运行过程当中,咱们还遇到了一些问题:编程
接下来,咱们要对现有依赖进行升级,而且对现有的功能进行一些拓展和延伸,造成一套完整的 Spring Cloud 微服务体系与监控体系。json
本次项目代码,请参考:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford
此次咱们抽象出更加具体的各类场景的依赖。通常的,咱们的整个项目通常会包括:
为什么微服务要抽象分离出响应式的和传统 servlet 的呢?
<?xml version="1.0" encoding="UTF-8"?> <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.4</version> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.github.hashjang</groupId> <artifactId>spring-cloud-iiford</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <properties> <project.version>1.0-SNAPSHOT</project.version> </properties> <dependencies> <!--junit单元测试--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <!--spring-boot单元测试--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--mockito扩展,主要是须要mock final类--> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-inline</artifactId> <version>3.6.28</version> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2020.0.2</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.6.1</version> <configuration> <!--最好用JDK 12版本及以上编译,11.0.7对于spring-cloud-gateway有时候编译会有bug--> <!--虽然官网说已解决,可是11.0.7仍是偶尔会出现--> <source>11</source> <target>11</target> </configuration> </plugin> </plugins> </build> </project>
<?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-iiford</artifactId> <groupId>com.github.hashjang</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>spring-cloud-iiford-common</artifactId> <properties> <guava.version>30.1.1-jre</guava.version> <fastjson.version>1.2.75</fastjson.version> <disruptor.version>3.4.2</disruptor.version> <jaxb.version>2.3.1</jaxb.version> <activation.version>1.1.1</activation.version> </properties> <dependencies> <!--内部缓存框架统一采用caffeine--> <!--这样Spring cloud loadbalancer用的本地实例缓存也是基于Caffeine--> <dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> </dependency> <!-- guava 工具包 --> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>${guava.version}</version> </dependency> <!--内部序列化统一采用fastjson--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>${fastjson.version}</version> </dependency> <!--日志须要用log4j2--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency> <!--lombok简化代码--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--log4j2异步日志须要的依赖,全部项目都必须用log4j2和异步日志配置--> <dependency> <groupId>com.lmax</groupId> <artifactId>disruptor</artifactId> <version>${disruptor.version}</version> </dependency> <!--JDK 9以后的模块化特性致使javax.xml不自动加载,因此须要以下模块--> <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>${jaxb.version}</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>${jaxb.version}</version> </dependency> <dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <version>${jaxb.version}</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-xjc</artifactId> <version>${jaxb.version}</version> </dependency> <dependency> <groupId>javax.activation</groupId> <artifactId>activation</artifactId> <version>${activation.version}</version> </dependency> </dependencies> </project>
1. 缓存框架 caffeine
很高效的本地缓存框架,接口设计与 Guava-Cache 彻底一致,能够很容易地升级。性能上,caffeine 源码里面就有和 Guava-Cache, ConcurrentHashMap,ElasticSearchMap,Collision 和 Ehcache 等等实现的对比测试,而且测试给予了 yahoo 测试库,模拟了近似于真实用户场景,而且,caffeine 参考了不少论文实现不一样场景适用的缓存,例如:
因此,咱们选择 caffeine 做为咱们的本地缓存框架
参考:https://github.com/ben-manes/caffeine
2. guava
guava 是 google 的 Java 库,虽然本地缓存咱们不使用 guava,可是 guava 还有不少其余的元素咱们常常用到。
参考:https://guava.dev/releases/snapshot-jre/api/docs/
3. 内部序列化从 fastjson 改成 jackson
json 库通常都须要预热一下,后面会提到怎么作。
咱们项目中有一些内部序列化是 fastjson 序列化,可是看 fastjson 已经好久没有更新,有不少 issue 了,为了不之后出现问题(或者漏洞,或者性能问题)增长线上可能的问题点,咱们这一版本作了兼容。在下一版本会把 fastjson 去掉。后面会详细说明如何去作。
4. 日志采用 log4j2
主要是看中其异步日志的特性,让打印大量业务日志不成为性能瓶颈。可是,仍是不建议在线上环境输出代码行等位置信息,具体缘由以及解决办法后面会提到。因为 log4j2 异步日志特性依赖 disruptor,还须要加入 disruptor 的依赖。
参考:
5. 兼容 JDK 9+ 须要添加的一些依赖
JDK 9以后的模块化特性致使 javax.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"> <parent> <artifactId>spring-cloud-iiford</artifactId> <groupId>com.github.hashjang</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>spring-cloud-iiford-service-common</artifactId> <dependencies> <dependency> <groupId>com.github.hashjang</groupId> <artifactId>spring-cloud-iiford-common</artifactId> <version>${project.version}</version> </dependency> <!--注册到eureka--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!--不用Ribbon,用Spring Cloud LoadBalancer--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-loadbalancer</artifactId> </dependency> <!--微服务间调用主要靠 openfeign 封装 API--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!--resilience4j 做为重试,断路,限并发,限流的组件基础--> <dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-spring-cloud2</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/io.github.resilience4j/resilience4j-feign --> <dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-feign</artifactId> </dependency> <!--actuator接口--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!--调用路径记录--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> </dependency> <!--暴露actuator相关端口--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!--暴露http接口, servlet框架采用nio的undertow,注意直接内存使用,减小GC--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> </dependency> </dependencies> </project>
这里面相关的依赖,咱们后面会用到。
对于 Webflux 响应式风格的微服务,其实就是将 spring-boot-starter-web
替换成 spring-boot-starter-webflux
便可
参考:pom.xml