• 微服务架构笔记


    经验

    梳理陌生微服务工程的组件架构

    分析pom.xml的依赖包组件:pom文件查看必备的微服务组件。

    简介

    SpringCloud(多种框架组件技术集合的总框架)笔记
    传统单体架构VS微服务分布式架构
    单体架构特点?

    • 简单方便,高度耦合,扩展性差,适合小型项目。例如:学生管理系统

    分布式架构特点?

    • 松耦合,扩展性好,但架构复杂,难度大。适合大型互联网项目,例如:京东、淘宝

    微服务:一种良好的分布式架构方案

    • 优点: 拆分粒度更小、服务更独立、耦合度更低
    • 缺点:架构非常复杂,运维、监控、部署难度提高

    在这里插入图片描述
    在这里插入图片描述
    微服务是一种经过良好架构设计的分布式架构方案,微服务架构特征:

    • 单一职责:微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责,避免重复业务开发
    • 面向服务:微服务对外暴露业务接口
    • 自治:团队独立、技术独立、数据独立、部署独立
    • 隔离性强:服务调用做好隔离、容错、降级,避免出现级联问题

    在这里插入图片描述

    微服务架构

    先是拆分为微服务,然后注册每个微服务,接着配置微服务之间的调用关系,最后管理微服务之间的通信。

    微服务技术栈必备组件:

    1、拆分为微服务集群的框架
    spring boot构建平台,spring cloud搭建微服务。

    微服务这种方案需要技术框架来落地,全球的互联网公司都在积极尝试自己的微服务落地技术。
    在国内最知名的就是SpringCloud和阿里巴巴Dubbo
    SpringCloud是目前国内使用最广泛的微服务框架

    2、注册中心:(解决去哪里找微服务以及微服务功能,例:Nacos)

    • 登记注册微服务的信息:IP:PORT地址,功能等

    3、配置中心:(配置服务消费者和提供者:Feign,HSF等)

    • 配置管理微服务。

    4、消息队列

    • 暂存消息实现微服务之间异步通信,因为HTTP实时可能处理不过来。

    5、服务网关:(例:Nginx,GateWay)

    • 请求路由,负载均衡到不同IP:PORT的微服务。

    在这里插入图片描述

    完整的微服务技术栈
    在这里插入图片描述
    在这里插入图片描述

    微服务方案对比

    SpringCloudAlibaba兼容前两种方案
    在这里插入图片描述
    企业需求(实际应用)
    在这里插入图片描述

    SpringCloud

    spring boot构建平台,spring cloud搭建微服务。
    在这里插入图片描述

    注册中心(Eureka和Nacos)

    解决去哪里找微服务以及微服务功能

    • 登记注册微服务的信息:IP:PORT地址,功能等

    Eureka

    说明架构

    提供者和消费者
    服务调用关系

    • 服务提供者:暴露接口给其它微服务调用
    • 服务消费者:调用其它微服务提供的接口
    • 提供者与消费者角色其实是相对的一个服务可以同时是服务提供者和服务消费者

    Eureka作用
    在Eureka架构中,微服务角色有两类

    EurekaServer:服务端,注册中心

    • 记录服务信息
    • 心跳监控

    EurekaClient:客户端

    • Provider:服务提供者,例如案例中的 user-service
      注册自己的信息到EurekaServer
      每隔30秒向EurekaServer发送心跳
    • consumer:服务消费者,例如案例中的 order-service
      根据服务名称从EurekaServer拉取服务列表
      基于服务列表做负载均衡,选中一个微服务后发起远程调用

    总结
    消费者该如何获取服务提供者具体信息?

    • 服务提供者启动时向eureka注册自己的信息
    • eureka保存这些信息
    • 消费者根据服务名称向eureka拉取提供者信息

    如果有多个服务提供者,消费者该如何选择?

    • 服务消费者利用负载均衡算法,从服务列表中挑选一个

    消费者如何感知服务提供者健康状态?

    • 服务提供者会每隔30秒向EurekaServer发送心跳请求,报告健康状态
    • eureka会更新记录服务列表信息,心跳不正常会被剔除
    • 消费者就可以拉取到最新的信息
    1、EurekaServer服务搭建步骤

    搭建EurekaServer微服务步骤如下:

    1. 创建maven项目,引入spring-cloud-starter-netflix-eureka-server的依赖
    
    	org.springframework.cloud
    	spring-cloud-starter-netflix-eureka-server
    
    
    • 1
    • 2
    • 3
    • 4
    1. 编写启动类,添加@EnableEurekaServer注解
    2. 添加application.yml文件,编写下面的配置:
    server:
    	port: 10086
    spring:
    	application: 
    	 name: eurekaserver
    eureka:
    	client:
    	  service-url:
    	  	defaultZone: http://127.0.0.1:10086/eureka/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    eureka会注册到自身。
    在这里插入图片描述

    在这里插入图片描述

    2、客户端服务发现注册

    将user-service服务注册到EurekaServer步骤如下:

    • 引入Eureka客户端依赖
      在user-service项目引入spring-cloud-starter-netflix-eureka-client的依赖
    
     	org.springframework.cloud
     	spring-cloud-starter-netflix-eureka-client
     
    
    • 1
    • 2
    • 3
    • 4
    • 在application.yml文件,编写下面的配置:
    spring:
      application:
        name: userservice
    eureka:
      client:
        service-url:
          defaultZone: http://127.0.0.1:10086/eureka/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    3、服务拉取调用

    在order-service完成服务拉取
    服务拉取是基于服务名称获取服务列表,然后在对服务列表做负载均衡

    • 修改OrderService的代码,修改访问的url路径,用服务名代替ip、端口:
    String url = "http://userservice/user/" + order.getUserId();
    
    • 1
    • 在order-service项目的启动类OrderApplication中的RestTemplate添加负载均衡注解:
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {    
    	return new RestTemplate();
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    Ribbon负载均衡(@LoadBalanced)

    注意:ribbon组件不用了 现在用springcloud LoadBalancer
    发起请求方添加LoadBalanced注解则可以实现负载均衡。
    1、利用拦截器拦截请求获取请求的服务名称
    2、根据名称获取注册的服务列表
    3、从列表中根据规则(如随机、轮询等)选取一个服务
    4、根据选取的服务执行请求
    在这里插入图片描述

    总结:

    Eureka服务注册以注册的服务名为单位:一个服务名可以注册多个微服务实例为Ribbon负载均衡提供条件。

    一个服务名来注册多个实例来实现负载均衡。这个概念在分布式系统中被称为服务发现和服务注册。

    Eureka服务调用也是以注册的服务名代表IP:PORT,类似域名代表IP:PORT。

    Nacos

    Nacos是阿里巴巴的产品,现在是SpringCloud中的一个组件。相比Eureka功能更加丰富,在国内受欢迎程度较高。
    默认端口8848
    临时实例可以手动开关,Nacos动态剔除已关闭临时实例的注册信息,非临时实例反之,Nacos不动态剔除反而报错并持续监测实例状态是否复活。
    在这里插入图片描述

    Nacos服务注册或发现
    • 父项目引入nacos.discovery依赖
    • 客户端微服务配置nacos地址spring.cloud.nacos.server-addr

    1、在cloud-demo父工程中添加spring-cloud-alilbaba的管理依赖:

    
        com.alibaba.cloud
        spring-cloud-alibaba-dependencies
        2.2.6.RELEASE
        pom
        import
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2、注释掉order-service和user-service中原有的eureka依赖。
    3、微服务添加nacos的客户端依赖:

    
    
        com.alibaba.cloud
        spring-cloud-starter-alibaba-nacos-discovery
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    4、修改user-service&order-service中的application.yml文件,注释eureka地址,添加nacos地址:

    spring:
    	cloud:
    		nacos:
    			server-addr: localhost:18808#nacos服务端地址
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    5、启动并测试:
    在这里插入图片描述

    Nacos集群配置(异地容灾)

    同一服务名的多个实例,分集群存放在异地。

    Nacos服务分级存储模型

    • 一级是服务,例如userservice
    • 二级是集群,例如杭州或上海
    • 三级是实例,例如杭州机房的某台部署了userservice实例的服务器

    如何设置实例的集群属性

    • 修改application.yml文件,添加spring.cloud.nacos.discovery.cluster-name属性即可

    配置步骤:
    apllication.yml

      cloud:
        nacos:
          server-addr: localhost:18808 #nacos服务端地址
          discovery:
            cluster-name: HZ # 配置集群名称,也就是机房位置,例如:HZ,杭州
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    在这里插入图片描述

    NacosRule负载均衡(基于Ribbon)

    NacosRule负载均衡策略

    • 优先选择同集群服务实例列表
    • 本地集群找不到提供者,才去其它集群寻找,并且会报警告
    • 确定了可用实例列表后,再采用随机负载均衡挑选实例

    1、修改order-service中的application.yml,设置集群为HZ:

    spring:
      cloud:
          nacos:
                server-addr: localhost:8848 # nacos 服务端地址
                      discovery:
                              cluster-name: HZ # 配置集群名称,也就是机房位置
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2、然后在order-service中设置负载均衡的IRule为NacosRule,这个规则优先会寻找与自己同集群的服务:

    userservice:
      ribbon:
          NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则 
    
    • 1
    • 2
    • 3
    Nacos权重负载均衡

    借助Nacos自身可视化页面调整权重
    实例的权重控制

    • Nacos控制台可以设置实例的权重值,0~1之间
    • 同集群内的多个实例,权重越高被访问的频率越高
    • 权重设置为0则完全不会被访问

    实际部署中会出现这样的场景: 服务器设备性能有差异,部分实例所在机器性能较好,另一些较差,我们希望性能好的机器承担更多的用户请求
    Nacos提供了权重配置来控制访问频率,权重越大则访问频率越高

    1、在Nacos控制台可以设置实例的权重值,首先选中实例后面的编辑按钮
    在这里插入图片描述
    2、将权重设置为0.1,测试可以发现8081被访问到的频率大大降低
    在这里插入图片描述

    Nacos环境隔离

    Nacos环境隔离

    • 每个namespace都有唯一id
    • 服务设置namespace时要写id而不是名称
    • 不同namespace下的服务互相不可见

    Namespace命名空间包含Group集群,Group集群包含Service实例.
    集群包含服务,服务包含集群 集群包含实例
    在这里插入图片描述
    1、在Nacos控制台可以创建namespace,用来隔离不同环境
    在这里插入图片描述
    2、然后填写一个新的命名空间信息:
    在这里插入图片描述
    3、保存后会在控制台看到这个命名空间的id:
    在这里插入图片描述
    4、修改order-service的application.yml,添加namespace:

    spring:
      datasource:
          url: jdbc:mysql://localhost:3306/heima?useSSL=false
              username: root
                  password: 123
                      driver-class-name: com.mysql.jdbc.Driver 
                        cloud:
                            nacos:
                                  server-addr: localhost:8848
                                        discovery:
                                                cluster-name: SH # 上海
                                                        namespace: 492a7d5d-237b-46a1-a99a-fa8e98e4b0f9 # 命名空间,填ID
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    5、重启order-service后,再来查看控制台:
    在这里插入图片描述
    6、此时访问order-service,因为namespace不同,会导致找不到userservice,控制台会报错:
    在这里插入图片描述

    Nacos对比Eureka

    Nacos与eureka的共同点

    • 都支持服务注册和服务拉取
    • 都支持服务提供者心跳方式做健康检测

    Nacos与Eureka的区别

    • Nacos支持服务端主动检测提供者状态:临时实例采用心跳模式,非临时实例采用主动检测模式
    • 临时实例心跳不正常会被剔除,非临时实例则不会被剔除
    • Nacos支持服务列表变更的消息推送模式,服务列表更新更及时
    • Nacos集群默认采用AP方式,当集群中存在非临时实例时,采用CP模式;Eureka采用AP方式
      A:高可用 C:一致性 P:分区容错性

    总结

    注册中心注册微服务流程
    1、配置注册中心服务或父工程。
    2、客户端微服务导入注册中心客户端依赖,配置文件配置包含注册中心IP:PORT==登记微服务IP:PORT。
    负载均衡的物理前提
    一个服务名来注册多个实例来实现负载均衡。这个概念在分布式系统中被称为服务发现和服务注册。
    在这里插入图片描述

    远程调用

    微服务之间的远程调用方式

    1. 模拟前端http请求。

    微服务调用方式

    • 基于RestTemplate发起的http请求实现远程调用
    • http请求做远程调用是与语言无关的调用,只要知道对方的ip、端口、接口路径、请求参数即可。

    启动类

    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.client.RestTemplate;
    
    @MapperScan("cn.itcast.order.mapper")
    @SpringBootApplication
    public class OrderApplication {
        public static void main(String[] args) {
            SpringApplication.run(OrderApplication.class, args);
        }
    
        /*创建restTemplate*/
        @Bean
        @LoadBalanced
        public RestTemplate restTemplate(){
            return new RestTemplate();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    service调用代码

    package cn.itcast.order.service;
    
    import cn.itcast.order.mapper.OrderMapper;
    import cn.itcast.order.pojo.Order;
    import cn.itcast.order.pojo.User;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.web.client.RestTemplate;
    
    import java.awt.geom.RectangularShape;
    
    @Service
    public class OrderService {
    
        @Autowired
        private OrderMapper orderMapper;
        @Autowired
        private RestTemplate restTemplate;
        public Order queryOrderById(Long orderId) {
            // 1.查询订单
            Order order = orderMapper.findById(orderId);
            String url="http://userservice/user/"+order.getUserId();
            User user=restTemplate.getForObject(url,User.class);
            order.setUser(user);
            // 4.返回
            return order;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    在这里插入图片描述

    BUG

    yml文件键值对书写规范

    key键冒号后需要带个空格与value间隔
    原因:如果value是url则会带:,通过有没有空格来区分key和value。
    标准格式

    key: value

    图中这种key键泛白的就是格式错误。
    在这里插入图片描述
    正确格式
    在这里插入图片描述

  • 相关阅读:
    金色传说:SAP-ABAP- PM工单:IW32组件增强
    Mybatis-Plus 条件构造器
    电脑篇——Windows/Ubuntu系统一些有趣的终端命令
    2407. 最长递增子序列 II(dp)
    java 版本企业招标投标管理系统源码+多个行业+tbms+及时准确+全程电子化
    如何压缩图片大小?图片压缩到200k以下跟我学
    RepVGG网络学习记录
    Java中interrupt的理解(个人)
    网络安全在2024好入行吗?
    【操作系统】第三章同步、通信与死锁1
  • 原文地址:https://blog.csdn.net/qq_43813373/article/details/132857700