一、微服务的概念以及发展过程
微服务是指只提供一项功能的服务。 微服务是围绕某个业务领域展开的。比如把电商业务比较一个业务领域,技术部、产品部等就是围绕电商业务领域展开的微服务。在电商项目领域,由支付、商品、订单等微服务组成。
微服务架构风格是一类将单一应用程序作为由众多小型服务构成之套件加以开发的方式,其中各项服务都拥有自己的进程并利用轻量化机制(通常为HTTP源API)实现通信。这些服务围绕业务功能建立而成,且凭借自动化部署机制实现独立部署。
微服务将应用程序逻辑分为明确定义的职责范围的粒度组件,这些组件相互协调提供解决方案
每一个组件都有一个小的职责领域,可以完全部署,也就是说一个服务可以跨越多个应用程序复用。
服务之间通信基于一些基本的原则,比如服务采用http+json这样的轻量级通信协议,在不同服务之间进行数据交换。这样不同服务可以使用不同的技术栈,互不影响。
拆分为微服务之后,服务的数量变多,因此需要有统一的服务治理平台,来对各个服务进行管理。
(一)、单体架构
单体架构的缺点是 处理并发量有限,不能承载高并发量的访问。每个物理主机的吞吐量都是有限的,当并发量起来后,承载应用程序的服务器性能会下降,甚至可能宕机。要解决高并发问题,应用程序开始做集群。
(二)、单数据库多应用架构
为了解决并发量的问题,开始对应用程序做集群,并使用nginx做负载均衡 。
单数据库多应用架构,在应用程序上解决了并发量问题。随着并发量的增加,数据量也会骤增。数据量问题出现,数据库的性能下降,影响整个系统的性能。
(三)、微服务应用架构
二、微服务的优点
-
每个服务都比较简单,只关注于一个业务功能。
-
微服务架构方式是松耦合的,可以提供更高的灵活性。
-
微服务可通过最佳及最合适的不同的编程语言与工具进行开发,能够做到有的放矢地解决针对性问题。
-
每个微服务可由不同团队独立开发,互不影响,加快推出市场的速度。
-
微服务架构是持续交付(CD)的巨大推动力,允许在频繁发布不同服务的同时保持系统其他部分的可用性和稳定性。
- 灵活性高:它将应用程序分解为小型服务(松散耦合),使其开发、维护更快,更易于理解,可以提供更高的灵活性;
- 独立扩展:它使每个服务能够独立扩展,将系统中的不同功能模块拆分成多个不同的服务,这些服务进行独立地开发和部署,每个服务都运行在自己的进程内,这样每个服务的更新都不会影响其他服务的运行;
- 支持多种编程语言:微服务可通过最佳及最合适的不同的编程语言与工具进行开发,能够做到有的放矢地解决针对性问题;
- 自动部署与持续集成工具集成:它允许以灵活的方式将自动部署与持续集成工具集成,例如Jenkins,Hudson等;
- 通用性:通过服务实现应用的组件化(按功能拆分、可独立部署和维护),围绕业务能力组织服务,根据业务不同的需求进行不同组件的使用,所做产品非项目化,对于平台具有一定的通用性。
三、微服务得到拆分策略
服务粒度的划分是伴随着架构演进进行的,需要考虑当前的人力、物力等来有效的统筹,在项目的初期可以把服务的粒度设计大一点,随着项目的不断壮大,团队的规模不断变大,可以对现有的粗粒度服务进行有效的拆分,逐步的向细粒度服务发展。
基于业务逻辑进行拆分
“职责范围”的理解差异很大,因此根据业务拆分需要权衡当前项目组的情况。
基于可扩展拆分
“日志服务”和“升级服务”放在同一个子系统中;不稳定的服务粒度可以细一些,但也不要太细,始终记住要控制服务的总数量。这样拆分主要是为了提升项目快速迭代的效率,避免在开发的时候,不小心影响了已有的成熟功能导致线上问题。
基于可靠性拆分
将系统中的业务模块按照优先级排序,将可靠性要求高的核心服务和可靠性要求低的非核心服务拆分开来,然后重点保证核心服务的高可用。这样拆分带来下面几个好处:(避免非核心服务故障影响核心服务、核心服务高可用方案可以更简单、能够降低高可用成本)
基于性能拆分
基于性能拆分和基于可靠性拆分类似,将性能要求高或者性能压力大的模块拆分出来,避免性能压力大的服务影响其他服务。常见的拆分方式和具体的性能瓶颈有关,可以拆分 Web 服务、数据库、缓存等。
四、微服务搭建实战
现在的java后端基本都是通过微服务的方式进行搭建。当我们对需求进行分割时,可以通过横向或者纵向对服务进行划分。或者当某一块的业务我们希望通过一个单独的服务进行开发时,就需要新增新的服务,本文通过springtool suite工具介绍,微服务搭建过程。
1、现在的工程目录如下:
我的工程为:ctg-blockchain-plat
现在这个工程一共有4个微服务,分别为:
hn-base-admin、hn-base-gateway、hn-blockchain-business、hn-member-business
我们先看一下父工程的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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.2</version>
</parent>
<groupId>cn.ctg</groupId>
<artifactId>ctg-member-plat</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<base.version>1.0-SNAPSHOT</base.version>
<java.version>1.8</java.version>
<spring-cloud.version>2020.0.3</spring-cloud.version>
<spring-boot.version>2.5.2</spring-boot.version>
<mysql.version>8.0.17</mysql.version>
<druid.version>1.1.13</druid.version>
<mybatisplus.version>3.4.3.4</mybatisplus.version>
<mybatis-spring.version>2.2.0</mybatis-spring.version>
<apollo.version>1.8.0</apollo.version>
<dameng.version>7.6.0.142</dameng.version>
<fastjson.version>1.2.83</fastjson.version>
<swagger2.version>2.9.2</swagger2.version>
<hutool.version>5.7.7</hutool.version>
<poi.version>3.17</poi.version>
<commons-lang3.version>3.8.1</commons-lang3.version>
<xstream.version>1.4.18</xstream.version>
<log4j-to-slf4j.version>2.15.0</log4j-to-slf4j.version>
<java-jwt.version>3.8.2</java-jwt.version>
<zxing.version>3.3.0</zxing.version>
<barcode4j.version>2.1</barcode4j.version>
<bcprov-jdk15to18.version>1.66</bcprov-jdk15to18.version>
<rocketmq.version>4.7.1</rocketmq.version>
<mq-http-sdk.version>1.0.3.2</mq-http-sdk.version>
<aliyun-sdk-oss.version>3.13.2</aliyun-sdk-oss.version>
<cos_api.version>5.6.89</cos_api.version>
<sharding-sphere.version>4.0.0-RC2</sharding-sphere.version>
<shardingsphere.version>5.0.0-beta</shardingsphere.version>
</properties>
<modules>
<module>hn-base-common</module>
<module>hn-base-gateway</module>
<module>hn-base-admin</module>
<module>hn-member-business</module>
<module>hn-base-interceptor</module>
<module>hn-blockchain-business</module>
</modules>
</project>
再看一下一个子工程hn-blockchain-business的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.0</modelVersion>
<parent>
<artifactId>ctg-member-plat</artifactId>
<groupId>cn.ctg</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>hn-blockchain-business</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>cn.ctg</groupId>
<artifactId>hn-base-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.ctg</groupId>
<artifactId>hn-base-interceptor</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<!-- apollo -->
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>${apollo.version}</version>
</dependency>
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-core</artifactId>
<version>${apollo.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger2.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger2.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<exclusions>
<exclusion>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>${xstream.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatisplus.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--oss -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>${aliyun-sdk-oss.version}</version>
</dependency>
<!--cos -->
<dependency>
<groupId>com.qcloud</groupId>
<artifactId>cos_api</artifactId>
<version>${cos_api.version}</version>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>${rocketmq.version}</version>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-acl</artifactId>
<version>${rocketmq.version}</version>
</dependency>
<dependency>
<groupId>com.aliyun.mq</groupId>
<artifactId>mq-http-sdk</artifactId>
<!--以下版本号请替换为Java SDK的最新版本号-->
<version>${mq-http-sdk.version}</version>
<classifier>jar-with-dependencies</classifier>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- 分库分表 -->
<!--
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>${sharding-sphere.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-namespace</artifactId>
<version>${sharding-sphere.version}</version>
</dependency>
-->
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<configuration>
<target>
<copy todir="../deploy" overwrite="true">
<fileset dir="${project.build.directory}">
<include name="${project.artifactId}.jar" />
</fileset>
</copy>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
然后假设我们要新建一个新的服务hn-maoheyeren-business,右键ctg-blockchain-plat,选择maven,选择new maven module project
出现下面对话框,在Module Name中填写hn-maoheyeren-business,依赖额父工程填写父工程中的artifactId :ctg-member-plat ,工作目录 working set 选择项目的工作目录。
点击next,选择maven 快速架构类型,点击next
点击next,再点击finish
微服务模块就生成了:
我们看一下pom
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.ctg</groupId>
<artifactId>ctg-member-plat</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>cn.ctg</groupId>
<artifactId>hn-maoheyeren-business</artifactId>
<version>1.0-SNAPSHOT</version>
<name>hn-maoheyeren-business</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
然后我们需要改一下微服务的pom,我们可以把hn-blockchain-business的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.0</modelVersion>
<parent>
<artifactId>ctg-member-plat</artifactId>
<groupId>cn.ctg</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>hn-maoheyeren-business</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>cn.ctg</groupId>
<artifactId>hn-base-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.ctg</groupId>
<artifactId>hn-base-interceptor</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<!-- apollo -->
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>${apollo.version}</version>
</dependency>
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-core</artifactId>
<version>${apollo.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger2.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger2.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<exclusions>
<exclusion>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>${xstream.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatisplus.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--oss -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>${aliyun-sdk-oss.version}</version>
</dependency>
<!--cos -->
<dependency>
<groupId>com.qcloud</groupId>
<artifactId>cos_api</artifactId>
<version>${cos_api.version}</version>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>${rocketmq.version}</version>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-acl</artifactId>
<version>${rocketmq.version}</version>
</dependency>
<dependency>
<groupId>com.aliyun.mq</groupId>
<artifactId>mq-http-sdk</artifactId>
<!--以下版本号请替换为Java SDK的最新版本号-->
<version>${mq-http-sdk.version}</version>
<classifier>jar-with-dependencies</classifier>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- 分库分表 -->
<!--
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>${sharding-sphere.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-namespace</artifactId>
<version>${sharding-sphere.version}</version>
</dependency>
-->
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<configuration>
<target>
<copy todir="../deploy" overwrite="true">
<fileset dir="${project.build.directory}">
<include name="${project.artifactId}.jar" />
</fileset>
</copy>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
最后新增一下资源文件,配置服务的端口信息等。
bootstrap.yml
#应用ID
app:
id: ctg-member-plat
#应用端口
server:
port: 9003
#服务名称
spring:
application:
name: hn-maoheyeren-business
servlet:
multipart:
max-file-size: 1024MB #指定上传文件允许的最大大小。 默认值为1MB
max-request-size: 10240MB #指定multipart/form-data请求允许的最大大小。 默认值为10MB。
#配置注册中心
eureka:
instance:
prefer-ip-address: true
instance-id: ${spring.cloud.client.ip-address}:${server.port}
client:
service-url:
defaultZone: ${eureka.defaultZone} #服务注册到的地址
fetch-registry: true
#阿波罗配置信息
apollo:
bootstrap:
enabled: true
namespaces: application,txyunjdbc.yml,redis.yml
meta: http://member-config:8080
mybatis:
#mapper配置文件
mapper-locations: classpath:mapper/*.xml
#开启驼峰命名法
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mybatis-plus:
configuration:
# 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
id-type: ASSIGN_UUID
#日志级别配置信息
logging:
level:
root: INFO
cn.ctg.member.dao: DEBUG
最后给在网关中配置一下微服务的转发路径,就可以进行开发了 。