微信号:DianrongMafia

介绍:点融黑帮——一个充满激情和梦想的技术团队,吸引了来自金融及信息科技领域的顶尖人才.我们正在用技术创新改变传统金融.

干货分享微服务Spring-cloud(一)

2017-10-16 19:00 杨虎强

由于文章篇幅较长

此文分两次推送

目录如下



前言


读者:对spring、spring boot有一定了解

难度:初中级,旨在快速应用于项目

参考文献:网络、书籍、官方文档,有任何错误欢迎大家留言拍砖指正

实战模拟源码:https://github.com/yhqnh/demo-springcloud,使用spring-cloud dalston版本 



Spring boot  



1.1依赖关系

spring cloud 强依赖spring boot

spring boot强依赖spring

弱弱说一句强依赖就是没有它不行,所以有必要对spring或spring boot一些特性作简单介绍


1.2. 元注解和组合注解

元注解:可以注解到别的注解上的注解,被注解的注解称之为组合注解。

例如@SpringBootApplication就是组合注解,它组和了

@SpringBootConfiguration@EnableAutoConfiguration等。


 


1.3. 自动配置

spring boot会根据在类路径中的jar包和类,为jar包里的类自动配置bean,这样会极大地减少我们要使用的配置。

spring boot通过spring4.X提供的条件注解condition来实现。

spring4.x提倡使用java配置和注解配置组合,不需要任何xml配置即可实现spring所有配置。也可使用@ImportResource({“application1.xml”,“application2.xml”})对 xml配置的支持。


关闭特定的自动配置使用@SpringBootConfiguration的exclude属性,例如exclude = {DataSourceAutoConfiguration.class}来关闭数据源自动配置


 


@condition根据满足某一特定条件创建一个特定的bean,比方说当类路径存在某一jar包时候,自动配置一个或多个bean。

@ConditionalOnBean:当容器里有指定的bean的条件下

@ConditionalOnClass:当类路径下有指定的类的条件下

@ConditionalOnMissingBean:当容器里没有指定bean的情况下

@ConditionalOnResource:类路径是否有指定的值

例如RabbitAutoConfiguration当发现类路径下没有ConnectionFactory类型的bean时创建一个


 


我们来看看EnableAutoConfiguration注解的源码


 


这里最关键的@import功能导入配置,EnableAutoConfigurationImportSelector使用SpringFactoriesLoader.loadFactories方法来扫描具有META-INF/spring.factories文件的jar包,而spring-boot-autoconfiguration的jar包里有spring.fatories文件,此文件包含了所有自动配置。


 

 

1.4. 多环境配置

在spring boot中,多环境配置文件名需要满足application-{profile}.properties的格式,其中{profile}对应你的环境标识。{profile}通过spring.profiles.active=test属性来设置则会加载application-test.properties配置文件。


1.5. 加载顺序

Spring boot加载属性顺序,数值越小优先级越高

1) 在命令行中的参数

2) SPRING_APPLICATION_JSON中的属性。SPRING_APPLICATION_JSON是以json格式配置在系统环境变量中

3) java:comp/env中的JNDI属性

4) Java的系统属性,可以通过System.getProperties()获得的内容

5) 操作系统的环境变量

6) 通过random.*配置的随机属性

7) 位于当前应用jar包之外,针对不同{profile}环境的配置文件内容,例如application-{profile}.properties或是YAML定义的配置文件

8) 位于当前应用jar包之内,针对不同{profile}环境的配置文件内容,例如application-{profile}.properties或是YAML定义的配置文件

9) 位于当前应用jar包之外的application.properties和YAML配置内容

10) 位于当前应用jar包之内的application.properties和YAML配置内容

11) @Configuration注解修改的类中,通过@PropertySource注解定义的属性

12) 应用默认属性,使用SpringApplication.setDefaultProperties定义的内容


例如Spring Cloud Config从git等外部获取配置来取代jar包内本地配置文件,这样即使同样名称的本地调试配置文件对其他demo、staging、prod也没有任何影响,因为7优先级高于8或者说9优先级高于10


1.6. actuator与原生端点

spring-boot-starter-actuator模块的实现对于实施微服务可以有效省去或减少监控系统在采集应用指标时的开发量。它提供了一些原始端点。


 

 


Spring cloud   



2.1. 版本说明

spring-cloud 版本号并没有像其他spring项目使用类似1.x.x的命名方式。由于spring cloud不像spring社区其他一些项目那样相对独立,它是一个拥有众多项目的大型项目,其包含的各个子项目也独立进行着内容更新与迭代,各自都维护着自己的发布版本号。因此每一个spring cloud的版本都会包含多个不同版本的子项目,为了管理每个版本的子项目清单,避免spring cloud的版本号与其他子项目版本号相混淆,没有采用版本号的方式,而是通过命名的方式。


2.2. 服务治理对比

Feature

Consul

zookeeper

etcd

euerka

服务健康检查

服务状态,内存,硬盘等

(弱)长连接,keepalive

连接心跳

可配支持

多数据中心

支持

kv存储服务

支持

支持

支持

一致性

raft

paxos

raft

CAP

CA

CP

CP

AP

使用接口(多语言能力)

支持http和dns

客户端

http/grpc

http(sidecar)

watch支持

全量/支持long polling

支持

支持 long polling

支持 long polling/大部分增量

自身监控

metrics

metrics

metrics

安全

acl /https

acl

https支持(弱)

spring cloud集成

已支持

已支持

已支持

已支持


总的来看,目前Consul 自身功能,和spring cloud对其集成的支持都相对较为完善,而且运维的复杂度较为简单,Eureka 设计上比较符合场景,但还需持续的完善。根据自身业务场景自行选择最适合的服务治理方案。


分布式领域CAP理论

Consistency(一致性), 数据一致更新,所有数据变动都是同步的

Availability(可用性), 好的响应性能

Partition tolerance(分区容错性) 可靠性


定理:任何分布式系统只可同时满足二点,没法三者兼顾。


2.3. 实战模拟

我们会讲解企业经常使用的sping cloud 模块, 包括Spring Cloud Config(配置管理)、spring-cloud-starter-eureka(服务治理)、spring-cloud-starter-feign(声明式服务调用)、spring-cloud-starter-hystrix(熔断器)、spring-cloud-starter-ribbon(客户端负载均衡)、spring-cloud-starter-zuul(api网关)、Spring Cloud Zookeeper(服务治理与配置)


注意:在使用demo过程中DiscoveryClient服务发现的时间默认是30秒。比如先启动注册中心,已经启动了一个服务提供者client1,再启动消费者,这时消费者能消费client1,这时再启动client2,注册中心会看到client2已经注册成功,但是消费者并不能马上访问到client2服务,需要等30秒后方能访问


2.4. 服务治理eureka

Spring cloud eureka是spring cloud netflix微服务套件中的一部分,它基于Netflix eureka增加了二次封装,主要负责完成微服务架构中的服务治理功能


2.4.1. 单机注册中心

创建一个spring boot基础工程命名为demo-springcloud-server1,添加关键依赖


 


在启动类Server1Application上添加@EnableEurekaServer注解启动一个服务注册中心



application.properties配置,其中服务名为demo-springcloud-server


 

启动Server1Application的main方法,打开浏览器访问http://localhost:1111/成功。但是启动时报错了,报错原因是服务向注册中心注册自己失败。



报错信息很明显,不能识别peer1,所以我们在host文件中模拟域名映射。笔者使用的是windows系统,所以C:\Windows\System32\drivers\etc\hosts文件添加127.0.0.1 peer1,再次启动将不会报错


 


使用浏览器访问(http://localhost:1111/http://peer1:1111/)都会成功。

Instances currently registered with Eureka下的Application注册了一个DEMO-SPRINGCLOUD-SERVER服务。


 

在默认配置下,eureka.client.fetch-registry=true,作为客户端定期获取服务列表,更新客户端的服务清单,以保证服务访问的正确性。作为注册中心一般我们会置为false,因为注册中心不需要更新服务清单。eureka.client.register-with-eureka=true该服务会向注册中心注册它自己,以便其他应用可以发现它。如果我们需要禁用它的客服端行为,这种场景只适合单机注册中心,只需在application.properties中增加如下配置



再次浏览器访问http://localhost:1111/将不会注册自己为服务端,No instances available



2.4.2. 注册中心HA

Eureka Server的高可用实际上就是将自己作为服务向其他服务注册中心注册自己,这样可以形成一组相互注册的服务注册中心,以实现服务列表的互相同步,达到高可用的目的。复制单机注册中心并命名为demo-springcloud-server2,启动类命名为Server2Application,同理hosts文件需要配置peer2, eureka.client.register-with-eureka必须设置为true向注册中心注册自己,以便注册中心之间同步服务列表,注册中心1和2主要区别在于配置文件。

demo-springcloud-server1配置文件application.properties向eureka.client.service-url.defaultZone=http://peer2:1112/eureka注册中心2同步服务列表


 

demo-springcloud-server2配置文件application.properties向eureka.client.service-url.defaultZone=http://peer1:1111/eureka注册中心1同步服务列表


 


2.4.3. 服务提供者

有了注册中心,下面新建spring boot项目并命名为demo-springcloud-client1,启动类命名为Client1Application,添加注解@EnableDiscoveryClient开启服务提供者Eureka对DiscoveryClient的实现自动配置



项目关键依赖,spring-boot-starter-web表示是web应用


 

配置文件application.properties,为了验证注册中心服务列表是否同步,这里我们只向注册中心1注册服务eureka.client.service-url.defaultZone=http://peer1:1111/eureka


 

既然是服务提供者,我们这里演示新建一个YhqController提供rest的hello服务


 

启动服务中心1,服务中心2,启动服务提供者demo-springcloud-client1

用浏览器访问(http://localhost:2221/hello)看到hello服务访问正常


 

这里可能对spring不熟悉的人会觉得为什么返回client1而不是页面,因为这里的用到了之前讲到的组合注解,根本原因在于@RestController注解组合了@Controller和@ResponseBody


 


用浏览分别访问(http://peer1:1111/)和(http://peer2:1112/)都可以看到Instances currently registered with Eureka注册服务提供者DEMO-SPRINGCLOUD-CLIENT,证明服务列表已经同步,但实际使用中我们不推荐这样使用,我们一般会同时向注册中心1、注册中心2同时注册服务,而不是单一只向注册中心1注册服务


 

 

2.5. 负载均衡ribbon与熔断器hystrix

Ribbon是一个基于http和tcp的客户端负载均衡工具

Hystrix具备服务降级、服务熔断、线程和信号隔离、请求缓存、请求合并以及服务监控

为了方便消费者负载均衡效果,复制demo-springcloud-client1并重名为demo-springcloud-client2,修改配置文件和启动类,服务提供者1和2服务名均为spring.application.name=demo-springcloud-client

 

 

 

修改YhqContoller实现,为了方便负载均衡观察效果,demo-springcloud-client2项目返回字符串client2


 

创建消费者项目demo-springcloud-restTemplate-consumer,创建启动类RestTemplateApplication,@EnableDiscoveryClient启动服务发现和注册自动配置,以便能够发现前面注册的服务提供者demo-springcloud-client1和demo-springcloud-client2。@EnableCircuitBreaker开启熔断器自动配置


 


创建负载平衡RestTemplate,@Bean并使用@LoadBalanced限定符。如果没有spring-cloud-starter-ribbon依赖,@LoadBalanced的负载均衡轮询算法将不会生效。使用spring-cloud-starter-eureka依赖,ribbon服务发现将交由Eureka提供。添加熔断器依赖spring-cloud-starter-hystrix 


 

创建YhqController提供rest服务restTemplateConsumer来消费之前的服务1和2,


 


服务通过注入的YhqService的RestTemplate对象负载均衡调用我们的服务提供者demo-springcloud-client1和demo-springcloud-client2

  


启动注册中心,启动服务提供者1和2,启动消费者demo-springcloud-restTemplate-consumer,浏览器访问http://localhost:3331/restTemplateConsumer返回的字符串client1和client2交替出现,这是因为负载均衡轮询的效果。



熔断器Hystrix使用fallback命令执行失败时使用的后备方法,用来实现服务的降级处理逻辑。这时关闭服务提供者demo-springcloud-client2,浏览器访问http://localhost:3331/restTemplateConsumer返回的字符串client1和我是降级逻辑交替出现

 

 


当通过注解方法实现熔断器时,通过使用@HystrixCommand的commandProperties来设置属性值,例如设置fallback.enabled


 


今日文章到这结束啦

敬请期待

文章下半部分

就在明日~





点击回顾往期精彩内容

AE能做的动效,都能在App中实现了?

监测数组变动的两种实现

React 中使用context实现数据穿越

帮助你发现问题核心本质的简易方法

Python3异步编程

python音频库dejavu原理浅析

视错觉与UI元素间的可能

今天我们来聊聊公司估值

那些工程师们玩的聚会桌游

从Java看字符编码

浅析Spring AOP

香港金融科技周即将开启,点融成为钻石赞助商

Vue世界中的Redux——Vuex

点融荣登“中国网贷先锋榜”

Affordance杂谈

浅谈金融类APP测试

今天我们来谈谈信息收集这件小事

用Django编写后端任务流程



想了解更多请关注我们



 
点融黑帮 更多文章 AE能做的动效,都能在App中实现了? 监测数组变动的两种实现 React 中使用context实现数据穿越 帮助你发现问题核心本质的简易方法 Python3异步编程
猜您喜欢 【WorldQuant 101 Alphas】之#41 Use Kotlin for Money’s sake. 在一个千万级的数据库查寻中,如何提高查询效率? 坑系列 --- 高可用架构的银弹 【视频】►手机应用有猫腻 泄露用户隐私