Java生鲜电商平台-微服务入门与服务的拆分架构实战

刚开始进入软件行业时还是单体应用的时代,前后端分离的概念都还没普及,开发的时候需要花大量的时间在“强大”的JSP上面,那时候SOA已经算是新技术了。现在,微服务已经大行其道,有哪个互联网产品不说自己是微服务架构呢?

但是,对于微服务的理解每个人都不太一样,这篇文章主要是聊一聊我对微服务的理解以及如何搭建经典的微服务架构,目的是梳理一下自己的一些想法,如果存在不同看法的欢迎指正!

什么是微服务

首先,什么是微服务呢?

单体应用

相对的,要理解什么是微服务,那么可以先理解什么是单体应用,在没有提出微服务的概念的“远古”年代,一个软件应用,往往会将应用所有功能都开发和打包在一起,那时候的一个B/S应用架构往往是这样的:

 
B/S

但是,当用户访问量变大导致一台服务器无法支撑时怎么办呢?加服务器加负载均衡,架构就变成这样了:

 
B/S+负载均衡

后面发现把静态文件独立出来,通过CDN等手段进行加速,可以提升应用的整体相应,单体应用的架构就变成:

 
B/S+前后端分离

上面3中架构都还是单体应用,只是在部署方面进行了优化,所以避免不了单体应用的根本的缺点:

  • 代码臃肿,应用启动时间长;(代码超过1G的项目都有!)
  • 回归测试周期长,修复一个小小bug可能都需要对所有关键业务进行回归测试。
  • 应用容错性差,某个小小功能的程序错误可能导致整个系统宕机;
  • 伸缩困难,单体应用扩展性能时只能整个应用进行扩展,造成计算资源浪费。
  • 开发协作困难,一个大型应用系统,可能几十个甚至上百个开发人员,大家都在维护一套代码的话,代码merge复杂度急剧增加。

微服务

我认为任何技术的演进都是有迹可循的,任何新技术的出现都是为了解决原有技术无法解决的需求,所以,微服务的出现就是因为原来单体应用架构已经无法满足当前互联网产品的技术需求。

在微服务架构之前还有一个概念:SOA(Service-Oriented Architecture)-面向服务的体系架构。我认为的SOA只是一个架构模型的方法论,并不是一个明确而严谨的架构标准,只是后面很多人将SOA与The Open Group的SOA参考模型等同了,认为严格按照TOG-SOA标准的才算真正的SOA架构。SOA就已经提出的面向服务的架构思想,所以微服务应该算是SOA的一种演进吧。

撇开架构先不说,什么样的服务才算微服务呢?

  • 单一职责的。一个微服务应该都是单一职责的,这才是“微”的体现,一个微服务解决一个业务问题(注意是一个业务问题而不是一个接口)。
  • 面向服务的。将自己的业务能力封装并对外提供服务,这是继承SOA的核心思想,一个微服务本身也可能使用到其它微服务的能力。
    我觉得满足以上两点就可以认为典型的微服务。

微服务典型架构

微服务架构,核心是为了解决应用微服务化之后的服务治理问题。

应用微服务化之后,首先遇到的第一个问题就是服务发现问题,一个微服务如何发现其他微服务呢?最简单的方式就是每个微服务里面配置其他微服务的地址,但是当微服务数量众多的时候,这样做明显不现实。所以需要使用到微服务架构中的一个最重要的组件:服务注册中心,所有服务都注册到服务注册中心,同时也可以从服务注册中心获取当前可用的服务清单:

 
服务注册中心

解决服务发现问题后,接着需要解决微服务分布式部署带来的第二个问题:服务配置管理的问题。当服务数量超过一定程度之后,如果需要在每个服务里面分别维护每一个服务的配置文件,运维人员估计要哭了。那么,就需要用到微服务架构里面第二个重要的组件:配置中心,微服务架构就变成下面这样了:

 
配置中心

以上应用内部的服务治理,当客户端或外部应用调用服务的时候怎么处理呢?服务A可能有多个节点,服务A、服务B和服务C的服务地址都不同,服务授权验证在哪里做?这时,就需要使用到服务网关提供统一的服务入口,最终形成典型微服务架构:

 
典型微服务架构

上面是一个典型的微服务架构,当然微服务的服务治理还涉及很多内容,比如:

  • 通过熔断、限流等机制保证高可用;
  • 微服务之间调用的负载均衡;
  • 分布式事务(2PC、3PC、TCC、LCN等);
  • 服务调用链跟踪等等。

微服务框架

目前国内企业使用的微服务框架主要是Spring Cloud和Dubbo(或者DubboX),但是Dubbo那两年的停更严重打击了开发人员对它的信心,Spring Cloud已经逐渐成为主流,比较两个框架的优劣势的文章在网上有很多,这里就不重复了,选择什么框架还是按业务需求来吧,业务框架决定技术框架。
Spring Cloud全家桶提供了各种各样的组件,基本可以覆盖微服务的服务治理的方方面面,以下列出了Spring Cloud一些常用组件:

 
Spring Cloud常用组件

搭建典型微服务架构

本章节主要介绍如何基于Spring Cloud相关组件搭建一个典型的微服务架构。
首先,创建一个Maven父项目spring-cloud-examples,用于管理项目依赖包版本。由于Spring Cloud组件很多,为保证不同组件之间的兼容性,一般通过spring-cloud-dependencies统一管理Spring Cloud组件版本,而非每个组件单独引入。

pom.xml配置如下:

    <!-- 继承SpringBoot父项目,注意与SpringCloud版本的匹配 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
</parent> <properties>
<spring.boot.version>2.1.4.RELEASE</spring.boot.version>
<spring.cloud.version>Greenwich.SR1</spring.cloud.version>
<lombok.version>1.18.8</lombok.version>
<maven.compiler.plugin.version>3.8.1</maven.compiler.plugin.version>
</properties> <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>

搭建服务配置中心

  • spring-cloud-examples项目下创建一个子项目spring-cloud-example-config,添加Spring Cloud Config Server端的相关依赖包:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
</dependencies>
  • 添加Spring Boot配置文件application.yml,配置如下:
spring:
application:
name: spring-cloud-example-config
profiles:
active: native #启用本地配置文件
cloud:
config:
server:
native:
search-locations: classpath:/configs/ #配置文件扫描目录 server:
port: 8000 #服务端口
  • 启动类添加注解@EnableConfigServer通过启用Config Server服务。
@SpringBootApplication
@EnableConfigServer
public class Application { public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

搭建服务注册中心

  • spring-cloud-examples项目下创建一个子项目spring-cloud-example-registry,在pom.xml中添加Eureka Server相关依赖包:
    <dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-eureka-server</artifactId>
</dependency> <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies>
  • spring-cloud-example-config配置中心项目的src/main/resource/configs目录下添加一个服务配置文件spring-cloud-example-registry.yml,配置如下:
spring:
application:
name: spring-cloud-example-registry # Eureka相关配置
eureka:
client:
register-with-eureka: false #不注册服务
fetch-registry: false #不拉去服务清单
serviceUrl:
defaultZone: http://localhost:${server.port}/eureka/ #多个通过英文逗号分隔 server:
port: 8001
  • spring-cloud-example-registry项目的src/main/resource/目录添加bootstrap.yml配置文件,配置如下:
spring:
cloud:
config:
name: spring-cloud-example-registry #配置文件名称,多个通过逗号分隔
uri: http://localhost:8000 #Config Server服务地址
  • 启动类添加注解@EnableEurekaServer通过启用Eureka Server服务。
@SpringBootApplication
@EnableEurekaServer
public class Application { public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

搭建业务服务A

  • spring-cloud-examples项目下创建一个业务服务A的子项目spring-cloud-example-biz-a,在pom.xml中添加以下依赖包:
    <dependencies>
<!-- Spring Boot Web Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <!-- feign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency> <!-- Eureka Client Starter -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency> <!-- Config Client Starter -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies>
  • spring-cloud-example-config配置中心项目的src/main/resource/configs目录下添加一个服务配置文件spring-cloud-example-biz-a.yml,配置如下:
spring:
application:
name: spring-cloud-example-biz-a server:
port: 8010 # Eureka相关配置
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8001/eureka/
instance:
lease-renewal-interval-in-seconds: 10 # 心跳时间,即服务续约间隔时间(缺省为30s)
lease-expiration-duration-in-seconds: 60 # 发呆时间,即服务续约到期时间(缺省为90s)
prefer-ip-address: true
instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
  • spring-cloud-example-biz-a项目的src/main/resource/目录添加bootstrap.yml配置文件,配置如下:
spring:
cloud:
config:
name: spring-cloud-example-biz-a #配置文件名称,多个通过逗号分隔
uri: http://localhost:8000 #Config Server服务地址
  • 添加一个示例接口,代码参考:
@RestController
@RequestMapping("/hello")
public class HelloController {
/**
* 示例方法
*
* @return
*/
@GetMapping
public String sayHello() {
return "Hello,This is Biz-A Service.";
}
}

搭建业务服务B

参考上面业务服务A搭建另外一个业务服务B。

搭建服务网关

  • spring-cloud-examples项目下创建一个业务服务A的子项目spring-cloud-example-gateway,在pom.xml中添加以下依赖包:
    <dependencies>
<!-- zuul -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency> <!-- Eureka Client Starter -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency> <!-- Config Client Starter -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies>
  • spring-cloud-example-config配置中心项目的src/main/resource/configs目录下添加一个服务配置文件spring-cloud-example-gateway.yml,配置如下:
spring:
application:
name: spring-cloud-example-gateway server:
port: 8002 # Eureka相关配置
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8001/eureka/
instance:
lease-renewal-interval-in-seconds: 10 # 心跳时间,即服务续约间隔时间(缺省为30s)
lease-expiration-duration-in-seconds: 60 # 发呆时间,即服务续约到期时间(缺省为90s)
prefer-ip-address: true
instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
  • spring-cloud-example-gateway项目的src/main/resource/目录添加bootstrap.yml配置文件,配置如下:
spring:
cloud:
config:
name: spring-cloud-example-gateway #配置文件名称,多个通过逗号分隔
uri: http://localhost:8000 #Config Server服务地址
  • 启动类添加注解@EnableZuulProxy通过启用网关代理服务。
@SpringBootApplication
@EnableZuulProxy
public class Application { public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

启动示例

  • 启动顺序
    spring-cloud-example-config>>spring-cloud-example-eureka>>spring-cloud-example-biz-a/spring-cloud-example-biz-b/spring-cloud-example-gateway

  • 通过网关访问服务A接口

     
    服务A调用
  • 通过网关访问服务B接口

     
    服务B调用

服务之间调用

  • 在业务服务A中添加一个Feign Client Bean,参考代码如下:
@FeignClient(name = "spring-cloud-example-biz-b") # 指定服务名称
public interface RemoteService { /**
* 调用服务B的hello方法
*
* @return
*/
@GetMapping("/hello") #指定请求地址
String sayHello();
}
  • 业务服务A示例接口类增加call2b接口,代码如下:
@RestController
@RequestMapping("/hello")
public class HelloController { @Autowired
private RemoteService remoteService; /**
* 示例方法
*
* @return
*/
@GetMapping
public String sayHello() {
return "Hello,This is Biz-A Service.";
} /**
* 示例方法:调用服务B
*
* @return
*/
@GetMapping(path = "/call2b")
public String sayHello2B() {
return remoteService.sayHello();
}
}
  • 重启业务服务A,通过调用/hello/call2b接口:

     
    服务之间调用

下一代微服务

目前网上很多说是下一代微服务架构就是Service Mesh,Service Mesh主流框架有Linkerd和Istio,其中Istio有大厂加持所以呼声更高。Service Mesh我接触还不多,但是个人感觉并不一定能称为下一代微服务架构,可能认为是服务治理的另外一种解决方案更合适,是否能够取代当前的微服务架构还需要持续观察。

Java生鲜电商平台-微服务入门与服务的拆分架构实战的更多相关文章

  1. Java生鲜电商平台-商家支付系统与对账系统架构实战

    Java生鲜电商平台-商家支付系统与对账系统架构实战 说明:关于生鲜电商平台,支付系统是连接消费者.商家(或平台)和金融机构的桥梁,管理支付数据,调用第三方支付平台接口,记录支付信息(对应订单号,支付 ...

  2. Java生鲜电商平台-微服务架构概述

    Java生鲜电商平台-微服务架构概述 单体架构存在的问题 在传统的软件技术架构系统中,基本上将业务功能集中在单一应用内,或者是单一进程中.尽管现代化的软件架构理论以及设计原则已推广多年,但实际技术衍化 ...

  3. Java生鲜电商平台-商品无限极目录的设计与架构

    Java生鲜电商平台-商品无限极目录的设计与架构 说明:任何一个商品都应该是先属于某一个目录,然后在目录中添加商品,目录理论上最多支持三级,因为级别太多,不容易管理.但是设计中需要设计无限制的级别. ...

  4. Java生鲜电商平台-SpringCloud微服务开发中的数据架构设计实战精讲

    Java生鲜电商平台-SpringCloud微服务开发中的数据架构设计实战精讲 Java生鲜电商平台:   微服务是当前非常流行的技术框架,通过服务的小型化.原子化以及分布式架构的弹性伸缩和高可用性, ...

  5. Java生鲜电商平台-SpringCloud分布式请求跟踪系统设计与实践

    Java生鲜电商平台-SpringCloud分布式请求跟踪系统设计与实践 Java生鲜电商平台微服务现状 某个服务挂了,导致上游大量报警,如何快速定位哪个服务出问题? 某个核心挂了,导致大量报错,如何 ...

  6. Java开源生鲜电商平台-订单抽成模块的设计与架构(源码可下载)

    Java开源生鲜电商平台-订单抽成模块的设计与架构(源码可下载) 说明:订单抽成指的是向卖家收取相应的信息服务费.(目前市场上有两种抽成方式,一种是按照总额的抽成比率,另外一种是按照订单明细的抽成比率 ...

  7. Java生鲜电商平台-生鲜系统中微服务架构设计与分析实战

    Java生鲜电商平台-生鲜系统中微服务架构设计与分析实战 说明: Java生鲜系统中微服务的拆分应该如何架构设计与分析呢?以下是我的实战中的设计与经验分析. 目录 1. 微服务简介2. 当前现状3. ...

  8. Java生鲜电商平台-SpringCloud微服务架构中分布式事务解决方案

    Java生鲜电商平台-SpringCloud微服务架构中分布式事务解决方案 说明:Java生鲜电商平台中由于采用了微服务架构进行业务的处理,买家,卖家,配送,销售,供应商等进行服务化,但是不可避免存在 ...

  9. Java生鲜电商平台-深入理解微服务SpringCloud各个组件的关联与架构

    Java生鲜电商平台-深入理解微服务SpringCloud各个组件的关联与架构 概述 毫无疑问,Spring Cloud是目前微服务架构领域的翘楚,无数的书籍博客都在讲解这个技术.不过大多数讲解还停留 ...

随机推荐

  1. NFS客户端挂载及永久生效

    1.NFS客户端挂载的命令格式: 挂载命令 挂载的格式类型 NFS服务器提供的共享目录 NFS客户端要挂载的目录mount -t nfs 服务器IP:/共享目录 /本地的挂载点(必须存在) 重启失效 ...

  2. JavaScript -- 筑基

    本片博客记录了我JavaScript筑基阶段的学习内容,JavaScript不是Java,但是我下意识的把它和java对比学习,有些地方比较有趣,有些地方从java角度看,简直匪夷所思,不过现在总体感 ...

  3. PHP给图片加上图片水印和文字水印实例

    下面给大家分享一下PHP给图片加上图片水印和文字水印实例,这也是网站经常用到的功能,把代码加上去,调用就很简单了. 核心代码: function imageWaterMark($groundImage ...

  4. javaWeb技术第二篇之CSS、事件和案例

    <!--内联式 CSS (层叠样式表) 编辑 层叠样式表(英文全称:Cascading Style Sheets) CSS不仅可以静态地修饰网页,还可以配合各种脚本语言动态地对网页各元素进行格式 ...

  5. 自学_DOM<五>

    类库DOM DOM(document object medol)文档对象模型. DOM就是HTML页面的模型,将每个标签都做为一个对象,JavaScript通过调用DOM中的属性.方法就可以对网页中的 ...

  6. 剑指offer笔记面试题13----机器人的运动范围

    题目:地上有一个m行n列的方格.一个机器人从坐标(0, 0)的格子开始移动,它每次可以向左.右.上.下移动一格,但不能进入行坐标和列坐标的数位之和大于k的格子.例如,当k为18时,机器人能够进入方格( ...

  7. PHP mysqli_stat MySQLi 函数

    定义和用法 mysqli_stat - 获取当前系统状态信息 版本支持 PHP4 PHP5 PHP7 不支持 支持 支持 语法 mysqli_stat ( mysqli $link ) mysqli_ ...

  8. Linux相关集合

    本篇概述 Linux xshell6 连接 Hadoop 启动关闭 Linux xshell6 连接相关问题 首先,虚拟机 得先能通成网(具体教程可百度) 然后,进行 本机 ip 的查询(xshell ...

  9. 【三】Gradle中的Task

    gradle中,最经常被使用的,一个task,一个是dependencies 1.Task声明 task默认是DefaultTask类, Task中有两个属性 group description,最佳 ...

  10. Redis—配置文件详解

    https://www.cnblogs.com/shizhengwen/p/9283973.html https://www.cnblogs.com/yangy608/p/4443665.html h ...