对SpringCloud微服务架构的理解

微服务

微服务 将all in one的项目拆分,可以按业务拆分成独立的模块等,降低模块与模块之间的耦合性,每个微服务还能有自己独立的数据库。每个微服务在自己独立的进程中运行,不会互相干扰。异构。支持不同语言、不同类型的数据库

集群:一组集成的计算机软件连接起来

  • 高性能:多台计算机完成同一工作,分摊压力
  • 高可用:多台计算机工作内容、过程一致,可以相互顶替

分布式:一组计算机通过网络通信协调它们之间的行为。组件之间交互来实现一个共同的目标。

  • 低耦合:模块间独立,易扩展,提高资源利用率
  • 高吞吐:功能拆分,分散到不同的模块执行

集群和分布式不冲突。分布式的某个需要扩展的模块可以使用集群。

CAP:强一致性C、极致可用性A、分区容错性P。这三个不能同时满足。

微服务的特点:

  • 一系列微小的服务共同组成
  • 单独部署,跑在自己的进程里
  • 每个服务是独立的业务开发
  • 分布式的管理

不适合微服务的:

  • 系统中包含很多很多强事务场景的
  • 业务相对稳定,迭代周期长
  • 访问压力不大,可用性不高

服务拆分的方法:

  • 如何拆“功能:
    • 单一职责,松耦合、高内聚
    • 关注点分离
      • 按职责
      • 按通用性
      • 按粒度级别
  • 服务和数据的关系
    • 先考虑业务功能,再考虑数据
    • 无状态服务(数据不被服务依赖)

微服务架构

这是一种新型、轻量的架构,利用REST API来保持微服务之间的通信。与dubbo不同的是,dubbo用的是rpc通信。

维度:开发、配置与管理、消息队列、服务接口调用、治理、注册与发现、负载均衡、监控。。。。

SpringCloud微服务架构:

image.png

这里面的常用组件:

  • 服务治理:Spring Cloud Eureka
  • 负载均衡:Spring Cloud Ribbon
  • 熔断限流:Spring Cloud Hystrix
  • 服务调用:Spirng Cloud Feign
  • 网关服务:Spring Cloud Zuul/Gateway
  • 配置中心:Spring Cloud Config
  • 消息总线:Spring Cloud Bus
  • 消息驱动:Spring Cloud Stream
  • 服务追踪:Spring Cloud Sleuth

Spring Cloud网关 (Zuul/GateWay)

应用场景:统一外部入口、请求路由、认证授权、请求限流、请求日志和监控

SpringCloud Zuul功能:①服务路由,②自定义过滤器,需要继承ZuulFilter并重写方法。下面的Autorizefilter模拟身份验证功能,它继承了ZuulFilter抽象类,重写了filterType filterOrder shouldFilter run方法

@Component
public class Authorizefilter extends ZuulFilter {
    private static final Logger logger = LoggerFactory.getLogger(Authorizefilter.class);
    private static String access_token;

    public Authorizefilter(){
        access_token = UUID.randomUUID().toString();
        logger.info(access_token+"-==========----------");
    }
    /**
     * 外部请求-> zuul-(pre) ->选择路由的服务-(routing) ->请求服务-(post) ->zuul
     * pre:在请求路由之前执行
     * routing:在请求路由之后执行
     * post:在请求路由到服务之后执行
     * error:在其他阶段发生错误的时候执行
     * @return 过滤器的类型是什么
     */
    @Override
    public String filterType() {
        return "pre";
    }

    /**
     *
     * @return 过滤器执行的顺序
     */
    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     *
     * @return 是否执行过滤器
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     * 具体逻辑
     * @return Some arbitrary artifact may be returned. Current implementation ignores it.
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        String access_token = request.getParameter("access_token");
//        模拟授权
        if (Objects.equals(access_token,Authorizefilter.access_token)){
            requestContext.setResponseStatusCode(HttpStatus.OK.value());
            requestContext.setResponseBody("Authorize");
            requestContext.setSendZuulResponse(false);
        }else {
            requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
            requestContext.setResponseBody(HttpStatus.UNAUTHORIZED.getReasonPhrase());
            requestContext.setSendZuulResponse(false);
        }
        return null;
    }
}

Spring Cloud GateWay出现是由于Zuul 在2版本后不维护了,它是zuul的扩展。

SpringCloud服务治理 (Eureka/Consul)

  • Eureka Client:服务注册
  • Eureka Server:服务发现

Eureka:保证了高可用性A

  • 服务注册快,不需要等待注册信息复制到其他节点,也不保证复制成功
  • 当注册信息不相同时,每个Eureka节点依然能够正常对外提供服务

Consul:保证强一致性C

  • 服务注册相比Eureka会稍慢,Consul要求过半的节点都写入成功
  • Leader挂掉时,在有新的Leader之前整个Consul不可用

对Eureka Server端的application使用@EnableEurekaServer注解表示加载EurekaServer的配置;

在客户端Client,对application使用@EnableDiscoveryClient注解表示加载EnableDiscoveryClientImportSelector的配置,用于被Service发现

服务发现的两种方式:客户端发现(Eureka),服务器发现(Nginx、Zookeeper、Kubernetes)

SpringCloud服务调用(Feign)

  • RestTemplate 利用它的public T getForObject(String url, Class responseType, Object... uriVariables) throws RestClientException方法 获取url地址对应接口的返回对象,后面的uriVariables是url中的参数;url中的ip可以为通信服务的application name
  • Feign
    • 需要在Application上添加@EnableFeignClients
    • 自定义一个接口,添加@FeignClient(name = "application name")注解,并且写出想要使用服务的接口

Feign 采用了基于注解的接口,是声明式REST客户端(虽然在他的接口中看不到http请求)

SpringCloud 配置中心(Config)

为啥使用配置中心?

当把配置文件都放在项目包下,不方便之后的维护;需要测试时,对配置文件修改之后,不方便另外的人员维护;配置内容中数据库的账号密码不能随意暴露给开发者;更新配置项目需要重启。

统一配置中心?

  • config-server 从远端git pull下来放在本地git;如果远端git挂掉,可以使用本地git

如何配置?

  • 配置Config的Server端

    1. 配置pom文件,加入spring-cloud-config-server依赖和spring-cloud-starter-netflix-eureka-client依赖

    2. 给Application文件添加@EnableConfigServer和@EnableDiscoveryClient(将它注册)

    3. 添加yml配置,下面的配置中basedir的目录是远程的配置拉下来的所在文件夹

      spring:
        application:
          name: config
        cloud:
          config:
            server:
              git:
                uri: https://gitee.com/luotianhao25182/config
                username: 18235190623
                password: iamlth0539cro
                basedir: F://config
      eureka:
        client:
          service-url:
            defaultZone: http://localhost:8761/eureka/
      
    4. 远端的配置文件的命名要对应它的application name。在配置服务器端使用url访问加上如/{name}-{profiles}.yml或/{label}/{name}-{profiles}.yml来访问远端的配置文件。

  • 配置config的客户端

    1. 给pom添加spring-cloud-config-client依赖

    2. 给Application添加@EnableDiscoveryClient注解,将服务客户端注册

    3. 将原来的application.yml改名为bootstrap.yml,并添加如下内容。其中的enabled表示需要从配置服务端拿配置,service-id的内容表示的是配置服务中心的application name

      spring:
        application:
          name: client
        cloud:
          config:
            discovery:
              enabled: true
              service-id: CONFIG
      

配置服务中心可以看作: 远端git仓库——配置中心服务端——配置客户端

在远端git仓库中,最好是将一个服务共有的配置提取出来为 如client.yml,再将不同配置放入如client-dev.yml等中。为什么要这样做?因为配置客户端会将远端的带client命名的所有yml拉下来并且合并起来,所以如果两个配置文件一样,你只改了其中一个文件是等于无效的。

SpringCloud配置中心配置同步

当我们在远端git仓库上修改了配置文件之后,其实我们的配置服务端并没有做出响应,那么也就没有说把新的配置文件传给下面的配置客户端,我们只能通过重启配置服务器来同步。但是这样做显得过于不便,现在可以使用Bus这个组件来实现配置中心配置同步。

image.png

你可能感兴趣的:(对SpringCloud微服务架构的理解)