SpringCloud 是利用SpringBoot的开发便利性巧妙的简化了分布式系统基础设施的开发 ,如服务注册与发现,配置中心,网关服务,负载均衡,熔断器,消息总线,数据监控等,若是想了学习如下内容请先对SpringBoot有必定的了解 ,本简书主要从SpringCloud的入门到SpringCloud的项目实战做为学习路线 如没有SpringBoot的基础请先关注 暂时不要阅读java
在介绍SpringCloud以前不少人都会将SpringCloud与Dubbo进行对比 首先要认可Dubbo的性能确实比SpringCloud的性能好 由于SpringCloud是基于Http协议每次都要建立链接传输的也是文本内容 而Dubbo是基于Netty的TCP协议及二进制的传输协议 更接近底层,因此在性能方面不用质疑的web
Eureka: 服务注册与发现,用于服务管理spring
Ribbon: 基于客户端的负载均衡组件bootstrap
Hystrix: 容错框架,可以防止服务的雪崩效应api
Feign: Web服务客户端,可以简化Http接口的调用安全
Zuul: API网关提供路由转发,请求过滤等功能springboot
Config: 分布式配置管理bash
Sleuth: 服务链路跟踪网络
Stream: 构建消息驱动的微服务应用程序的框架架构
Bus : 消息代理的集群消息总线(集成消息中间件Kafka ,RabbitMQ) . . . . . .
注册中心在微服务架构中是必不可少的一部分,主要是用来实现服务的治理功能. 常见的注册中心有Eureka和Zookeeper 在分布式系统领域有个CAP定理 C:数据一致性 A:服务可用性 P: 服务对网络分区故障的容错性 这三个特性在任何分布式系统中都不能同时知足,最多同时知足两个 Eureka是基于AP原则构建 Zookeeper是基于CP原则构建 若是要保证AP就要用Eureka 想要保证CP就要用Zookeeper Dubbo大部分都是基于Zookeeper做为注册中心 ,SpringCloud都是使用Eureka做为注册中心
首先建立一个maven项目 spring-eureka-registry 在pom.xml里添加相关依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jolokia</groupId>
<artifactId>jolokia-core</artifactId>
</dependency>
</dependencies>
复制代码
建立一个启动类EurekaRegistryMsApplication
@EnableEurekaServer
@SpringBootApplication
public class EurekaRegistryMsApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(EurekaRegistryMsApplication.class).web(true).run(args);
}
}
复制代码
@EnableEurekaServer注解表示开启EurekaServer 接下来建立一个application.yml 咱们这里使用yml格式的
server:
port: ${port:${PORT:8763}}
management:
port: 9274
context-path: '/55395018-70b7-47c3-8fef-5bf24c9da9af'
eureka:
instance:
hostname: eureka1
prefer-ip-address: false
instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}
metadata-map:
cluster: prontera
management:
port: ${management.port}
context-path: ${management.context-path}
health:
path: ${management.context-path}/health
status-page-url-path: ${management.context-path}/info
health-check-url-path: ${management.context-path}/health
client:
service-url:
defaultZone: 'http://${eureka.instance.hostname}:${server.port}/eureka/'
fetch-registry: false
register-with-eureka: false
server:
renewal-percent-threshold: '0.8'
spring:
application:
name: 'registry'
复制代码
这里须要注意的是register-with-eureka: false 属性 不须要注册本身 接下来就能够直接运行EurekaRegistryMsApplication启动类了 而后访问http://localhost:8763/ 就能够看到Eureka提供的Web控制台了
这里用了@SpringCloudApplication注解,它整合了@SpringBootApplication、@EnableDiscoveryClient、@EnableCircuitBreaker,主要目的仍是简化配置。
####2.Ribbon 客户端负载均衡 目前主流的负载方案有两种:一是集中式负载均衡,在消费者和服务提供方中间使用独立的代理方式进行负载,有硬件的(F5),也有软件的(Nginx).另外一种就是客户端本身作负载均衡,根据本身的请求作负载,Ribbon就属于客户端本身作负载均衡. 经过Spring Cloud Ribbon的封装,咱们在微服务架构中使用客户端负载均衡调用很是简单,只须要以下两步:
- 服务提供者只须要启动多个服务实例并注册到一个注册中心或是多个相关联的服务注册中心.
- 服务消费者直接经过调用被@LoadBalanced注解修饰过的RestTemplate来实现面向服务的接口调用.
这样咱们就能够将服务提供者的高可用以及服务消费者的负载均衡调用一块儿实现了.
Spring Cloud整合Ribbon只须要在pom.xml中加入依赖便可 其余的能够不用配置 由于Eureka中已经中已经引用了Ribbon
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
复制代码
@SpringBootApplication
@EnableEurekaClient
public class SpringbootRestTemplateApplication {
@Autowired
private RestTemplateBuilder builder;
@Bean
@LoadBalanced // 添加负载均衡支持,很简单,只须要在RestTemplate上添加@LoadBalanced注解,那么RestTemplate即具备负载均衡的功能,若是不加@LoadBalanced注解的话,会报java.net.UnknownHostException:springboot-h2异常,此时没法经过注册到Eureka Server上的服务名来调用服务,由于RestTemplate是没法从服务名映射到ip:port的,映射的功能是由LoadBalancerClient来实现的。
public RestTemplate restTemplate() {
return builder.build();
}
public static void main(String[] args) {
SpringApplication.run(SpringbootRestTemplateApplication.class, args);
}
}
复制代码
@RestController
public class RestTemplateController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/hello/{id}")
public User findById(@PathVariable Long id) {// 将原来的ip:port的形式,改为注册到Eureka Server上的应用名便可
User u = this.restTemplate.getForObject("http://SERVICE-HELLO/hello" + id, User.class);
System.out.println(u);
return u;
}
}
复制代码
除了使用@LoadBalanced注解外,咱们还能够直接使用Ribbon所提供的LoadBalancerClient来实现负载均衡: application.yml
stores:
ribbon:
listOfServers: www.baidu.com,www.jianshu.com,www.163.com
复制代码
@RestController
public class HelloController { protected Logger logger = LoggerFactory.getLogger(HelloController.class);
@Autowired private RestTemplate restTemplate;
@Autowired private LoadBalancerClient loadBalancerClient;
@RequestMapping(value = "/hello", method = RequestMethod.GET) public String hello() {
return restTemplate.getForEntity("http://SERVICE-HELLO/hello", String.class).getBody();
}
@RequestMapping(value = "/helloEx", method = RequestMethod.GET)
public String helloEx() {
ServiceInstance instance = this.loadBalancerClient.choose("SERVICE-HELLO");
URI helloUri = URI.create(String.format("http://%s:%s/hello", instance.getHost(), instance.getPort()));
logger.info("Target service uri = {}. ", helloUri.toString());
return new RestTemplate().getForEntity(helloUri,String.class).getBody(); } }
复制代码
API网关是对外服务的一个入口,隐藏了内部的实现,是微服务架构中必不可少的一个组件.API网关能够为咱们管理大量的API接口,还能够对接客户,适配协议,进行安全认证,路由转发,限制流量,日志监控,防止爬虫,进行灰度发布等, Zuul可以与Eureka,Ribbon,Hystrix等组件配合使用.
建立一个项目命名application-gateway 加入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
复制代码
为了最后的实战演练 下面是须要添加的所有依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-sidecar</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.jolokia</groupId>
<artifactId>jolokia-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
</dependencies>
复制代码
spring-cloud-starter-zuul依赖中还包含了:
spring-cloud-start-hystrix: 该依赖用来在网关服务中实现对微服务转发时候的保护机制,经过线程隔离和断路器,防止微服务的故障引起API网关资源没法释放,从而影响其余应用的对外服务
spring-cloud-starter-ribbon: 该依赖用来实如今网关服务进行路由转发时候的客户端负载均衡以及请求重试. spring-boot-starter-actuator: 该依赖用来提供常规的微服务管理端点.另外 在Spring Cloud Zuul 中还提供了 /routes端点来返回当前的全部路由规则
建立启动类ApiGatewayMsApplication 使用@EnableZuulProxy注解开启Zuul的API网关服务功能
@EnableZuulProxy
@SpringCloudApplication
public class ApiGatewayMsApplication {
public static void main(String[] args) {
SpringApplication.run(ApiGatewayMsApplication.class, args);
}
}
复制代码
配置文件bootstrap.yml
server:
port: 7291
management:
port: 10211
context-path: '/fb83deee-dd46-472b-99a9-f0ebffe20d0e'
eureka:
client:
service-url:
defaultZone: 'http://eureka1:8763/eureka/,http://eureka2:8762/eureka/'
instance:
instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}
metadata-map:
cluster: prontera
management:
port: ${management.port}
context-path: ${management.context-path}
health:
path: ${management.context-path}/health
status-page-url-path: ${management.context-path}/info
health-check-url-path: ${management.context-path}/health
prefer-ip-address: false
zuul:
routes:
quartz:
sensitiveHeaders: "*"
serviceId: application-quartz
stripPrefix: false
path: /quartz/**
manager:
sensitiveHeaders: "*"
serviceId: trade-manager
stripPrefix: false
path: /manager/**
api:
sensitiveHeaders: "*"
serviceId: trade-api
stripPrefix: false
path: /api/**
spring:
application:
name: gateway
cloud:
loadbalancer:
retry:
enabled: false #关闭重试
zipkin:
base-url: 'http://zipkin_server:9411/'
ribbon:
MaxAutoRetries: 0
MaxAutoRetriesNextServer: 0
OkToRetryOnAllOperations: false
ConnectTimeout: 6500
ReadTimeout: 60000
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 65000
复制代码
完成上面的工做后 启动网关服务 就经过Zuul实现了API网关服务
咱们此时能够经过Eureka查看注册的服务
在这里读者须要看一下个人配置文件
在这里是面向服务的路由,简单的说就是让路由的path不是映射具体的url而是让他映射到具体的服务 而具体的url则交给Eureka的服务发现机制去自动维护
举个栗子: http://localhost:7291/manager/hello: 改url符合/manager/**规则 由manager路由负责转发 ,该路由映射的serviceId为trade-manager,因此最终 /hello 请求会被发送到trade-manager服务的一个实例上去
这个服务会在实战中介绍给你们 先附一张图理解一下
在微服务架构中存在多个可直接调用的服务.这些服务若在调用时出现故障会致使连锁效应,也就是可能会让整个系统变得不可用,这种状况咱们称之为服务雪崩效应,这里咱们经过Hystrix来实现服务容错处理.
简单使用 添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
复制代码
在启动类上添加@EnableHystrix或者@EnableCircuitBreaker
@GetMapping("/callHello")
@HystrixCommand(fallbackMethod = "defaultCallHello")
public String callHello(){
String result = restTemplate.getForObject(
"http://loan/hello",String.class);
return result;
}
复制代码
当调用失败触发熔断时会调用defaultCallHello方法来回退具体内容
public String defaultCallHello(){
return "fail";
}
复制代码
熔断简单的介绍这里 后面咱们会针对每个接口都作熔断处理