微服务导学
首先要明确一点:
微服务技术栈介绍
微服务技术第一点要做的就是拆分,单体架构中的项目随着业务越来越复杂导致最后代码耦合度过高并且后期难以维护,所以必须对业务功能做拆分。
把每个功能都拆分成独立的一个项目,每个项目完成一部分业务功能,将来独立开发和部署。
这种独立的项目就叫一个服务,这些成百上千的服务最后就组成了一个集群。所以这个时候往往一个业务就需要多个服务来共同完成。
比如一个消息来了,请求了服务A,A又可能调B,B又调C这样。业务非常多使服务与服务之间的调用关系就会非常复杂,人工是很难记录和维护的。
所以这个时候注册中心的概念就出来了,它就是用来记录每一个服务的IP、端口以及它能干什么事的基本信息。也就是一个服务如果要调用另一个服务的话就只需要去找注册中心拿端口号IP就行了。
随着服务越来越多,每个服务都会有自己的配置文件,而这些配置文件也会有一个专门的东西来存储,即配置中心,以方便进行集中管理和维护。
微服务运行起来之后,用户就可以来访问我们了,但这个时候还需要一个服务网关的概念。服务网管会对用户身份以及权限做校验然后再去请求服务的路由,这期间也可以做些负载均衡的操作。
然后服务再去调用数据库查询数据(数据库也是集群服务),而数据库再多也不会有用户人多,即数据库承受不住这么大的访问压力,所以还需要分布式缓存的存在来缓解读写压力。
简单查询可以用分布式缓存解决,但是海量的数据、复杂的搜索、统计和分析分布式缓存也做不了,所以就需要分布式搜索。
最后在微服务中还需要一种异步通信的消息队列的存在,为什么需要消息队列很简单,众多服务之间互相请求,那么请求时间必然有先后之分,那么怎么安排这些请求的先后顺序必然需要一个单独的配置来进行配置,所以出现了消息队列。
但是还没结束,这么庞大的项目,如果出现了问题无疑是不好排查的,所以在微服务运行的过程中还需要两个组件来解决这种问题,一个是分布式日志服务,它可以记录整个分布式集群的日志信息、统计以及分析。还有一个是系统监控链路追踪,它可以监控整个服务集群中的各个节点的运行状态,CPU的负载内存的占用等等。
最后这么大的项目集群也不可能是由人工来进行部署了,都是自动化部署,利用例如Jenkins进行自动化的编译,再基于docker进行一些打包形成镜像,最后基于K8S或者Rancher这样的技术来实现自动化的部署,这一套就是持续集成。
这两套结合起来,才是完整的微服务技术栈:
认识微服务
微服务架构的演变过程
单体架构
我们之前的项目都是基于单体架构的。
分布式架构
但分布式也并非没有问题:
解决的办法很多,但是最近几年的最流行解决方案就是微服务架构。
总结
微服务结构
微服务技术对比
2012你那,阿里巴巴开源了他们公司的微服务技术实现的方案Dubbo,但是Dubbo并非严格意义上的分布式框架,它的功能有点弱,并且对于分布式架构的实现也不够完整,直到2015到17年这段时间,SpringCloud的出现大一统了全球关于分布式架构的解决方案,可以说是集百家之长。后来阿里巴巴也意识到了自己和SpringCloud的差距,于是近几年奋起直追开发出了SpringCloudAlibaba,要注意的是这个名字并非乱起,alibaba是基于SpringCloud研发的,也就是alibaba是Cloud的一部分,其内部实现了Cloud的所有标准接口。也正是因为如此,所以springcloudalibaba兼容刚刚提到的两种分布式架构。
企业需求
微服务的一种实现:SpringCloud
Cloud和Boot版本兼容关系
服务拆分与远程调用
服务拆分注意事项
导入服务拆分Demo
准备:
Order表如下:
可以看见和user表的id是做了关联的,但因为是不同的两个数据库,所以我们是无法做关联查询的。
运行demo工程后:
会有提示:
点击show那一行,idea就会为我们展示这个工程中的所有的微服务:
我们需要将这两个微服务给启动起来:
然后来看项目结构:
CloudDemo是父工程,在其pom文件里面主要是定义了依赖的版本:
<?xml version="1.0" encoding="UTF-8"?>
<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.0</modelVersion>
<groupId>cn.itcast.demo</groupId>
<artifactId>cloud-demo</artifactId>
<version>1.0</version>
<modules>
<module>user-service</module>
<module>order-service</module>
</modules>
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.9.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR10</spring-cloud.version>
<mysql.version>5.1.47</mysql.version>
<mybatis.version>2.1.1</mybatis.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- springCloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
然后两个微服务:
每个微服务都是独立的一个项目,启动之后访问对应的端口,可以看见都是正常的:
案例测试
案例需求
我们的需求如下:
但是我们现在还无法实现,访问订单接口时返回的结果如下:
可以看法用户user信息是无法返回的,同时各个微服务的数据库又是独立的,所以我们只能通过远程调用服务来进行用户信息的查询:
远程调用
如何完成远程调用?
类比浏览器的http请求或者JavaScript的Ajax请求,我们只要在Java代码中也做到类似的功能,那么就可以实现远程调用:
远程调用步骤
RestTemplate就是Spirng为我们提供的来发起HTTP请求的工具。因为我们需要发起远程调用的服务是Order服务,所以我们在Order服务中注册RestTemplate:
然后我们就要对order服务的service模块进行修改,我们通过order里的userId并通过http请求来进行用户信息的查询:
重启后我们访问就顺利拿到用户信息了: