微服务架构

微服务架构及解决方案

文章目录

  • 微服务架构及解决方案
      • 一. 微服务简介
        • 1.1 背景分析
        • 1.2 什么是微服务
      • 二. SpringCloud Alibaba微服务解决方案
        • 2.1 概述
        • 2.2 核心组件分析
        • 2.3 解决方案架构设计
      • 三 构建SpringCloud 聚合项目并进行环境初始化
        • 3.1 工程结构
        • 3.2 创建空项目(maven项目)
        • 3.3 项目初始化配置
        • 3.4 创建聚合父工程
        • 3.5 创建服务提供方模块
        • 3.6 创建服务消费方模块
        • 3.7 创建API网关服务模块
        • 3.8 服务关系以及调用关系设计
      • 四. 课堂练习
      • 五. 总结(Summary)
        • 5.1 核心知识点
        • 5.2 常见问题分析
        • 5.3 常见Bug分析

一. 微服务简介

1.1 背景分析

讲微服务之前,我们先分析以下单体应用。所谓单体应用一般是基于idea/eclipse,maven等建一个工程,然后基于SpringBoot,spring,mybatis框架进行整合,接下来再写一堆dao、mapper、service、controller,再加上一些的配置文件,有可能还会引入redis、elasticsearch、mq等其它项目的依赖,开发好之后再将项目打包成一个jar包/war包。然后再将包扔到类似tomcat这样的web服务中,最后部署到公司提供给你的linux服务器上。 接下来,你针对服务提供的访问端口(例如8080端口)发起http请求,请求会由tomcat直接转交给你的spring web组件,进行一层一层的代码调用。对于这样的设计一般适合企业的内部应用,访问量不大,体积比较小,5人以内的团队即可开发和维护。但对于一些大型互联网项目,假如需要10人以上的开发和维护团队,仅频繁的创建代码分支,编写业务功能,然后合并分支,就会出现很多代码冲突。每次解决这些大量的代码冲突,可能就会耗费好几天的时间。基于这样的背景微服务诞生了.

在微服务架构设计中,建议超出需要10人开发和维护的项目要进行系统拆分,就是把大系统拆分为很多小系统,几个人负责一个服务这样每个服务独立的开发、测试和上线,代码冲突少了,每次上线就回归测试自己的一个服务即可,测试速度快了,上线是独立的,只要向后兼容接口就行了,不需要跟别人等待和协调,技术架构和技术版本的升级,几个人ok就行,成本降低,更加灵活了。

1.2 什么是微服务

微服务架构(MSA)的基础是将单个应用程序开发为一组小型独立服务,这些独立服务在自己的进程中运行,独立开发和部署。如图所示:

微服务架构_第1张图片

这些服务使用轻量级 API 通过明确定义的接口进行通信。这些服务是围绕业务功能构建的,每项服务执行一项功能。由于它们是独立运行的,因此可以针对各项服务进行更新、部署和扩展,以满足对应用程序特定功能的需求。

程序中的微服务,就是将各个业务系统的共性再进行抽取,做成独立的服务,如图所示:

微服务架构_第2张图片

总之,微服务是分布式系统中的一种流行的架构模型,它并不是银弹,所以,也不要寄希望于微服务构架能够解决所有的问题。微服务架构主要解决的是如何快速地开发和部署我们的服务,这对于一个能够适应快速开发和成长的公司是非常必要的。同时,微服务设计中有很多很不错的想法和理念,通过学习微服务架构我们可以更快的迈向卓越。

二. SpringCloud Alibaba微服务解决方案

2.1 概述

Spring Cloud Alibaba 是Spring Cloud的一个子项目,致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。

2.2 核心组件分析

Spring Cloud Alibaba 默认提供了如下核心功能(先了解):

  • 服务限流降级:
    默认支持 WebServlet、OpenFeign、RestTemplate、Spring Cloud Gateway, RocketMQ 限流降级功能的接入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级 Metrics 监控。
  • 服务注册与发现:
    基于Spring Cloud 服务注册与发现标准,借助Nacos进行实现,默认还集成了 Ribbon 的支持。
  • 分布式配置管理:
    基于Nacos支持分布式系统中的外部化配置,配置更改时自动刷新。
  • 消息驱动能力:
    基于Spring Cloud Stream 为微服务应用构建消息驱动能力。
  • 分布式事务:
    使用 @GlobalTransactional 注解, 高效并且对业务零侵入地解决分布式事务问题。。
  • 分布式任务调度:
    提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有 Worker上执行。

2.3 解决方案架构设计

基于Spring Cloud Alibaba实现的微服务,解决方案设计架构如图所示:

微服务架构_第3张图片

三 构建SpringCloud 聚合项目并进行环境初始化

3.1 工程结构

微服务项目一般都会采用聚合工程结构,可通过聚合工程结构实现共享资源的复用,简化项目的管理方式。本小节以一个聚合工程结构为案例,讲解微服务架构方案中的maven聚合工程的基本结构,例如:

GitCGB2108IVProjects (工作区/空项目)
├── 01-sca   //(微服务父工程)
     ├── sca-provider            //服务提供方法
     ├── sca-consumer         //服务消费方法
     ├── sca-gateway            //网关服务

3.2 创建空项目(maven项目)

打开Idea,创建一个空项目(Empty Project),项目名为GitCGB2108IVProjects,例如:

微服务架构_第4张图片

微服务架构_第5张图片

其中,这个空项目就类似磁盘中的一个空的文件夹,可以将此文件夹作为一个代码工作区。

3.3 项目初始化配置

第一步:配置maven环境(只要是新的工作区,都要重新配置),注意本地库选择新的位置不要与其它项目共用本地库,因为多个项目所需要依赖的版本不同时,可能会有一些依赖版本的冲突。.

微服务架构_第6张图片

说明,这里的本地库名字最要不要选择中文,单词之间也不要有空格。

第二步:配置JDK编译环境

聚合工程在编译时,需要对相关依赖的工程进行一起编译,所以需要做一些配置,例如:

微服务架构_第7张图片

指定一下当前工作区的jdk编译版本,例如:

微服务架构_第8张图片

第三步:配置工作区中项目编码方式

微服务架构_第9张图片

3.4 创建聚合父工程

我们后续在创建微服务工程进行学习时,相关服务依赖版本的管理,公共依赖,项目编译,打包设计等都可以放在此工程下,进行统一的配置,然后实现共享。

第一步:创建父工程模块,例如:

微服务架构_第10张图片

第二步:删除工程中的src目录(父工程不需要这个目录),例如:

第三步:修改项目pom.xml文件内容,例如:


<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>
    
    <groupId>com.jtgroupId>
    <artifactId>01-scaartifactId>

    <version>1.0-SNAPSHOTversion>

    
    
    

    
    <dependencyManagement>
        <dependencies>
            
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-dependenciesartifactId>
                <version>2.3.2.RELEASEversion>
                <type>pomtype>
                <scope>importscope>
            dependency>

            
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-dependenciesartifactId>
                <version>Hoxton.SR9version>
                <type>pomtype>
                <scope>importscope>
            dependency>

            
            <dependency>
                <groupId>com.alibaba.cloudgroupId>
                <artifactId>spring-cloud-alibaba-dependenciesartifactId>
                <version>2.2.6.RELEASEversion>
                <type>pomtype>
                <scope>importscope>
            dependency>
        dependencies>
    dependencyManagement>
    
    <dependencies>
        
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <scope>providedscope>
        dependency>
        
         <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.jupitergroupId>
                    <artifactId>junit-jupiter-engineartifactId>
                exclusion>
            exclusions>
        dependency>
        
    dependencies>
    
    <build>
        <plugins>
            
            <plugin>
                <groupId>org.apache.maven.pluginsgroupId>
                <artifactId>maven-compiler-pluginartifactId>
                 
                <version>3.8.1version>
                <configuration>
                    <source>8source>
                    <target>8target>
                configuration>
            plugin>
        plugins>
    build>

project>

其中,服务核心依赖版本可参考如下网址(涉及到一个兼容性问题,不能随意指定其版本):

https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E

3.5 创建服务提供方模块

创建服务提供方工程,继承01-sca,例如:

微服务架构_第11张图片

3.6 创建服务消费方模块

创建服务消费方工程,继承01-sca,例如:

微服务架构_第12张图片

3.7 创建API网关服务模块

创建网关工程(这个工程后续会作为API服务访问入口),继承01-sca,例如:

微服务架构_第13张图片

3.8 服务关系以及调用关系设计

基于前面章节创建的项目,后续我们会讲解服务的注册,服务的配置,服务之间的调用,负载均衡,限流,熔断,网关等相关知识,现在先了解一个简易结构,例如:

微服务架构_第14张图片

我们最终会基于这个结构的设计,实现一个从网关到服务消费方,再从服务消费方到服务提供方的一个调用链路的业务及代码实践过程。

四. 课堂练习

  • 构建01-sca的工程(父工程),修改pom文件

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>


    
    <groupId>com.jtgroupId>
    <artifactId>01-scaartifactId>
    <packaging>pompackaging>
    <version>1.0-SNAPSHOTversion>
    <modules>
        <module>sca-providermodule>
        <module>sca-consumermodule>
        <module>sca-gatewaymodule>
        <module>sca-commonmodule>
    modules>

    
    
    <dependencyManagement>
        <dependencies>
            
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-dependenciesartifactId>
                <version>2.3.2.RELEASEversion>
                
                <type>pomtype>
                
                <scope>importscope>
            dependency>
            
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-dependenciesartifactId>
                <version>Hoxton.SR9version>
                <type>pomtype>
                <scope>importscope>
            dependency>
            
            <dependency>
                <groupId>com.alibaba.cloudgroupId>
                <artifactId>spring-cloud-alibaba-dependenciesartifactId>
                <version>2.2.6.RELEASEversion>
                <type>pomtype>
                <scope>importscope>
            dependency>
        dependencies>

    dependencyManagement>
    
    <dependencies>

        <dependency>
            
            
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
        dependency>

        <dependency>
            
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            
            <scope>testscope>
            
            
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintagegroupId>
                    <artifactId>junit-vintage-engineartifactId>
                exclusion>
            exclusions>
        dependency>

    dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.pluginsgroupId>
                <artifactId>maven-compiler-pluginartifactId>
                
                <version>3.8.1version>
                <configuration>
                    
                    
                    <source>8source>
                    <target>8target>
                configuration>
            plugin>
        plugins>
    build>
project>
  • 构建01-sca的子工程,工程名为sca-common。

  • 在sca-common工程中创建单元测试类IntegerTests,对整数池进行测试。

package com.jt;

import org.junit.jupiter.api.Test;

public class IntegerTests {
    /*
    * 测试整数池
    * */
    @Test
    void testIntegerCache(){
        //Integer类在加载时会在内存中创建一个整数池,池中默认储存-128到+127
        //JDK提供了一种自动装箱机制,会自动将100转换为Integer
        Integer a=100; //Integer.valueOf(100)
        Integer b=100; //享元模式
        System.out.println(a==b); //true
        Integer c=200;
        Integer d=200;  //c==d?
        System.out.println(c==d); //false
    }
}
  • 在sca-common工程中定义工具类StringUtils,并定义判断字符串是否为空的静态方法isEmpty(String str)。
package com.jt.common.util;

public class StringUtils {
    /*
    * 判定一个字符串是否为空
    * */
    public static boolean isEmpty(String str){
        return str==null || str.equals("");
    }
}
  • 在sca-gateway工程的单元测试方法中引用sca-common工程中的StringUtils类进行单元测试分析。
package com.jt;

import com.jt.common.util.StringUtils;
import org.junit.jupiter.api.Test;

public class StringTest {
    @Test
    void TestEmpty(){
        String token=null;
        boolean flag = StringUtils.isEmpty(token);
        System.out.println(flag);
    }
}
  • 在sca-gateway工程中添加StringTemplate和SimpleStringTemplate类(此类继承StringTemplate)并交给spring管理,然后在单元测试类中获取这两个类的对象?(依赖,@Component,启动类,单元测试类)
package com.jt;

import org.springframework.stereotype.Component;

/*
* 1.将此类交给spring管理
* 2.在单元测试类中获取此此类对象
* */
@Component//bean的名字默认为stringTemplate
public class StringTemplate {
}
package com.jt;

import org.springframework.stereotype.Component;

@Component
public class SimpleStringTemplate extends StringTemplate{
}
package com.jt;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
//从启动类所在的包或者子包中查找有特定注解的类,将扫描到的类代为管理
public class GatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}
package com.jt;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest  //注释掉此注解,直接打印会打印出null,调用方法会出现空指针
public class StringTemplateTest {
    /*
    * @Autowired描述属性时,用于告诉Spring按照指定的规则为此注解描述的属性注入一个值
    * 默认会先按照属性的类型查找对象的对象,假如找不到直接抛出异常,找到一个直接注入,
    * 找到多个会按照属性名和spring容器当中bean的名字对比,有相同的直接注入,没有相同的抛出异常
    * 假如我们希望注入指定名字的bean,还可以在@Autowired的注解上再加上一个@Qualifier注解
    * */
    @Autowired  //注释掉此注解,直接打印会打印出null,调用方法会出现空指针
//    @Qualifier("simpleStringTemplate")//假如不想用这个注解,将属性的变量名改为spring容器中与bean对象名字一样的即可;
    private StringTemplate stringTemplate;
    @Autowired
    private StringTemplate simpleStringTemplate;

    @Test
    void testStringTemplate(){
        System.out.println(stringTemplate);//com.jt.StringTemplate@c8b96ec
        System.out.println(simpleStringTemplate);//com.jt.SimpleStringTemplate@4cc61eb1
    }
}

五. 总结(Summary)

总之,微服务是一个架构设计方式,此架构中的每个服务(service)都是针对一组功能而设计的,并专注于解决特定的问题。如果开发人员逐渐将更多代码增加到一项服务中并且这项服务变得复杂,那么可以将其拆分成多项更小的服务(软件即服务,所有软件对外的表现形式就诗提供一种或多种业务服务)。接下来进行独立的开发、测试、部署、运行、维护。进而更好,更灵活的处理客户端的请求并提高系统的可靠性,可扩展性。

5.1 核心知识点

  • 微服务架构诞生的背景(软件即服务,将一个大型软件,拆成若干个小系统;分而治之~北京一个火车站到多个火车站)
  • 微服务架构解决方案(大厂基本自研~自己研发各种组件,中小公司用Spring Cloud Netflix,Alibaba,…)
  • 微服务架构下Maven聚合项目的创建方式?(Maven聚合项目~资源复用:extends,import,简化编译,打包,部署方式)
  • 微服务架构入门聚合项目创建?(01-sca,sca-consumer,sca-provider,sca-gateway,sca-common)
  • 微服务中聚合工程之间的引用设计?(将一个工程作为依赖添加到其它工程~重点是坐标)
  • 工程中单元测试案例分析及实践?

5.2 常见问题分析

  • 为什么需要微服务?(对系统分而治,解决因并发访问过大带来的系统复杂性(例如:业务,开发,测试,升级,可靠性等)
  • 微服务设计的特点?(单一职责,独立进程,开发测试效率高,可靠性高,升级难度小,但会带来一定的维护成本)
  • 微服务解决方案有哪些?(大厂自研,中小企业采用开源Spring Cloud Alibaba,Spring Cloud Netfix等 )
  • 微服务设计中需要哪些关键组件(服务的注册,发现,配置,限流降级,访问入口管理,分布式事务管理等)
  • 创建聚合工程的目的?(实现工程之间资源的的共享,简化工程管理)
  • 如何修改聚合工程中项目的编译和运行版本?(pom.xml:build->plugins->plugin->maven-compiler-plugin)
  • maven工程中build元素的作用?(定义项目的编译,打包方式)
  • maven父工程的packaging元素内的值是什么?(父工程默认打包方式为pom方式)
  • maven父工程中dependencyManagement元素的作用是什么?(项目依赖的版本,当前工程或子工程不需要再指定版本)
  • Maven父工程中如何统一定义JDK编译和运行版本?(配置maven编译插件:maven-compiler-plugin)
  • Maven工程pom.xml文件有删除线怎么解决?(修改idea中maven的配置)
  • @Autowired注解描述属性时,系统底层执行DI的过程是怎样?

5.3 常见Bug分析

  • maven配置错误(idea中指定你本地库)
  • maven依赖无法下载(首先要确保你的依赖的是正确,maven配置是正确,都正确就放大招)
  • 单元测试@Test注解包引入错误(junit4,junit5)
  • 单元测试类写错了位置。

你可能感兴趣的:(微服务,架构,java)