浅谈现公司的Spring Cloud微服务框架

目录

  • 说在前面
  • 服务注册与发现
  • 服务网关及熔断
  • 配置中心
  • 消息中心、服务链路追踪
  • 小言

说在前面

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

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时则开启熔断器。

  • 具体的hystrix所欲配置讲解,请参考:https://www.cnblogs.com/li3807/p/7501427.html

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

关于超时,由于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
  • spring Cloud超时总结参考:http://www.itmuch.com/spring-cloud-sum/spring-cloud-timeout/

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

  • 当stripPrefix=true的时候 (http://127.0.0.1:8181/api/user/list -> http://192.168.1.100:8080/user/list)
  • 当stripPrefix=false的时候(http://127.0.0.1:8181/api/user/list -> http://192.168.1.100:8080/api/user/list)

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


配置中心

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

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有了广义上实质的了解。

原文地址:https://www.cnblogs.com/wangshiwen/p/10253656.html

时间: 2024-10-07 09:52:08

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

Spring Cloud微服务框架 实战企业级优惠券系统

第1章 课程介绍[终于等到你,快来认识我]本章中将对课程中涉及到的技术.工具.业务等进行简单介绍. 第2章 准备工作[工欲善其事,必先利其器]本章中将对课程中使用到的技术工具做介绍,包括Maven.MySQL.Redis.Kafka:会对它们的功能.安装.基本的使用方法进行介绍. 第3章 SpringBoot 开发框架[基础打不牢,学问攀不高]课程主体业务使用SpringCloud框架开发实现,但是SpringCloud基于SpringBoot实现.为便于更顺畅学习,本章中会对SpringBoo

简单Spring Cloud 微服务框架搭建

微服务是现在比较流行的技术,对于程序猿而言,了解并搭建一个基本的微服务框架是很有必要滴. 微服务包含的内容非常多,一般小伙伴们可以根据自己的需求不断添加各种组件.框架. 一般情况下,基本的微服务框架包含:框架:注册中心.负载均衡.声明式服务(feign).容错(hystrix).网关(权限)gateway 和 配置(resource) 注册中心:现在比较常用的有eureka.nacos 负载均衡:包括feign.ribbon等技术,相关对比可以参考另一位老哥的博客:<负载均衡之feign与rib

关于Spring Cloud微服务架构

微服务架构 Spring Cloud解决的第一个问题就是:服务与服务之间的解耦.很多公司在业务高速发展的时候,服务组件也会相应的不断增加.服务和服务之间有着复杂的相互调用关系,经常有服务A调用服务B,服务B调用服务C和服务D ...,随着服务化组件的不断增多,服务之间的调用关系成指数级别的增长,这样最容易导致的情况就是牵一发而动全身.经常出现由于某个服务更新而没有通知到其它服务,导致上线后惨案频发.这时候就应该进行服务治理,将服务之间的直接依赖转化为服务对服务中心的依赖.Spring Cloud

Spring Cloud微服务架构实现+Guava缓存+redis+数据库设计+微服务原理改造房产销售

Spring Cloud微服务架构实现+Guava缓存+redis+数据库设计+微服务原理改造房产销售 一.分布式服务框架的发展 1.1 第一代服务框架 代表:Dubbo(Java).Orleans(.Net)等 特点:和语言绑定紧密 1.2 第二代服务框架 代表:Spring Cloud等 现状:适合混合式开发(例如借助Steeltoe OSS可以让ASP.Net Core与Spring Cloud集成),正值当年 1.3 第三代服务框架 代表:Service Mesh(服务网格) => 例如

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

导读 我们知道在基于Spring Cloud的微服务体系中,各个微服务除了在内部提供服务外,有些服务接口还需要直接提供给客户端,如Andirod.IOS.H5等等. 而一个很尴尬的境地是,如果直接将提供外部接口的微服务暴露给公网,那么意味着为了增强这个微服务的安全性,需要做很多额外的安全性措施,如报文数字签名.加密等:而大部分场景下,微服务本身又是提供给内部其他微服务调用的,即便所有的微服务都会不同程度地直接面向App客户端提供公网服务,那么为了这确保这些微服务的安全性,涉及的微服务也都需要实现

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

Spring Cloud作为当下主流的微服务框架,可以让我们更简单快捷地实现微服务架构.Spring Cloud并没有重复制造轮子,它只是将目前各家公司开发的比较成熟.经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂.易部署和易维护的分布式系统开发工具包.Spring Cloud中各个组件在微服务架构中扮演的角色如下图所示,黑线表示注释说明,蓝线由A指向B,表示B从A处获取服务. Spring Cloud组成的

Spring cloud微服务安全实战完整教程

本文配套视频教程及资料获取:点击这里 Spring Cloud微服务安全实战 采用流行的微服务架构开发,应用程序访问安全将会面临更多更复杂的挑战,尤其是开发者最关心的三大问题:认证授权.可用性.可视化.本课程从简单的API安全入手,过渡到复杂的微服务场景,解决上述三大问题痛点,并结合实际给出相应解决方案.帮助大家形成对安全问题的系统性思考,实战开发一套可在中小公司落地的完整的安全方案. 学习目标: 技术要点: 环境参数: 本文配套视频教程及资料获取:点击这里 原文地址:https://www.c

Spring Cloud微服务Sentinel+Apollo限流、熔断实战

在Spring Cloud微服务体系中,由于限流熔断组件Hystrix开源版本不在维护,因此国内不少有类似需求的公司已经将眼光转向阿里开源的Sentinel框架.而以下要介绍的正是作者最近两个月的真实项目实践过程,这中间被不少网络Demo示例级别水文误导过,为了以正视听特将实践过程加以总结,希望能够帮到有类似需要的朋友! 一.Sentinel概述 在基于Spring Cloud构建的微服务体系中,服务之间的调用链路会随着系统的演进变得越来越长,这无疑会增加了整个系统的不可靠因素.在并发流量比较高

Spring Cloud微服务架构在互联网中应用

夜行侠老师录制的:Spring Cloud微服务架构在互联网中应用 由大象分享网出版:http://www.itjoin.org/course/detail/5934a58c0cf2159b39641f80夜行侠课程集合:http://www.xuetuwuyou.com/user/29 第1节.Springcloud介绍第2节.Eureka的使用第3节.Eureka集群第4节.restful请求第5节.restful请求负载均衡第6节.配置中心第7节.获取配置中心数据第8节.配置中心高可用第9