一、微服务概念
1.1 单体架构及其不足
一个典型单体应用Java工程包含表示层的JSP、业务逻辑层的Service、Controller和数据访问层的Dao,然后打成war包部署在Tomcat、Jetty等Servlet容器中运行,如图1-1所示
表 示 层:用于直接和用户交互,通常是UI、网页等
业务逻辑层:业务逻辑处理层,例如数据要经过业务逻辑层处理后,才能展现
数据访问层:用于操作数据库,用户在表示层会产生大量的数据,通过数据访问层对数据进行操作
在应用初始阶段,业务复杂度和业务体量都比较低,单体架构无论在开发速度上,还是运维难度上,还是服务器成本上都有显著优点。随着业务的发展和业务复杂度的提高,这种架构开始出现不足,主要体现在:
(1)业务越来越复杂,代码的可读性、可维护性和可拓展性下降
(2)用户越来越多,单体应用的并发能力有限
(3)业务扩张,复杂度增加,修改业务或增加业务会影响其他业务,测试难度越来越大。
1.2 单体架构使用集群及其不足
那么,将单体架构集群部署,是否更好些呢?
如图1-2:
(1)用负载均衡服务器分发高并发网络请求;
(2)通过添加缓存服务器以缓解数据库读取数据的压力;
(3)当有大量读写操作时,将数据库进行读写分离,能够改善数据库的负载能力。

单体服务集群化,有一定的处理高并发的能力,也能应对一定复杂的业务需求,改善系统性能,但依然没有改变系统为单体架构的事实,还存在以下不足之处:
(1)依然为单体应用,代码的可读性和可维护性依然很差。
(2)面对海量的用户,数据库将会成为瓶颈。解决办法将使用分布式数据库,将数据库分库分表。
(3)持续交付能力差,业务越复杂,代码越多,修改或添加代码所需的时间越长。新人熟悉代码的时间长,成本高。
虽然在应用初期,单体应用从成本、开发时间和运维等方面有优势。但随着用户增加,单体架构暴露的缺点显而易见,已经不能满足复杂的业务和海量用户系统。于是,微服务架构应运而生。
1.3微服务简介
微服务大概从2017年开始在各大技术社区、博客、论坛和新闻报道中经常被提及,是程序员和架构师经常讨论的话题。“微服务”最初是由Martin Fowler在2014年写的一篇文章《MicroService》中提出来的。他的理解:
“简而言之,微服务架构的风格,就是将单一程序开发成一个微服务,每个微服务运行在自己的进程中,并使用轻量级机制通信,通常是HTTP RESTFUL API。这些服务围绕业务能力来划分构建的,并通过完全自动化部署机制来独立部署。这些服务可以使用不同的编程语言,以及不同数据存储技术,以保证最低限度的集中式管理。”
思考Martin Fowler对微服务的理解,总结微服务具有如下特点:
(1)按业务划分为一个独立运行的程序,即服务单元
(2)服务之间通过HTTP通信
(3)自动化部署
(4)可以用不同的编程语言构建微服务
(5)可以用不同的存储技术
(6) 服务集中化管理
(7)是一个分布式系统
下面按以上几点展开对微服务的阐述
1. 微服务多 “微”才合适?
“微”到什么程度?一直“微”下去,也不能“大事化小,小事化无”。
根据代码量来定义
根据开发时间长短来定义
根据业务大小来划分…(比较常用)
划分要求:服务单一职责
低耦合、高内聚
拓展性和复用性良好…
具体讲业务拆分到什么粒度,需要开发人员自己去决定
【常见实践一:统一服务层】
最粗犷的玩法,所有基础数据,都通过一个统一的服务来进行访问。在业务不是特别复杂的时候,这不失为一个快速分层的方案,一旦业务变得复杂,服务层会变得非常重,成为耦合焦点

【常见实践一:统一服务层2】
统一的服务层,用户信息,好友信息,群组信息,消息信息都通过这个服务层来访问

【常见实践二:一个子业务一个服务】
统一的服务层,用户信息,好友信息,群组信息,消息信息都通过这个服务层来访问。服务粒度变细之后,出现一个新的问题,业务与服务的连接关系变复杂了,有什么好的优化方案么?

加入一个高可用服务分发层(例如Service Mesh),并在协议设计时加入服务号,可以减少蜘蛛网状的依赖关系。

【常见实践三:一个数据库对应一个服务】
在一个子业务对应一个服务的基础上,如图1-7,拆分成一个数据库一个服务。群信息库,群成员库,群消息库之间也解耦开,不会相互影响

【常见实践四:一个接口对应一个服务】
微服务架构中,更极端的,甚至一个接口对应一个微服务,架构从图1-9演变为图1-10。多个服务操纵同一个数据库,任何接口服务出问题,都不会影响其他接口服务
(以上是4类常见实践,以“子业务”作为微服务粒度是最常用,订单服务,用户服务,支付服务等等)

2. 微服务通过HTTP来相互通信
微服务单元之间的通信方式一般倾向于使用HTTP这种简单的通信机制,更多的时候是使用RESTful API。这种接受请求、处理业务逻辑、返回数据的HTTP模式非常高效,且这种通信机制与平台和语言无关,如图1-11。
不过,服务之间也可以通
过轻量级消息总线来通信,
例如RabbitMQ、Kafka等。
通信数据格式一般为XML、
JSON

3. 微服务的数据库独立
在单体架构中,所有的业务都共用一个数据库,如图1-12。随着业务的增加,数据库的数据量越来越多,难以管理和维护,并且数据量的增加会导致查询速度越来越慢。

一个典型的微服务架构,每个微服务都有自己独立的数据库,数据库之间没有任何联系。主要有两点好处:
(1)随着业务不断扩张,服务与服务不需要提供数据集成,而是提供API接口相互调用;
(2)数据库独立,单业务的数据量少,易于维护,数据库性能有着明显优势,数据库迁移也方便。
随着存储方式多样化,一个典型的微服务系统,还有可能每一个服务的数据库都不同,需要根据业务需要来选择。如图1-13

4. 微服务的自动化部署

5. 服务集中化管理
按业务单元划分的微服务,数量越多,管理起来越复杂,因为要使用集中化管理。目前流行的微服务框架中,Spring Cloud采用Eureka来注册和发现服务,Zookeeper、Consul等都是比较凸出的服务集中化管理框架。
6. 微服务架构是分布式架构
微服务架构是分布式架构,基于微服务框架构建的系统是分布式系统,采用集群部署。它所带来的好处:
(1)能够处理海量用户请求
(2)对用户透明无感,还以为是一台服务器在提供服务
(3)在空间上没有任何限制,可以部署在不同机房和不同地区
…
分布式系统复杂的地方:
(1)服务的独立性和服务相互调用的可靠性
(2)分布式事务、全局锁、全局ID等
(3)集群化部署,会给数据一致性带来困难
(4)”雪崩效应”(后面介绍)
…
如果在A的链路上某个或几个被调用的子服务
不可用或延迟较高,则会导致调用A服务的请求被
堵住。堵住的请求会消耗占用掉系统的线程、io等
资源,当该类请求越来越多,占用的计算机资源越
来越多的时候,会导致系统瓶颈出现,造成其他的
请求同样不可用,最终导致业务系统崩溃,
又称:雪崩效应。


7. 熔断机制
为防止“雪崩效应”事件的发生,分布式系统采用了熔断机制。在用Spring Cloud构建的微服务系统中,采用了Hystrix组件的circuit Breaker(熔断器)去做熔断。
微服务系统中,有a、b、c、d、e、f、g、h多个服务,用户请求通过网关后,再到具体服务,服务之间相互依赖,例如b依赖f,一个对外暴露的API接口需要b和f协作才能完成,如图1-18。

如果此时b出现故障或网络延迟,会怎么样?
(1)高并发情况下,b会出现线程阻塞,
线程耗尽,导致b本身不可用
(2)其他依赖b的服务会一直等待b的处理,导致大量请求堆积到这些服务,而不仅仅是b…
(3)情况如此恶化下去,从而由b开始,由于故障的传播性,导致整个系统的不可用
于是,微服务框架引入熔断机制
当b出现故障,请求失败次数超过设定的阀值之后,b就会开启熔断器,之后b不进行业务逻辑处理,并咨询过快速失败,直接返回请求失败的信息。这样,就不会出现线程阻塞甚至“雪崩效应”事件。保证了除了b和依赖于b的其他服务正常被使用。

总结-微服务的优势
(1)增加了代码的可读性和可拓展性
(2)服务之间没有任何耦合,可以根据业务再拆分业务,具有极强的横向拓展能力
(3)服务之间完全独立且采用HTTP网络通信协议来通信,使得微服务可以采用任何开发语言和技术来实现。提高开发效率、降低开发成本
(4)微服务有坚实的服务边界,重写某个服务就相当于重写某个业务代码,降低了修改代码产生的风险,节省了修改代码的时间
(5)微服务的修改和部署不影响其他服务,相比单体应用,大大减少了测试和部署的时间
(6)采用CAP理论中的AP架构,具有高可用和分区容错的特点(CAP理论指的是一个分布式系统最多只能同时满足一致性[Consistency]、可用性[Availability]和分区容错性[Partition tolerance]这三项中的两项。如图1-20)

总结-微服务的不足
(1)微服务的复杂度
(2)分布式事务
(3)服务的划分
(4)服务的部署
二、Spring Cloud概念及常用组件
2.1 微服务应该具备的功能
1. 服务注册与发现
服务注册是指向注册中心注册一个服务实例。服务提供者将自己的服务名、IP地址等信息告知服务注册中心。
服务发现是指当服务消费者需要消费另一个服务的情况时,服务注册中心能够告知服务消费者她所要消费服务的实例信息。
服务注册中心会提供服务的健康检查方案,检查被注册的服务是否可用。

2. 服务的负载均衡
在微服务架构中,服务间相互调用一般通过HTTP通信协议来实现。网络往往具有不可靠性,为了保证服务的高可用,服务单元往往是集群化部署,集群化部署必然会用到负载均衡,一般最流行的做法如图2-2所示,服务消费者集成负载均衡组件即可,该组件每隔一段时间向服务消费者重新刷新获取服务注册表信息,当消费服务时,通过一定的负载均衡策略(可配置),选择一个服务提供者,向该实例进行服务消费。

2_2. 服务的负载均衡-注册中心高可用
注册中心不仅接收每个服务的心跳,而且每个服务要定期获取服务注册表信息,当服务数量很多时,注册中心承担非常大的负载。注册中心在微服务系统起到关键作用,所以必须实现高可用。一般做法是将注册中心集群化,如图3-3

3. 服务容错
由于微服务系统中服务数量很多且相互间的依赖性错综复杂(如图2-4),一个网络请求需要调用多个服务才能完成。避免因个别服务不可用导致的多个服务不可用、级联故障、甚至系统瘫痪,即“雪崩效应”,必不可少。分布式系统引入熔断器机制来解决。

3. 服务容错-熔断器机制
熔断器机制,不仅能够防止系统的“雪崩效应”,还具有以下作用:
(1)隔离资源
(2)服务降级功能
(3)自我修复能力

4. 服务网关
网关意义:
(1)统一聚合所有服务的API接口资源
(2)用户身份认证、权限认证
(3)实现监控功能
(4)做流量监控,高流量时对服务降级
(5)API接口从内部服务分离出来,方便做测试
网关需要做高可用,否则网关本身可能成为瓶颈。最常用的网关组件有Zuul、Nginx等

5. 服务配置统一管理
大致过程:
(1)Config Server读取配置文件仓库的配置信息。配置文件仓库可以存放在配置服务的本地仓库,也可以放在远程的Git仓库(GitHub、Coding等)
(2)配置服务启动后,读取配置文件信息,读取完成的配置信息存放在配置服务内存中
(3)当服务A、B启动时,由于A、B指向了向配置服务读取配置信息,A、B向配置服务读取配置信息
(4)当配置信息需要修改且修改完成后,向配置服务发送Post请求进行刷新,A、B会重新读取配置文件

6. 服务链路追踪
为什么需要服务链路追踪?
由于微服务单元数量很多且业务复杂,服务与服务之间的调用可能非常复杂,一旦出现异常和错误,就会很难去定位。所以,在微服务架构中,必须实现分布式链路追踪。目前,常见的开源链路追踪组件有Google的Dapper、Twitter的Zipkin、以及阿里的Eagleeye等。

3.2 Spring Cloud及相关组件
1. Spring Cloud简介
Spring Cloud首要目标就是通过提供一系列开发组件和框架,帮助开发者迅速搭建一个分布式的微服务系统。在开发部署上继承了Spring Boot的一些优点,提高其在开发和部署上的效率。
Spring Cloud来自于Spring Resource社区,由Pivotal和Netflix两大公司和一些其他的开发者提供技术上的更新迭代。
Spring Cloud提供了诸如服务注册与发现、配置中心、熔断器、智能路由、微代理、控制总线、全局锁、分布式会话等开发分布式微服务系统的一些常用组件。下面介绍如何使用这些常用组件
2. 服务注册与发现组件Eureka
(1) 添加Maven依赖
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
注:这个依赖的artifactId在Edgware以前是spring-cloud-starter-eureka-server,而在之后变成了spring-cloud-starter-netflix-eureka-server。其他组件也是类似
(2) 在启动类中加入注解@EnableEurekaServer
@SpringBootApplication
@EnableEurekaServer
public class EurekaCenter {
public static void main(String[] args) {
SpringApplication.run(EurekaCenter.class, args);
}
}
注:这个依赖的artifactId在Edgware以前是spring-cloud-starter-eureka-server,而在之后变成了spring-cloud-starter-netflix-eureka-server。其他组件也是类似
3. 熔断组件Hystrix
(1) 添加Maven依赖
org.springframework.cloud
spring-cloud-starter-netflix-hystrix
(2) 启动类上添加@EnableHystrix注解
@EnableHystrix //在启动类上添加@EnableHystrix注解开启Hystrix的熔断器功能。
@EnableEurekaClient
@SpringBootApplication
public class RibbonConsumerApplication {
//当添加@LoadBalanced注解,就代表启动Ribbon,进行负载均衡
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(RibbonConsumerApplication.class, args);
}
}
(3) 添加HystrixConsumerController
/** 消费者 /
@Slf4j
@RestController
@RequestMapping("/hystrix/consumer")
public class HystrixConsumerController {
@Autowired
private RestTemplate restTemplate;
/* 调用 user微服务*/
@HystrixCommand(fallbackMethod = “getDefaultUser”)
@GetMapping(“getUser”)
public String getUser(Integer id) {
String url = “http://user-service/provider/getUser?id=” + id;
return restTemplate.getForObject(url, String.class);
}
(3) 添加HystrixConsumerController
public String getDefaultUser(Integer id) {
System.out.println(“熔断,默认回调函数”);
return “{“id”:-1,“name”:“熔断用户”,“password”:“123456”}”;
}
}
(4)测试
代码编写之后,按顺序启动spring-cloud-eureka、spring-cloud-user-service和spring-cloud-consumer-ribbon,此时打开浏览器访问http://localhost:8082/hystrix/consumer/getUser?id=2,服务正常和异常,图如下:

4. 负载均衡Ribbon
(1) 添加Maven依赖
org.springframework.cloud
spring-cloud-starter-ribbon
(2) application.yml配置
server:
port: 8015 #端口号
spring:
application:
name: loadbalance-service # 服务名称
#取消Ribbon使用Eureka
ribbon:
eureka:
enabled: false;
helloword-service:
ribbon:
#配置Ribbon能访问 的微服务节点,多个节点用逗号隔开
listOfServers: localhost:8001,localhost:8002,localhost:8003,localhost:8004,localhost:8005
#配置Ribbon负载均衡策略
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule;
(3) LoadBalanceController类
@RestController
@RequestMapping(“loadbalance”)
public class LoadBalanceController {
@Autowired
RestTemplate restTemplate;
@Autowired
private LoadBalancerClient loadBalancer;
@RequestMapping(value = “/hello”,method = RequestMethod.GET)
public String getRequest(){
ServiceInstance instance = loadBalancer.choose(“helloword-service”);
String host = instance.getHost();
int port = instance.getPort();
System.out.println(“负载均衡请求:” + host + “:” +port);
return “负载均衡请求:” + host + “:” +port;
}
}
(4)LoadBalanceMain类
@SpringBootApplication
public class LoadBalanceMain {
@Bean
@LoadBalanced
RestTemplate getrestTemplate(){
return new RestTemplate();
}
@Bean
public IRule ribbonRule() {
return new RandomRule();
}
public static void main(String[] args) {
SpringApplication.run(LoadBalanceMain.class,args);
}
}
(5) 测试
启动main,在浏览器中输入http://localhost:8015/loadbalance/hello,多次请求,可以看到页面呈现不同的请求路径。而且这些请求都是随机出现,查看后台打印

5. 路由网关Zuul
Zuul有智能路由和过滤的功能。内部服务的API接口通过Zuul网关统一对外暴露,不直接暴露,防止内部服务敏感信息对外暴露。在默认情况下,Zuul和Ribbon相结合,能够做到负载均衡、智能路由。Zuul的过滤功能是通过拦截请求来实现的,可以对用户的角色和权限进行判断,起到安全验证的作用,同事也可以用于输出实时的请求日志。
总结,上述Eureka、Hystrix、Ribbon、Zuul都来自Netflix公司,统一称为Spring Cloud Netflix
相关链接:https://www.jianshu.com/p/511db36c1b3e
6. Spring Cloud Config
Spring Cloud Config组件提供了配置文件统一管理的功能,包括Server端和Client端,Server读取本地仓库或远程仓库的配置文件,所有的Client向Server读取配置信息,从而达到配置文件统一管理的目的。通常情况下,Spring Cloud Config和Spring Cloud Bus相互配合刷新指定Client或所有的Client的配置文件。
相关链接:https://blog.csdn.net/qazwsxpcm/article/details/88578076
7. Spring Cloud Security
Spring Cloud Security是对Spring Security组件的封装,向服务单元提供了用户验证和权限认证。它一般和Spring Cloud OAuth2组件一起使用,通过搭建授权服务,验证Token或JWT这种形式对整个微服务系统进行安全验证。
相关链接:http://www.imooc.com/article/298880
8. Spring Cloud Sleuth
Spirng Cloud Sleuth是一个分布式链路追踪组件,封装了Dapper、Zipkin和Kibana等组件,通过它可以知道服务之间的相互依赖关系,并实时观察链路的调用情况。
相关链接:https://www.cnblogs.com/lishiqi-blog/p/11898841.html
9. Spring Cloud Stream
Spirng Cloud Stream是Spring Cloud框架的数据流操作包,可以封装RabbitMq、ActiveMQ、Karaf、Redis等消息组件,利用Spring Cloud Stream可以实现消息的接收和发送。
相关链接:https://www.cnblogs.com/fengzheng/p/11576661.html
本文深入浅出地介绍了微服务的概念,包括单体架构的不足、微服务的优势与特点,以及微服务架构中的服务注册与发现、负载均衡、服务容错等核心概念。此外,详细讲解了Spring Cloud中的Eureka、Hystrix、Ribbon和Zuul组件,以及它们在微服务架构中的作用和实现方式,帮助初学者理解微服务的实践应用。
&spm=1001.2101.3001.5002&articleId=105998986&d=1&t=3&u=4abc8f198a604f0098e5fce1c0361d7c)
1万+

被折叠的 条评论
为什么被折叠?



