微服务架构

微服务架构

概述

介绍

  • http://c.biancheng.net/springcloud/micro-service.html

  • 微服务架构(Microservice Architecture)是一种架构概念,旨在通过将功能分解到各个离散的服务中,从而降低系统的耦合性,并提供更加灵活的服务支持

  • 概念

    • 把一个大型的单个应用程序和服务拆分为数个甚至数十个的支持微服务,它可扩展单个组件而不是整个应用程序,从而满足服务等级协议
  • 定义

    • 围绕业务领域组件来创建应用,这些应用可独立地进行开发、管理和迭代
  • 本质

    • 用一些功能比较明确、业务比较精练的服务去解决更大、更实际的问题
  • 优点

    • 复杂度可控,独立按需扩展,技术选型灵活,容错,可用性高
  • 缺点(挑战)

    • 系统部署依赖,服务间通信成本,数据一致性,系统集成测试,重复工作,性能监控等

系统架构业务驱动力

  • 提高敏捷性

    • 及时响应业务需求,促进企业发展
  • 提升用户体验

    • 提升用户体验,减少用户流失
  • 降低成本

    • 降低增加产品、客户或业务方案的成本

传统开发模式

  • 介绍

    • 和Microservice相对应的,这种方式一般被称为Monolithic(单体式开发)
    • 所有的功能打包在一个WAR包里,基本没有外部依赖,部署在一个JEE容器(Tomcat,JBoss,WebLogic)里,包含了DO/DAO,Service,UI等所有逻辑
  • 架构

  • 优点

    • 开发简单,集中式管理
    • 基本不会重复开发
    • 功能都在本地,没有分布式的管理和调用消耗
  • 缺点

    • 效率低

      • 开发都在同一个项目改代码,相互等待,冲突不断
    • 维护难

      • 代码功功能耦合在一起,新人不知道何从下手
    • 不灵活

      • 构建时间长,任何小修改都要重构整个项目,耗时
    • 稳定性差

      • 一个微小的问题,都可能导致整个应用挂掉
    • 扩展性不够

      • 无法满足高并发下的业务需求

微服务的特征

  • 一些独立的服务共同组成系统
  • 单独部署,跑在自己的进程中
  • 每个服务为独立的业务开发
  • 分布式管理
  • 非常强调隔离性

实践微服务

  • 客户端如何访问这些服务

    • 一般在后台N个服务和UI之间会配置一个代理或者叫API Gateway

    • 代理作用

      • 提供统一服务入口,让微服务对前台透明
      • 聚合后台的服务,节省流量,提升性能
      • 提供安全,过滤,流控等API管理功能
    • API Gateway也有可能成为单点故障或性能瓶颈

  • 每个服务之间如何通信

    • 同步调用

      • REST(JAX-RS,Spring Boot)
      • RPC(Thrift, Dubbo)
    • 异步消息调用(Kafka, Notify, MetaQ)

  • 如此多的服务,如何实现?

    • 通过zookeeper等类似技术做服务注册信息的分布式管理

    • 客户端做

      • 当服务上线时,服务提供者将自己的服务信息注册到ZK(或类似框架),并通过心跳维持长链接,实时更新链接信息
      • 优点是架构简单,扩展灵活,只对服务注册器依赖。缺点是客户端要维护所有调用服务的地址,有技术难度,如Dubbo
    • 服务端做

      • 服务调用者通过ZK寻址,根据可定制算法, 找到一个服务,还可以将服务信息缓存在本地以提高性能。当服务下线时,ZK会发通知给服务客户端
      • 优点是简单,所有服务对于前台调用方透明,一般在小公司在云服务上部署的应用采用的比较多
  • 服务挂了,如何解决

    • 重试机制、限流、熔断机制、负载均衡、降级(本地缓存)

微服务项目-mall

项目地址

  • https://gitee.com/macrozheng/mall

项目介绍

  • mall项目是一套电商系统,包括前台商城系统及后台管理系统,基于SpringBoot+MyBatis实现,可采用Docker容器化部署
  • 前台商城系统(mall-admin-web)包含首页门户、商品推荐、商品搜索、商品展示、购物车、订单流程、会员中心、客户服务、帮助中心等模块
  • 后台管理系统(mall-swarm)包含商品管理、订单管理、会员管理、促销管理、运营管理、内容管理、统计报表、财务管理、权限管理、设置等模块

技术选型

  • 后端技术

  • 前端技术

系统架构图

业务架构图

mall项目部署环境

主机

  • IP地址

    • 运行服务

      • 最小配置

nginx

  • 1.1.1.21

    • nginx、mall-admin

      • 2U2G

mysql

  • 1.1.1.22

    • mysql

      • 2U2G

redis

  • 1.1.1.23

    • redis、rabbitmq、mongodb

      • 2U2G

es

  • 1.1.1.24

    • elasticsearch

      • 2U4G

nacos

  • 1.1.1.25

    • nacos

      • 1U1G

mall

  • 1.1.1.26

    • mall-swarm

      • 2U4G(可能不够,最好5G)

mall-swarm-master

后端项目部署

mysql

  • 上传文件

    • 微服务项目Mall\mall-swarm-master\document\sql\mall.sql
  • 配置yum源

    • [root@mysql ~]# vim /etc/yum.repos.d/mysql-community.repo
      [mysql57]
      name=mysql 5.7
      baseurl=https://mirrors.bfsu.edu.cn/mysql/yum/mysql-5.7-community-el7-x86_64/
      enabled=1
      gpgcheck=0

[root@mysql ~]# yum clean all && yum makecache fast

  • 安装、启动

    • [root@mysql ~]# yum install -y mysql-community-server
      [root@mysql ~]# systemctl start mysqld
      [root@mysql ~]# systemctl enable mysqld
  • 登录

    • [root@mysql ~]# grep “password” /var/log/mysqld.log
      Nov 12 00:40:45 mysql mysqld_pre_systemd: 2021-11-11T16:40:45.935149Z 1 [Note] A temporary password is generated for root@localhost: aaaa;Cw.#1Hj

[root@mysql ~]# mysql -u root -p’aaaa;Cw.#1Hj’

  • 设置弱密码
    (生产环境切勿设置)

    • mysql> set global validate_password_policy=0;
      mysql> set global validate_password_length=4; #最少4位
      mysql> alter user user() identified by ‘root’;
      mysql> create database mall;
      mysql> create database nacos;
      mysql> grant all on mall.* to ‘mall’@‘1.1.1.%’ identified by “mall”;
      mysql> grant all on nacos.* to ‘nacos’@‘192.168.10.%’ identified by “nacos”;
  • 导入mall.sql文件

    • [root@mysql ~]# mysql -umall -pmall -D mall -h 1.1.1.22 < mall.sql

redis

  • 上传文件

    • 微服务项目Mall\packages\redis-6.2.7.tar.gz
  • 安装依赖包

    • [root@redis ~]# yum -y install gcc gcc-c++
  • 编译安装

    • [root@redis ~]# tar xf redis-6.2.7.tar.gz -C /usr/local/
      [root@redis ~]# ln -s /usr/local/redis-6.2.7 /usr/local/redis
      [root@redis ~]# cd /usr/local/redis
      [root@redis ~]# make
  • 配置redis

    • [root@redis redis]# vim redis.conf

      bind 0.0.0.0
      daemonize yes
  • 启动服务

    • [root@redis redis]# src/redis-server redis.conf

rabbitmq

  • 上传文件

    • 微服务项目Mall\packages\rabbitmq-server-3.7.18-1.el7.noarch.rpm
      微服务项目Mall\packages\esl-erlang_22.1-1_centos_7_amd64.rpm
  • 软件安装

    • [root@redis ~]# yum localinstall -y esl-erlang_22.1-1_centos_7_amd64.rpm rabbitmq-server-3.7.18-1.el7.noarch.rpm
  • 复制配置文件

    • [root@redis ~]# cp /usr/share/doc/rabbitmq-server-3.7.18/rabbitmq.config.example /etc/rabbitmq/rabbitmq.config
  • 配置允许远程登录

    • [root@redis ~]# vim /etc/rabbitmq/rabbitmq.config
      {loopback_users, []} #取消这行的注释,并去掉后面的逗号
  • 启动服务

    • [root@redis ~]# systemctl start rabbitmq-server
      [root@redis ~]# systemctl enable rabbitmq-server
  • 开启WEB界面管理工具

    • [root@redis ~]# rabbitmq-plugins enable rabbitmq_management
  • 登录WEB

    • 账号

      • 默认用户名: guest;密码: guest
    • 创建用户

      • Admin->Users->Add a user->Username:mall->Password:mall->Tags:Admin->Add user
    • 配置虚拟主机

      • Admin->Virtual Hosts->Add a new virtual host->Name:/mall->Add virtual host->进入/mall->Set permission->User选择mall->Set permission

mongodb

  • 上传文件

    • 微服务项目Mall\packages\mongodb-linux-x86_64-rhel70-4.2.11.tgz
  • 安装mongodb

    • [root@redis ~]# tar xf mongodb-linux-x86_64-rhel70-4.2.11.tgz -C /usr/local/
      [root@redis ~]# ln -s /usr/local/mongodb-linux-x86_64-rhel70-4.2.11/ /usr/local/mongo
  • 配置环境变量

    • [root@redis ~]# vim /etc/profile.d/mongo.sh
      export MONGO_HOME=/usr/local/mongo
      export PATH= P A T H : PATH: PATH:MONGO_HOME/bin
      [root@redis ~]# . /etc/profile.d/mongo.sh
  • 创建数据目录

    • [root@redis ~]# mkdir -p /var/lib/mongo
      [root@redis ~]# mkdir -p /var/log/mongodb
  • 启动mongodb

    • [root@redis ~]# mongod --dbpath /var/lib/mongo --logpath /var/log/mongodb/mongod.log --bind_ip=0.0.0.0 --fork
  • 查看是否启动成功

    • 端口 27017

es

  • 因机器内存限制,在此仅安装 ElasticSearch

  • 上传文件

    • 微服务项目Mall\packages\elasticsearch-7.11.2-linux-x86_64.tar.gz
      版本7自带jdk,否则还需安装jdk
  • 安装 elasticsearch

    • [root@es ~]# tar xf elasticsearch-7.11.2-linux-x86_64.tar.gz -C /usr/local/
      [root@es ~]# ln -s /usr/local/elasticsearch-7.11.2/ /usr/local/es
      [root@es ~]# mkdir -p /data/es/{data,logs}
      [root@es ~]# useradd es
      [root@es ~]# chown es.es /usr/local/elasticsearch-7.11.2/ /data/es/ -R
  • 修改配置文件

    • [root@es ~]# cd /usr/local/es
      [root@es ~]# vim config/elasticsearch.yml
      cluster.name: es-cluster
      node.name: es
      cluster.initial_master_nodes: [“es”] #单节点增加该条目
      node.master: true
      node.data: true
      path.data: /data/es/data
      path.logs: /data/es/logs
      bootstrap.memory_lock: false
      bootstrap.system_call_filter: false
      network.host: 0.0.0.0
      http.port: 9200
      http.cors.enabled: true
      http.cors.allow-origin: “*”
      #discovery.zen.ping.unicast.hosts: [“172.16.244.26”, “172.16.244.27”]
      ##discovery.zen.minimum_master_nodes: 2
      ##discovery.zen.ping_timeout: 150s
      ##discovery.zen.fd.ping_retries: 10
      ##client.transport.ping_timeout: 60s
  • 修改资源限制

    • [root@es ~]# vim /etc/security/limits.conf
      es soft nofile 65536
      es hard nofile 131072
      es soft nproc 4096
      es hard nproc 4096
      es soft memlock unlimited
      es hard memlock unlimited

[root@es ~]# echo “vm.max_map_count=262144” >> /etc/sysctl.conf
[root@es es]# sysctl -p
vm.max_map_count = 262144

[root@es ~]# sed -i.bak ‘s/-Xms1g/-Xms2g/’ /usr/local/es/config/jvm.options

[root@es ~]# sed -i.bak ‘s/-Xmx1g/-Xmx2g/’ /usr/local/es/config/jvm.options

  • 启动elasticsearch

    • [root@es ~]# su - es -c ‘nohup /usr/local/es/bin/elasticsearch &’
  • 查看elasticsearch是否启动成功

    • 端口 9200/9300
    • curl 1.1.1.24:9200能显示uuid

nacos

  • nacos文档

    • https://nacos.io/zh-cn/docs/what-is-nacos.html
  • 上传文件

    • 微服务项目Mall\packages\jdk-8u181-linux-x64.tar.gz
      微服务项目Mall\packages\nacos-server-1.4.0.tar.gz
  • 安装jdk8

    • [root@nacos ~]# tar xf jdk-8u181-linux-x64.tar.gz
      [root@nacos ~]# mv jdk1.8.0_181/ /usr/local/java
      [root@nacos ~]# vim /etc/profile.d/java.sh
      export JAVA_HOME=/usr/local/java
      export PATH= J A V A H O M E / b i n : JAVA_HOME/bin: JAVAHOME/bin:PATH
      [root@nacos ~]# . /etc/profile.d/java.sh
  • 安装nacos

    • [root@nacos ~]# tar xf nacos-server-1.4.0.tar.gz -C /usr/local/
  • 修改配置文件

    • [root@nacos ~]# cd /usr/local/nacos/
      [root@nacos nacos]# vim conf/application.properties
      server.contextPath=/nacos
      server.servlet.contextPath=/nacos
      server.port=8848
      db.num=1
      db.url.0=jdbc:mysql://192.168.10.201:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
      db.user=nacos
      db.password=nacos
  • 启动nacos

    • [root@nacos nacos]# ./bin/startup.sh -m standalone
    • 若关机后无法启动:删掉数据目录(先关闭服务再关机)
  • 查看否启动成功

    • 端口 8848
  • 使用浏览器访问

    • http://1.1.1.25:8848/nacos/index.html

      • 用户名:nacos;密码:nacos
    • 服务注册成功后在‘服务管理->服务列表’中展示

mall

  • 上传文件

    • 微服务项目Mall\packages\jdk-8u181-linux-x64.tar.gz
      微服务项目Mall\packages\apache-maven-3.5.4-bin.tar.gz
      微服务项目Mall\mall-swarm-master
  • 安装jdk8

    • [root@nacos ~]# tar xf jdk-8u181-linux-x64.tar.gz
      [root@nacos ~]# mv jdk1.8.0_181/ /usr/local/java
      [root@nacos ~]# vim /etc/profile.d/java.sh
      export JAVA_HOME=/usr/local/java
      export PATH= J A V A H O M E / b i n : JAVA_HOME/bin: JAVAHOME/bin:PATH
      [root@nacos ~]# . /etc/profile.d/java.sh
  • 安装maven

    • [root@mall ~]# tar xf apache-maven-3.5.4-bin.tar.gz -C /usr/local/
      [root@mall ~]# ln -s /usr/local/apache-maven-3.5.4/ /usr/local/maven
  • 配置环境变量

    • [root@mall ~]# vim /etc/profile.d/mvn.sh
      export MVN_HOME=/usr/local/maven
      export PATH= P A T H : PATH: PATH:MVN_HOME/bin

[root@mall ~]# . /etc/profile.d/mvn.sh
[root@mall ~]# mvn -v

  • 配置国内镜像加速器

    • [root@mall ~]# vim /usr/local/maven/conf/settings.xml


      alimaven
      aliyun maven
      https://maven.aliyun.com/nexus/content/groups/public/
      central

  • 修改各项目配置文件

    • mall-swarm-master\config

      • 每个服务的dev.yaml、prod.yaml文件,共10个
    • application.yml

      • ./mall-search/src/main/resources/application.yml
        ./mall-portal/src/main/resources/application.yml
        ./mall-monitor/src/main/resources/application.yml 不用改
        ./mall-gateway/src/main/resources/application.yml
        ./mall-demo/src/main/resources/application.yml
        ./mall-auth/src/main/resources/application.yml 不用改
        ./mall-admin/src/main/resources/application.yml
    • bootstrap-dev.yml

      • ./mall-search/src/main/resources/bootstrap-dev.yml
        ./mall-portal/src/main/resources/bootstrap-dev.yml
        ./mall-monitor/src/main/resources/application-dev.yml
        ./mall-gateway/src/main/resources/bootstrap-dev.yml
        ./mall-demo/src/main/resources/bootstrap-dev.yml
        ./mall-auth/src/main/resources/bootstrap-dev.yml
        ./mall-admin/src/main/resources/bootstrap-dev.yml
    • bootstrap-prod.yml

      • ./mall-search/src/main/resources/bootstrap-prod.yml
        ./mall-portal/src/main/resources/bootstrap-prod.yml
        ./mall-monitor/src/main/resources/application-prod.yml
        ./mall-gateway/src/main/resources/bootstrap-prod.yml
        ./mall-demo/src/main/resources/bootstrap-prod.yml
        ./mall-auth/src/main/resources/bootstrap-prod.yml
        ./mall-admin/src/main/resources/bootstrap-prod.yml
    • 修改内容

      • 服务器IP(看配置区分)、数据库用户密码、rabbitmq用户密码
  • 项目打包

    • [root@mall mall-swarm-master]# mvn package -Dskip.test=true
  • 整理jar包

    • [root@mall ~]# mkdir /usr/local/apps
      [root@mall ~]# find ./ -name *.jar |xargs -i cp {} /usr/local/apps
  • 运行服务

    • [root@mall ~]# mkdir /var/log/mall
      [root@mall ~]# cd /usr/local/apps
      [root@mall apps]# nohup java -jar mall-portal-1.0-SNAPSHOT.jar > /var/log/mall/mall-portal.log &
      [root@mall apps]# nohup java -jar mall-gateway-1.0-SNAPSHOT.jar > /var/log/mall/mall-gateway.log &
      [root@mall apps]# nohup java -jar mall-auth-1.0-SNAPSHOT.jar > /var/log/mall/mall-auth.log &
      [root@mall apps]# nohup java -jar mall-admin-1.0-SNAPSHOT.jar > /var/log/mall/mall-admin.log &
      [root@mall apps]# nohup java -jar mall-search-1.0-SNAPSHOT.jar > /var/log/mall/mall-search.log &
      [root@mall apps]# nohup java -jar mall-monitor-1.0-SNAPSHOT.jar > /var/log/mall/mall-monitor.log &
  • 服务端口

    • mall-gateway:8201
      mall-auth:8401
      mall-admin:8080
      mall-search:8081
      mall-monitor:8101
      mall-portal:8085
  • 监控中心

    • http://1.1.1.26:8101

      • 账号:macro;密码:123456

  • API文档

    • http://1.1.1.26:8201/doc.html
  • nacos

    • http://1.1.1.25:8848/nacos/index.html

mall-admin-web

前端项目部署

nginx

  • 上传文件

    • 微服务项目Mall\packages\node-v14.19.3-linux-x64.tar.gz
      微服务项目Mall\mall-admin-web
  • 安装nginx

    • yum -y install nginx
  • nginx配置-
    解决跨域问题

    • [root@nginx ~]# vim /etc/nginx/nginx.conf

      server {
      listen 80;
      server_name _;
      include /etc/nginx/default.d/*.conf;
      location / {
      root /usr/share/nginx/html;
      index index.html index.htm;
      add_header Access-Control-Allow-Origin *;
      add_header Access-Control-Allow-Methods ‘GET, POST, OPTIONS’;
      add_header Access-Control-Allow-Headers ‘DNT, X-Mx-ReqToken, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Authorization’;
      if ($request_method = ‘OPTIONS’) {
      return 204;
      }
      }

    location /mall-admin {
    proxy_pass http://1.1.1.26:8201/mall-admin; # 这里是网关的IP及端口
    proxy_redirect off;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forward-For $remote_addr;
    proxy_set_header X-Real-IP $remote_addr;
    add_header Access-Control-Allow-Methods *;
    add_header Access-Control-Max-Age 3600;
    add_header Access-Control-Allow-Credentials true;
    add_header Access-Control-Allow-Origin $http_origin;
    add_header Access-Control-Allow-Headers h t t p a c c e s s c o n t r o l r e q u e s t h e a d e r s ; i f ( http_access_control_request_headers; if ( httpaccesscontrolrequestheaders;if(request_method = OPTIONS ) {
    return 200;
    }
    }

    }

  • 安装node

    • [root@nginx ~]# tar xf node-v14.19.3-linux-x64.tar.gz -C /usr/local/
      [root@nginx ~]# ln -sf /usr/local/node-v14.19.3-linux-x64/ /usr/local/node
      [root@nginx ~]# vim /etc/profile.d/node.sh
      export NODE_HOME=/usr/local/node
      export PATH= N O D E H O M E / b i n : NODE_HOME/bin: NODEHOME/bin:PATH

[root@nginx ~]# . /etc/profile.d/node.sh
[root@nginx ~]# node -v
v14.19.3
[root@nginx ~]# npm -v
6.14.17

  • 安装webpackage

    • [root@nginx ~]# npm install webpack -g --registry=http://registry.npmmirror.com
      [root@nginx ~]# npm install -g cnpm --registry=http://registry.npmmirror.com
      [root@nginx ~]# cnpm install -g @vue/cli-service
  • 项目打包部署

    • 修改mall-admin-web/config下dev.env.js和prod.env.js
      module.exports = {
      NODE_ENV: ‘“production”’,
      BASE_API: ‘“http://1.1.1.21/mall-admin”’ #改为nginx的IP
      }
    • [root@nginx mall-admin-web]# cnpm install # 下载项目依赖
      [root@nginx mall-admin-web]# cnpm run build # 打包dev环境的包
  • 发布

    • [root@nginx mall-admin-web]# cp -a dist/* /usr/share/nginx/html/
  • 启动nginx

    • [root@nginx mall-admin-web]# systemctl start nginx
  • 访问测试

    • http://1.1.1.21

      • 密码:macro123