微服务springcloud
1)首先说微服务的架构
微服务,更加强调的是独立、自治、灵活。
独立: 把每个功能分成每个独立的服务,通过fegin客户端实现服务之间的调用,服务和服务之间互不影响.
自治: 每个服务虽然小,但是''五脏俱全''
灵活: 在微服务框架中,一般都会采用基于Http的Rest风格服务的请方式,可以做到夸语言跨平台
缺点:在http请求方式下消息封装比较臃肿,不能够自定义消息传输格式,不过在feign中提供了请求数据的压缩的配置可以相应的减小性能损耗
微服务的特点:
-
单一职责:微服务中每一个服务都对应唯一的业务能力,做到单一职责
-
微:微服务的服务拆分粒度很小,例如一个用户管理就可以作为一个服务。每个服务虽小,但“五脏俱全”。
-
面向服务:面向服务是说每个服务都要对外暴露Rest风格服务接口API。并不关心服务的技术实现,做到与平台和语言无关,也不限定用什么技术实现,只要提供Rest的接口即可。
-
自治:自治是说服务间互相独立,互不干扰
-
团队独立:每个服务都是一个独立的开发团队,人数不能过多。
-
技术独立:因为是面向服务,提供Rest接口,使用什么技术没有别人干涉
-
前后端分离:采用前后端分离开发,提供统一Rest接口,后端不用再为PC、移动段开发不同接口
-
数据库分离:每个服务都使用自己的数据源
-
部署独立,服务间虽然有调用,但要做到服务重启不影响其它服务。有利于持续集成和持续交付。每个服务都是独立的组件,可复用,可替换,降低耦合,易维护
2)微服务是一种架构方式,最终肯定需要技术架构去实施。
微服务的实现方式很多,但是最火的莫过于Spring Cloud了。为什么?
-
后台硬:作为Spring家族的一员,有整个Spring全家桶靠山,背景十分强大。
-
技术强:Spring作为Java领域的前辈,可以说是功力深厚。有强力的技术团队支撑,一般人还真比不了
-
群众基础好:可以说大多数程序员的成长都伴随着Spring框架,试问:现在有几家公司开发不用Spring?SpringCloud与Spring的各个框架无缝整合,对大家来说一切都是熟悉的配方,熟悉的味道。
-
使用方便:相信大家都体会到了SpringBoot给我们开发带来的便利,而SpringCloud完全支持SpringBoot的开发,用很少的配置就能完成微服务框架的搭建
下面使用springcloud集成的顶级服务框架来搭建微服务
1.Eureka:注册中心
实时监控服务的状态,服务的调用,负载均衡,统一管理配置
-
服务管理
-
自动注册和发现服务:服务会向eureka注册自己的信息提供什么配置,
-
实现服务状态监管: 服务会定期发送http请求,证明自己没有宕机, Eureka会将对应服务的所有提供者地址列表发送给需要服务的服务,并且定期更新
-
通过zuul网关实现服务的动态路由
-
-
通过Ribbon负载均衡和Hystix熔断机制解决容灾问题
-
失效剔除
-
eureka.server.eviction-interval-timer-in-ms: xx
来设置失效剔除时间,但是在生产换将下如果时间小的话,会占用带宽,影响其他服务的效率,造成请求堵塞
-
-
自我保护
-
在生产环境下由于网络原因服务没有按时时发送心跳,但此时服务可能没有宕机,这样把服务剔除就不妥当,此时eureka会把此服务实例保护起来默认时间是15分钟,一般开发环境会把这个机制关闭!
-
-
重试机制
-
如果当前服务宕机,可以配置重新连接当前服务的次数,可以配置连接下一个相同服务的配置次数,如果不行返回失败,尝试的次数取决于配置文件中的属性值
-
在服务的消费方引入依赖
-
<dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency>
-
配置文件配置
-
spring: cloud: loadbalancer: retry: enabled: true # 开启Spring Cloud的重试功能 ribbon: ConnectTimeout: 250 # Ribbon的连接超时时间 ReadTimeout: 1000 # Ribbon的数据读取超时时间 OkToRetryOnAllOperations: true # 是否对所有操作都进行重试 MaxAutoRetriesNextServer: 1 # 切换实例的重试次数 MaxAutoRetries: 1 # 对当前实例的重试次数 feign: hystrix: enabled: true # 开启Feign的熔断功能
-
-
-
服务实现统一配置
server: port: 10086 # 端口 spring: application: name: eureka-server # 应用名称,会在Eureka中显示 eureka: server: enable-self-preservation: false # 关闭自我保护模式(缺省为打开) eviction-interval-timer-in-ms: 1000 # 扫描失效服务的间隔时间(缺省为60*1000ms) client: register-with-eureka: false # 是否注册自己的信息到EurekaServer,默认是true fetch-registry: false # 是否拉取其它服务的信息,默认是true service-url: # EurekaServer的地址,现在是自己的地址,如果是集群,需要加上其它Server的地址。 defaultZone: http://127.0.0.1:${server.port}/eureka
2.Ribbon:负载均衡,Hystix:熔断器
-
负载均衡
-
相同的服务可能会被布置到多个机器上,我们不可能只调用一个服务
-
负载均衡器 ribbon
-
ribbon默认的负载均衡策略是轮询我们可以通过配置晚间的方式更改策略
-
-
user-service: # 消费方配置文件设置 ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
- Hystix:熔断器
-
正常情况下客户调用服务接口,服务出现异常时直接回滚失败,服务做降级处理
-
当服务繁忙时,如果服务出现异常,不是粗暴的直接报错,而是返回一个友好的提示,虽然拒绝了用户的访问,但是会返回一个结果。
-
-
3.Feign:服务调用
Feign可以把Rest的请求进行隐藏,伪装成类似SpringMVC的Controller一样。你不用再自己拼接url,拼接参数等等操作,一切都交给Feign去做。
他内置了熔断器Hystix和 负载均衡策略 ribbon
feign对请求与相应的压缩
feign: compression: request: enabled: true # 开启请求压缩 mime-types: text/html,application/xml,application/json # 设置压缩的数据类型 min-request-size: 2048 # 设置触发压缩的大小下限
fegin的日志输出
通过
logging.level.xx=debug
来设置日志级别。然而这个对Fegin客户端而言不会产生效果。因为@FeignClient
注解修改的客户端在被代理时,都会创建一个新的Fegin.Logger实例。我们需要额外指定这个日志的级别才可以。1)设置cn.itcast包下的日志级别都为debug
logging: level: cn.itcast: debug
2)编写配置类,定义日志级别
@Configuration public class FeignConfig { @Bean Logger.Level feignLoggerLevel(){ return Logger.Level.FULL; } }
-
Zuul:服务网关
-
Eureka实现了服务注册中心以及服务注册与发现;而服务间通过Ribbon或Feign实现服务的消费以及均衡负载;通过Spring Cloud Config实现了应用多环境的外部化配置以及版本管理。为了使得服务集群更为健壮,使用Hystrix的融断机制来避免在微服务架构中个别服务出现异常时引起的故障蔓延。这些还是不够,因为这样我们的服务地址就暴露了,这样的话所有人都可以访问,不安全,而如果自己做权限管理的话代码重复多,有多少服务就会做多少权限控制,所以望门需要一个统一的服务入口来拦截所有请求进行权限控制服务的动态路由,这样我们就需要服务网关了
-
通过服务网关统一向外系统提供REST API的过程中,除了具备服务路由、均衡负载功能之外,它还具备了
权限控制
等功能。Spring Cloud Netflix中的Zuul就担任了这样的一个角色,为微服务架构提供了前门保护的作用,同时将权限控制这些较重的非业务逻辑内容迁移到服务路由层面,使得服务集群主体能够具备更高的可复用性和可测试性。 -
这样不管是来自于客户端(PC或移动端)的请求,还是服务内部调用。一切对服务的请求都会经过Zuul这个网关,然后再由网关来实现 鉴权、动态路由等等操作。Zuul就是我们服务的统一入口。
引依赖 <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency> <--用于拉去服务列表实现动态路由 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies> 启动类 @SpringBootApplication @EnableDiscoveryClient //开启eureka服务注册中心 @EnableZuulProxy // 开启Zuul的网关功能 public class ZuulDemoApplication { public static void main(String[] args) { SpringApplication.run(ZuulDemoApplication.class, args); } } yml配置 server: port: 10010 #服务端口 spring: application: name: api-gateway #指定服务名 zuul: prefix: /api # 添加路由前缀 routes: user-service: /user-service/** # 这里是映射路径
我们通过
zuul.prefix=/api
来指定了路由的前缀,这样在发起请求时,路径就要以/api开头。路径
/api/user-service/user/1
将会被代理到/user-service/user/1
zuul的过滤器
ZuulFilter是过滤器的顶级父类。在这里我们看一下其中定义的4个最重要的方法:
public abstract ZuulFilter implements IZuulFilter{ abstract public String filterType(); abstract public int filterOrder(); boolean shouldFilter();// 来自IZuulFilter Object run() throws ZuulException;// IZuulFilter }
Zuul的Ribbon负载均衡和Hystix熔断机制
Zuul中默认就已经集成了Ribbon负载均衡和Hystix熔断机制。但是所有的超时策略都是走的默认值,比如熔断超时时间只有1S,很容易就触发了。因此建议我们手动进行配置:
zuul: retryable: true ribbon: ConnectTimeout: 250 # 连接超时时间(ms) ReadTimeout: 2000 # 通信超时时间(ms) OkToRetryOnAllOperations: true # 是否对所有操作重试 MaxAutoRetriesNextServer: 2 # 同一服务不同实例的重试次数 MaxAutoRetries: 1 # 同一实例的重试次数 hystrix: command: default: execution: isolation: thread: timeoutInMilliseconds: 6000
-
shouldFilter
:返回一个Boolean
值,判断该过滤器是否需要执行。返回true执行,返回false不执行。 -
run
:过滤器的具体业务逻辑。 -
filterType
:返回字符串,代表过滤器的类型。包含以下4种:-
pre
:请求在被路由之前执行 -
route
:在路由请求时调用 -
post
:在routing和errror过滤器之后调用 -
error
:处理请求时发生错误调用
-
-
filterOrder
:通过返回的int值来定义过滤器的执行顺序,数字越小优先级越高。
-
-