第2章-环境搭建

第2章 环境搭建

1. Linux虚拟机

1.1 VirtualBox&Vagrant

  • VirtualBox

  • https://www.virtualbox.org/wiki/Downloads

Vagrant

  • 下载地址:https://www.vagrantup.com/downloads
  • 镜像仓库:https://app.vagrantup.com/boxes/search
  • 常用命令
# 检查是否安装成功
cmd
vagrant

# 创建虚拟机
vagrant init centos/7

# 启动环境
vagrant up

# ssh连接--默认账号
vagrant ssh

# 退出
exit

# 再次启动虚拟机
vagrant up

# 重启
vagrant reload

端口网络设置

image-20220207163144906

更改C:\Users\lilinfei\Vagrantfile进行设置

image-20220207163434495

# Create a private network, which allows host-only access to the machine
  # using a specific IP.
  config.vm.network "private_network", ip: "192.168.56.10" 
  
# 虚拟机
ip addr

# Ping测试

1.2 安装Docker

  • 镜像仓库:docker hub

image-20220207163759238

# 卸载系统之前的docker 
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
sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

#  安装DOCKER引擎
sudo yum install docker-ce docker-::wqce-cli containerd.io

#  启动Docker.
sudo systemctl start docker

# 配置镜像加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://rhos4sf5.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

# 开机自启
sudo systemctl enable docker

问题 – 未解决

重启之后:

Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

systemctl unmask docker.service
systemctl unmask docker.socket
systemctl start docker.service

1.3 安装MySQL

# 拉去mysql镜像
sudo docker pull mysql:5.7

# 启动mysql容器
# --name指定容器名字 -v目录挂载 -p指定端口映射  -e设置mysql参数 -d后台运行
sudo 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

# 使用su - root(切换为root,这样就不用每次都sudo来赐予了)
su - root
# 进入mysql容器
docker exec -it 容器名称|容器id bin/bash

docker exec -it mysql bin/bash

# 进去mysql
mysql -p -uroot
// root

# 更改mysql配置
# /mydata/mysql/conf
vi /mydata/mysql/conf/my.cnf


# 配置文件信息
[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

image-20220207170424502

1.4 安装Redis

# 1 在docker hub搜索redis镜像
docker search redis

# 2 拉取redis镜像到本地
docker pull redis:6.0.10

# 3 修改需要自定义的配置(docker-redis默认没有配置文件,
# 自己在宿主机建立后挂载映射)
# 创建并修改/usr/local/redis/redis.conf
bind 0.0.0.0 开启远程权限
appendonly yes 开启aof持久化

# 挂载
mkdir -p /mydata/redis/conf
touch /mydata/redis/conf/redis.conf

# 4 启动redis服务运行容器
docker run -p 6379:6379 --name redis \
-v /mydata/redis/data:/data \
-v /mydata/redis/conf/redis.conf:/etc/redis/redis.conf \
-d redis:6.0.10 redis-server /etc/redis/redis.conf
 
# 5  直接进去redis客户端
docker exec -it redis redis-cli
  • Redis使用
# 进去rerdis
docker exec -it redis redis-cli

# redis配置
vi /mydata/redis/conf/redis.conf

appendonly yes

# 重启
docker restart redis

set key value
get key
  • Redis客户端

https://redisdesktop.com/download

1.5 自启动

创建数据库之前需要启动docker服务

sudo docker ps
sudo docker ps -a
# 这两个命令的差别就是后者会显示  【已创建但没有启动的容器】

# 我们接下来设置我们要用的容器每次都是自动启动
sudo docker update redis --restart=always
sudo docker update mysql --restart=always
# 如果不配置上面的内容的话,我们也可以选择手动启动
sudo docker start mysql
sudo docker start redis

2. IDEA

2.1 Maven

在maven配置文件配置

  • 配置阿里云镜像
<mirrors>
	<mirror>
		<id>nexus-aliyun</id>
		<mirrorOf>central</mirrorOf>
		<name>Nexus aliyun</name>
		<url>http://maven.aliyun.com/nexus/content/groups/public</url>
	</mirror>
</mirrors>
  • 配置 jdk 1.8 编译项目
<profiles>
	<profile>
		<id>jdk-1.8</id>
		<activation>
			<activeByDefault>true</activeByDefault>
			<jdk>1.8</jdk>
		</activation>
		<properties>
			<maven.compiler.source>1.8</maven.compiler.source>
			<maven.compiler.target>1.8</maven.compiler.target>
			<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
		</properties>
	</profile>
</profiles>
  • IDEA指定Maven

image-20220207180024883

  • IDEA装插件

lombok/MyBatisX

2.2 VScode前端插件

  • ESLint

  • Auto Rename Tag

  • Auto Close Tag

  • HTML CSS Support

  • JavaScript (ES6) code snippets

  • Live Server

  • open in browser

  • Vetur

3. 项目开发环境

3.1 项目仓库配置

  • git ssh
  • 创建项目:Java + Maven

3.2 创建服务模块

创建以下模块
商品服务product
存储服务ware
订单服务order
优惠券服务coupon
用户服务member
每个模块导入web和openFeign
  • 命名规范
Name: gulimall-xxx
Group:com.lif314.gulimall
Artifact:gulimall-xxx
Package Name:com.lif314.gulimall.xxx
Java:8

  • 导入必要组件

Web->Speing Web

Spring Cloud Routing–> OpenFeign

3.3 聚合模块配置Pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.lif314.gulimall</groupId>
    <artifactId>gulimall</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>gulimall</name>
    <description>聚合服务</description>
    <packaging>pom</packaging>

    <!--  聚合-->
    <modules>
        <module>gulimall-coupon</module>
        <module>gulimall-member</module>
        <module>gulimall-order</module>
        <module>gulimall-product</module>
        <module>gulimall-ware</module>
    </modules>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

</project>

3.4 .gitignore模板

**/target/

4. 数据库设计–逆向工程

  • PowerDesiger
  • 每个服务有自己的数据库
  • 所有表不进行外键关联

4.1 创建数据库

# 如果要进入已启动的容器
sudo docker exec -it mysql /bin/bash


接着创建数据库
然后接着去sqlyog直接我们的操作,在左侧root上右键建立数据库:
字符集选utf8mb4,他能兼容utf8且能解决一些乱码的问题。分别
建立了下面数据库

gulimall_oms
gulimall_pms
gulimall_sms
gulimall_ums
gulimall_wms

所有的数据库数据再复杂也不建立外键,因为在电商系统里,数据量大,
做外键关联很耗性能。

由于Vagrant不好用,直接使用云服务器

5. 人人开源

  • 克隆
# 后台管理系统
git clone https://gitee.com/renrenio/renren-fast?_from=gitee_search

# 前端系统
git clone https://gitee.com/renrenio/renren-fast-vue.git

5.1 配置环境

image-20220207202238989

  • 创建数据库
gulimall-admin
  • 修改数据库配置
# application-dev.yml
spring:
    datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        druid:
            driver-class-name: com.mysql.cj.jdbc.Driver
            url: jdbc:mysql://xxx.xx.xx.xxx:3306/gulimall-admin?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
            username: root
            password: root
  • 指定项目JDK

5.2 VSCode 前端项目

  • 安装Node.js
# 配置淘宝镜像
npm config set registry http://registry.npm.taobao.org/

# 下载依赖
npm install

如果报错

然后在VScode的终端进入项目中输入 npm install,会报错,然后进行如下操作:
报错:
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! chromedriver@2.27.2 install: `node install.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the chromedriver@2.27.2 install script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     E:\installation_program\nodeRepository\npm_cache\_logs\2021-02-09T07_38_47_075Z-debug.log

解决报错:
npm install chromedriver --chromedriver_cdnurl=http://cdn.npm.taobao.org/dist/chromedriver
  • 运行
npm run dev
  • 解决报错

<% if (process.env.NODE_ENV === ‘production‘) { %> <% }else { %> <% } %>

1、先确保npm 和node版本必须符合,node>= 8.11.1,npm>= 5.6.0,VScode的终端执行node -v 和 npm -version,符合条件。

2、安装2个组件:node-sass、sass-loader 。3、VScode的终端中使用 npm run dev 运行项目就ok了。

npm install node-sass --save --unsafe-perm=true
npm install sass-loader --unsafe-perm=true

npm rebuild node-sass
npm uninstall node-sass 
npm i node-sass --sass_binary_site=https://npm.taobao.org/mirrors/node-sass/
npm install
npm run dev
  • 登录
浏览器输入localhost:8001 就可以看到内容了,
登录账号admin 密码admin

image-20220207212441563

5.3 逆向工程搭建–代码生成器

# clone
git clone https://gitee.com/renrenio/renren-generator.git

# 导入项目中
<modules>
		<module>gulimall-coupon</module>
		<module>gulimall-member</module>
		<module>gulimall-order</module>
		<module>gulimall-product</module>
		<module>gulimall-ware</module>
		<module>renren-fast</module>
		<module>renren-generator</module>
</modules>
  • 修改配置数据库源以生成相应代码
# application.yml
server:
  port: 80

# mysql
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    #MySQL配置
    driverClassName: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://xx.xx.xx.xx:3306/gulimall_pms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: root
  • 修改生成信息
# 修改generator.properties
mainPath=com.lif314 # 主目录
package=com.lif314.gulimall # 包名
moduleName=product   # 模块名
author=lif314  # 作者
email=lifer314@163.com  # email
tablePrefix=pms_   # 我们的pms数据库中的表的前缀都有pms,
  • 代码生成

image-20220207215512454

  • 将生成代码后的main替换掉下项目中的文件

image-20220207220052372

  • 依次生成所有的文件
gulimall_oms
gulimall_pms
gulimall_sms
gulimall_ums
gulimall_wms

6. 公共依赖

然后在项目上右击(在项目上右击很重要)new modules— maven—然后在name上输入gulimall-common。

在pom.xml中也自动添加了<module>gulimall-common</module>

在common项目的pom.xml(我们把每个微服务里公共的类和依赖放到common里。)中添加
<!-- mybatisPLUS-->
# pom


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>gulimall</artifactId>
        <groupId>com.lif314.gulimall</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>gulimall-common</artifactId>
    <description>公共依赖</description>

    <dependencies>
    <!-- MyBatis-Plus https://baomidou.com/pages/bab2db/#release -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>
<!--  lombok  -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
        </dependency>
        <!-- httpcomponent包https://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore -->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpcore</artifactId>
            <version>4.4.13</version>
        </dependency>
        <!-- 数据库驱动 https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.17</version>
        </dependency>
        
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

</project>
  • 在每一个子模块中导入公共依赖
<dependency>
    <groupId>com.lif314.gulimall</groupId>
    <artifactId>gulimall-common</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
  • 在renren-fast中找公工具包
import com.lif314.common.utils.PageUtils;
import com.lif314.common.utils.R;
  • 权限注解问题 — 先注释
 @RequiresPermissions("product:attrattrgrouprelation:list")

7. 整合MyBatis-Plus

7.1 导入common依赖

    <!-- MyBatis-Plus https://baomidou.com/pages/bab2db/#release -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>

7.2 配置

https://baomidou.com/pages/226c21/#%E9%85%8D%E7%BD%AE

配置数据源

  • 导入数据库驱动

common-pom中

<!-- 数据库驱动 https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.17</version>
</dependency>
  • 配置数据源

创建application.yml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://xx.xx.xx.xx:3306/gulimall_pms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: root

配置MyBatis-PLUS

  • 使用@Mapper-Scan
package com.lif314.gulimall.product;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


@MapperScan("com.lif314.gulimall.product.dao")
@SpringBootApplication
public class GulimallProductApplication {

    public static void main(String[] args) {
        SpringApplication.run(GulimallProductApplication.class, args);
    }

}
  • 配置映射文件
# sql映射文件位置
mybatis-plus:
  mapper-locations: classpath:/mapper/**/*.xml
  global-config:
    db-config:
      # 主键自增
      id-type: auto

7.3 测试

测试过程中出错的包导入在common中即可

package com.lif314.gulimall.product;

import com.lif314.gulimall.product.entity.BrandEntity;
import com.lif314.gulimall.product.service.BrandService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import javax.sound.midi.Soundbank;

@SpringBootTest
class GulimallProductApplicationTests {

    @Autowired
    BrandService brandService;

    @Test
    void contextLoads() {
        BrandEntity brandEntity = new BrandEntity();
        brandEntity.setName("华为");
        brandService.save(brandEntity);
        System.out.println("保存成功-----");
    }
}

其它模块类似上述方法

7.4 端口编排

gulimall-coupon:5000
gulimall-member:6000
gulimall-order:7000
gulimall-product:8000
gulimall-ware:9000

8. 分布式组件 – SpringCloud Alibaba

image-20220207235030093

  • https://github.com/alibaba/spring-cloud-alibaba/blob/2.2.x/README-zh.md

image-20220207233415250

Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。

依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。

此外,阿里云同时还提供了 Spring Cloud Alibaba 企业版 微服务解决方案,包括无侵入服务治理(全链路灰度,无损上下线,离群实例摘除等),企业级 Nacos 注册配置中心和企业级云原生网关等众多产品。

主要功能


  • 服务限流降级:默认支持 WebServlet、WebFlux、OpenFeign、RestTemplate、Spring Cloud Gateway、Zuul、Dubbo 和 RocketMQ 限流降级功能的接入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级 Metrics 监控。
  • 服务注册与发现:适配 Spring Cloud 服务注册与发现标准,默认集成了 Ribbon 的支持。
  • 分布式配置管理:支持分布式系统中的外部化配置,配置更改时自动刷新。
  • 消息驱动能力:基于 Spring Cloud Stream 为微服务应用构建消息驱动能力。
  • 分布式事务:使用 @GlobalTransactional 注解, 高效并且对业务零侵入地解决分布式事务问题。
  • 阿里云对象存储:阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任何时间、任何地点存储和访问任意类型的数据。
  • 分布式任务调度:提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有 Worker(schedulerx-client)上执行。
  • 阿里云短信服务:覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。

组件


Sentinel:把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

Nacos:一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。

RocketMQ:一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。

Dubbo:Apache Dubbo™ 是一款高性能 Java RPC 框架。

Seata:阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案。

Alibaba Cloud OSS: 阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。

Alibaba Cloud SchedulerX: 阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。

Alibaba Cloud SMS: 覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。

引入依赖


  • 版本选择:
1.5.x 版本适用于 Spring Boot 1.5.x
2.0.x 版本适用于 Spring Boot 2.0.x
2.1.x 版本适用于 Spring Boot 2.1.x
2.2.x 版本适用于 Spring Boot 2.2.x
2021.x 版本适用于 Spring Boot 2.4.x

  • doc:https://spring-cloud-alibaba-group.github.io/github-pages/hoxton/en-us/index.html#_dependency_management

common-pom

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.2.7.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

8.1 Nacos – 注册中心/配置中心

  • doc:https://nacos.io/zh-cn/docs/what-is-nacos.html

  • 服务发现和服务健康监测

    Nacos 支持基于 DNS 和基于 RPC 的服务发现。服务提供者使用 原生SDKOpenAPI、或一个独立的Agent TODO注册 Service 后,服务消费者可以使用DNS TODOHTTP&API查找和发现服务。

    Nacos 提供对服务的实时的健康检查,阻止向不健康的主机或服务实例发送请求。Nacos 支持传输层 (PING 或 TCP)和应用层 (如 HTTP、MySQL、用户自定义)的健康检查。 对于复杂的云环境和网络拓扑环境中(如 VPC、边缘网络等)服务的健康检查,Nacos 提供了 agent 上报模式和服务端主动检测2种健康检查模式。Nacos 还提供了统一的健康检查仪表盘,帮助您根据健康状态管理服务的可用性及流量。

  • 动态配置服务

    动态配置服务可以让您以中心化、外部化和动态化的方式管理所有环境的应用配置和服务配置。

    动态配置消除了配置变更时重新部署应用和服务的需要,让配置管理变得更加高效和敏捷。

    配置中心化管理让实现无状态服务变得更简单,让服务按需弹性扩展变得更容易。

    Nacos 提供了一个简洁易用的UI (控制台样例 Demo) 帮助您管理所有的服务和应用的配置。Nacos 还提供包括配置版本跟踪、金丝雀发布、一键回滚配置以及客户端配置更新状态跟踪在内的一系列开箱即用的配置管理特性,帮助您更安全地在生产环境中管理配置变更和降低配置变更带来的风险。

  • 动态 DNS 服务

    动态 DNS 服务支持权重路由,让您更容易地实现中间层负载均衡、更灵活的路由策略、流量控制以及数据中心内网的简单DNS解析服务。动态DNS服务还能让您更容易地实现以 DNS 协议为基础的服务发现,以帮助您消除耦合到厂商私有服务发现 API 上的风险。

    Nacos 提供了一些简单的 DNS APIs TODO 帮助您管理服务的关联域名和可用的 IP:PORT 列表.

  • 服务及其元数据管理

    Nacos 能让您从微服务平台建设的视角管理数据中心的所有服务及元数据,包括管理服务的描述、生命周期、服务的静态依赖分析、服务的健康状态、服务的流量管理、路由及安全策略、服务的 SLA 以及最首要的 metrics 统计数据。

8.1.1 安装
  • 下载编译后压缩包方式。您可以从 最新稳定版本 下载 nacos-server-$version.zip 包。

  • 启动服务器

    启动命令(standalone代表着单机模式运行,非集群模式):

    sh startup.sh -m standalone
    

    如果您使用的是ubuntu系统,或者运行脚本报错提示[[符号找不到,可尝试如下运行:

    bash startup.sh -m standalone
    
  • 修改配置conf,更改数据源

### Connect URL of DB:
db.url.0=jdbc:mysql://xx.xx.xx.xx:3306/gulimall_nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=root
db.password.0=root
  • 访问

http://xx.xx.xx.xx:8848/nacos/

8.1.2 Nacos服务发现
  • common-pom中服务发现
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
  • 每个服务进行配置
spring:
  # 服务发现
  cloud:
    nacos:
      discovery:
        server-addr: xx.xx.xx.xx:8848
  # 模块名
  application:
    name: gulimall-productspring:
  cloud:
    nacos:
      discovery:
        server-addr: xx.xx.xx.xx:8848
  • 启动服务发现
package com.lif314.gulimall.coupon;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

// 服务发现
@EnableDiscoveryClient
@MapperScan("com.lif314.gulimall.coupon.dao")
@SpringBootApplication
public class GulimallCouponApplication {

    public static void main(String[] args) {
        SpringApplication.run(GulimallCouponApplication.class, args);
    }

}
  • 测试

版本问题

com.alibaba.nacos.api.exception.NacosException: Request nacos server failed: 
	at com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy.requestToServer(NamingGrpcClientProxy.java:279) ~[nacos-client-2.0.3.jar:na]
	at com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy.doSubscribe(NamingGrpcClientProxy.java:227) ~[nacos-client-2.0.3.jar:na]
	at com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy.subscribe(NamingGrpcClientProxy.java:212) ~[nacos-client-2.0.3.jar:na]
	at com.alibaba.nacos.client.naming.remote.NamingClientProxyDelegate.subscribe(NamingClientProxyDelegate.java:147) ~[nacos-client-2.0.3.jar:na]
	at com.alibaba.nacos.client.naming.NacosNamingService.subscribe(NacosNamingService.java:393) ~[nacos-client-2.0.3.jar:na]
	at com.alibaba.cloud.nacos.discovery.NacosWatch.start(NacosWatch.java:134) ~[spring-cloud-starter-alibaba-nacos-discovery-2.2.7.RELEASE.jar:2.2.7.RELEASE]
	at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:178) [spring-context-5.3.15.jar:5.3.15]
	at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:54) [spring-context-5.3.15.jar:5.3.15]
	at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:356) [spring-context-5.3.15.jar:5.3.15]
	at java.lang.Iterable.forEach(Iterable.java:75) ~[na:1.8.0_302]
	at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:155) [spring-context-5.3.15.jar:5.3.15]
	at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:123) [spring-context-5.3.15.jar:5.3.15]
	at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:935) ~[spring-context-5.3.15.jar:5.3.15]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:586) ~[spring-context-5.3.15.jar:5.3.15]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.6.3.jar:2.6.3]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732) ~[spring-boot-2.6.3.jar:2.6.3]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:414) ~[spring-boot-2.6.3.jar:2.6.3]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:302) ~[spring-boot-2.6.3.jar:2.6.3]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303) ~[spring-boot-2.6.3.jar:2.6.3]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292) ~[spring-boot-2.6.3.jar:2.6.3]
	at com.lif314.gulimall.product.GulimallProductApplication.main(GulimallProductApplication.java:14) ~[classes/:na]
Caused by: com.alibaba.nacos.api.exception.NacosException: Client not connected,current status:STARTING
	at com.alibaba.nacos.common.remote.client.RpcClient.request(RpcClient.java:655) ~[nacos-client-2.0.3.jar:na]
	at com.alibaba.nacos.common.remote.client.RpcClient.request(RpcClient.java:635) ~[nacos-client-2.0.3.jar:na]
	at com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy.requestToServer(NamingGrpcClientProxy.java:269) ~[nacos-client-2.0.3.jar:na]
	... 20 common frames omitted
  • 尝试安装2.0.3版本 – 问题解决

image-20220208004433097

8.2 OpenFeign–远程调用

  • 测试:想要获取当前会员领取到的所有优惠券。先去注册中心找优惠券服务, 注册中心调一台优惠券服务器给会员,会员服务器发送请求给这台优 惠券服务器,然后对方响应。

  • OpenFeign: 声明式远程调用。feign是一个声明式的HTTP客户端,他的目的就是让远程调用更加简单。 给远程服务发的是HTTP请求。

使用测试

  • coupon – 填写优惠券信息
@RequestMapping("coupon/coupon")
public class CouponController {
    @Autowired
    private CouponService couponService;

    // OpenFeign使用测试
    @RequestMapping("/member/list")
    public R membercoupons(){    //全系统的所有返回都返回R
        // 应该去数据库查用户对于的优惠券,但这个我们简化了,不去数据库查了,构造了一个优惠券给他返回
        CouponEntity couponEntity = new CouponEntity();
        couponEntity.setCouponName("满100减10");//优惠券的名字
        return R.ok().put("coupons",Arrays.asList(couponEntity));
    }
  • 在微服务中引入依赖,以提供远程调用的功能(coupon/member)
		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
  • 编写接口,告诉SpringCloud这个接口需要调用远程服务

    • 声明接口的每个方法需要调用远程服务的请求URL

      package com.lif314.gulimall.member.feign;
      
      import com.lif314.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();
          }
      
    • 开启远程调用功能

    package com.lif314.gulimall.member;
    
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    import org.springframework.cloud.openfeign.EnableFeignClients;
    
    @MapperScan("com.lif314.gulimall.member.dao")
    @SpringBootApplication
    @EnableDiscoveryClient
    // 开启远程调用功能 -- 扫描该包下的远程调用服务
    @EnableFeignClients(basePackages = "com.lif314.gulimall.member.feign")
    public class GulimallMemberApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(GulimallMemberApplication.class, args);
        }
    
    }
    
  • controller调用测试

public class MemberController {
    @Autowired
    private MemberService memberService;

    // 远程调用测试
    @Autowired
    CouponFeignService couponFeignService;

    @RequestMapping("/coupons")
    public R test(){
        MemberEntity memberEntity = new MemberEntity();
        memberEntity.setNickname("张三");
        R membercoupons = couponFeignService.membercoupons();
        return R.ok().put("member", memberEntity).put("coupons", membercoupons.get("coupons"));
    }
}
  • 查看

Error:No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-loadbalancer?

使用Spring Initializr初始化项目引入了openfeign,没有在意版本。直到运行项目进行远程调用时报错.

在服务中添加依赖 – nacos"包中移除ribbion依赖,并加入loadbalancer依赖"

<!--服务注册-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    <!--不使用Ribbon 进行客户端负载均衡-->
    <exclusions>
        <exclusion>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!--使用Spring Cloud LoadBalancer 进行客户端负载均衡-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>

如果还存在问题,将maven clean后重新启动

  • 访问http://localhost:8100/member/member/coupons

Error: 网页可能暂时无法连接,或者它已永久性地移动到了新网址

解决方法

  • org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.choose

解决:在nacos"包中移除ribbion依赖,并加入loadbalancer依赖"

在common-pom使用

<!--服务注册-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <!--不使用Ribbon 进行客户端负载均衡-->
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--使用Spring Cloud LoadBalancer 进行客户端负载均衡-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-loadbalancer</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>
  • 测试成功

image-20220208042753259

8.3 Nacos配置中心

8.3.1 简单配置
  • 引入配置中心依赖,放到common中
<dependency>
     <groupId>com.alibaba.cloud</groupId>
     <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
 </dependency>
  • 在coupons项目中创建/src/main/resources/bootstrap.properties ,这个文件是
    springboot里规定的,他优先级别application.properties高

    改名字,对应nacos里的配置文件名

    spring.application.name=gulimall-coupon
    spring.cloud.nacos.config.server-addr=192.168.11.1:8848
    
  • 配置文件中写入配置 application.properties

coupon.user.name=lilinfei
coupon.user.age=14
  • 在controller中编写测试
@RestController
@RequestMapping("coupon/coupon")
public class CouponController {
    @Autowired
    private CouponService couponService;

    @Value("${coupon.user.name}")//从application.properties中获取//不要写user.name,他是环境里的变量
    private String name;
    @Value("${coupon.user.age}")
    private Integer age;
    @RequestMapping("/test")
    public R test(){

        return R.ok().put("name",name).put("age",age);
	}
}
  • 访问 http://localhost:8500/coupon/coupon/test

image-20220208044925685

  • 如果要更改配置,可以动态修改,而不用重新打包部署 – 动态获取并配置
// contoller 动态刷新配置
@RefreshScope

// 获取配置值
@Value("${coupon.user.age}")
private Integer age;
  • nacos的配置内容优先于项目本地的配置内容。
8.3.2 配置中心

命名空间

命名空间:用作配置隔离。(一般每个微服务一个命名空间)

默认public。默认新增的配置都在public空间下。如:开发、测试、开发可以用命名空间分割。properties每个空间有一份。

# 在bootstrap.properties里配置
# 可以选择对应的命名空间 ,即写上对应环境的命名空间ID
spring.cloud.nacos.config.namespace=b176a68a-6800-4648-833b-be10be8bab00  	
  • 可以为每个微服务配置一个命名空间,微服务互相隔离。只加载自己的配置

每个微服务命名Kona关键中提供prod,dev环境

配置集:一组相关或不相关配置项的集合。

配置集ID:类似于配置文件名,即Data ID

配置分组:默认所有的配置集都属于DEFAULT_GROUP。自己可以创建分组,比如双十一,618,双十二

spring.cloud.nacos.config.group=DEFAULT_GROUP  # 更改配置分组

加载多配置集

我们要把原来application.yml里的内容都分文件抽离出去。我们在nacos里创建好 后,在coupons里指定要导入的配置即可。

  • 每个微服务有自己的命名空间,通过配置分组来区分环境,如prod,dev

  • 每个配置服务分离

# datasource.yml
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.1.103:3306/gulimall_sms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: root
# mybatis.yml
mybatis-plus:
  mapper-locations: classpath:/mapper/**/*.xml
  global-config:
    db-config:
      id-type: auto
# other.yml
spring:
  application:
    name: gulimall-coupon
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.11.1:8848
  • 加载多配置集
# bootstrap.properties
spring.application.name=gulimall-coupon
spring.cloud.nacos.config.server-addr=xx.xx.xx.xx:8848


spring.cloud.nacos.config.namespace=ed042b3b-b7f3-4734-bdcb-0c516cb357d7  # # 可以选择对应的命名空间 ,即写上对应环境的命名空间ID
spring.cloud.nacos.config.group=dev  # 配置文件所在的组

spring.cloud.nacos.config.ext-config[0].data-id=datasource.yml
spring.cloud.nacos.config.ext-config[0].group=dev
spring.cloud.nacos.config.ext-config[0].refresh=true

spring.cloud.nacos.config.ext-config[1].data-id=mybatis.yml
spring.cloud.nacos.config.ext-config[1].group=dev
spring.cloud.nacos.config.ext-config[1].refresh=true

spring.cloud.nacos.config.ext-config[2].data-id=other.yml
spring.cloud.nacos.config.ext-config[2].group=dev
spring.cloud.nacos.config.ext-config[2].refresh=true


server:
  port: 7000

注意事项

  • 微服务任何配置信息都可以放在配置中心中
  • 只需要在bootstrap.properties中说明加载配置中心中哪些文件即可
  • 获取配置方式不变 @Value @ConfigurationProperties
  • 优先使用配置中心中的配置数据

8.4 Spring Cloud Gateway 网关

8.4.1 概念

image-20220208051420789

  • 介绍:发送请求需要知道商品服务的地址,如果商品服务器有100服务器,1号掉线后,还得改,所以需要网关动态地管理,他能从注册中心中实时地感知某个服务上线还是下线。

​ 请求也要加上询问权限,看用户有没有权限访问这个请求,也需要网关。

​ 所以我们使用spring cloud的gateway组件做网关功能。

  • 功能:网关是请求浏览的入口,常用功能包括路由转发,权限校验,限流控制等。springcloud gateway取到了zuul网关。

  • 三大核心概念:

    满足断言条件才能进行路由。过滤器则过滤请求

    • Route: The basic building block of the gateway. It is defined by an ID, a
      destination URI, a collection of predicates断言, and a collection of filters.
      A route is matched if the aggregate predicate is true.
      发一个请求给网关,网关要将请求路由到指定的服务。路由有id,目的地uri,断言的集合,匹配了断言就能到达指定位置,
    • Predicate断言: This is a Java 8 Function Predicate. The input type is a Spring
      Framework ServerWebExchange. This lets you match on anything from the
      HTTP request, such as headers or parameters.就是java里的断言函数,匹配请求里的任何信息,包括请求头等
    • Filter: These are instances of Spring Framework GatewayFilter that have been
      constructed with a specific factory. Here, you can modify requests and
      responses before or after sending the downstream request.
      过滤器请求和响应都可以被修改。
      客户端发请求给服务端。中间有网关。先交给映射器,如果能处理就交给handler
      处理,然后交给一系列filer,然后给指定的服务,再返回回来给客户端。
8.4.2 使用

创建gulimall-gateway

image-20220208051956352

image-20220208052052021

配置网关

  • 依赖common:内含注册中心和配置中心
		<dependency>
            <groupId>com.lif314.gulimall</groupId>
            <artifactId>gulimall-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
  • 网关开启服务注册发现
package com.lif314.gulimall.gateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

// 开启服务注册发现
@EnableDiscoveryClient
@SpringBootApplication
public class GulimallGatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(GulimallGatewayApplication.class, args);
    }

}
  • 配置nacos注册中心地址applicaion.properties
spring.application.name=gulimall-gateway
spring.cloud.nacos.discovery.server-addr=192.168.11.1:8848
server.port=8080
  • bootstrap.properties 填写配置中心地址
spring.application.name=gulimall-gateway
spring.cloud.nacos.config.server-addr=xx.xx.xx.xx:8848
spring.cloud.nacos.config.namespace=gateway
  • 创建名称空间

image-20220208111838066

Error:Failed to configure a DataSource: ‘url’ attribute is not specified and no embedded datasource could be configured.

原因:引入MyBatisPLUS有自动数据源配置,需要排除数据源的配置

package com.lif314.gulimall.gateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

// 开启服务注册发现
@EnableDiscoveryClient
// 排除数据源配置
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class GulimallGatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(GulimallGatewayApplication.class, args);
    }

}
  • 网关使用:满足某种断言后路由到某处

测试 http://localhost:8080?url=baidu # 跳到百度页面

测试 http://localhost:8080?url=qq # 跳到qq页面

# 在项目里创建application.yml
spring:
  cloud:
    gateway:
      routes:
        - id: baidu_route
          uri: http://www.baidu.com
          predicates:
            - Query=url,baidu # 希望参数值url有baidu

        - id: test_route
          uri: http://www.qq.com
          predicates:
            - Query=url,qq
  • bootstrap.properties 填写配置中心地址
spring.application.name=gulimall-gateway
spring.cloud.nacos.config.server-addr=xx.xx.xx.xx:8848
spring.cloud.nacos.config.namespace=gateway
  • 创建名称空间

[外链图片转存中…(img-mokdt9Ag-1646392240732)]

Error:Failed to configure a DataSource: ‘url’ attribute is not specified and no embedded datasource could be configured.

原因:引入MyBatisPLUS有自动数据源配置,需要排除数据源的配置

package com.lif314.gulimall.gateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

// 开启服务注册发现
@EnableDiscoveryClient
// 排除数据源配置
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class GulimallGatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(GulimallGatewayApplication.class, args);
    }

}
  • 网关使用:满足某种断言后路由到某处

测试 http://localhost:8080?url=baidu # 跳到百度页面

测试 http://localhost:8080?url=qq # 跳到qq页面

# 在项目里创建application.yml
spring:
  cloud:
    gateway:
      routes:
        - id: baidu_route
          uri: http://www.baidu.com
          predicates:
            - Query=url,baidu # 希望参数值url有baidu

        - id: test_route
          uri: http://www.qq.com
          predicates:
            - Query=url,qq
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值