目录
github代码:https://github.com/XinCongming/SpringCloud
一.系统架构演变、微服务介绍
1、集中式架构:当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。
2、垂直拆分:当访问量逐渐增大,单一应用无法满足需求,为了应对更高的并发和业务需求,我们根据业务功能对系统进行拆分
3、分布式服务:当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。
4、服务治理(SOA):当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键
5、微服务:微服务是一种架构风格,即将单体应用划分为小型的服务单元,微服务之间使用 HTTP 的 API 进行资源访问与操作。
微服务架构的演变更像是一个公司的发展过程,从最开始的小公司,到后来的大集团。大集团可拆分出多个子公司,每个子公司的都有自己独立的业务、员工,各自发展,互不影响,合起来则是威力无穷。
微服务架构的优势
1)服务的独立部署:每个服务都是一个独立的项目,可以独立部署,不依赖于其他服务,耦合性低。
2)服务的快速启动:拆分之后服务启动的速度必然要比拆分之前快很多,因为依赖的库少了,代码量也少了。
3)更加适合敏捷开发:敏捷开发以用户的需求进化为核心,采用迭代、循序渐进的方法进行。服务拆分可以快速发布新版本,修改哪个服务只需要发布对应的服务即可,不用整体重新发布。
4)职责专一,由专门的团队负责专门的服务:业务发展迅速时,研发人员也会越来越多,每个团队可以负责对应的业务线,服务的拆分有利于团队之间的分工。
5)服务可以动态按需扩容:当某个服务的访问量较大时,我们只需要将这个服务扩容即可。
6)代码的复用:每个服务都提供 REST API,所有的基础服务都必须抽出来,很多的底层实现都可以以接口方式提供。
二、初始SpringCloud
Spring最擅长的就是集成,把世界上最好的框架拿过来,集成到自己的项目中。SpringCloud也是一样,它将现在非常流行的一些技术整合到一起,实现了诸如:配置管理,服务发现,智能路由,负载均衡,熔断器,控制总线,集群状态等等功能。其主要涉及的组件包括:
netflflix、Eureka:注册中心、Zuul:服务网关、Ribbon:负载均衡、Feign:服务调用、Hystix:熔断器等等
三、微服务场景模拟
1、认识Eureka 注册中心
Eureka负责管理、记录服务提供者的信息。服务调用者无需自己寻找服务,而是把自己的需求告诉Eureka,然后Eureka会把符合你需求的服务告诉你。同时,服务提供方与Eureka之间通过“心跳”机制进行监控,当某个服务提供方出现问题,Eureka自然会把它从列表中剔除。这样就实现了服务的自动注册、发现、状态监控。
基础架构
Eureka架构中的三个核心角色:
- 服务注册中心:Eureka的服务端应用,提供服务注册和发现功能,对应项目eureka-server
- 服务提供者:提供服务的应用,可以是SpringBoot应用,也可以是其他任意技术实现,只要对外提供的是Rest风格服务即可,本例中就是我们实现的user-service
- 服务消费者:消费应用从注册中心获取服务列表,从而得知每个服务方的信息,知道去哪里调用服务方。本例是consumer-service
高可用Eureka Server
Eureka Server即服务的注册中心,它也可以是一个集群。
服务同步:多个Eureka Server之间也会互相注册为服,当服务提供者注册到Eureka Server集群中的某个节点时,该节点会把服务的信息同步给集群中的每个节点,从而实现数据同步。因此,客户端访问到Eureka Server集群中的任意一个节点,都可以拉取到完整的服务列表信息。
#application.yml相关配置信息
server:
port: 10086 # 端口
eureka: #eureka服务注册
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka,http://127.0.0.1:10087/eureka #高可用
instance:
prefer-ip-address: true #可以将IP注册到Eureka Server上,如果不配置就是机器的主机名
ip-address: 127.0.0.1
spring:
application:
name: eureka-server #服务名称,不写否则就是UNKNOWN
#启动类声明
@EnableEurekaServer // 声明这个应用是一个EurekaServer
复制一个EurekaApplication2,在两个启动的配置VM Options中分别添加:
-Dserver.port=10086 -Deureka.client.serviceurl.defaultZone=http://localhost:10086/eureka,http://localhost:10087/eureka
-Dserver.port=10087 -Deureka.client.serviceurl.defaultZone=http://localhost:10086/eureka,http://localhost:10087/eureka
服务提供者 user-service
服务提供者要向EurekaServer注册服务,并且完成服务续约(心跳机制)等工作。
#eureka配置信息、注册地址 application.yml
spring:
datasource:
username: root
url: jdbc:mysql://localhost:3306/crm?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
password: zxc123456
driver-class-name: com.mysql.cj.jdbc.Driver
application: #应用名称
name: user-service
eureka:
client:
service-url:
defaultZone: http://localhost:10086/eureka
instance:
prefer-ip-address: true # 当调用getHostname获取实例的hostname时,返回ip而不是host名称
ip-address: 127.0.0.1 # 指定自己的ip信息,不指定的话会自己寻找
#启动类加一个注解
@EnableDiscoveryClient // 开启EurekaClient功能
服务消费者 consumer-service
#application.yml配置信息
spring:
application:
name: consumer-service #服务名称
#向eureka进行注册
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
#启动类加一个注解
@EnableDiscoveryClient // 开启EurekaClient功能
2、负载均衡Ribbon
(1)开启两个服务提供者实例
user-service中,复制一个启动类UserApplication2,并改配置:
(2)开启负载均衡Ribbon
consumer-service中,添加依赖:
<!--负载均衡-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
restTemplate添加@LoadBalanced
//使用HttpClient 或者urlConnection进行远程访问
@Bean
@LoadBalanced //ribbon负载均衡
public RestTemplate restTemplate(){return new RestTemplate();}
@Autowired
private RestTemplate restTemplate;
public User queryById(long id) {
restTemplate.getForObject("http://"+host+":"+port+"/user/"+id,User.class);
//利用eureka通过服务应用名称获取提供服务的host+port user-service对应提供服务端配置文件中application name
return
restTemplate.getForObject("http://user-service/user/"+id,User.class);
}
Ribbon会自动实现负载均衡,默认是简单的轮询策略
3、Hystrix 熔断器
容错处理是指软件运行时,能对由非正常因素引起的运行错误给出适当的处理或信息提示,使软件运行正常结束。
在分布式环境中,许多服务依赖项中的一些必然会失败。Hystrix是一个库,通过添加延迟容忍和容错逻辑,帮助你控制这些分布式服务之间的交互。Hystrix通过隔离服务之间的访问点、停止级联失败和提供回退选项来实现这一点,所有这些都可以提高系统的整体弹性。
雪崩问题:微服务中,服务间调用关系错综复杂,一个请求,可能需要调用多个微服务接口才能实现,会形成非常错综复杂的调用链路。如果一个微服务发生异常,求情阻塞,用户不会得到响应,则tomcat的这个线程不会释放,于是越来越多的用户请求来,越来越多的线程阻塞,服务器支持的线程和并发数有限,请求会一直阻塞,会导致服务器资源耗尽,从而导致其他服务都不能用,形成雪崩效应。
Hystrix解决雪崩的问题有两个方法:1、线程隔离、服务降级 2、服务熔断
(1)线程隔离、服务降级
Hystrix为每个依赖服务调用分配一个小的线程池,如果线程池已满调用将被立即拒绝,默认不采用排队,加速失败判定时间
案例:consumer-service中,添加依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
开启熔断:consumer-service的启动类添加 @EnableCircuitBreaker 注解或者 @EnableHystrix
consumer-service加入注解后,如果访问超时等出现问题,会执行失败回滚处理函数,详情代码见github
(2)服务熔断 熔断器,也较断路器
为了方便测试熔断器,先修改配置参数
@HystrixCommand(commandProperties = { //设置超时时间3000 只对此方法生效
// @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000"), //超时
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"), //最小请求次数,默认20
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"),//休眠时长,默认5000
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60")//失败请求最小占比,默认50%
})
然后访问十遍http://localhost:8003/cs/consumer/hystrix/2,这样熔断器的状态机就会open,在10秒内访问http://localhost:8003/cs/consumer/hystrix/1也是执行错误回滚函数,十秒后正常访问。
4、Feign伪装
Feign可以把Rest请求进行隐藏,伪装成类似SpringMVC的Controller一样。你不用自己拼接url,拼接参数等操作,全部交给Feign
(1)添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
(2)feign客户端
@FeignClient("user-service") //声明这是一个feign客户端
public interface userClient {
@GetMapping("/user/{id}")
User queryUserById(@PathVariable("id") Long id);
}
启动类:
@EnableFeignClients //开启Feign
controller中调用
@Autowired
private userClient userClient;
@GetMapping("{id}")
public User queryById(@PathVariable("id") Long id) {
return userClient.queryUserById(id); //feign
}
(3)feign中同时支持了熔断和负载均衡,所以对应的hystrix依赖也可以完全去掉
(4)Feign支持请求和响应进行GZIP压缩,以减少通信过程中的性能消耗
feign:
compression:
request:
enabled: true #开启请求压缩
mime-types: text/html,application/json #设置压缩的数据类型,默认也是如此
min-request-size: 2048 #设置触发压缩额最下限,默认也是如此
response:
enabled: true #开启响应压缩
5、Zuul网关
以上就是实现springcloud微服务的基本架构,如下:
加入zuul网关后的架构:
(1)快速入门
新建module,加入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
启动类加注解 @EnableZuulProxy
#配置文件
spring:
application:
name: api-gateway #指定服务名
zuul:
routes:
hehe: #路由id,随意
path: /user-service/** #映射路径
url: http://127.0.0.1:8081 #映射路径对应的实际url地址
启动访问http://localhost:10010/user-service/user/1