面向服务的架构SOA
SOA也是一种分布式架构,简单来说SOA就是在在分布式的基础上,使每个子应用都可以通过网络通信协议向其他子应用提供服务或者消费服务。即,子系统可以调其他子系统的接口。
SOA优点
-
模块拆分,使用API通信,降低模块之间的耦合度
-
项目拆分多个子应用,每个子应用业务简单,代码简单,方便维护开发。
-
不同技术人员可以负责不同的子应用
-
提高服务之间的重用性,业务逻辑可组合。
SOA缺点:
-
服务之间的API接口开发增加了工作量,
-
SOA服务之间的网络通信调用对性能有一定的影响(尽管很小)
-
相对于单体应用来说,技术,人力成本较高。
-
部署和运维相对麻烦
微服务架构
为服务架构就是将一个单一的应用拆分成许多细小的服务,每个服务独立运行,只需要专注于自己的业务即可,且每个服务都可以有自己的数据库。
微服务的优点
在项目规模较大的时候,相对于单体应用来说,微服务具备很多优势,主要体现在如下方面:
-
单个服务业务简单,代码简单方便开发维护
-
服务之间无耦合,服务之间升级维护互不影响
-
轻量级HTTP通信机制,使得的不同的服务可以采用不同的编程语言
-
微服务有极强的扩展能力,业务量大的服务可以再次拆分服务,也可以进行集群部署,剔除服务也很方便
-
更大的系统负载能力和容错能力(集群)
-
对于开发人员来说,通常只需要关注单一服务,新员工上手也比较快
-
微服务架构对现在流行的敏捷开发支持优化
缺点
-
分布式事务 :服务通信机制增加了事务的复杂性,架构师要选择合适的分布式方案(CAP理论)
-
部署麻烦 :微服务众多,部署麻烦,需要借助容器技术和自动化部署工具,这又增加了开发人员的学习成本。
-
技术成本高 :微服务架构本身比较复杂,技术成本高,开发人员需要花更多的时间学习相关技术。
-
服务通信对性能的损耗 : 微服务架构一定要考虑服务通信延迟对服务调用性能的损耗问题,开发人员需要选择合适的通信方式解决这一问题。
SpringCloud介绍
SpringCloud基本概念
Spring cloud是一个基于Spring Boot实现的服务治理工具包,用于微服务架构中管理和协调服务的。Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。有了SpringCloud之后,让微服务架构的落地变得更简单。
SpringCloud常用组件
当我们的项目采用微服务架构之后就会引发一些列的难题需要去解决,如众多微服务的通信地址应该如何管理,微服务之间应该使用何种方式发起调用,微服务故障该如何处理,众多微服务的配置文件如何集中管理等等,SpringCloud为这一系列的难题提供了相应的组件来解决,下面我们简单来理解一下SpringCloud最核心的几大组件如如下:
Netflix Eureka
当我们的微服务过多的时候,管理服务的通信地址是一个非常麻烦的事情,Eureka就是用来管理微服务的通信地址清单的,有了Eureka之后我们通过服务的名字就能实现服务的调用。
Netflix Ribbon\Feign : 客户端负载均衡
Ribbon和Feign都是客户端负载均衡器,它的作用是在服务发生调用的时候帮我们将请求按照某种规则分发到多个目标服务器上,简单理解就是用来解决微服务之间的通信问题。
Netflix Hystrix :断路器
微服务的调用是非常复杂的,有的时候一个请求需要很多的微服务共同完成,那么一旦某个服务发生故障,导致整个调用链上的微服务全都出现异常,甚至导致整个微服务架构瘫痪。Hystrix就是用来解决微服务故障,保护微服务安全的组件。
Netflix Zuul : 服务网关
zuul作为服务网关,我们可以把它看作是微服务的大门,所有的请求都需要经过zuul之后才能到达目标服务,根据这一特性,我们可以把微服务公共的是事情交给zuul统一处理,如:用户鉴权,请求监控等。
Spring Cloud Config :分布式配置
微服务架构中的服务实例非常的多,服务的配置文件分散在每个服务中,每次修改服务的配置文件和重新服务实例都是一个很麻烦的工作,Spring Cloud Config作为分布式配置管理中心就是用来统一的管理服务的配置文件。
Spring Cloud Bus : 消息总线
消息总线是在微服务中给各个微服务广播消息的一个组件,我们使用消息总线构建一个消息中心,其他微服务来接入到消息中心,当消息总线发起消息,接入的微服务都可以收到消息从而进行消费。
Spring Cloud sleuth :微服务链路追踪
当我们的应用采用微服务架构之后,后台可能有几十个甚至几百个服务在支撑,一个请求请求可能需要多次的服务调用最后才能完成,链路追踪的作用就是来监控维护之间的调用关系,让程序员方便直观的感受到一个请求经历了哪些微服务,以及服务的请求时间,是否有异常等。
EurekaServer实战
多模块项目结构
搭建一个父项目,其下有三个子项目,EurekaServer,orderServer和userServer,其中浏览器发送请求到orderServer,orderServer有发送请求到userServer返回一个User类型的数据,所以还需要在定义一个子项目,存放User类型对象,将其引入orderServer和userServer中
父项目导入依赖
<!--1.管理 SpringBoot的jar包-->
<!--SpringBoot-->
<parent>
<groupId> org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
<!--2.管理 SpringCloud的jar包
-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!--3.这里是所有子项目都可以用的jar包-->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
EurekaServer依赖
<artifactId>springcloud-eureka-server-1010</artifactId>
<name>springcloud-eureka-server-1010</name>
<dependencies>
<!--spring-cloud-starter-netflix-eureka-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
EurekaServer的yml文件
server: port: 10010 #端口 eureka: instance: hostname: localhost #主机 client: #客户端配置 registerWithEureka: false #EurekaServer自己不要注册到EurekaServer自己 ,只有EurekaClient才注册 fetchRegistry: false #EurekaServer不要拉取服务的通信地址列表 ,只有EurekaClient才拉取地址列表 serviceUrl: #注册中心的注册地址 defaultZone: http://localhost:10010/eureka/ #http://${eureka.instance.hostname}:${server.port}/eureka/ server: enable-self-preservation: false #关闭自我保护警告
EurekaServer启动类
@SpringBootApplication
@EnableEurekaServer
public class EruekaApplication {
public static void main(String[] args) {
SpringApplication.run(EruekaApplication.class,args);
}
}
在项目启动类上使用@EnableEurekaServer,可以将项目作为SpringCloud中的注册中心。
userServer和orderServer依赖
<dependencies> <!--spring-cloud-starter-netflix-eureka-server --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 你写的user类的项目依赖 --> <dependency> <groupId>*.*</groupId> <artifactId>springboot-netfix-pojo-user</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
*.*是你的user类型对象的包路径
springboot-netfix-pojo-user:项目名
userServer和orderServer的yml文件
eureka: client: serviceUrl: defaultZone: http://localhost:10010/eureka/ instance: instance-id: server-user spring: application: name: server-user server: port: 10030
user和order不同在于instance-id、name和port 改成order和你自己想要的port
最后userServer和orderServer的启动类
启动步骤
先启动EurekaServer
当orderServer和userServer启动时会自动注册到EurekaServer,可以在网址输入localhost:10010访问查看(10010是你yml自己写的端口号)
OrderControoller接收网页请求
@RestController
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/order/{id}")
public User getById(@PathVariable("id")Long id){
User forObject = restTemplate.getForObject("http://SERVER-USER/user/" + id, User.class);
return forObject;
}
}
使用Ribbon负载均衡需要注入restTemplate,在Order启动类手动注入
@Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); }
SERVER-USER:是你userServer注册到EurekaServer的服务名称
UserControoller接收网页请求
@GetMapping("/user/{id}") public User getById(@PathVariable("id") Long id){ return new User(id,"大帅",22); }
最后网页发送请求
测试负载均衡Ribbon
在写一个userServer的子项目,更改yml的 instance-id 和 port,再在两个userServer的congtroller中读取配置文件的server.port,返回给order就可已看到,请求不同的端口
@Value("${server.port}") private String port;
可以看到SERVER-USER下有两个服务
默认轮询
简单了解Ribbon内置负载均衡算法
可以在启动类@Bean注入,如:
//负载均衡算法
@Bean
public RandomRule randomRule(){
return new RandomRule();
}