微服务和微服务架构介绍

  • 前言
  • 什么是微服务
  • 什么是微服务架构
  • springcloud搭建(注意下面讲解的会以图文结合,如果你想跟着手敲代码可以去git地址先下载项目下来,例如pom文件这些配置)
  • 创建一个父工程(microservice)
  • 创建项目api工程(microservice-api)
  • 创建传统的服务提供项目(dao.service.controller--microservice-provider-dept-8001)
  • 创建服务消费者工程(microservice-consumer-dept-801)
  • 创建eureka服务(microservice-eureka-7001)
  • 修改服务提供项目(8001端口)加入eureka配置
  • 创建eureka服务集群(7002,7003)
  • 修改8001工程
  • 创建与8001相同功能的微服务(microservice-provider-dept-8002、microservice-provider-dept-8003)
  • 向801消费者微服务加入ribbon功能模块
  • api工程加入feign进行负载均衡
  • 新建服务消费者(以feign方式调用)
  • 新建hystrix-8001服务提供项目,加入Hystrix(方法级别熔断)
  • Hystrix熔断(类级别)
  • 新建路由zuul微服务
  • 新建服务配置项目(microservice-config)
  • 新建服务配置中心(microservice-config-8888)
  • 修改microservice项目
  • 创建microservice-config-client-3355
  • 改造8001项目,加入服务配置中心相关


前言

截止目前最新版springcloud是 Hoxton.SR9,最老的版本是本文教学的版本,但为什么还要出一版这个呢(因为本人菜只会这个)。其实因为今年找工作时候,在学习微服务的道路上首先看的就是尚硅谷阳哥教学的微服务架构Dalston版本,然后跟着自己手敲了一边。一步一步来,下一步就是跟着H版敲了(150多集。。。。学无止境)

以是自己个人学习历程见解。

什么是微服务

微服务项目组合_spring cloud


这里引用spring官网多微服务的介绍

微服务与微服务架构请记得区分开来是两个不同概念的事务,从官网的介绍来看:微服务是构造一个小型、独立且可以运行的应用程序。用于解决某一个功能模块或者提供某一项技术支持。可以类比成开发工具里面的一个工程(Eclipse)或者一个模块(Idea)。

优点

  1. 每个微服务代码都是实现同一类业务需求下功能,实现设计模式中常提及的高内聚
  2. 开发简单和高效,一个服务可能专做一个业务功能,可以让小团队或者一个人进行单独开发
  3. 微服务是低耦合的,模块与模块之间可以分开部署
  4. 微服务之间可以使用不用的语言,例如你做业务模块可以使用java,你想去爬取信息可以用python。适当的选取当下最新的技术选型,只要能对外暴露出相应的接口即可
  5. 每个微服务是单独部署的,所以可以有各自的数据库实现数据与应用一起,当然也可以使用同一个数据库

缺点

  1. 既然是分开部署,开发人员或者说架构师要处理各种的分布式系统面临的问题,如数据统一性,登录有效性等
  2. 运维压力大,要部署多个项目(其实这里可以使用docker简化一下多项目部署)

什么是微服务架构

微服务项目组合_spring cloud_02


简单一句话就是多个微服务或技术栈组成的一个系统就是微服务架构。以前单应用版时候,一个项目就是一个进程,然后不能功能不能模块利用进程中的线程去实现。要对外提供操作接口,内部要配置容错机制、配置文件等。这样做容易部署并且测试时候开启一个项目即可调试不用想模块与模块之前的调度。但正所谓合久必分,在微服务架构里面就像上面的图一样,各个系统独占一个进程有对外提供路由的、有配置管理中心、有服务注册与发现、数据库、消息队列、熔断器和一个个服务提供者所组成的一个云环境。

本文最终将会搭建一个SpringCloudConfig(服务配置中心)、Eureka(服务注册与发现)、zuul(路由网关)、Ribbon/Feign(负载均衡)、Hystrix(服务熔断器)、Springboot/Spring(服务开发)的微服务环境。过程会是先从最基本的一个传统服务提供方式(Springboot)一步一步加入技术栈(网关、负载、熔断器等)

springcloud搭建(注意下面讲解的会以图文结合,如果你想跟着手敲代码可以去git地址先下载项目下来,例如pom文件这些配置)

github地址:(https://github.com/gitHubChenjm/microservice)

创建一个父工程(microservice)

微服务项目组合_分布式_03

  1. 创建父工程,删除src目录并且记得修改打包方式是pom如上图红色方框。用于同一管理之后微服务的各种版本号做到版本一致,若有特殊需求在相应微服务中定义参数即可(这是maven管理相关知识这里不懂得同学自行百度关键词:maven dependencyManagement)
  2. 配置pom文件定义相关包的版本号

创建项目api工程(microservice-api)

作用:以往一个工程里面包括了所有的类,每个包下的方法都能直接引用这些公用的类,但在微服务里面可能每个moudle也有公用的类或者参数,这时候为了不重复写就在api包中定义存放各个微服务会公用的类或参数,例如实体类,Feign负载均衡类等,然后相应的微服务要用的时候,在pom文件中进行依赖
如:

<dependency>
            <groupId>org.chenjm.springcloud</groupId>
            <artifactId>microservicescloud-api</artifactId>
</dependency>
  1. 构建一个api工程,继承父工程的pom
  2. 创建部门表实体类Dept(@Data注解是lombok包的,pom文件引入一下,否则可以自己实现get/set方法)

.

创建传统的服务提供项目(dao.service.controller–microservice-provider-dept-8001)

  1. 创建一个子module继承父工程的pom文件
  2. 创建基本三层结构 数据库层,服务层,控制层和主启动类
  3. 创建mapper映射文件注意namespace这里要指向dao层的类
  4. 创建application文件注意:mapper-locations指向你创建mapper.xml的文件目录(如果报Invalid bound statement (not found),可查看本链接进行解决

创建服务消费者工程(microservice-consumer-dept-801)

创建module的步骤不截图了,大致相同 如果有特殊操作后续才会放上来。

  1. 向spring容器中注入 bean:restTemplate。作用是使用这个rest风格模板进行服务提供者对外暴露的url调用。(题外话,类似这种模板还有很有例如 JdbcTemplate、redistemplate)
  2. 新建controller层使用restTemplate模板调用8001服务提供者提供的服务。(这里地址前缀暂时写:ip+port形式,后面加入ribbon后修改成微服务名称 这些就不用暴露访问地址在代码中)

    step1:最终效果是在一个微服务架构里面,有一个服务提供者(8001端口),有一个服务消费者(801端口)。用户通过访问消费者地址进行功能展示
    git地址:https://github.com/gitHubChenjm/microservice.git(step1分支)

创建eureka服务(microservice-eureka-7001)

  1. pom文件:加入eureka服务端包依赖
  2. 启动类加入相关注解
  3. 新增application.xml文件,增加eureka相关配置。
  4. 上面配置文件中有-----hostname: eureka7001.com 这个就要修改host文件(如果不想修改host文件可以直接写成 hostname: localhost,但这样在日后区分eureka集群时候看localhost不太好看而已)

修改服务提供项目(8001端口)加入eureka配置

  1. pom.xml:加入eureka客户端包的依赖
  2. 主启动类新增eureka客户端注解
  3. 修改application.yml文件,配置服务在eureka上面信息和注册到哪个eureka中
  4. 测试服务是否已经注册上开启的eureka微服务中,如果成功会在下图中的位置显示相应服务的微服务名称

    step2:最终效果服务提供者项目(8001),成功注册到eureka服务上面
    git地址:https://github.com/gitHubChenjm/microservice.git(step2分支)

创建eureka服务集群(7002,7003)

  1. 具体操作和eureka7001创建相同,下面贴出的是不同点
  2. 修改7001、7002、7003:application.yml文件中eureka.client.service-url.defaultZone字段,将其余两个eureka服务注册到服务上去,以7001为例子,注册7002,7003的eureka地址到本服务中心中

修改8001工程

  1. 修改eureka服务为集群环境
  2. 分别查看集群eureka上,是否都有8001微服务

    step3:最终结果是有三个eureka集群,并且8001服务已经注册到三个注册与发现服务中了(eureka)
    git地址:https://github.com/gitHubChenjm/microservice.git(step3分支)

创建与8001相同功能的微服务(microservice-provider-dept-8002、microservice-provider-dept-8003)

  1. 两个新建项目除了配置文件中(application.yml)某些参数不一致,其他完全一致,以8002为范例如下显示。(注意:这里三个不同服务提供者微服务分别连接不同的数据库,dept01,dept02,dept03这个请阅读README.md,分别创建三个数据库 是数据库!!不是表!!,表是一样的都叫dept)

微服务项目组合_spring cloud_04

向801消费者微服务加入ribbon功能模块

  1. 原来801端口的服务,在消费8001moudle时候,直接写死了ip地址,现在服务提供者也是集群了(8001,8002,8003三个),并且都注册到了eureka中,所以应该是801消费者上eureka中找到相应的调用接口
  2. 微服务项目组合_spring boot_05

  3. 801消费者服务修改pom文件,增加ribbon的依赖,因为也是要注册到eureka中寻找服务,所以除了ribbon依赖外,还有eureka客户端相关依赖
  4. 微服务项目组合_spring cloud_06

  5. 主启动类新增注解
  6. 微服务项目组合_微服务项目组合_07

  7. 修改application.yml,将服务指定eureka集群(注意:并非注册到eureka集群,即在eureka集群是看不到801这个服务的)
  8. 微服务项目组合_spring boot_08

  9. 现在801端口是根据restTemplate这个模板进行远程调用的,所以要做到客户端的负载均衡(ribbon),就在这个模板上面做手脚添加相关注解
  10. 微服务项目组合_spring_09

  11. 还记得上面有说过消费者是写死地址的吗,现在应该是要上eureka找到相关服务,所以控制层也需要改变
  12. 微服务项目组合_微服务项目组合_10

  13. step4:查看最终效果,访问801服务的接口,应该会出现查询不同数据库数据的情况,进行了客户端负载均衡(需要启动项目3个eureka集群7001-7003,3个微服务提供8001-8003,801消费者)
    git地址:https://github.com/gitHubChenjm/microservice.git(step4分支)
  14. 微服务项目组合_spring boot_11


  15. 微服务项目组合_微服务项目组合_12

api工程加入feign进行负载均衡

  1. pom文件添加feign依赖(ps:为什么放在api包,是因为只要使用远程调用都要这个类,防止每个消费者或者提供者都重新加入该依赖包,其他微服务都会继承该包,所以统一放到api包里面)
  2. 新增服务,以接口+注解方式声明服务(这也是feign的特点)

新建服务消费者(以feign方式调用)

  1. 新建controller层,调用api中的feign声明的服务接口(回归控制层调用服务接口层,后面有和原来的对比)
  2. 主启动类,增加feign注解
  3. 对比两个801微服务控制层写法
    A:使用feign负载均衡的,回归原始的逻辑,就是控制层调用服务层。
    B:使用ribbon负载均衡的,还是使用spring框架提供的模板工具进行远程调用

    step5:最终效果,访问801服务url会显示不同库查出来的结果,其实和ribbon效果一致因为都是客户端的负载均衡只是使用技术不同而已(需要启动项目3个eureka集群7001-7003,3个微服务提供8001-8003,801-feign消费者)
    git地址:https://github.com/gitHubChenjm/microservice.git(step5分支)

新建hystrix-8001服务提供项目,加入Hystrix(方法级别熔断)

  1. 创建8001服务,增加pom依赖
  2. 其他设置和8001服务大致相同,修改controller文件,增加HystrixCommand注解,并且实现相应的容错机制方法processHystrix_findById。这里使用如果是查询不存在时候进行错误异常报错,模拟日常情况下发生错误需要进行熔断机制
  3. 主启动类新增注解
  4. 效果,访问数据库中有的数据时候正常,访问数据库没有的数据时候返回熔断方法执行的信息。
    该熔断机制是方法级别的,就证明每个对外暴露的接口都要对应一个熔断方法(如processHystrix_findById),这样导致新的方法越来越多,并且方法实现在控制层内导致代码的耦合度高,违反了高内聚低耦合的设计模式理念

Hystrix熔断(类级别)

  1. api工程新增一个实现了 FallbackFactory的类DeptClientServiceFallBackFactory,注意该类一定要添加@Component注册到spring容器中!!!!
  2. 微服务项目组合_spring_13

  3. 在实现方法里面编写相关的报错情况下执行的方法(这里演示只实现了findById的熔断)
  4. 微服务项目组合_spring cloud_14

  5. feign调用中,声明熔断错误处理类
  6. 微服务项目组合_spring_15

  7. 修改feign-801项目的yml文件,开启熔断机制
  8. 微服务项目组合_spring_16

  9. 效果是当服务正常时候,访问feign-801的端口一切正常,当我们停止了8001微服务就调用编写的熔断方法。(项目启动:7001-7003,feign-801,8001— 测试正常情况后关闭8001服务在测试,出现下图)
  10. 微服务项目组合_spring boot_17

  11. step6:实现方法级别的熔断机制,实现类级别的熔断机制
    git地址:https://github.com/gitHubChenjm/microservice.git(step6分支)

新建路由zuul微服务

  1. 新建zuul微服务,增加pom文件依赖zuul
  2. 配置yml文件,定义微服务端口,服务名称,eureka和路由规则。
    path:定义访问前缀是什么
    serviceId:该访问前缀下在eureka中寻找哪个微服务
  3. 主启动类,增加相关注解
  4. 效果直接访问http://localhost:8001/dept/get/1和http://localhost:9527/CLOUD-DEPT/dept/get/1进行对比

一直认真看下来的应该有发现,每次新增新的功能或者框架时候,一般操作流程都是
A:引入相关的包
B:修改yml配置文件
C:添加相关注解(启动类或者其他类)
所以日后添加相关其他框架时候也可以这么操作

step7:最终效果增加zuul路由,以后可以访问9527这个端口,进行统一服务调用,不用管后面哪个端口提供的服务
git地址:https://github.com/gitHubChenjm/microservice.git(step7分支)

新建服务配置项目(microservice-config)

  1. 新建一个新moudel,独立于上面的微服务(这是有别与上面microservice,注意他的parent是空的,之前的都是继承microservice)
  2. 增加application.yml文件(分别是dev环境显示名字为 xxx-dev,sit环境显示名字为 xxx-sit)

    最后了加油,把服务配置中心加上,一套最基本的微服务架构就完成了

新建服务配置中心(microservice-config-8888)

  1. 新建项目,继承microservice(和之前zuul、eureka一样)
  2. 微服务项目组合_spring boot_18

  3. 新增服务配置中心config-server依赖,并添加相关的注解在主启动类中

微服务项目组合_spring_19


微服务项目组合_spring_20


3. 配置application.yml

server:
  port: 8888

spring:
  application:
    name: config-server
  ##cloud:
  ##  config:
  ##    server:
  ##      git:
  ##        uri:    ##git配置
  profiles:
    active: native
  cloud:
    config:
      server:
        native:
          search-locations: D:/chenjm/开发信息/ocr/microservice-config/config  #本地配置,这里指向你项目绝对路径
eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7003.com:7003/eureka,http://eureka7002.com:7002/eureka
      ## 单机版 defaultZone: http://localhost:7001/eureka  #eureka注册中心 服务端地址
  instance:
    instance-id: config-server8888 #服务上面,status栏位中的名字
    prefer-ip-address: true #访问路径可以显示ip
  1. 启动项目主启动类,测试 输入http://localhost:8888/application-dev.yml 和 http://localhost:8888/application-sit.yml查看区别,效果如下证明服务配置中心微服务可以连通获取配置文件的途径了。

修改microservice项目

新增application-client.yml文件,配置不同环境下,服务端口号不一致

微服务项目组合_spring cloud_21

创建microservice-config-client-3355

  1. 导入pom依赖
  2. 编写bootstrap.yml
  3. 编写一个对外接口查看相关数据
  4. 启动服务配置中心(8888)和该项目(microservice-config-client-3355),然后访问:http://localhost:8201/view/config,可以看到相关配置文件信息,当切换第二步中profile参数时候,相关配置文件信息会改变。

    step8:最终效果是,配置服务中心(服务端8888)可以去配置文件存放项目(microservice-config)中获取配置,客户端(microservice-config-client-3355)从配置服务中心获取自己的配置信息。
    git:https://github.com/gitHubChenjm/microservice.git(step8分支)
    配置文件项目:https://github.com/gitHubChenjm/microservice-config.git (main分支)

ps:上面是演示配置中心去配置文件项目拿配置文件,然后客户端从配置中心拿配置文件的过程,下面实际加到具体项目中,通过配置文件获取的微服务架构,以8001项目进行改造为范例学习

改造8001项目,加入服务配置中心相关

  1. 增加配置文件,将8001的application.yml全部复制,然后修改其中的数据库配置,数据库根据版本(dev/sit)更换
  2. 8001项目,添加服务配置中心客户端依赖
  3. 8001项目,删除application.yml(在配置中心有了),新增bootstrap.yml文件
  4. 启动配置中心(8888),启动服务提供者(8001),访问http://localhost:8001/dept/get/1,根据修改第三步中的profile:sit/dev,查询不同数据库即下图红框

    step9:最终效果服务提供者(8001),根据profile设置的值获取不同的配置参数
    git:https://github.com/gitHubChenjm/microservice.git(step9分支)

完结啦完结啦!!!!!!!!撒花撒花!!!!!!!!!!!!!
大家发现什么bug啊啥的,记得留言 大家相互学习一起拿好offer