系统架构

概述

随着互联网的发展,网站应用的规模不断扩大。需求的激增,带来的是技术上的压力。 系统架构也因此也不断的演进、升级、迭代。

从单一应用,到垂直拆分,到分布式服务,到SOA,以及现在火热的微服务架构

集中式架构

概述

当网站流量很小时,只需一个应用 将所有功能都部署在一起,以减少部署节点和成本 从头到尾就一个工程,部署的时候 , 只需要打成一个war包

特点

  1. 代码耦合,开发维护困难
  2. 无法针对不同模块进行针对性优化
  3. 无法水平扩展
  4. 单点容错率低,并发能力差

垂直拆分

概述

当访问量逐渐增大,单一应用无法满足需求,此时为了应对更高的并发和业务需求,我们根据业务功能对系统进行拆分

特点

  1. 系统拆分实现了流量分担,解决了并发问题
  2. 可以针对不同模块进行优化
  3. 方便水平扩展,负载均衡,容错率提高
  4. 系统间相互独立,会有很多重复开发工作,影响开发效率

系统架构分类

微服务

微服务就是把原本臃肿的一个项目的所有模块拆分开来并做到互相没有关联,甚至可以不使用同一个数据库

微服务的特点:

  1. 单一职责微服务中每一个服务都对应唯一的业务能力,做到单一职责
  2. 服务拆分粒度很小例如一个用户管理就可以作为一个服务
  3. 面向服务面向服务是说每个服务都要对外暴露服务接口API,并不关心服务的技术实现,做到与平台和语言无关,不限定用什么技术实现,只要提供Rest的接口即可
  4. 自治自治是说服务间互相独立,互不干扰

分布式服务:

概述:

当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务

分布式,就是将偌大的系统划分为多个模块(这一点和微服务很像)部署到不同机器上 因为一台机器可能承受不了这么大的压力

各个模块通过接口进行数据交互,其实 分布式也是一种微服务。

特点:

  1. 将基础服务进行了抽取,系统间相互调用,提高了代码复用和开发效率
  2. 系统间耦合度变高,调用关系错综复杂,难以维护

微服务和分布式的区别:

微服务与分布式都是把模块拆分开来变为独立的单元,提供接口来调用

他们本质的区别在于目标的不同:

  1. 分布式的目标是:一台机器承受不了的,或者是成本问题 , 不得不使用多台机器来完成服务的部署
  2. 微服务的目标 :只是让各个模块拆分开来,不会被互相影响,比如模块的升级亦或是出现BUG等等...

微服务要面临的问题:

  1. 服务治理(SOA)

    概述:

当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现, 此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。

(SOA)用于提高机器利用率的资源调度和治理中心

问题:

服务越来越多,需要管理每个服务的地址 调用关系错综复杂,难以理清依赖关系 服务过多,服务状态难以管理,无法根据服务情况动态管理

服务治理要做什么:

服务注册中心,实现服务自动注册和发现,无需人为记录服务地址 服务自动订阅,服务列表自动推送,服务调用透明化,无需关心依赖关系

动态监控服务状态监控报告,人为控制服务状态

  1. 监听服务有没有宕机:部署很多服务后 ,如果监听到服务有没有宕机
  2. 负载均衡:一个服务吃不消,要部署多个服务,部署的多个服务均衡调用
  3. 熔断:服务出现了问题,不能让程序卡在那里
  4. 限流:限流就是针对超过预期的流量,通过预先设定的限流规则选择性的对某些请求进行限流“熔断”
  5. 降级:当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易正常运作或高效运作
  6. 网关:统一管理API的一个网络关口、通道,是整个微服务平台所有请求的唯一入口

springClould是什么

微服务只是一种项目的架构方式,或者说是一种概念

Spring-Cloud便是对这种技术的实现

对微服务面临的问题进行统一的封装处理

远程调用方式:

RPC:

  1. Remote Produce Call远程过程调用,类似的还有RMI。自定义数据格式,基于原生TCP通信,速度快,效率高
  2. 早期的webservice,现在热门的dubbo,都是RPC的典型
  3. 限制了平台,只能是Java平台

Http:

  1. http其实是一种网络传输协议,基于TCP,规定了数据传输的格式
  2. 现在客户端浏览器与服务端通信基本都是采用Http协议。也可以用来进行远程服务调用。缺点是消息封装臃肿
  3. 不限制平台

模拟微服务:

  1. 创建一个普通父工程,删除src目录,保留pom文件



  2. 在父工程当中添加springboot依赖



    代码:
	<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.3.RELEASE</version>
</parent>
  1. 创建子模块user



  2. 添加springboot-web启动器依赖



    代码:
	<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
  1. 创建user工程启动类UserApplication



    代码:
@SpringBootApplication
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class,args);
}
}
  1. 创建util包,把ResponseResult工具类复制到该包中



    代码:
public class ResponseResult extends HashMap {
public static String SUCCESS_CODE = "200";
public static String ERROR_CODE = "500";
public static String DATA_KEY = "data";
public static String MSG_KEY = "msg"; private ResponseResult() {
} public ResponseResult set(String key, Object object) {
super.put(key, object);
return this;
} private static ResponseResult newResponseResult() {
return new ResponseResult();
} public static ResponseResult success() {
return ResponseResult.newResponseResult()
.set("code", ResponseResult.SUCCESS_CODE)
.set(ResponseResult.MSG_KEY, "操作成功");
} public static ResponseResult success(String msg) { return ResponseResult.newResponseResult()
.set("code", ResponseResult.SUCCESS_CODE)
.set(ResponseResult.MSG_KEY, msg);
} public static ResponseResult success(String msg, Object object) { return ResponseResult.newResponseResult()
.set("code", ResponseResult.SUCCESS_CODE)
.set(ResponseResult.MSG_KEY, msg)
.set(ResponseResult.DATA_KEY, object);
} public ResponseResult data(Object obj) {
return this.set("data", obj);
} public static ResponseResult error() {
return ResponseResult.newResponseResult()
.set(ResponseResult.MSG_KEY, "操作失败")
.set("code", ResponseResult.ERROR_CODE);
} public static ResponseResult error(String msg) {
return ResponseResult.newResponseResult()
.set(ResponseResult.MSG_KEY, msg)
.set("code", ResponseResult.ERROR_CODE);
} public static ResponseResult error(String msg, Object object) {
return ResponseResult.newResponseResult()
.set(ResponseResult.MSG_KEY, msg)
.set(ResponseResult.DATA_KEY, object)
.set("code", ResponseResult.ERROR_CODE);
} }
  1. 创建子包controller,在controller当中创建UserController



    代码:
@RestController
public class UserController {
@RequestMapping("/getUser.do")
public ResponseResult getUser() {
return ResponseResult.success("返回成功","myUser");
}
}
  1. 在resources目录下创建application.yml

  2. 启动访问http://localhost:5000/getUser.do

  3. 创建子模块goods

  4. 配置和user一样,修改server-port端口为:5001



  5. 启动访问http://localhost:5001/getGoods.do

  6. user工程调用goods工程当中的接口

    在UserApplication中添加RestTemplate的Bean



    代码:
 @Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}

在user工程的UserController当中注入restTemplate



通过restTemplate实现工程之间的接口调用



同时运行两个工程, 访问http://localhost:5000/getGoods.do



以上操作就实现了两个工程之间的调用

使用nginx实现集群搭建

  1. 下载nginx 网址:nginx下载地址



    下载后解压:注意解压目录不要带有中文
  2. 创建一个新的goods1工程 和goods一模一样 只需要改端口号即可,用于搭建集群。

  3. 修改nginx的配置文件



    把之前的server的代码删掉,替换成这样



    代码:
  upstream mServer {
server localhost:5001;
server localhost:5002;
} server {
listen 80;
server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; location / {
root html;
index index.html index.htm;
proxy_pass http://mServer;
}
  1. 配置完成后启动nginx.exe



    启动会一闪而过 属于正常情况

  2. 把user中调用方的端口号改为80

  3. 启动user,goods,goods1 访问user的地址:http://localhost:5000/getGoods.do





    会发现每次刷新访问,都会返回两个不同的工程的controller,完成集群的搭建。

存在问题, 如果其中的一个服务停止了, 当访问的时候 , 会出现有时会很慢的情况

解决方案:用到SpringCloud的Eureka注册中心来管理我们的服务



下次更新 Spring-Cloud-Netflix-Eureka的使用方法

Spring-Cloud-Netflix-系统架构的更多相关文章

  1. Spring Cloud Netflix概览和架构设计

    Spring Cloud简介 Spring Cloud是基于Spring Boot的一整套实现微服务的框架.他提供了微服务开发所需的配置管理.服务发现.断路器.智能路由.微代理.控制总线.全局锁.决策 ...

  2. Spring Cloud netflix 概览和架构设计

    pring Cloud是基于Spring Boot的一整套实现微服务的框架.他提供了微服务开发所需的配置管理.服务发现.断路器.智能路由.微代理.控制总线.全局锁.决策竞选.分布式会话和集群状态管理等 ...

  3. Spring Cloud 微服务架构学习笔记与示例

    本文示例基于Spring Boot 1.5.x实现,如对Spring Boot不熟悉,可以先学习我的这一篇:<Spring Boot 1.5.x 基础学习示例>.关于微服务基本概念不了解的 ...

  4. 一张图了解Spring Cloud微服务架构

    Spring Cloud作为当下主流的微服务框架,可以让我们更简单快捷地实现微服务架构.Spring Cloud并没有重复制造轮子,它只是将目前各家公司开发的比较成熟.经得起实际考验的服务框架组合起来 ...

  5. 放弃Dubbo,选择最流行的Spring Cloud微服务架构实践与经验总结

    http://developer.51cto.com/art/201710/554633.htm Spring Cloud 在国内中小型公司能用起来吗?从 2016 年初一直到现在,我们在这条路上已经 ...

  6. Spring Cloud 微服务架构解决方案

    1 理解微服务 1.1 软件架构演进 软件架构的发展经历了从单体结构.垂直架构.SOA架构到微服务架构的过程. 1.1.1 单体架构 特点: 1.所有的功能集成在一个项目工程中. 2.所有的功能打一个 ...

  7. SpringCloud学习笔记(2)----Spring Cloud Netflix之Eureka的使用

    1.  Spring Cloud Netflix Spring Cloud Netflix 是Spring Cloud 的核心子项目,是对Netflix公司一系列开源产品的封装.它为Spring Bo ...

  8. 基于Spring Cloud Netflix的TCC柔性事务和EDA事件驱动示例

    Solar Spring Cloud为开发者提供了快速构建分布式系统中的一些常见工具,如分布式配置中心,服务发现与注册中心,智能路由,服务熔断及降级,消息总线,分布式追踪的解决方案等. 本次实战以模拟 ...

  9. Spring Cloud Netflix Zuul 重试会自动跳过经常超时的服务实例的简单说明和分析

    在使用E版本的Spring Cloud Netflix Zuul内置的Ribbon重试功能时,发现Ribbon有一个非常有用的特性: 如果某个服务的某个实例经常需要重试,Ribbon则会在自己维护的一 ...

  10. Spring Cloud 入门教程(十):和RabbitMQ的整合 -- 消息总线Spring Cloud Netflix Bus

    在本教程第三讲Spring Cloud 入门教程(三): 配置自动刷新中,通过POST方式向客户端发送/refresh请求, 可以让客户端获取到配置的最新变化.但试想一下, 在分布式系统中,如果存在很 ...

随机推荐

  1. JAVA有关位运算的全套梳理

    一.在计算机中数据是如何进行计算的? 1.1:java中的byte型数据取值范围 我们最开始学习java的时候知道,byte类型的数据占了8个bit位,每个位上或0或1,左边第一位表示符号位,符号位如 ...

  2. 前端解决跨域问题的终极武器——Nginx反向代理

    提到代理,分为:正向代理和反向代理. 正向代理:就是你访问不了Google,但是国外有个VPN可以访问Google,你访问VPN后叫它访问Google,然后把数据传给你. 正向代理隐藏了真实的客户端. ...

  3. Web安全相关(一):CSRF/XSRF(跨站请求伪造)和XSS(跨站脚本)

    XSS(Cross Site Script):跨站脚本,也就是javascript脚本注入,一般在站点中的富文本框,里面发表文章,留言等表单,这种表单一般是写入数据库,然后再某个页面打开. 防御: 1 ...

  4. 大型Java进阶专题(三) 软件架构设计原则(下)

    前言 ​ 今天开始我们专题的第二课了,本章节继续分享软件架构设计原则的下篇,将介绍:接口隔离原则.迪米特原则.里氏替换原则和合成复用原则.本章节参考资料书籍<Spring 5核心原理>中的 ...

  5. 图像IO

    图像IO 潜伏期值得思考 - 凯文 帕萨特 在第13章“高效绘图”中,我们研究了和Core Graphics绘图相关的性能问题,以及如何修复.和绘图性能相关紧密相关的是图像性能.在这一章中,我们将研究 ...

  6. [C++入门篇]了解C++

    前言 我是杨某人,点击右下方"+"一键关注我.如果你喜欢我的文章,那么拒绝白嫖行为.然后..请多来做客鸭. 如果你是已经入门的大佬,请滑到下方点个推荐再走. 我个人认为,博客有两种 ...

  7. django 从零开始 13 返回文件

    进行一些操作返回文件,flask和django差不多,基本都是在返回response 并且对其中的返回头部写入返回文件信息 # image def image(request): f = open(r ...

  8. 在Java中使用Collections.sort 依据多个字段排序

    一.如何使用Collections工具类进行排序 使用Collections工具类进行排序主要有两种方式: 1.对象实现Comparable接口,重写compareTo方法 /** * @author ...

  9. 判断 tableZen 是否有 横向滚动条

    判断 tableZen 是否有 横向滚动条 const outWidth = this.$refs.tableInnerZen.$el.clientWidth ].$el.clientWidth

  10. 微信小程序开发(一)开发准备

    微信小程序开发(一)开发准备 微信小程序,近几年,越来越火,应用场景越来越多,好大学习起来,比较容易,学习曲线平缓,你要是会前端开发,那简直可以用易如反掌来形容. 小程序,开发工具官方也提供了,他兼容 ...