Spring-Cloud简易全家桶实践
目标组合为:Eureka+Ribbon+Feign+Hystrix+Actuator+Dashboard+Config+Zuul
此处只为基本使用的关键点和范例的解读,源码阅读后续再补充
注意点:
1.注意使用的spring-cloud的各个组件的版本需要能对应
这里有一个可能有坑的地方是,各个组件间或多或少会有依赖,实践时因为仓库受限缘故,选用的启动器或组件有时候会因为仓库中下载不到而手动切换版本,如果切换的版本有不兼容,代码明面上不会有提示(很坑),但是对应组件就是不会生效(很坑double)。印象中maven-repository有依赖的最低版本提示的,但是当前用ali系不能访问这个仓库,用ali仓库虽然包的树结构很优雅,但是并没有找到有提示版本最低依赖的地方(这里demo偷懒的解决版本是都采用最新版本)。这里有尝试用IDEA+maven多仓库来解决,但是尝试了几次,setting中的多仓库配置在IDEA中未能生效,这里后续还要研究下。(可以考虑用maven本身不加IDEA来解决这个问题)
当前demo的版本依赖如下:
<spring-cloud.version>Hoxton.SR3</spring-cloud.version>
<starter.version>1.4.7.RELEASE</starter.version>
2.spring-cloud组件本身有更迭,所使用的配置方式可能版本间存在差异
1和2点个人觉得也是部分公司不选用全套Spring-Cloud的缘由。因为存在版本依赖和配置更迭问题,Spring-Cloud虽然开箱即用,但是版本更迭中可能会存在较大修改(比如配置这种)。如果公司本身场景很复杂,要面对很多极限情况,最好使用自己团队能完全把控和修改的框架。(当然,不选用全套并不意味着一个不选,不学习其精华)
Eureka关键点:
Eureka是做服务注册的,Eureka保证了CAP(C:强一致性,A:高可用性,P:分区容错性,三者中能选2)中的AP(如果一个服务挂掉,不会立马被同步,也就是无法保证P)。Zookeeper保证了CP(Zookeeper的一个问题是,如果master节点挂掉, 重新选举过程中服务会不可用,服务瘫痪,也就是没法保证A)。
Eureka分服务器和客户端的概念
服务器:
服务器当前范例为单独部署,依赖和配置如下(私以为单独部署的方式很费解....)
依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
配置示范:(不做过多解读,阅读源码时再来详细解读)
server:
port: 7001
eureka:
instance:
hostname: eurka7001.com
client:
registerWithEureka: false
fetchRegistry: false
service-url:
defaultZone: http://127.0.0.1:7002/eureka,http://127.0.0.1:7003/eureka/
spring:
application:
name: eurekaserver01
启动注解:
@EnableEurekaServer
客户端:
依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
配置示范:
eureka:
client: #客户端注册进eureka服务列表内
service-url:
#defaultZone: http://localhost:7001/eureka
defaultZone: http://127.0.0.1:7001/eureka/,http://127.0.0.1:7002/eureka/,http://127.0.0.1:7003/eureka/
instance:
instance-id: provider01-x
prefer-ip-address: true #访问路径可以显示IP地址
启动注解:
@EnableEurekaClient
@EnableDiscoveryClient //印象中这个也是必要的,尚未阅读源码还不太确定
Ribbon关键点:
Ribbon用于做客户端负载均衡,此处没有单独用,而是集合Feign一起用
依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
使用方式:
@Configuration
public class ConfigBean //boot -->spring applicationContext.xml --- @Configuration配置 ConfigBean = applicationContext.xml
{
@Bean
@LoadBalanced//Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端 负载均衡的工具。
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
@Bean
public IRule myRule() {
//return new RoundRobinRule();
return new RandomRule();//达到的目的,用我们重新选择的随机算法替代默认的轮询。
// return new RetryRule();
}
}
注意:
@RibbonClient可以对指定实例做定制化的负载均衡(但是这里有一个坑,这里定制化指定的规则类不能被Spring自动扫描到,否则会成为所有实例通用的负载均衡规则)
Feign关键点
Feign是一个http请求的轻量级调度框架。
依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
使用Feign首先要能发现服务(这里使用Eureka的服务发现,对应代码就不在这里写了),通常也会和hystrix一起使用
使用代码
@FeignClient(value = "PROVIDER-01"
, fallbackFactory = TestServiceFallbackFactory.class
)
public interface TestService {
@RequestMapping(value = "/test", method = RequestMethod.GET)
public String pringTest();
}
配置项:
feign:
hystrix:
enabled: true
Hystrix关键点
Hystrix是断路器的意思,主要用于添加延迟容忍和容错逻辑。另外Hystrix好像也是可以和Hystrix-dashboard一起使用来做分布式服务数据的监控
依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
使用:
@FeignClient(value = "PROVIDER-01"
, fallbackFactory = TestServiceFallbackFactory.class
)
@Component //注意这里要组件化
public class TestServiceFallbackFactory implements FallbackFactory<TestService> {
@Override
public TestService create(Throwable throwable) {
return new TestService() {
@Override
public String pringTest() {
return "大爷呀,出错了呀!没服务可用了呀";
}
};
}
}
Hystrix-Dashboard关键点
很可耻的木有搞成功,是单服务简单部署,但是抓取不到服务。看了一下对应的集成了hystrix端,也没有对应的服务信息。应该还是在版本或者配置上有问题导致的服务端没有注册hystrix信息,所以dashboard这边采集不到导致的。具体问题后续看源码时再来解决。
Actuator关键点
这个就可以认为是一个工具包,提供对于实例信息的补充信息定制
依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
使用范例:
info:
app.name: test-provider
company.name: www.test.com
build.artifactId: $project.artifactId$
build.version: $project.version$
Config
尚未实践
Zuul
依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
<!-- 这个不能少,不然发现不了服务的 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
配置:
# Eureka的配置信息就不在这里写了
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:7001/eureka/,http://127.0.0.1:7002/eureka/,http://127.0.0.1:7003/eureka/
instance:
instance-id: test-zuul
prefer-ip-address: true
zuul:
prefix: /
ignored-services: "*"
routes:
test:
serviceId: providername #注意这里是对应暴露服务的spring.application.name
path: /test/**
开启标签
@EnableZuulProxy
这里如果不引入Eureka的依赖会有
Caused by: com.netflix.client.ClientException: Load balancer does not have available server for client: providername
的报错。如果配置写错会有其他奇奇怪怪的(比如访问eureka配置写错的话,会自动访问到默认的eureka地址去,也就是128.0.0.1:8761上.... 囧囧,不要问我为什么会知道...)
总结
整体感觉全家桶可配置化程度比较高,做简单demo实践的过程还算比较容易。但也正因为可配置化程度较高,意味着要想做到较高的定制化,需要对于底层有一定的了解才行。