说在前面

本文偏小白,大佬慎入,若有错误或者质疑,欢迎留言提问,谢谢,祝大家新年快乐。

spring cloud

Spring Cloud 是将分布式系统中一系列基础框架/工具进行整合的框架。其中包含: 服务注册与发现、服务网关、熔断器、配置中心、消息中心、服务链路追踪等等 。这也是一个服务化架构的最小组成元素,有了这些基本的组成要素,就可以实现一个最简单的服务架构。

Spring Cloud 并没有重复造轮子,Spring Cloud只是依赖于Spring Boot屏蔽掉了各个框架复杂的配置。所有的组件就相当于Spring Cloud的插件,开发人员可以根据自己的需要自由结合使用。

有Spring Boot这个利器在,所有组件都可以轻松引入、便捷开发。也一定程度上降低了各组件的学习成本、调试成本、让开发人员可以轻松上手。


服务注册与发现

从最简单、最核心的问题出发,假设服务 A 要调用服务 B,会有什么问题?

服务在哪?(服务治理问题)怎么调用?(服务调用问题)

这两个是最核心的问题,也是任何微服务框架首要解决的两个问题。

为了解决第一个问题 Spring Cloud 提供了 Eureka、Zookeeper、Cloud Foundry、Consul 等服务治理框架的集成。它们的工作模式是将所有的微服务注册到一个 Server 上,然后通过心跳进行服务健康监测。这样服务 A 调用 B 时可以从注册中心拿到可用的服务 B 的地址、端口进行调用。

我公司就是使用的是Eureka

Eureka由两个组件组成:Eureka服务器和Eureka客户端。

先找到Eureka服务器,也就是我们项目的注册中心

EurekaApplication.java

@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaserverApplication.class, args);
}
}
  • 注解 @EnableEurekaServer 表示该 Spring Boot 应用是一个注册中心。Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。

配置文件 bootstrap.yml

server:
port: 8700 eureka:
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
server:
enableSelfPreservation: false
  • eureka.client.registerWithEureka: false 和fetchRegistry: false 来表明自己是一个 eureka server。
  • enableSelfPreservation: false表示在此eureka服务器中关闭自我保护模式,所谓自我保护模式是指,出现网络分区、eureka在短时间内丢失过多客户端时,会进入自我保护模式,即一个服务长时间没有发送心跳,eureka也不会将其删除。默认为true

以上是注册中心EurekaApplication.java,而所有单独开发的SB项目,就是client

而我在查看每个项目的配置文件时,发现并没有找到eureka.client.serviceUrl.defaultZone:...这样的配置

于是猜想可能在启动脚本中添加此参数,果不其然,找到服务器上的启动脚本:

-Deureka.client.serviceUrl.defaultZone=http://**.**.**.***:8700/eureka

这就是其作为eureka客户端的证据(真的很想吐槽为什么要写在启动脚本中)

第二个服务调用有人可能认为就是一个简单的 HTTP 或者 RPC 调用,不是什么问题。但是在分布式的场景下,服务调用需要考虑的因素会更多。比如一个服务有多个实例,此时请求进来了交给谁处理,请求的负载怎么平衡到各个实例,都是比较棘手的问题。Spring Cloud 提供了两种服务调用的方式:一种是 Ribbon + restTemplate,另一种是 Feign。

其中 Ribbon 是基于 HTTP 和 TCP 客户端的负载均衡器,restTemplate 是 Spring 提供的 Restful 远程调用的模板,两者结合就可以达到远程调用的负载均衡。

而 Feign 是一个更加声明式的 HTTP 客户端,开发者可以像调用本地方法一样调用它,完全感觉不到是远程调用,结合 Ribbon 也可以做负载均衡。


服务网关及熔断

微服务中的服务很多,直接暴露给用户一是不安全,二是对用户不友好。因此在微服务和面向服务的架构中,通常会有一个路由网关的角色,来负责路由转发和过滤。对应到 Spring Cloud 中有 Zuul 和 Gateway 两个组件可用。

据查看我公司只使用zuul做路由转发用

Zuul是Netflix开源的服务网关/API网关,提供动态路由、监控、弹性、安全性等功能。

ZuulApplication.java


@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulProxy
@RestController
public class ZuulApplication { public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
} /**
* 跨域许可设置
*/
@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource= new UrlBasedCorsConfigurationSource();
final CorsConfiguration corsConfig = new CorsConfiguration();
corsConfig.setAllowCredentials(true);
corsConfig.addAllowedOrigin("*");
corsConfig.addAllowedHeader("*");
corsConfig.addAllowedMethod("OPTIONS");
corsConfig.addAllowedMethod("HEAD");
corsConfig.addAllowedMethod("GET");
corsConfig.addAllowedMethod("PUT");
corsConfig.addAllowedMethod("POST");
corsConfig.addAllowedMethod("DELETE");
corsConfig.addAllowedMethod("PATCH");
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfig);
return new CorsFilter(urlBasedCorsConfigurationSource);
} @RequestMapping(value = "/")
public String heartbeat() {
return "";
}
}
  • 在zuul服务下添加一个corsFilter实现跨域

bootstrap.yml

server:
port: 8000 spring:
application:
name: zuul
cloud:
config:
discovery:
enabled: true
serviceId: CONFIG eureka:
instance:
preferIpAddress: true
leaseRenewalIntervalInSeconds: 1
leaseExpirationDurationInSeconds: 2
nonSecurePort: ${server.port}
client:
serviceUrl:
defaultZone: http://${eureka.host}:${eureka.port}/eureka/

application.yml


spring:
profiles:
active: eureka logging:
config: classpath:logback-error.xml server:
tomcat:
max-threads: 100 hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 60000 ribbon:
ConnectTimeout: 3000
ReadTimeout: 60000 hystrix:
command:
default:
execution:
timeout:
enabled: false
threadpool:
default:
coreSize: 50
maxQueueSize: 100
queueSizeRejectionThreshold: 100 javamelody:
login_name: viroyal
login_pwd: viroyal2017 ---
spring:
profiles: eureka zuul:
routes:
account:
path: /account/**
serviceId: USERMANAGER
stripPrefix: false about:
path: /about/**
serviceId: ABOUT
stripPrefix: false app:
path: /app/**
serviceId: CAMPUSCMS
stripPrefix: false res:
path: /res/**
serviceId: CMS
stripPrefix: false device:
path: /device/**
serviceId: CAMPUS-DEVICE
stripPrefix: false

hystrix就是熔断器

熔断器的原理很简单,如同电力过载保护器。它可以实现快速失败,如果它在一段时间内侦测到许多类似的错误,会强迫其以后的多个调用快速失败,不再访问远程服务器,从而防止应用程序不断地尝试执行可能会失败的操作,使得应用程序继续执行而不用等待修正错误,或者浪费CPU时间去等到长时间的超时产生。熔断器也可以使应用程序能够诊断错误是否已经修正,如果已经修正,应用程序会再次尝试调用操作。

hystrix默认是打开的,所以此配置中未进行过多设置,只设置了hystrix.threadpool.default.threadPool的相关属性,这里说一下queueSizeRejectionThreshold:100,是为队列设置拒绝阈值,当线程池队列到达100时则开启熔断器。

记住:熔断器就是保护服务高可用的最后一道防线。

关于超时,由于zuul本身就集合了hystrix和ribbon,zuul 中配置超时时间,据官方的介绍,分两种情况:

  • 用 serviceId 进行路由时,使用 ribbon.ReadTimeout 和 ribbon.SocketTimeout 设置

  • 用指定 url 进行路由时,使用 zuul.host.connect-timeout-millis 和 zuul.host.socket-timeout-millis 设置

    此配置文件是用 serviceId 进行路由的(根据请求path,分发到对应的serviceId上),所以未设置zuul超时,且hystrix.XX.timeout.enabled设置成了false,关掉了hystrix的超时设置(实际上,如果同时配置了 Ribbon 和 Hystrix 的超时时间,则以最小的为准)。所以,此项目只开启了ribbon的超时设置。像此例中的ribbon的超时是作用全局的。

直接使用 serviceId作为前缀,可以区分不同客户端下的配置,类似如下:

USERMANAGER:
ribbon:
ConnectTimeout: 5000
ReadTimeout: 5000

关于zuul.routes.XXX.stripPrefix的设置,当zuul.routes.XXX.path=/api/**时,作用如下例子:

路由网关接收了所有的用户请求,有着很高的负载,因此它通常是一个集群。用户的请求会先经过一层负载均衡被发到路由网关。


配置中心

在微服务应用中,服务数量巨多,而每个服务不同环境都有着不同的配置,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件。需要注意的是此处的配置与注册中心注册的配置信息是两个概念,此处的配置是服务本身的一些配置信息。

ConfigApplication.java

@SpringBootApplication
@EnableConfigServer
@EnableEurekaClient
public class ConfigApplication { public static void main(String[] args) {
SpringApplication.run(ConfigApplication.class, args);
}
}
  • 本身也是EurekaClient,使用@EnableConfigServer成为配置中心,提供配置服务

bootstraop.yml

#comment can't have chinese
#using outer net interface is convenient for local webapp start and debug
server:
port: 8888 spring:
application:
name: config
profiles:
active: native
cloud:
config:
server:
native:
searchLocations:
file:/var/configs
inetutils:
ignoredInterfaces:
- eth0 eureka:
instance:
preferIpAddress: true
leaseRenewalIntervalInSeconds: 1
leaseExpirationDurationInSeconds: 2
nonSecurePort: ${server.port}
client:
serviceUrl:
defaultZone: http://${eureka.host}:${eureka.port}/eureka/

这里 spring.appliction.name为config

我看了一下其他服务的bootstrap.yml中有两项配置

sprong.cloud.config.discovery.enabled: true
sprong.cloud.config.discovery.serviceId: CONFIG

第一个作用是:使用注册中心找寻config-server的地址

第二个作用是:配置中心在注册中心的applicationName

通过找到配置中心 发现 配置文件存储在/var/configs路径下,且读取文件名和本服务serviceId相同的文件中的配置


消息中心、服务链路追踪

据我查看,我公司并未实现消息中心和服务链路追踪,这里我就总结一下他们的作用吧

消息中心

在微服务架构的系统中,我们通常会使用轻量级的消息代理来构建一个共用的消息主题让系统中所有微服务实例都能连接上来,由于该主题中产生的消息会被所有实例监听和消费,所以我们称它为消息总线。在总线上的各个实例都可以方便地广播一些需要让其他连接在该主题上的实例都知道的消息,例如配置信息的变更或者其他一些管理操作等。

由于消息总线在微服务架构系统的广泛使用,所以它同配置中心一样,几乎是微服务架构中的必备组件。spring cloud作为微服务架构综合性的解决方案,对此自然也有自己的实现,这就是spring cloud bus。通过spring cloud bus,可以非常容易的搭建起消息总线,同时实现了一些消息总线中的常用功能,比如配合spring cloud config实现微服务应用配置信息的动态更新等。

服务链路追踪

微服务架构是一个分布式架构,它按业务划分服务单元,一个分布式系统往往有很多个服务单元。由于服务单元数量众多,业务的复杂性,如果出现了错误和异常,很难去定位。主要体现在,一个请求可能需要调用很多个服务,而内部服务的调用复杂性,决定了问题难以定位。所以微服务架构中,必须实现分布式链路追踪,去跟进一个请求到底有哪些服务参与,参与的顺序又是怎样的,从而达到每个请求的步骤清晰可见,出了问题,很快定位。

在微服务系统中,一个来自用户的请求,请求先达到前端A(如前端界面),然后通过远程调用,达到系统的中间件B、C(如负载均衡、网关等),最后达到后端服务D、E,后端经过一系列的业务逻辑计算最后将数据返回给用户。对于这样一个请求,经历了这么多个服务,怎么样将它的请求过程的数据记录下来呢?这就需要用到服务链路追踪。

我公司业务体系不大,所以就为完成此项集成吧。


小言

以上来看,可以说这是最精简的spring cloud分布式系统的构成了,不谈具体技术实现如何,大体的架构还是有的,也让我对spring cloud有了广义上实质的了解。

浅谈现公司的Spring Cloud微服务框架的更多相关文章

  1. 简单Spring Cloud 微服务框架搭建

    微服务是现在比较流行的技术,对于程序猿而言,了解并搭建一个基本的微服务框架是很有必要滴. 微服务包含的内容非常多,一般小伙伴们可以根据自己的需求不断添加各种组件.框架. 一般情况下,基本的微服务框架包 ...

  2. Spring Cloud微服务框架介绍

    Spring Cloud为开发人员提供了一整套的快速构建分布式应用的工具,入服务注册.服务发现.熔断.负载均衡.路由等,提供了开箱即用的各种依赖以及良好的可扩展机制. 目前在Spring Cloud的 ...

  3. spring cloud 微服务介绍(转)

    一.理解微服务   我们通过软件架构演进过程来理解什么是微服务,软件架构的发展经历了从单体结构.垂直架构.SOA架构到微服务架构的过程. 1. 单体架构 1.1 特点(1)所有的功能集成在一个项目工程 ...

  4. 一张图了解Spring Cloud微服务架构

    Spring Cloud作为当下主流的微服务框架,可以让我们更简单快捷地实现微服务架构.Spring Cloud并没有重复制造轮子,它只是将目前各家公司开发的比较成熟.经得起实际考验的服务框架组合起来 ...

  5. Spring Cloud微服务中网关服务是如何实现的?(Zuul篇)

    导读 我们知道在基于Spring Cloud的微服务体系中,各个微服务除了在内部提供服务外,有些服务接口还需要直接提供给客户端,如Andirod.IOS.H5等等. 而一个很尴尬的境地是,如果直接将提 ...

  6. Spring Cloud微服务下的权限架构调研

    随着微服务架构的流行,系统架构调整,项目权限系统模块开发提上日程,需要对权限架构进行设计以及技术选型.所以这段时间看了下相关的资料,做了几个对比选择. 一.架构图 初步设想的架构如下,结构很简单:eu ...

  7. Dubbo和Spring Cloud微服务架构比较

    Dubbo 出生于阿里系,是阿里巴巴服务化治理的核心框架,并被广泛应用于中国各互联网公司:只需要通过 Spring 配置的方式即可完成服务化,对于应用无入侵,设计的目的还是服务于自身的业务为主. 微服 ...

  8. Dubbo 和 Spring Cloud微服务架构 比较及相关差异

    你真的了解微服务架构吗?听听八年阿里架构师怎样讲述Dubbo和Spring Cloud微服务架构. 微服务架构是互联网很热门的话题,是互联网技术发展的必然结果.它提倡将单一应用程序划分成一组小的服务, ...

  9. 全链路实践Spring Cloud 微服务架构

    Spring Cloud 微服务架构全链路实践Spring Cloud 微服务架构全链路实践 阅读目录: 网关请求流程 Eureka 服务治理 Config 配置中心 Hystrix 监控 服务调用链 ...

随机推荐

  1. Schlumberger Petrel 2016.3 地震解释 油藏模拟

    Schlumberger Petrel 2016.3 地震解释 油藏模拟世界上顶尖的三维地质建模软件,软件为用户提供的工具可以用于地震解释.地质建模.油藏数 值模拟等方面的使用,清晰的地质模型可以描述 ...

  2. centOS 7 设置DNS方法 同之前版本不同

    在CentOS 7下,手工设置 /etc/resolv.conf 里的DNS,过了一会,发现被系统重新覆盖或者清除了.和CentOS 6下的设置DNS方法不同,有几种方式: 1.使用全新的命令行工具 ...

  3. 外贸建站之图片预加载JS代码分享

    外贸建站之图片预加载JS代码分享 function preloadimg() { setTimeout(function() { new Image().src = "images/2017 ...

  4. JDK8 HashMap--treeify()树形化方法

    /*创建红黑树*/ final void treeify(Node<K,V>[] tab) { TreeNode<K,V> root = null;// 定义红黑树根节点roo ...

  5. it入门之:学会使用Git 分布式版本控制工具

    环境:window 工具:git & TortoiseGit 下载安装以及配置环境变量 :略略略 创建Github账户:登录https://github.com/用自己的常用邮箱创建账户,用来 ...

  6. 【JavaScript】学习中遇到的一些问题

    一.JavaScript中没法直接比较两个object和array是否相等

  7. spring boot jpa 整合

    1,Eclipse JPA Tool配置 https://www.cnblogs.com/wgslucky/p/10109300.html 2,项目地址 https://gitee.com/wgslu ...

  8. react知识总结

    用于构建用户界面的 JavaScript 库 JSX语法 style let style = { color: 'r'+'ed', fontSize: '30px' } let jsx = <d ...

  9. php读取和导出Excel文件

    require 'vendor/PHPExcel/PHPExcel.php';require 'vendor/PHPExcel/PHPExcel/IOFactory.php'; public func ...

  10. 利用BLEU进行机器翻译检测(Python-NLTK-BLEU评分方法)

    双语评估替换分数(简称BLEU)是一种对生成语句进行评估的指标.完美匹配的得分为1.0,而完全不匹配则得分为0.0.这种评分标准是为了评估自动机器翻译系统的预测结果而开发的,具备了以下一些优点: 计算 ...