Skip to content

第6章 SpringCLoud 模拟京东在线购物

第6章-SpringCLoud-模拟京东在线购物

本章所讲内容:

6.1 基于 Springcloud 开发的电商平台微服务架构解读

6.2 单体架构 vs 微服务架构对比分析

6.3 SpringCloud 基本介绍

6.4 部署 Springcloud 开发的电商平台到 k8s 集群:部署 eureka 服务

实验环境:k8s 集群:

k8s 的控制节点

​ ip:192.168.20.201 ; 主机名:k8s-master01 ; 配置:4vCPU/4Gi 内存

​ ip:192.168.20.202 ; 主机名:k8s-master02 ; 配置:4vCPU/4Gi 内存

​ ip:192.168.20.203 ; 主机名:k8s-master03 ; 配置:4vCPU/4Gi 内存

k8s 的工作节点:

​ ip:192.168.20.204 ; 主机名:k8s-node01; 配置:4vCPU/8Gi 内存

​ ip:192.168.20.205 ; 主机名:k8s-node02; 配置:4vCPU/8Gi 内存

harbor 机器:

​ ip:192.168.20.206 ; 主机名:harbor ; 配置:4vCPU/2Gi 内存

Mysql 服务:mysql 部署在 k8s-master01 上,暴露的端口是 3306

下面实验依赖的服务有 harbor、Ingress controller、mysql,上一节课已经安装成功了注:为什么要将 SpringCloud 项目迁移到 K8S 平台?

SpringCloud 很多功能都跟kubernetes 重合,比如服务发现,负载均衡,配置管理,所以如果把

SpringCloud 部署到k8s,那么很多功能可以直接使用 k8s 原生的,减少复杂度。

6.1 基于 Springcloud 开发的电商平台微服务架构解读

6.1.1 基于 springcloud 的电商平台功能图

img

画图工具: Xmind Visio

https://www.processon.com

6.1.2 基于 springcloud 的电商平台架构图

img

6.2 单体架构vs 微服务架构对比分析

什么是单体架构?

所有的服务放到一个代码块里开发,如果是 java 开发的代码,启动一个 jar 文件之后,所有功能都自动实现了。耦合性太高了,更新一个功能,整个代码都需要重新部署。

优点:部署方便

缺点:升级的时候只改动一个功能,可能会影响所有的服务

什么是微服务架构?

把一个大的平台,拆分成很多小的功能模块,每个模块单独开发,单独部署。优点:维护的时候,改动一个功能模块,不会影响其他的功能模块

缺点:服务太多,需要人员维护

6.3 SpringCloud 基本介绍

6.3.1 SpringCloud 是什么? 官方解释:

官网: https://spring.io/projects/spring-cloud/

SpringCloud 是一系列框架的有序集合。它利用 SpringBoot 的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用SpringBoot 的开发风格做到一键启动和部署。SpringCloud 并没有重复制造轮子,它只是将各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过 SpringBoot 风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。

6.3.2 SpringCloud 优缺点

1) SpringCloud 来源于 Spring,质量、稳定性、持续性都可以得到保证。

SpirngCloud 以 SpringBoot 为基础开发框架,可以给开发者大量的微服务开发经验,例如,只要极少量的标签,你就可以创建一个配置服务器,再加一些标签,你就可以得到一个客户端库来配置你的服务,更加便于业务落地。

2) SpringCloud 是 Java 领域最适合做微服务的框架,对 Java 开发者来说就很容易开发。

3) 耦合度低,不影响其他模块

4) 多个开发团队可以并行开发项目,提高开发效率

5) 直接写自己的代码即可,然后暴露接口,通过组件进行服务通信。

缺点:

只能针对 Java 开发部署麻烦、组件多

6.3.3 为何要将 SpringCloud 项目部署到 k8s 平台?

k8s 是一个容器编排工具,能跑任何代码,k8s 本身的功能也很多:

自动扩缩容、能跑任何代码、服务发现和负载均衡、配置管理中心、k8s 结合 istio 可以实现熔断、超时、重试这些功能。

springcloud 开发的代码部署到 k8s 里,那 springcloud 自带的很多功能可以直接用 k8s 取实现, 如 springcloud 有eureka:服务注册和发现,可以用 k8s 的 coredns 和 service,springcloud 里的网段服务 Springcloud Gateway 可以用 k8s 的 ingress-nginx-controller 去实现,spirngcloud config 可以用 K8s 的 configmap 或者 secret 实现,springcloud 里的 hystrix(熔断)可以基于Istio 实现。

6.3.4 将公司业务部署到 k8s 的完整流程

第一步:写代码、开发人员要基于 Springcloud 框架开发代码,基于 Springcloud 开发的代是微服务架构。

第二步:获取代码(可以从代码仓库获取开发写好的代码,代码可以是 gitlab 或者 svn 都可以) 第三步:编译代码,如果是 Springcloud 开发的 java 代码,mvn 命令去编译

第四步:基于 dockerfile 制作镜像,把代码和依赖的服务封装到镜像里第五步:把做好的镜像传到私有镜像仓库,私有镜像仓库用 harbor

第六步:创建 pod(选择一个合适的控制器管理 Pod,如 deployment 或者 Statefulset)

什么样的服务用 Deployment 管理 pod?

无状态的服务用 Deployment,那么问题来了,什么样的服务叫做无状态?

1、坏一个服务,对整体没影响,如 tomcat

2、不需要做会话保持

什么样的服务用 Statefulset 管理 pod?

有状态的服务用 Statefulset,有状态服务特点?

1、坏一个服务,对整体有影响,mysql 主从

2、需要做会话保持:statefulset 创建的 pod 有序的

3、需要做共享数据

第七步:在 Pod 前端创建一个 Service 资源,实现四层代理

img

第八步:如果是一个前端服务,映射到公网上的,比方说电商网站首页,需要搞成 https 安全加密的方式访问,那就需要基于 Ingress-nginx-controller 实现七层代理。

第九步:需要对 pod 里面的服务进行数据持久化(比方说 mysql、oracle、elasticsearch 等服务,需要存数据的),如何存数据?可以用分布式的存储:ceph、云存储。

第十步:需要把监控系统(Promethues+Grafana+Alertmanager 或者zabbix)搭建出来、需要把日志平台搭建出来(EFK、EFK+logstash+kafka/redis)

引申一个面试题:

上线一个新项目,需要多少 k8s 节点?

首先要看看在 K8s 里运行的服务大概有哪些,比方说运行的服务有 A、B、C A 服务需要部署两个,2 个 pod:10g、10VCPU

B 服务需要部署 10 个:10 个 Pod:20g、20VCPU C 服务需要部署 6 个:6 个 pod:12g、12VCPU

具体每个服务部署几个 pod,我们要压测,由运营或者项目经理去评估大概业务量,根据压测的结果:比方说请求量是一百万,我们需要使用 4g 内存、4vCPU,那有了这个数据,每个服务数量就可以大概确定。

A、B、C 三个服务运行的 pod 一共是占用 42g 内存、42VCPU,所有的 pod 总的内存和 cpu 都有了,那 k8s 节点配置就大概有数了。

控制节点至少 3 个做高可用:每个节点 8G 内存、12VCPU 工作节点 2 个: 每个节点 26g、26VCPU

6.4 部署 Springcloud 开发的电商平台到 k8s 集群:部署

eureka 服务

以下步骤均在 k8s 的控制节点xuegod63 上操作

6.4.1 SpringCloud 的微服务电商框架

img

6.4.2 安装 openjdk 和maven

在 k8s 控制节点 k8s-master01上操作

[root@k8s-master01 springcloud]# yum install java-1.8.0-openjdk maven-3.0.5* -y

6.4.3 上传微服务源码包到 k8s 的控制节点 上

#解压

[root@k8s-master01 springcloud]# unzip microservic-test.zip 
[root@k8s-master01 springcloud]# cd microservic-test

6.4.4 修改源代码,更改数据库连接地址在 k8s 控制节点 上操作

1) 修改库存服务 stock 的数据库连接地址

[root@k8s-master01 springcloud]# vim microservic-test/stock-service/stock-service-biz/src/main/resources/application-fat.yml 
[root@k8s-master01 springcloud]# cat microservic-test/stock-service/stock-service-biz/src/main/resources/application-fat.yml
spring:
  datasource:
    url: jdbc:mysql://192.168.20.201:3306/tb_stock?characterEncoding=utf-8
    username: root
    password: 111111
    driver-class-name: com.mysql.jdbc.Driver

eureka:
  instance:
    prefer-ip-address: true
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka-0.eureka.ms:8888/eureka,http://eureka-1.eureka.ms:8888/eureka,http://eureka-2.eureka.ms:8888/eureka

改成如下:

    url: jdbc:mysql://192.168.20.201:3306/tb_stock?characterEncoding=utf-8 #变成自己的数据库地址

2) 修改产品服务 product 的数据库连接地址

[root@k8s-master01 springcloud]# vim microservic-test/product-service/product-service-biz/src/main/resources/application-fat.yml 
[root@k8s-master01 springcloud]# cat microservic-test/product-service/product-service-biz/src/main/resources/application-fat.yml
spring:
  datasource:
    url: jdbc:mysql://192.168.20.201:3306/tb_product?characterEncoding=utf-8
    username: root
    password: 111111
    driver-class-name: com.mysql.jdbc.Driver

eureka:
  instance:
    prefer-ip-address: true
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka-0.eureka.ms:8888/eureka,http://eureka-1.eureka.ms:8888/eureka,http://eureka-2.eureka.ms:8888/eureka

改成如下:

    url: jdbc:mysql://192.168.20.201:3306/tb_product?characterEncoding=utf-8 #变成自己的数据库地址

3) 修改订单数据库

[root@k8s-master01 springcloud]# vim microservic-test/order-service/order-service-biz/src/main/resources/application-fat.yml 
[root@k8s-master01 springcloud]# cat microservic-test/order-service/order-service-biz/src/main/resources/application-fat.yml
spring:
  datasource:
    url: jdbc:mysql://192.168.20.201:3306/tb_order?characterEncoding=utf-8
    username: root
    password: 111111
    driver-class-name: com.mysql.jdbc.Driver

eureka:
  instance:
    prefer-ip-address: true
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka-0.eureka.ms:8888/eureka,http://eureka-1.eureka.ms:8888/eureka,http://eureka-2.eureka.ms:8888/eureka

改成如下:

    url: jdbc:mysql://192.168.20.201:3306/tb_order?characterEncoding=utf-8 #变成自己的数据库地址

6.4.5 通过 Maven 编译、构建、打包源代码在 k8s 控制节点 上操作

修改源代码数据库的地址之后回到/root/springcloud/microservic-test 目录下执行如下命令:

[root@k8s-master01 microservic-test]# pwd
/root/springcloud/microservic-test
[root@k8s-master01 microservic-test]# mvn clean package -D maven.test.skip=true

编译完成大概需要 15-20 分钟,看到如下说明编译打包已经成功了:

[INFO] gateway-service ................................... SUCCESS [5:52.813s]
[INFO] eureka-service .................................... SUCCESS [1:19.355s]
[INFO] product-service ................................... SUCCESS [0.000s]
[INFO] product-service-api ............................... SUCCESS [0.152s]
[INFO] stock-service ..................................... SUCCESS [0.001s]
[INFO] stock-service-api ................................. SUCCESS [0.151s]
[INFO] product-service-biz ............................... SUCCESS [5.176s]
[INFO] stock-service-biz ................................. SUCCESS [0.183s]
[INFO] order-service ..................................... SUCCESS [0.000s]
[INFO] order-service-api ................................. SUCCESS [0.133s]
[INFO] order-service-biz ................................. SUCCESS [0.203s]
[INFO] basic-common-bom .................................. SUCCESS [0.001s]
[INFO] portal-service .................................... SUCCESS [0.567s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 10:29.437s
[INFO] Finished at: Tue Aug 29 17:49:35 CST 2023
[INFO] Final Memory: 73M/551M
[INFO] ------------------------------------------------------------------------

6.4.6 在 k8s 中部署 Eureka 组件

修改 所有 上的 docker 的配置文件:

$ cat > /etc/docker/daemon.json <<EOF
{
 "registry-mirrors":["https://vh3bm52y.mirror.aliyuncs.com","https://registry.docker-cn.com","https://docker.mirrors.ustc.edu.cn","https://dockerhub.azk8s.cn","http://hub-mirror.c.163.com"],
  "exec-opts": ["native.cgroupdriver=systemd"],
  "insecure-registries":["192.168.20.206","harbor"]
}
EOF

注意:

daemon.json 中新增加了如下一行内容:

  "insecure-registries":["192.168.20.206","harbor"]

这样才可以使用 harbor 私有镜像仓库

重启 docker 使配置生效

$ systemctl daemon-reload && systemctl restart docker && systemctl status docker

登录 harbor

$ docker login 192.168.20.206
Authenticating with existing credentials...
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

在 k8s 的控制节点 xuegod63 上操作创建拉取私有镜像仓库需要的 secret

[root@k8s-master01 microservic-test]# kubectl create ns ms && kubectl create secret docker-registry registry-pull-secret --docker-server=192.168.20.206 --docker-username=admin --docker-password=Harbor12345 -n ms

在 harbor 上创建一个项目 microservice

img

1) 构建镜像

上传基础镜像到控制节点

[root@k8s-master01 springcloud]# docker load -i jave-8.tar.gz  #构建镜像
[root@k8s-master01 eureka-service]# pwd
/root/springcloud/microservic-test/eureka-service
[root@k8s-master01 eureka-service]# docker build -t 192.168.20.206/microservice/eureka:v1 .
[root@k8s-master01 eureka-service]# docker push 192.168.20.206/microservice/eureka:v1

2) 部署服务

[root@k8s-master01 microservic-test]# vim k8s/eureka.yaml

img

修改 eureka.yaml 文件,把镜像变成 image: 192.168.1.62/microservice/eureka:v1

[root@k8s-master01 microservic-test]# cat k8s/eureka.yaml |egrep "image|ingressClassName"
  ingressClassName: nginx
      imagePullSecrets:
        image: 192.168.20.206/microservice/eureka:v1

3) 更新 yaml 文件

[root@k8s-master01 microservic-test]# kubectl apply -f k8s/eureka.yaml

4)查看 pod 状态

[root@k8s-master01 eureka-service]# kubectl get pod -n ms |grep eureka
eureka-0                  1/1     Running   0   3m12s
eureka-1                  1/1     Running   0   116s
eureka-2                  1/1     Running   0   49s

上面运行没问题之后,找到自己电脑的 hosts 文件,新加如下一行:

192.168.20.204 eureka.ctnrs.com

在浏览器访问 eureka.ctnrs.com 即可,可看到如下,说明 eureka 部署成功了:

img

注意:

要想访问域名 eureka.ctnrs.com,

这个需要在自己电脑的 hosts 文件新增加如下内容,192.168.20.204 是 ingress-nginx-controller

这个 pod 的 ip 地址。

192.168.20.204 eureka.ctnrs.com

总结:

6.1 基于 Springcloud 开发的电商平台微服务架构解读

6.2 单体架构 vs 微服务架构对比分析

6.3 SpringCloud 基本介绍

6.4 部署 Springcloud 开发的电商平台到 k8s 集群:部署 eureka 服务