SpringCloud
入门问题
- 微服务概念
- 微服务之间如何通信
- SpringCloud与Dubbo的区别
- SpringBoot与SpringCloud的关系
- 服务熔断和服务降级概念
- 微服务的优缺点
- 微服务技术栈
- eureka和zookeeper的区别
微服务概述
微服务起源:微服务
微服务将单一应用程序划分为一组小服务,每个服务独立在及自己的进程中,通过Restful方式互相沟通、调用。每个服务提供单个业务功能,去耦合。
微服务与微服务架构
微服务:指系统中的一个服务应用。
微服务架构:架构风格,即包括微服务及微服务之间的通信。
微服务的优缺点
优点
- 服务高内聚,完成一个细微化的业务或功能
- 单个服务的开发更便捷,开发简单、开发效率高
- 微服务可由独立团队开发
- 松耦合,开发及部署都独立
- 可以由不同语言开发,易于集成
- 前后端分离、灵活分配数据库
缺点
- 分布式系统的复杂性
- 运维难度增加,系统部署依赖问题
- 服务间通信额外花费
- 数据一致性、系统集成测试难度
- 性能监控难
微服务技术栈
微服务 | 技术 |
---|---|
开发 | Spring、SpringBoot、SpringMVC |
配置管理 | Archaius(Netflix)、Diamond(Ali) |
注册与实现 | Eureka、Consul、Zookeeper |
调用 | Rest、RPC、gRPC |
熔断器 | Hystrix、Envoy |
负载均衡 | Ribbon、Nginx |
接口调用工具 | Feign |
消息队列 | Kaflka、RabbitMQ、ActiveMQ |
配置中心管理 | SpringCloudConfig、Chef |
路由(API网关) | Zuul |
监控 | Zabbix、Nagios、Metrics、Spectator |
全链路追踪 | ZipKin、Brave、Dapper |
部署 | Docker、OpenStack、Kubernates |
数据流操作 | SpringCloud Steam(Redis、Rabbit...) |
事件消息总线 | Spring Cloud Bus |
SpringCloud 架构
主流选用
厂商 | 技术选用 |
---|---|
阿里 | Dubbo/HSF |
京东 | JSF |
新浪微博 | Motan |
当当 | Dubbo |
框架对比
功能 | Spring Cloud | Motan | gRPC | Thrift | Dubbo/DubboX |
---|---|---|---|---|---|
定位 | 完整微服务 | RPC+ZK/Consul | RPC | RPC | RPC |
Rest | 支持 | 否 | 否 | 否 | 否 |
RPC | 否 | 是 | 是 | 是 | 是 |
多语言 | 是 | 否 | 是 | 是 | 否 |
注册/发现 | (Eurka) | Zookeeper/Consul | 否 | 否 | 是 |
负载均衡 | Zuul+Ribbon | 是 | 否 | 否 | 是 |
配置服务 | Archaius/sp config servier | ||||
调用链监控 | Zuul API | ||||
高可用/容错 | Hystrix Ribbon | ||||
其他 |
SpringCloud简介
SpringCloud微服务架构,涵盖了服务注册/发现、配置中心、全链路监控、服务网管、负载均衡、熔断器等,使用SpringBooot简化开发,提供快速构建分布式系统的工具,包括配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策精选、分布式会话等,都可以使用SpringBoot开发进行快速启动和部署。
SpringCloud:一站式分布式微服务解决方案
Dubbo 对比 SpringCloud
对比 | Dubbo | SpringCloud |
---|---|---|
注册中心 | Zookeeper | Eureka |
调用方式 | RPC | REST API |
监控 | Dubbo-minitor | spring boot admin |
断路器 | 不完善 | SC Netfilx Hystrix |
网管 | 无 | SC Netfilx Zull |
分布式配置 | 无 | SC config |
跟踪 | 无 | SC Sleuth |
消息总线 | 无 | SC Bus |
数据流 | 无 | SC Stream |
批量任务 | 无 | SC Task |
... |
文档
实战
版本
- Cloud: Dalston.SR1
- Boot: 1.5.9
创建工程
创建父工程Maven配置打包类型为Pom
在父工程中创建子工程模块
创建子工程
Eureka
服务注册与发现,注册订阅后可以依据服务标识符访问服务,不需要修改配置文件,功能和Zookeeper类似,遵循AP原则。
功能对比 | Eurka | Zookeeper |
---|---|---|
架构 | CS架构 Server端注册服务器 | RPC |
稳定性 | 冗余备份,所有集群均可独立工作 | 主从备份,选举费时 |
Eureka简介
服务端:提供服务注册服务,存储所有可用服务节点的信息。
客户端:Java客户端,简化同服务端的交互,包含负载均衡器,启动后会向服务端周期发送心跳(默认30s),当服务器在多个周期中未受到某节点心跳(默认90s),节点将会移除。
注册中心
server: port: 7001 eureka: instance: hostname: localhost client: register-with-eureka: false #不注册自身 fetch-registry: false #服务端 service-url: defalutZone: http://${eureka.instance.hostname}:${s
@SpringBootApplication @EnableEurekaServer public class EurekaServer7001_App { public static void main(String[] args) { SpringApplication.run(EurekaServer7001_App.class,args); } }
服务提供者
eureka: client: #客户端注册进eureka服务列表内 service-url: defaultZone: http://localhost:7001/eureka #defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ instance: instance-id: microservicecloud-dept-8001 prefer-ip-address: true #访问路径可以显示IP地址
@EnableEurekaClient @SpringBootApplication public class DeptProvider8001_App { public static void main(String[] args) { SpringApplication.run(DeptProvider8001_App.class,args); } }
服务消费者
server: port: 80
@Configuration public class ConfigBean { @Bean @LoadBalanced//Spring Cloud Ribbon 负载均衡的工具。 public RestTemplate getRestTemplate() { return new RestTemplate(); } }
private static final String REST_URL_PREFIX = "http://localhost:8001"; //private static final String REST_URL_PREFIX = "http://MICROSERVICECLOUD-DEPT"; @Autowired private RestTemplate restTemplate; @RequestMapping(value = "/consumer/dept/add") public boolean add(Dept dept) { return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class); } @RequestMapping(value = "/consumer/dept/get/{id}") public Dept get(@PathVariable("id") Long id) { return restTemplate.getForObject(REST_URL_PREFIX + "/dept/get/" + id, Dept.class); } @SuppressWarnings("unchecked") @RequestMapping(value = "/consumer/dept/list") public List<Dept> list() { return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list", List.class); } // 测试@EnableDiscoveryClient,消费端可以调用服务发现 @RequestMapping(value = "/consumer/dept/discovery") public Object discovery() { return restTemplate.getForObject(REST_URL_PREFIX + "/dept/discovery", Object.class); }
负载均衡
Ribbon
客户端负载均衡工具
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency>
@Configuration public class ConfigBean { @Bean @LoadBalanced//Spring Cloud Ribbon 负载均衡的工具。 public RestTemplate getRestTemplate() { return new RestTemplate(); } }
@Bean public IRule myRule() { //return new RoundRobinRule(); //return new RandomRule();//达到的目的,用我们重新选择的随机算法替代默认的轮询。 return new RetryRule(); }
算法
RoundRobinRule
轮询
RandomRule
随机
AvaliabilityFilteringRule
过滤访问导致故障处于断路器跳闸的服务、超并发阈值服务,剩余轮询
WeightedResponseTimeRule
根据平均响应时间分配权重,权重大的被选中几率大,服务启动使用轮询,后切换为WeightedResponseTimeRule。
RetryRule
按照轮询获取服务,失败时,在指定时间内重试。
BestAvaliableRule
过滤故障跳闸服务,选择并发量小的服务。
ZoneAvoidanceRule
默认规则,复合判断服务性能和选择可用服务。
自定义负载均衡策略
import com.wang.myrule.MySelfRule; ///////////////// @RibbonClient(name="microservicecloud-dept",configration=MySelfRule.class) ///////////////// @EnableEurekaClient @SpringBootApplication public class ConsumerDept80 { public static void main(String[] args) { SpringApplication.run(ConsumerDept80.class,args); } }
//自动配置类 不能载SpringBoot的自动扫描范围 //如果被扫描 所有的客户端将共享这个配置 package com.wang.myrule;//与主配置并列包 import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.netflix.loadbalancer.IRule; import com.netflix.loadbalancer.RoundRobinRule; @Configuration public class MySelfRule { @Bean public IRule myRule() { //return new RandomRule(); //return new RoundRobinRule(); return new RandomRule();// 自己编写的类 } }
自定义规则编写
自定义策略类
package com.atguigu.myrule; import java.util.List; import com.netflix.client.config.IClientConfig; import com.netflix.loadbalancer.AbstractLoadBalancerRule; import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.Server; public class RandomRuleUserDefined extends AbstractLoadBalancerRule { // total = 0 // 当total==5以后,我们指针才能往下走, // index = 0 // 当前对外提供服务的服务器地址, // total需要重新置为零,但是已经达到过一个5次,我们的index = 1 // 分析:我们5次,但是微服务只有8001 8002 8003 三台,OK? // private int total = 0; // 总共被调用的次数,目前要求每台被调用5次 private int currentIndex = 0; // 当前提供服务的机器号 public Server choose(ILoadBalancer lb, Object key) { if (lb == null) { return null; } Server server = null; while (server == null) { if (Thread.interrupted()) { return null; } List<Server> upList = lb.getReachableServers(); List<Server> allList = lb.getAllServers(); int serverCount = allList.size(); if (serverCount == 0) { /* * No servers. End regardless of pass, because subsequent passes only get more * restrictive. */ return null; } // int index = rand.nextInt(serverCount);// java.util.Random().nextInt(3); // server = upList.get(index); // private int total = 0; // 总共被调用的次数,目前要求每台被调用5次 // private int currentIndex = 0; // 当前提供服务的机器号 if(total < 5) { server = upList.get(currentIndex); total++; }else { total = 0; currentIndex++; if(currentIndex >= upList.size()) { currentIndex = 0; } } if (server == null) { /* * The only time this should happen is if the server list were somehow trimmed. * This is a transient condition. Retry after yielding. */ Thread.yield(); continue; } if (server.isAlive()) { return (server); } // Shouldn't actually happen.. but must be transient or a bug. server = null; Thread.yield(); } return server; } @Override public Server choose(Object key) { return choose(getLoadBalancer(), key); } @Override public void initWithNiwsConfig(IClientConfig clientConfig) { // TODO Auto-generated method stub } }
策略类继承关系
Feign
声明式Rest客户端,使得编写Web服务客户端更简单,可以与Eurek、Rebbon组合使用。 定义一个接口添加注解,即可使用。 Ribbon+RestTemplate:调用 接口+注解:调用
依赖
<dependency> <groupId>cn.springcloud.feign</groupId> <artifactId>venus-cloud-starter-feign</artifactId> </dependency>
接口+注解
//@FeignClient(value = "MICROSERVICECLOUD-DEPT",fallbackFactory=DeptClientServiceFallbackFactory.class) //熔断器类 @FeignClient(value = "MICROSERVICECLOUD-DEPT") public interface DeptClientService { @RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET) public Dept get(@PathVariable("id") long id); @RequestMapping(value = "/dept/list", method = RequestMethod.GET) public List<Dept> list(); @RequestMapping(value = "/dept/add", method = RequestMethod.POST) public boolean add(Dept dept); }
Controller
@RestController public class DeptController_Consumer { @Autowired private DeptClientService service; @RequestMapping(value = "/consumer/dept/get/{id}") public Dept get(@PathVariable("id") Long id) { return this.service.get(id); } @RequestMapping(value = "/consumer/dept/list") public List<Dept> list() { return this.service.list(); } @RequestMapping(value = "/consumer/dept/add") public Object add(Dept dept) { return this.service.add(dept); } }
集成了Rabbon,Ribbon+RestTemplate调用微服务 ==》接口+注解,调用接口的方式调用服务,即是在调用某个微服务的方式从使用RestTemplate的方式转为使用接口方式调用,Fegin还是可以使用Rabbon的负载均衡。
Hystrix
处理分布式系统的延迟和容错的开源库,分布式系统中,服务调用不可避免会有调用失败、超时、异常出现,Hystrix保证在服务出现为题时,不会导致整体服务失败,避免级联故障,提高分布式系统的弹性。当某个服务出现故障,通关断路器的故障监控,向调用方法返回一个符合预期的、可处理的备选响应,而不是进行等待或抛出异常,保证调用线程不会长时间等待、返回无用信息,避免故障蔓延。
使用方法
依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency>
启用
@SpringBootApplication @EnableEurekaClient @EnableDiscoveryClient @EnableCircuitBreaker //对hystrix熔断机制的支持 public class DeptProviderHystrix { public static void main(String[] args) { SpringApplication.run(DeptProviderHystrixp.class, args); } }
Controller
@RestController public class DeptController { @Autowired private DeptService service = null; //调用服务方法失败并抛出了错误信息 //自动调用@HystrixCommand标注好的fallbackMethod调用类中的指定方法 @HystrixCommand(fallbackMethod = "processHystrix_Get") @RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET) public Dept get(@PathVariable("id") Long id) { Dept dept = this.service.get(id); if (null == dept) { throw new RuntimeException("该ID:" + id + "没有没有对应的信息"); } return dept; } //类似异常通知 public Dept processHystrix_Get(@PathVariable("id") Long id) { return new Dept().setDeptno(id).setDname("该ID:" +id + "没有没有对应的信息,null--@HystrixCommand") .setDb_source("no this database in MySQL"); } }
熔断机制,当微服务在某个服务处发生了超时、异常时,由Hystrix返回一个结果,结果符合调用服务者的要求。举例实际使用,需要重写FallbackFactory接口并在Feign注解中配置fallbackFactory,即可实现异常处理与业务模块分离,解耦和。
服务降级
服务降级在客户端完成,暂时关闭服务,为其他服务节省资源,当服务关闭后,Hystrix依旧会为接口调用时返回一个信息。
//实现FallbackFactory接口 @Component public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService> { @Override public DeptClientService create(Throwable throwable) { return new DeptClientService() { @Override public Dept get(long id) { return new Dept().setDeptno(id).setDname("该ID:" + id + "没有没有对应的信息") .setDb_source("no this database in MySQL"); //,Consumer客户端提供的降级信息,此刻服务Provider已经关闭 } @Override public List<Dept> list() { return null; } @Override public boolean add(Dept dept) { return false; } }; } }
HystrixDashboard
服务监控,持续记录通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展现给用户,即微服务的图形化监控。
依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId> </dependency>
主类
@SpringBootApplication @EnableHystrixDashboard public class DeptConsumerDashBoard { public static void main(String[] args) { SpringApplication.run(DeptConsumerDashBoard.class, args); } }
服务
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
监控指标
- Delay:轮询监控信息的延迟事件,默认2000毫秒
- Title:监控标题
- 失败
- 超时
- 成功
- 错误请求
- 拒绝
- 短路
- 错误
Zuul路由网关
路由功能,对外部请求进行转发,即外部访问与服务的路由网关,提供过滤、路由功能,将以一个服务注册到Eureka中,同时实现网关功能,可以配置其他服务的路由访问规则。
依赖
<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>
配置
server: port: 9527 //server_port //服务将通过路由进行访问 spring: application: name: microservicecloud-zuul-gateway eureka: client: service-url: defaultZone: eureka-ip instance: instance-id: intance_id prefer-ip-address: true zuul: //服务地址映射定义 #ignored-services: microservicecloud-dept //过滤服务地址访问 prefix: /prefix //公共前缀 ignored-services: "*" //过滤全部服务地址 routes: mydept.serviceId: microservicecloud-dept mydept.path: /myurl/** info:
分布式配置中心
针对当出现大量的微服务时,提供一个配置中心,对微服务的配置进行集中管理。

服务端
在github中创建一个库并保存地址
- 在本地创建库并克隆创建的库
- 创建文件配置文件application.yml(UTF-8)
提交文件
server: port: 3344 spring: application: name: microservicecloud-config cloud: config: server: git: uri: *:*.git #GitHub上面的git仓库名字
客户端
bootstrap.xml
spring: cloud: config: name: microservicecloud-config-client #需要从github上读取的资源名称, #注意没有yml后缀名 profile: test #本次访问的配置项 label: master uri: ip/url:3344 #本微服务启动后先去找3344号服务, #通过SpringCloudConfig获取GitHub的服务地址
依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency>
微服务框架图
来源:https://www.cnblogs.com/Wu-Zang/p/9608929.html