尝试开发Mall系统
尝试开发mall系统,简单想法。
1. 动静分离
动静分离是将网站静态资源(HTML,JavaScript,CSS,img等文件)与后台应用分开部署,提高用户访问静态代码的速度,降低对后台应用访问。
- 静态资源部署至CDN上
项目中的JavaScript,CSS以及img文件都是存放在CDN服务器上,将HTML文件一起存放到CDN上之后 - 后端API提供数据
后端应用提供API,根据前端的请求进行处理,并将处理结果通过JSON格式返回至前端。 - 前后端域名
- 相同域名
用户请求api时可以避免跨域所带来的问题,相对开发更为快速,工作量也相对小一些。 - 不同域名
兼容跨域请求的情况,JSONP 或 CORS(需要浏览器支持)
- 相同域名
- 优点
api接口服务化; 前后端开发并行; 减轻后端服务器压力,提高静态资源访问速度 - 缺点
开发量变大 前后端交流成本升高 不利于网站SEO - 结论
小项目,有扩展可能,采用: 相同域名, nginx处理静态,go提供API。
初始状态:user –> nginx –> mall-api –> mysql
升级版本:user –> CDN/ haproxy –> nginx(多个) –> mall-api(多个) –> redis集群 –> mysql-proxy —> mysql master/slave(多个)
2.GO实现API
使用beego框架生成api
2.1 生成api
考虑用docker容器安装, 参考 docker笔记 启动mysql 将建表语句文件放在$HOME/docker/mall.sql中,执行建表SYS_MENU_INF, 创建mall-api
docker run -it --link malldb:mysql -v $HOME/docker:/home/ --rm mysql:8.0 sh -c 'exec mysql -h"172.17.0.2" -P3306 -uroot -prootpw mall </home/mall.sql'
cd $GOPATH/src/github.com/zerodollar
bee api mall-api -tables="SYS_MENU_INF" -driver=mysql -conn="root:rootpw@tcp(127.0.0.1:3306)/mall"
生成的文件结构是
mall-api
├── conf
│ └── app.conf
├── controllers
│ └── SYS_MENU_INF.go 对应表Post/GetOne/GetAll/Put/Delete
├── main.go
├── models
│ └── SYS_MENU_INF.go 表对应的结构
├── routers
│ └── router.go 路由 /v1/SYS_MENU_INF
└── tests
2.2 测试访问
插入预置数据到SYS_MENU_INF表中,以bee方式启动,可以监控文件变动自动编译、重启 注意检查conf/app.conf中EnableDocs = true
cd $GOPATH/src/github.com/zerodollar/mall-api
bee run watchall -gendoc=true -downdoc=true
打开浏览器访问http://localhost:8080/v1/SYS_MENU_INF/ , 会以json返回所有记录
2.3测试API文档
访问API文档 http://localhost:8080/swagger/, 如果要支持中文,修改mall-api/swagger/index.html,打开对应的lang注释, 重新访问就是中文了
<script src='lang/translator.js' type='text/javascript'></script>
<script src='lang/zh-cn.js' type='text/javascript'></script>
2.4 生成docker镜像
构建linux运行包生成镜像,但docker hub只支持一个仓库,无法再push
export GOOS=linux
go build
cp mall-api ~/docker
docker build -f Dockerfile.mall-api -t z29759/mall-api .
文件~/docker/Dockerfile.mall-api
FROM scratch
ADD ./mall-api /home/mall-api
ADD ./conf/app.conf /home/conf/app.conf
ENTRYPOINT ["/home/mall-api" ]
2.5 启动镜像
启动镜像,访问
export MYSQLIP=`docker inspect malldb|jq ".[0].NetworkSettings.IPAddress"|sed 's/"//g'`
docker run -p 8080:8080 --name mallapi --link malldb:mysql -d z29759/mall-api -db "root:rootpw@tcp($MYSQLIP:3306)/mall"
3.前端
前台用 Angular2.0+TypeScript 做js框架,使用AdminLTE做css框架
使用angular-cli脚手架
sudo npm config set registry https://registry.npm.taobao.org
sudo npm install -g typescript typings angular-cli@latest
ng completion 1>> ~/.oh-my-zsh/custom/zjy.zsh
ng new mall-cli --style less
cd mall-cli
npm start
引入 Admin-LTE
angular-cli.json 的 apps -> scripts ->添加
"../node_modules/jquery/dist/jquery.js",
"../node_modules/bootstrap/dist/js/bootstrap.js",
"../node_modules/admin-lte/dist/js/app.js"
package.json中dependencies增加
"admin-lte": "^2.3.8",
"bootstrap": "^3.3.7",
"jquery": "^3.1.1",
"font-awesome": "^4.7.0",
"angular2-toaster": "^1.0.2",
"ng2-translate": "^4.2.0",
"ionicons": "^3.0.0",
安装依赖插件
npm install
支持用户
用户模型定义/服务定义
ng g class models/user
ng g s services/user
定义currentUser: ReplaySubject
添加转换 Service
引用了use的语言设置,再设置translate
ng g s services/translate
assets/i18n/en.json 多语言 assets/img/ 图片· fonts 字体
添加主页 components
cd src/app
ng g c pages/home
app-header 导航条 app-menu-aside 左侧边栏 div中router-outlet 页面内容 app-footer 脚注 app-aside 右侧边栏
设置图标
fa-circle-o 类似的是从这里获取的: http://fontawesome.io/icons/
跨域
beego.InsertFilter("*", beego.BeforeRouter,cors.Allow(&cors.Options{
AllowOrigins: []string{"https://*.foo.com"},
AllowMethods: []string{"PUT", "PATCH"},
AllowHeaders: []string{"Origin"},
ExposeHeaders: []string{"Content-Length"},
AllowCredentials: true,
}))
参考vue跨域
func (c *BaseController) AllowCross() {
c.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Origin", "http://localhost:8080") //允许访问源
c.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS") //允许post访问
c.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Headers", "Content-Type,Authorization") //header的类型
c.Ctx.ResponseWriter.Header().Set("Access-Control-Max-Age", "1728000")
c.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Credentials", "true")
c.Ctx.ResponseWriter.Header().Set("content-type", "application/json") //返回数据格式是json
}
beego.NSNamespace("/*",
//Options用于跨域复杂请求预检
beego.NSRouter("/*", &v1.BaseController{}, "options:Options"),
),
func (c *BaseController) Options() {
c.AllowCross() //允许跨域
c.Data["json"] = map[string]interface{}{"status": 200, "message": "ok", "moreinfo": ""}
c.ServeJSON()
}
- Refused to set unsafe header “Origin”
客户端的Header不需要设置Origin
4.MySQL 读写分离
- 应用层实现
Sprint JDBC/mhBatis/Hibernate访问数据库时配置多数据源,组件会将请求分流到不同的数据源
一个MasterDataSource,更新数据时用
一个SlaveDataSource,查询数据时用,如果有多个从,集成AbstractRoutingDataSource自己实现算法 不需要底层复杂的配置/性能较好,对应用侵入比较强/不利于扩展 - 代理实现
应用层和数据库集群间添加一个代理服务。
MySql读写分离,及数据库高可用负载均衡的实现
proxy代理client和mysql服务,根据sql操作路由到master/或slave
实现读写分离的工具有很多,阿里巴巴的cobar/360的atlas/go写的kingshard
- 1.读写分离。
- 2.跨节点分表。
- 3.客户端IP访问控制。
- 4.平滑上线DB或下线DB,前端应用无感知。
5.各模块启动命令
mysql
cd mysql
docker build -t zerodollar/mysql .
docker ps |grep malldb|awk '{print $1}'|xargs docker stop
docker ps -a|grep malldb|awk '{print $1}'|xargs docker rm
docker run --name malldb -p 3306:3306 -e MYSQL_ROOT_PASSWORD=rootpw -v `pwd`/malldb_volume:/var/lib/mysql -d zerodollar/mysql
export MYSQLIP=`docker inspect --format malldb`
docker run -it --link malldb:mysql -v `pwd`:/home/ --rm zerodollar/mysql sh -c "exec mysql -h$MYSQLIP -P3306 -uroot -prootpw </home/mall.sql"
如果有仓库,直接push后run
没有,打包tar czvf mysql.tar.gz --exclude mysql/malldb_volume mysql
,上传aws后解压重复上面命令
mall-api
cd mall-api/docker
export GOOS="linux"
go build ..
cp -r ../conf .
docker build -t zerodollar/mall-api .
docker ps |grep mall-api|awk '{print $1}'|xargs docker stop
docker ps -a|grep mall-api|awk '{print $1}'|xargs docker rm
export MYSQLIP=`docker inspect --format malldb`
export MYHOSTIP=`ifconfig en0|grep -w inet|awk '{print $2}'`
docker run -p 8080:8080 -e GOPATH=/ -e "TRUST_URL=http://$MYHOSTIP" --name mallapi --link malldb:zerodollar/mysql -d zerodollar/mall-api -db "root:rootpw@tcp($MYSQLIP:3306)/mall"
如果有仓库,直接push后run
没有,打包tar czvf mall-api.tar.gz docker
,上传aws后解压重复上面命令
开发态简单,bee run
可以监控代码改动
mall-cli
cd mall-api
rm -fr docker/dist
ng build -prod --aot=true --output-path docker/dist
cd docker
docker build -t zerodollar/mall-cli .
docker ps |grep mall-cli|awk '{print $1}'|xargs docker stop
docker ps -a|grep mall-cli|awk '{print $1}'|xargs docker rm
docker run -p 80:80 -p 443:443 -d -t --name mall-cli zerodollar/mall-cli
如果有仓库,直接push后run
没有,打包tar czvf mall-cli.tar.gz docker
,上传aws后解压重复上面命令
开发态简单,npm start
可以监控代码改动
aws
- 配置默认用户ec2-user使用docker
通过ssh登陆aws虚拟机,配置ec2-user免sudo使用dockerssh -i your_certi.pem ec2-user@ec2****compute.amazonaws.com sudo passwd root #可以修改root密码 sudo systemctl start docker.service #root启动docker服务 sudo usermod -a -G docker ec2-user #加入docker组方法1 sudo gpasswd -a ec2-user docker #加入docker组方法2 sudo service docker restart #重启docker服务 newgrp - docker #切换当前会话组为docker groups #查看ec2-user用户属于组docker users docker ps #跨域使用了
-
创建docker仓库
aws管理台登陆,启用EC2 Container Service,创建存储库 mall-api,按查看推送命令得到具体指导 - 升级aws cli
系统自带的aws不支持aws ecr,需要升级wget https://bootstrap.pypa.io/get-pip.py sudo python get-pip.py sudo python get-pip.py sudo pip install --upgrade awscli
- 配置aws cli
我的安全凭证 > 访问密钥(访问密钥 ID 和私有访问密钥) > 创建访问密钥 ,需要立刻下载,后面不能再查看/下载, 访问密钥(Access Key ID),私有访问密钥(Secret Access Key) 推送命令显示aws ecr get-login --region us-west-2
得到Default region name为us-west-2 参考aws的官方文档,配置客户端:aws configure aws ecr get-login --region us-west-2 #拷贝输出信息并执行,成功后凭证保存在~/.docker/config.json
- 升级docker版本
docker 版本低,可能报Error response from daemon: Cannot find child for ...
, 升级到最新版本 由于安装的是suse,参考docker官方文档升级$ service docker stop $ sudo zypper addrepo https://yum.dockerproject.org/repo/main/opensuse/13.2/ docker-main $ sudo zypper refresh $ zypper search -s --match-exact -t package docker-engine $ sudo zypper install docker-engine-<VERSION_STRING> $ sudo service docker start
-
上传gz包
由于镜像较大,上传gz报到aws,在其上作镜像非常快 将3个gz包上传aws,sftp -i your_certi.pem ec2-user@ec2****compute.amazonaws.com
-
导入镜像
简单docker load - 启动
export AWS=920063008583.dkr.ecr.us-west-2.amazonaws.com #启动mysql docker run --name malldb -p 3306:3306 -e MYSQL_ROOT_PASSWORD=rootpw -v ~/malldb_volume:/var/lib/mysql -d $AWS/mysql export MYSQLIP=`docker inspect --format malldb` docker run -it --link malldb:${AWS}/mysql -v `pwd`:/home/ --rm ${AWS}/mysql sh -c "exec mysql -h$MYSQLIP -P3306 -uroot -prootpw </home/mall.sql" export MYSQLIP=`docker inspect --format malldb` docker run -p 8080:8080 -e GOPATH=/ --name mallapi --link malldb:$AWS/mysql -d $AWS/mall-api -db "root:rootpw@tcp($MYSQLIP:3306)/mall" docker run -p 80:80 -p 443:443 -d -t --name mall-cli $AWS/mall-cli
之后就可以通过
http://ec2-<IP>.us-west-2.compute.amazonaws.com/
访问了
FAQ
- 报错:service: no such service docker
systemctl unmask docker.service systemctl unmask docker.socket systemctl start docker.service
留下评论
您的电子邮箱地址并不会被展示。请填写标记为必须的字段。 *