分布式基础概念
微服务
微服务架构风格,就像是把一个单独的应用程序开发为一套小服务,每个小服务运行在自己的进程之中,并使用轻量级机制通信,通常是HTTP API,这些服务围绕业务能力来构建,并通过完全自动化部署机制来独立部署。这些服务使用不同的编程语言来书写,以及不同数据存储技术,并保持最低限度的集中式管理。
简而言之:拒绝大型单体应用,基于业务边界进行服务微化拆分,各个服务独立部署运行。
集群&分布式&节点
集群是个物理状态,分布式是个工作方式。
只要是一堆机器,就可以叫做集群,他们是不是一起协作着干活,这个谁也不知道。
分布式系统是若干独立计算机的集合,这些计算机对于用户来说就像单个相关系统
分布式系统(distributed system)是建立在网络之上的软件系统。
分布式是指将不同的业务分布在不同的地方。
集群指的是将几台服务器集中在一起,实现同一业务。
例如,京东是一个分布式系统,众多业务运行在不同的机器,所有业务构成一个大型的业务集群。每一个小的业务,比如用户系统,访问压力大的时候一台服务器是不够的。我们就应该将用户系统部署到多个服务器,也就是每一个业务系统也可以做集群化。
分布式中的每一个节点,都可以做集群,而集群并不一定就是分布式的。
节点:集群中的一个服务器
远程调用
在分布式系统中,各个服务可能处于不同主机,但是服务之间不可避免的需要互相调用,称为远程调用。
Spring Cloud中使用HTTP+JSON的方式完成远程调用。
负载均衡
分布式系统中,A服务需要调用B服务,B服务在多台机器中都存在,A调用任意一个服务器均可完成功能。
为了使得每一个服务器都不要太闲或者太忙,我们可以负载均衡的调用每一个服务器,提升网站的健壮性。
常见的负载均衡算法
轮询
为第一个请求选择健康池中的第一个后端服务器,然后按顺序往后一次选择,直到最后一个,然后循环。
最小连接
优先选择连接数最少,也就是压力最小的后端服务器,在会话较长的情况下可以考虑这种方式。
服务注册/发现&注册中心
A服务调用B服务,A服务并不知道B服务当前在哪几台服务器有,哪些正常的,哪些服务已经下线。解决这个问题可以引入注册中心;
如果某些服务下线,我们其他人可以实时感知到其它服务的状态,从而避免调用不可用的服务。
配置中心
每一个服务最终都有大量的配置,并且每个服务都可能部署在多台机器上。我们经常需要变更配置,我们可以让每个服务在配置中心获取自己的配置。
配置中心用来集中管理微服务的配置信息
服务熔断&服务降级
在微服务架构中,微服务之间通过网络进行通信,存在相互依赖,当其中一个服务不可用时,有可能会造成雪崩效应。要防止这样的情况,必须有容错机制来保护服务。
(1)、服务熔断
- 设置服务的超时,当被调用的服务经常失败达到某个阈值,我们可以开启断路保护机制,后来的请求不再去调用这个服务。本地直接返回默认的数据。
(2)、服务降级
- 在运维期间,当系统处于高峰期,系统资源紧张,我们可以让非核心业务降级运行。降级:某些服务不处理,或者简单处理【抛异常、返回NULL、调用Mock数据、调用Fallback处理逻辑】。
API网关
在微服务架构中,API Gateway作为整体架构的重要组件,它抽象了微服务中都需要的公共功能,同时提供了客户端负载均衡,服务自动熔断,灰度发布,统一认证,限流流控,日志统计等丰富的功能,帮助我们解决很多API管理难题。
环境搭建
docker安装mysql
下载镜像文件
docker pull mysql:5.6.50
创建实例并启动
docker run -p 3326:3326 --name mysql \
-v /mysata/mysql/log:/var/log/mysql \
-v /mydata/mysql/data:/var/lib/mysql \
-v /mydata/mysql/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:5.6.50
参数说明:
-p 3326:3326:将容器的3306端口映射到主机的3306端口
-v /mydata/mysql/conf:/etc/mysql:将配置文件夹挂载到主机
-v /mydata/mysql/log:/var/log/mysql:将日志文件夹挂载到主机
-v /mydata/mysql/data:/var/lib/mysql:将配置文件夹挂载到主机
-e MYSQL_ROOT_PASSWORD=root:初始化root用户的密码
-d mysql:5.6.50:使用这个镜像
docker安装redis
下载镜像文件
docker pull redis
创建实例并启动
mkdir -p /mydata/redis/conf
touch /mydata/redis/conf/redis.conf
docker run -p 6379:6379 -name redis \
-v /mydata/redis/data:/data \
-v /mydata/redis/conf/redis.conf:/etc/redis/redis.conf \
-d redis redis-server /etc/redis/redis.conf
docker exec -it redis redis-cli
#redis.conf
appendonly yes
开发环境配置
安装配置git
1、下载git:https://git-scm.com
2、配置git,进入git bash
# 配置用户名
git config --global user.name "username" //(名字)
# 配置邮箱
git config --global user.email "username@email.com" //(注册账号时用的邮箱)
3、配置ssh免密登录
进入git bash,使用:ssh-keygen -t rsa -C "xx@xxx.com"命令。连续三次回车。
一般用户目录下都会有
数据库配置
CREATE DATABASE `gulimall_oms` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE `gulimall_pms` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE `gulimall_wms` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE `gulimall_sms` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE `gulimall_ums` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Node.js
Node.js是基于Chrome V8引擎的JavaScript运行环境。我们关注node.js的npm功能就行,NPM是随同NodeJS一起安装的包管理工具,JavaScript-NPM,Java-Maven。
(1):官网下载安装node.js,并使用node -v检查版本
(2):配置npm使用淘宝镜像
npm config set registry http://registry.npm.taobao.org/
Node,js报错
npm install error: MSBUILD : error MSB3428: 未能加载 Visual C++ 组件“VCBuild.exe”
在管理员模式下运行cmd,输入npm install --global --production windows-build-tools
。
创建微服务项目
商品服务、仓储服务、订单服务、优惠券服务、用户服务
共同:
(1):web、openfeign
(2):每一个服务,包名com.atguigu.gulimall.xxx(product/order/ware/coupon/member)
(3):模块名,gulimall-xxx
分布式组件配置
微服务-注册中心、配置中心、网关
结合SpringCloud Alibaba 我们最终的技术搭配方案:
SpringCloud Alibaba - Nacos:注册中心 (服务发现/注册)
SpringCloud Alibaba - Nacos:配置中心 (动态配置管理)
SpringCloud - Ribbon:负载均衡
SpringCloud - Fegin:声明式HTTP客户端(调用远程服务)
SpringCloud Alibaba - Sentinel:服务容错(限流、降级、熔断)
SpringCloud Gateway:API网关(webflux编程模式)
SpringCloud Sleuth:调用链监控
SpringCloud Alibaba - Seata:原 Fescar:即分布式事务解决方案
nacos配置
下载nacos下载,运行,找到运行的地址和端口号
在Spring Boot的启动类中开启服务
启动nacos-server
- 双击bin中的
startup.cmd
文件 - 访问
http://localhost:8848/nacos/
- 使用默认的nacos/nacos进行登录
OpenFeign配置
Feign是一个声明式的HTTP客户端,它的目的就是让远程调用更加简单。Feign提供了HTTP请求的模板,通过编写简单的接口和插入注解,就可以定义好HTTP请求的参数、格式、地址等信息。
Feign整合了Ribbon(均衡负载)和Hystrix(服务熔断),可以让我们不再需要显式地使用这两个组件。
SpringCloudFeign在NetflixFeign的基础上扩展了对SpringMVC注解的支持,在其实现下,我们只需要创建一个接口并用注解的方式来配置它,即可以完成对服务提供方的接口绑定。简化了SpringCloudRibbon自行封装服务调用客户端的开发量。
远程调用示例
//GulimallCouponApplication.java
package com.atguigu.gulimall.member;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
/**
* 1、想要远程调用别的服务
* (1)、引入open-feign
* (2)、编写接口,告诉SpringCloud这个接口需要调用远程服务
* 声明接口的每一个方法都是调用哪个远程服务的哪个请求
* (3)、开启远程调用功能
* */
@EnableFeignClients(basePackages = "com.atguigu.gulimall.member.feign")
@EnableDiscoveryClient
@SpringBootApplication
public class GulimallMemberApplication {
public static void main(String[] args) {
SpringApplication.run(GulimallMemberApplication.class, args);
}
}
//CouponFeignService.java
package com.atguigu.gulimall.member.feign;
import com.atguigu.common.utils.R;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* 这是一个声明式的远程调用
* */
@FeignClient("gulimall-coupon")
public interface CouponFeignService {
@RequestMapping("coupon/coupon/member/list")
public R membercoupons();
}
//CouponController.java
@RestController
@RequestMapping("coupon/coupon")
public class CouponController {
@Autowired
private CouponService couponService;
@RequestMapping("/member/list")
public R membercoupons(){
CouponEntity couponEntity = new CouponEntity();
couponEntity.setCouponName("满100减10");
return R.ok().put("coupons", Arrays.asList(couponEntity));
}
Nacos配置中心
/**
* 1、如何使用Nacos作为配置中心统一管理配置
* 1)、引入依赖
* <!--配置中心来配置管理-->
* <dependency>
* <groupId>com.alibaba.cloud</groupId>
* <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
* </dependency>
* 2)、创建一个bootstrap.properties
* spring.application.name=gulimall-coupon
* spring.cloud.nacos.config.server-addr=192.168.209.1:8848
* 3)、需要给配置中心默认添加一个叫数据集(Data Id) gulimall-coupon.properties.默认规则,应用名.properties
* 4)、给 应用名.properties添加任何配置
* 5)、动态获取配置.
* @RefreshScope:动态获取刷新配置
* @Value("${配置项的名}"):获取到配置
* 如果配置中心和当前应用的配置文件中都配置了相同的项,优先使用配置中心的项
* **/
Gateway配置
前端技术
ES6
ECMAScript6.0是JavaScript语言的下一代标准。
商品服务API
三级分类
递归树形结构数据获取
网关统一配置跨域
跨域:指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。
同源策略:是指协议,域名,端口都要相同,其中有一个不同都会产生跨域;
跨域流程
非简单请求(PUT、DELETE)等,需要先发送预检请求
解决跨域(一)使用nginx部署为同一域
解决跨域(二)配置当次请求允许跨域
- 1.添加响应头
- Access-Control-Allow-Origin:支持哪些来源的请求跨域
- Access-Control-Allow-Methods:支持哪些方法跨域
- Access-Control-Allow-Credentials:跨域请求默认不包含cookie,设置为true可以包含cookie
- Access-Control-Expose-Headers:跨域请求暴露的字段
- CORS请求时,XMLHttpRequest对象的getResponseHeaders()方法只能拿到6个基本字段:
Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。
如果想拿到其它字段,就必须在Access-Control-Expose-Headers里面指定。
- CORS请求时,XMLHttpRequest对象的getResponseHeaders()方法只能拿到6个基本字段:
- Access-Control-Max-Age:表明该响应的有效时间为多少秒。在有效时间内,浏览器无须为同一请求再次发起预检请求。请注意,浏览器自身维护了一个最大有效时间,如果该首部字段的值超过了最大有效时间,将不会生效。