本文主要讲述了《谷粒商城》的项目背景、环境搭建以及项目结构初始化
市面上有5中常见的电商模式:B2B、B2C、C2B、C2C、O2O
1)B2B模式
B2B(Business to Business),是指商家与商家建立的商业关系,如阿里巴巴
2)B2C模式
B2C(Business to Consumer),是指商家与客户的模式,也就是通常的商业零售,如:苏宁易购、京东、天猫、小米商城
3)C2B模式
C2B(Customer to Business),即消费者对企业。先有消费者需求产生而后有企业生产,及先有消费者提出需求,后有生产企业按需求组织生产
4)C2C模式
C2C(Customer to Consumer),客户之间自己把东西放网上去卖,如:淘宝、闲鱼
5)O2O模式
O2O(online to offline),也即线下商务的机会与互联网结合在了一起,让互联网成为线下交易的前台。线上快速支付,线下优质服务。如:饿了么、美团、淘票票、京东到家
谷粒商城是一个B2C模式的电商平台,销售自营商品给客户
学习项目的前置知识:
服务架构风格,就像是把一个单独的应用程序开发为一套小服务,每个小服务运行在自己的进程中,并使用轻量级机制通信,通常是HTTP API。这些服务围绕业务能力来构建,并通过完全自动化部署机制来独立部署。这些服务使用不同的编程语言书写,以及不同数据存储技术,并保持最低限度的集中式管理
简而言之:拒绝大型单体应用,基于业务边界进行服务微化拆分,各个服务独立部署运行
集群是一个物理形态,分布式是个工作方式。只要是一堆机器,就可以叫集群,他们是不是一起协作着干活,这个谁也不知道。分布式是指将不同的业务分布在不同的地方,集群指的是将几台服务器集中在一起,实现同一业务。
例如:京东是一个分布式系统,众多业务运行在不同的机器,所有业务构成一个大型的业务集群。每个小的业务,比如用户系统,访问压力大的时候一台服务器是不够的。我们就应该将用户系统部署到多个服务器,也就是每个业务系统也可以做集群化
分布式中的每一个节点,都可以做集群。而集群并一定就是分布式的。
节点:集群中的一个服务器
在分布式系统中,各个服务可能处于不同主机,但是服务之间不可避免的需要互相调用,我们成为远程调用
Springcloud中使用HTTP+JSON的方式完成远程调用
分布式系统中,A服务需要调用B服务,B服务在多台机器中都存在,A调用任意一个服务器均可完成功能。为了使每一个服务器都不要太忙或太闲,我们可以负载均衡的调用每一个服务器,提升网站的健壮性
常见的负载均衡算法:
**轮询:**为第一个请求选择健康池中的第一个后端服务器,然后按顺序往后依次选择,直到最后一个,然后循环。
最小连接:优先选择连接数最小,也就是压力最小的后端服务器,在会话较长的情况下可以考虑采取这种方式。
散列:根据请求源的IP的散列(hash)来选择要转发的服务器。这种方式可以一定程度上保证特定用户能连接到相同的服务器。如果你的应用需要处理状态而要求用户能连接到和之前相同的服务器,可以考虑采用这种方式
A服务调用B服务,A服务并不知道B服务当前哪几台服务器上有,哪些正常,哪些服务已经下线。解决这个问题可以引入注册中心
如果这些服务下线,我们其他人可以实时的感知到其他服务的状态,从而避免调用不可用的服务
每一个服务最终都有大量的配置,并且每个服务都可能部署在多台机器上。我们京城需要变更配置,我们可以让每个服务在配置中心获取自己的配置
配置中心用来集中管理微服务的配置信息
在微服务架构中,微服务之间通过网络进行通信,存在相互依赖,当其中一个服务不可用时,有可能会造成雪崩效应。要防止这样的情况,必须要有容错机制来保护服务。
设置服务的超时,当被调用的服务经常失败到达某个阈值,我们可以开启熔断保护机制,后来的请求不再去调用这个服务。本地直接返回默认的数据
在运维期间,当系统处于高峰期,系统资源紧张,我们可以让非核心业务降级运行。
降级:某些服务不处理,或者简单处理(跑异常、返回null、调用Mock数据、调用Fallback处理逻辑)
在微服务架构中,API Gateway作为整体架构的重要组件,它抽象了微服务中都需要的公共功能,同时提供了客户端负载均衡,服务自动熔断,灰度发布,统一认证,限流留空,日志统计等丰富的功能,帮助我们解决很多API管理难题。
在本次课程里,Linux虚拟机使用的是VirtualBox。virtualBox是开源的,打开官网地址:https://www.virtualbox.org,下载安装即可。
可以先下载Linux系统镜像,然后点击新建,按照步骤一步步操作创建虚拟机。但这样操作有些麻烦,推荐使用一个新的技术vagrant。只要安装好virtualbox后,vagrant可以帮助我们快速创建一个虚拟机。(vagrant本身有一个镜像仓库,在这个镜像仓库中,官方有好多做好的镜像,我们使用vagrant,就可以连接virtualbox,快速地从官方镜像中创建出一个虚拟机。)
注意:virtualBox会与一些软件冲突:红蜘蛛、360、净网大师等
打开vagrant官方网站,点击下载Windows版本的vagrant,下载完成后,点击安装即可(推荐安装到非C盘的其他盘)。vagrant安装完成之后需要重启系统。
验证vagrant是否安装完成:打开cmd命令窗口,输入“vagrant”,出现vagrant的相关命令即为安装成功
https://app.vagrantup.com/boxes/search vagrant官方镜像仓库
https://www.vagrantup.com/downloads.html vagrant下载
简略步骤:
详细步骤:
其中的centos/7的写法,需要去看vagrant的官方镜像仓库,如下图所示:
虚拟机默认的网路设置是:网络地址转换+端口转发的方式,这种方式对后来的开发很不方便。
端口转发是指:Windows系统的端口3333对应virtualbox中的MySQL的默认端口3306,Windows系统的端口6666对应virtualbox中的Redis的默认端口6379。每增加一个端口映射,我们都需要在virtualbox上进行设置
当如果我们给虚拟机一个固定的IP地址,Windows和虚拟机可以互相ping通,在虚拟机中装好一个软件,我们直接拿虚拟机中端口进行访问就可以了。
修改vagrantfile文件
简略步骤:
详细步骤:
vagrantfile,虚拟机是根据这个文件帮我们创建出虚拟机信息的,而这个文件里面就有关于网络的配置:Config.cm.network”private_network”,ip:”192.168.56.10”。
这里的IP地址,是根据Windows主机的IP地址来判定。使用cmd命令ipconfig,查询出当前主机的IP地址,主要看关于virtualbox部分。
上面virtualbox的虚拟机网卡的地址是56.1,那么我们修改vagrantfile文件中的IP就可以为192.168.56.X即可,X随便是一个数字即可。
修改完后重启虚拟机即可:vagrant reload
使用命令:ip addr,可以看到虚拟机的地址
然后在Windows和虚拟机互相ping对方,看是否ping的通
什么是docker
Docker是一个虚拟化容器技术,docker基于镜像,可以秒级启动各种容器。每一种容器都是一个完整的运行环境,容器之间互相隔离
安装步骤:
Docker安装文档:https://docs.docker.com/install/linux/docker-ce/centos/
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
//设置之前首先安装一些工具包
sudo yum install -y yum-utils
//这一步告诉Linux,docker去哪里装
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io
sudo systemctl start docker
//检查一下docker的版本
docker -v
//使用docker命令查看docker现有的镜像
sudo docker images
sudo systemctl enable docker
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://3kdervwe.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
//如果mysql后面没有指定版本号,则下载最近的mysql,指定后则下载指定版本号
sudo docker pull mysql:5.7
有了上面的镜像,就可以使用docker创建一个mysql容器
//切换root用户,密码为vagrant
su root
//创建mysql容器
docker run -p 3306:3306 --name mysql \
-v /mydata/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.7
参数说明:
-p 3306:3306:将容器的3306端口映射到主机的3306端口
–name mysql:是在给容器命名为mysql
-v /mydata/mysql/log:/var/log/mysql \:将日志文件夹挂载到主机
-v /mydata/mysql/data:/var/lib/mysql \:将配置文件夹挂载到主机
-v /mydata/mysql/conf:/etc/mysql \:将配置文件夹挂载到主机
-d :后台运行
创建完之后,可以根据命令:
docker ps,查看当前正在运行中的容器
docker ps -l:查看当前所有的容器
docker exec -it mysql /bin/bash:可以进入到mysql容器控制台,命令中的mysql部分可以是容器的名字,也可以是容器的ID
修改mysql的字符集编码
使用命令:vi /mydata/mysql/conf/my.cnf,然后输入i进行修改,将如下内容添加,按esc后输入:wq保存退出
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqld]
init_connect=’SET collation_connection = utf8_unicode_ci’
init-connect=’SET NAMES utf8’
character-set-server=utf8
collation-server=utf8_unicode_ci
skip-character-set-client-handshake
skip-name-resolve
修改完成后需要重启mysql容器
docker restart mysql
重启完成后,我们重新进入到mysql容器内容,查看里面的配置文件是否随着docker中的修改而修改
//进入到mysql容器内部
docker exec -it mysql /bin/bash
然后按照目录/etc/mysql,找到my.cnf,使用cat my.cnf命令,查看文件内容,和之前在docker的目录下修改的内容一致!
问题:
修改完字符集后重启mysql容器,进入容器内部失败,报错如下:
解决:
报错显示容器没有启动,那么就是容器restart时没有启动成功。
使用命令:docker ps -a,看到mysql容器一分钟前退出了,
使用命令:docker logs [container ID]命令查看这个容器的运行日志,发现报错内容:
就是说我在修改mysql配置文件时,写错了utf-8,应该是utf8,修改文件后重启,再试
发现还是容器无法启动,查看日志还是原来的错误。
因为在保存时,一定要确保docker没有在运行,使用systemctl stop docker命令将docker关闭,否则保存后,docker仍然会依照老的配置文件启动容器,容器仍然不能启动
然而,在停掉docker服务时报错
使用命令:systemctl stop docker.socket,停掉被访问时自动启动服务
然后再继续停掉docker,修改my.cnf,保存退出,重启docker,重启mysql,成功
//redis后面添加版本号即下载固定版本,不添加则下载最新版本
docker pull redis
//因为Redis内部没有conf目录和redis.conf文件,所以提前创建
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 ps,查看当前运行的容器是否有Redis
使用命令:docker exec -it redis redis-cli,直接连上docker的Redis,就可以直接操作,例如:set a b
redis中的数据都不是持久化的,直接存储在内存中,所以当我们重启Redis服务后,之前存储的数据就不存在了。
想要持久化,找到挂在的目录,修改里面的配置文件redis.conf,添加如下内容:
appendonly yes
修改完成后重启redis
docker restart redis
此时再次存储数据,重启Redis,然后再次查重启之前存储的数据,则可以查看到
为了方便查看Redis中的数据,安装一个Redis的可视化客户端:redis-desktop-manager-0.8.8.384.exe
关于redis的redis.conf配置文件里面可以配置哪些文件,可以参考redis的官方文档。
查看Windows环境的jdk版本:cmd命令行里输入:java -version
查看Windows环境的maven版本:cmd命令行里输入:mvn -version
找到maven的安装目录,conf目录下的settings.xml配置文件,做如下修改:
配置阿里云镜像
将maven中的mirror替换成下面的代码
nexus-aliyun</id>
central</mirrorOf>
Nexus aliyun</name>
http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
</mirrors>
配置jdk1.8编译项目
将maven配置文件中的profile配置成如下内容:
jdk-1.8</id>
true</activeByDefault>
1.8</jdk>
</activation>
.compiler.source>1.8</maven.compiler.source>
.compiler.target>1.8</maven.compiler.target>
.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
</profiles>
配置好了之后,在idea中整合maven,具体整合办法百度一下即可。
再给idea中安装两个插件:Lombok、mybatis
npm config set registry http://registry.nom.taobao.org/
因为GitHub经常有访问不到的情况,所以推荐使用码云
下载安装git客户端
下载地址:https://git-scm.com/download/win
下载好之后,除了安装地址修改成自己想安装的地址,其余一路next即可。
安装完成后,在文件目录下右键,即可看到git的功能。
配置Git
右键,点击Git bash here,进入Git控制台,对Git进行一些基本配置。
//配置用户名:
git config --global user.name "***"
//配置邮箱:
git config --global user.email "*****.com"
登录码云,点击新建仓库
创建完成之后,复制项目地址
打开idea,选择file,new->project from version Control
在克隆的时候,idea会弹出输入码云用户名密码的窗口,是码云的,不是Git的。
这个项目作为总项目,接下来,会在这个项目下面创建各个微服务项目。
微服务项目:
微服务项目的共同点:
商品微服务创建过程如下:
右键项目,选择new->moudle
创建第一个微服务模块,第一个微服务模块,使用spring向导
因为是微服务,所以每个微服务下都会选择web下的spring web,springCloudRouting下的OpenFeign
根据如上步骤,依次创建出其它几个微服务。
在这几个微服务中随意找到一个pom.xml文件,复制到gulimall总项目中,先不同步到Git上。
因为gulimall是一个聚合项目,不需要jar包依赖,所以将pom.xml文件中的parent标签,各种依赖全部删掉。增加pom,同时将其它的模块添加到pom文件中,如下:
"1.0" encoding="UTF-8"?>
"http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0</modelVersion>
com.atguigu.gulimall</groupId>
gulimall-ware</artifactId>
0.0.1-SNAPSHOT</version>
gulimall</name>
聚合服务</description>
pom</packaging>
gulimall-coupon</module>
gulimall-member</module>
gulimall-order</module>
gulimall-product</module>
gulimall-ware</module>
</modules>
</project>
在idea右侧的maven里,添加总服务的pom.xml
修改总服务的gitignore文件:
gitignore文件是用来忽略一些垃圾文件,防止垃圾文件随着代码一起提交的。
**/mvnw
**/mvnw.cmd
**/.mvn
**/target/
.idea
**/.gitignore
然后在git的localchanges的地方,右键default changelist,选择add to vcs,将整理好的文件纳入版本控制
但这些文件如果想上传到码云,还需要下载gitee插件
在idea的file菜单下找到settings,在plugin中下载gitee插件
在控制台的Git页中,右键DefaultChanges,点击cmmit file,即可提交,但这是提交到本地git
点击commit ,在出现的界面右下角,选择commit的下拉框,选择commit and push,可以直接将项目上传到码云
提交完之后,打开码云即可查看到刚才提交的项目。
如果当时没有选择commit and push,选择了commit,也可以直接在文件目录下右键,选择git bash ,输入命令git push来提交代码到码云
此步骤需要安装powerdesigner工具,打开数据库设计的表结构,详细资料见百度网盘。
根据数据库的设计,我们可以根据逆向工程,快速创建出各个模块的增删改查代码,来简化开发。
每个模块对应一个数据库,表的字段和含义暂不做详解,等用到时再详细解释和介绍。
该数据库表的设计最大的特点是就是:表的设计再复杂,表之间没有外键关系,因为在电商项目里面,数据量超大,做外键关联是一个非常耗费数据库性能的操作。假设每张表都有几十万甚至几百万的数据,那么每次插入删除一条数据,数据库都需要对外键进行检查来保持自己的一致性。
具体的表结构语句也放在网盘中,可以根据语句直接创建出数据库表。
在cmd命令上输入vagrant ssh,连接上虚拟机,
再输入命令:docker ps,查看正在运行的容器中是否存在mysql,发现并没有容器运行。原因是:这些容器,在docker启动时并没有自动启动。
如果想要在docker启动时自动启动所有容器,可以进行如下操作:
1.先查看安装所有的容器:docker ps -a
2.然后设置重启时自动启动:
//其中的redis和mysql为前面查出的容器的name值
docker update redis --restart=always
docker update mysql --restart=always
重启虚拟机,重复之前的步骤,查看mysql是否已经随着docker的启动而自动启动。
显示mysql容器正在运行,此时用sqlyog连接上虚拟机上的数据库。