百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

已经被说“烂”的微服务,到底是什么鬼?拆分实战案例来带你入门。

ztj100 2025-03-04 15:57 9 浏览 0 评论

刚开始进入软件行业时还是单体应用的时代,前后端分离的概念都还没普及,开发的时候需要花大量的时间在“强大”的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配置如下:

    
    
        org.springframework.boot
        spring-boot-starter-parent
        2.1.4.RELEASE
    

    
        2.1.4.RELEASE
        Greenwich.SR1
        1.18.8
        3.8.1
    


    
        
            
                org.springframework.cloud
                spring-cloud-dependencies
                ${spring.cloud.version}
                pom
                import
            
        
    

搭建服务配置中心

  • 在spring-cloud-examples项目下创建一个子项目spring-cloud-example-config,添加Spring Cloud Config Server端的相关依赖包:

        
            org.springframework.cloud
            spring-cloud-config-server
        
    
  • 添加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相关依赖包:
    
        
            org.springframework.cloud
            spring-cloud-netflix-eureka-server
        

        
            org.springframework.cloud
            spring-cloud-starter-config
        
    
  • 在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中添加以下依赖包:
    
        
        
            org.springframework.boot
            spring-boot-starter-web
        

        
        
            org.springframework.cloud
            spring-cloud-starter-openfeign
        

        
        
            org.springframework.cloud
            spring-cloud-starter-netflix-eureka-client
        

        
        
            org.springframework.cloud
            spring-cloud-starter-config
        
    
  • 在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中添加以下依赖包:
    
        
        
            org.springframework.cloud
            spring-cloud-starter-netflix-zuul
        

        
        
            org.springframework.cloud
            spring-cloud-starter-netflix-eureka-client
        

        
        
            org.springframework.cloud
            spring-cloud-starter-config
        
    
  • 在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我接触还不多,但是个人感觉并不一定能称为下一代微服务架构,可能认为是服务治理的另外一种解决方案更合适,是否能够取代当前的微服务架构还需要持续观察。

相关推荐

告别手动操作:一键多工作表合并的实用方法

通常情况下,我们需要将同一工作簿内不同工作表中的数据进行合并处理。如何快速有效地完成这些数据的整合呢?这主要取决于需要合并的源数据的结构。...

【MySQL技术专题】「优化技术系列」常用SQL的优化方案和技术思路

概述前面我们介绍了MySQL中怎么样通过索引来优化查询。日常开发中,除了使用查询外,我们还会使用一些其他的常用SQL,比如INSERT、GROUPBY等。对于这些SQL语句,我们该怎么样进行优化呢...

9.7寸视网膜屏原道M9i双系统安装教程

泡泡网平板电脑频道4月17日原道M9i采用Win8安卓双系统,对于喜欢折腾的朋友来说,刷机成了一件难事,那么原道M9i如何刷机呢?下面通过详细地图文,介绍原道M9i的刷机操作过程,在刷机的过程中,要...

如何做好分布式任务调度——Scheduler 的一些探索

作者:张宇轩,章逸,曾丹初识Scheduler找准定位:分布式任务调度平台...

mysqldump备份操作大全及相关参数详解

mysqldump简介mysqldump是用于转储MySQL数据库的实用程序,通常我们用来迁移和备份数据库;它自带的功能参数非常多,文中列举出几乎所有常用的导出操作方法,在文章末尾将所有的参数详细说明...

大厂面试冲刺,Java“实战”问题三连,你碰到了哪个?

推荐学习...

亿级分库分表,如何丝滑扩容、如何双写灰度

以下是基于亿级分库分表丝滑扩容与双写灰度设计方案,结合架构图与核心流程说明:一、总体设计目标...

MYSQL表设计规范(mysql表设计原则)

日常工作总结,不是通用规范一、表设计库名、表名、字段名必须使用小写字母,“_”分割。...

怎么解决MySQL中的Duplicate entry错误?

在使用MySQL数据库时,我们经常会遇到Duplicateentry错误,这是由于插入或更新数据时出现了重复的唯一键值。这种错误可能会导致数据的不一致性和完整性问题。为了解决这个问题,我们可以采取以...

高并发下如何防重?(高并发如何防止重复)

前言最近测试给我提了一个bug,说我之前提供的一个批量复制商品的接口,产生了重复的商品数据。...

性能压测数据告诉你MySQL和MariaDB该怎么选

1.压测环境为了尽可能的客观公正,本次选择同一物理机上的两台虚拟机,一台用作数据库服务器,一台用作运行压测工具mysqlslap,操作系统均为UbuntuServer22.04LTS。...

屠龙之技 --sql注入 不值得浪费超过十天 实战中sqlmap--lv 3通杀全国

MySQL小结发表于2020-09-21分类于知识整理阅读次数:本文字数:67k阅读时长≈1:01...

破防了,谁懂啊家人们:记一次 mysql 问题排查

作者:温粥一、前言谁懂啊家人们,作为一名java开发,原来以为mysql这东西,写写CRUD,不是有手就行吗;你说DDL啊,不就是设计个表结构,搞几个索引吗。...

SpringBoot系列Mybatis之批量插入的几种姿势

...

MySQL 之 Performance Schema(mysql安装及配置超详细教程)

MySQL之PerformanceSchema介绍PerformanceSchema提供了在数据库运行时实时检查MySQL服务器的内部执行情况的方法,通过监视MySQL服务器的事件来实现监视内...

取消回复欢迎 发表评论: