摘要

本文主要以图文的形式讲解mall项目所需环境在windows下的安装,主要包括IDEA、Mysql、Redis、Elasticsearch、Mongodb、RabbitMQ、OSS。

IDEA

1.关于IDEA的安装与使用具体参考github.com/judasn/Inte…

2.搜索插件仓库,安装插件lombok

 

展示图片
3.将项目下载到本地,然后直接打开

 

 

展示图片

 

 

展示图片

 

Mysql

  1. 下载并安装mysql5.7版本,下载地址:dev.mysql.com/downloads/i…
  2. 设置数据库帐号密码:root root
  3. 下载并安装客户端连接工具Navicat,下载地址:www.formysql.com/xiazai.html
  4. 创建数据库mall
  5. 导入document/sql下的mall.sql文件

Redis

1.下载Redis,下载地址:github.com/MicrosoftAr…

 

展示图片

 

2.下载完后解压到指定目录

 

展示图片

 

3.在当前地址栏输入cmd后,执行redis的启动命令:redis-server.exe redis.windows.conf

 

展示图片

 

Elasticsearch

1.下载Elasticsearch6.2.2的zip包,并解压到指定目录,下载地址:www.elastic.co/cn/download…

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba266d0a341?w=669&h=350&f=png&s=28924

 

2.安装中文分词插件,在elasticsearch-6.2.2\bin目录下执行以下命令:elasticsearch-plugin install github.com/medcl/elast…

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba2688ac71d?w=993&h=174&f=png&s=8876

 

3.运行bin目录下的elasticsearch.bat启动Elasticsearch

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba29baf96b4?w=662&h=384&f=png&s=44105

 

4.下载Kibana,作为访问Elasticsearch的客户端,请下载6.2.2版本的zip包,并解压到指定目录,下载地址:artifacts.elastic.co/downloads/k…

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba29299f652?w=618&h=363&f=png&s=36769

 

5.运行bin目录下的kibana.bat,启动Kibana的用户界面

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba28dc4ae74?w=675&h=160&f=png&s=15289

 

6.访问http://localhost:5601 即可打开Kibana的用户界面

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba29ea62fe9?w=1058&h=484&f=png&s=36116

 

Mongodb

1.下载Mongodb安装包,下载地址:fastdl.mongodb.org/win32/mongo…

2.选择安装路径进行安装

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba2b04722ae?w=499&h=389&f=png&s=27747

 

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba2a551ba47?w=656&h=443&f=png&s=53848

 

3.在安装路径下创建data\db和data\log两个文件夹

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba29f6640fd?w=583&h=154&f=png&s=9511

 

4.在安装路径下创建mongod.cfg配置文件

systemLog:
    destination: file
    path: D:\developer\env\MongoDB\data\log\mongod.log
storage:
    dbPath: D:\developer\env\MongoDB\data\db
复制代码

5.安装为服务(运行命令需要用管理员权限)

D:\developer\env\MongoDB\bin\mongod.exe --config "D:\developer\env\MongoDB\mongod.cfg" --install
复制代码

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba2c6863ee8?w=821&h=170&f=png&s=4512

 

6.服务相关命令

启动服务:net start MongoDB
关闭服务:net stop MongoDB
移除服务:D:\developer\env\MongoDB\bin\mongod.exe --remove
复制代码

7.下载客户端程序:download.robomongo.org/1.2.1/windo…

8.解压到指定目录,打开robo3t.exe并连接到localhost:27017

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba2bf53eccc?w=716&h=478&f=png&s=30534

 

RabbitMQ

1.安装Erlang,下载地址:erlang.org/download/ot…

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba2c060dae9?w=503&h=390&f=png&s=19892

 

2.安装RabbitMQ,下载地址:dl.bintray.com/rabbitmq/al…

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba2cc11097b?w=503&h=390&f=png&s=19438

 

3.安装完成后,进入RabbitMQ安装目录下的sbin目录

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba2cd9d317f?w=750&h=296&f=png&s=34614

 

4.在地址栏输入cmd并回车启动命令行,然后输入以下命令启动管理功能:

rabbitmq-plugins enable rabbitmq_management
复制代码

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba2e53bd66e?w=993&h=195&f=png&s=10265

 

5.访问地址查看是否安装成功:http://localhost:15672/

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba2d968467e?w=986&h=321&f=png&s=21777

 

6.输入账号密码并登录:guest guest

7.创建帐号并设置其角色为管理员:mall mall

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba2e315b868?w=903&h=765&f=png&s=48415

 

8.创建一个新的虚拟host为:/mall

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba2e7558693?w=1349&h=611&f=png&s=70997

 

9.点击mall用户进入用户配置页面

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba2efa5f52a?w=744&h=729&f=png&s=43403

 

10.给mall用户配置该虚拟host的权限

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba2f6f8cff7?w=807&h=768&f=png&s=40200

 

11.至此,RabbitMQ的安装和配置完成。

OSS

开通OSS服务

  • 登录阿里云官网;
  • 将鼠标移至产品标签页,单击对象存储 OSS,打开OSS 产品详情页面;
  • 在OSS产品详情页,单击立即开通。

创建存储空间

  • 点击网页右上角控制台按钮进入控制台

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba2fee832ff?w=788&h=64&f=png&s=7050

 

  • 选择我的云产品中的对象存储OSS

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba30225395f?w=1407&h=151&f=png&s=12740

 

  • 点击左侧存储空间的加号新建存储空间

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba30aee9b91?w=220&h=281&f=png&s=7672

 

  • 新建存储空间并设置读写权限为公共读

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba30ff77866?w=790&h=796&f=png&s=61541

 

跨域资源共享(CORS)的设置

  • 选择一个存储空间,打开其基础设置

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba31e248b1c?w=791&h=363&f=png&s=26831

 

  • 点击跨越设置的设置按钮

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba31cc2d94d?w=727&h=183&f=png&s=8812

 

  • 点击创建规则

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba32833e571?w=597&h=84&f=png&s=5305

 

  • 进行跨域规则设置

 

https://user-gold-cdn.xitu.io/2019/6/26/16b93ba328d31c8d?w=810&h=682&f=png&s=25441

 

mall-admin

mall-search

mall-portal

 

...
浏览 : 1668 阅读全文

Linux防火墙Firewall和Iptables的使用

Thu, 18 Jun 2020 05:24:37 GMT

Linux中有两种防火墙软件,ConterOS7.0以上使用的是firewall,ConterOS7.0以下使用的是iptables,本文将分别介绍两种防火墙软件的使用。

Firewall

  • 开启防火墙:
systemctl start firewalld
复制代码
  • 关闭防火墙:
systemctl stop firewalld
复制代码
  • 查看防火墙状态:
systemctl status firewalld
复制代码
  • 设置开机启动:
systemctl enable firewalld
复制代码
  • 禁用开机启动:
systemctl disable firewalld
复制代码
  • 重启防火墙:
firewall-cmd --reload
复制代码
  • 开放端口(修改后需要重启防火墙方可生效):
firewall-cmd --zone=public --add-port=8080/tcp --permanent
复制代码

 

展示图片

 

  • 查看开放的端口:
firewall-cmd --list-ports
复制代码

 

展示图片

 

  • 关闭端口:
firewall-cmd --zone=public --remove-port=8080/tcp --permanent
复制代码

 

展示图片

 

Iptables

安装

由于CenterOS7.0以上版本并没有预装Iptables,我们需要自行装。

  • 安装前先关闭firewall防火墙
    展示图片
  • 安装iptables:
yum install iptables
复制代码
  • 安装iptables-services:
yum install iptables-services
复制代码

使用

  • 开启防火墙:
systemctl start iptables.service
复制代码

 

展示图片

 

  • 关闭防火墙:
systemctl stop iptables.service
复制代码
  • 查看防火墙状态:
systemctl status iptables.service
复制代码
  • 设置开机启动:
systemctl enable iptables.service
复制代码
  • 禁用开机启动:
systemctl disable iptables.service
复制代码
  • 查看filter表的几条链规则(INPUT链可以看出开放了哪些端口):
iptables -L -n
复制代码

 

展示图片

 

  • 查看NAT表的链规则:
iptables -t nat -L -n
复制代码

 

展示图片

 

  • 清除防火墙所有规则:
iptables -F
复制代码
iptables -X
复制代码
iptables -Z
复制代码
  • 给INPUT链添加规则(开放8080端口):
iptables -I INPUT -p tcp --dport 8080 -j ACCEPT
复制代码

 

展示图片

 

  • 查找规则所在行号:
iptables -L INPUT --line-numbers -n
复制代码

 

展示图片

 

  • 根据行号删除过滤规则(关闭8080端口):
iptables -D INPUT 1
复制代码

 

展示图片

 

...
浏览 : 1460 阅读全文

开发者必备Linux命令

Thu, 18 Jun 2020 05:24:12 GMT

摘要

开发者必备Linux常用命令,掌握这些命令绝对够了,基于CenterOS7.6。

系统服务管理

systemctl

  • 输出系统中各个服务的状态:
systemctl list-units --type=service
复制代码

 

展示图片

 

  • 查看服务的运行状态:
systemctl status firewalld
复制代码

 

展示图片

 

  • 关闭服务:
systemctl stop firewalld
复制代码

 

展示图片

 

  • 启动服务:
systemctl start firewalld
复制代码

 

展示图片

 

  • 重新启动服务(不管当前服务是启动还是关闭):
systemctl restart firewalld
复制代码
  • 重新载入配置信息而不中断服务:
systemctl reload firewalld
复制代码
  • 禁止服务开机自启动:
systemctl disable firewalld
复制代码

 

展示图片

 

  • 设置服务开机自启动:
systemctl enable firewalld
复制代码

 

展示图片

 

文件管理

ls

列出当前目录(/)下的所有文件:

ls -l /
复制代码

 

展示图片

 

pwd

获取目前所在工作目录的绝对路径

 

展示图片

 

cd

改变当前工作目录:

cd /usr/local
复制代码

 

展示图片

 

date

显示或修改系统时间与日期;

date '+%Y-%m-%d %H:%M:%S'
复制代码

 

展示图片

 

passwd

用于设置用户密码:

passwd root
复制代码

 

展示图片

 

su

改变用户身份(切换到超级用户):

su -
复制代码

clear

用于清除屏幕信息

man

显示指定命令的帮助信息:

man ls
复制代码

who

  • 查询系统处于什么运行级别:
who -r
复制代码

 

展示图片

 

  • 显示目前登录到系统的用户:
who -buT
复制代码

 

展示图片

 

free

显示系统内存状态(单位MB):

free -m
复制代码

 

展示图片

 

ps

显示系统进程运行动态:

ps -ef
复制代码

查看sshd进程的运行动态:

ps -ef | grep sshd
复制代码

 

展示图片

 

top

查看即时活跃的进程,类似Windows的任务管理器

 

展示图片

 

mkdir

创建目录

 

展示图片

 

more

用于文件过长时分页查看文件内容 每页10行查看boot.log文件

more -c -10 /var/log/boot.log
复制代码

 

展示图片

 

cat

查看Linux启动日志文件文件,并标明行号:

cat -Ab /var/log/boot.log
复制代码

 

展示图片

 

touch

创建text.txt文件:

touch text.txt
复制代码

 

展示图片

 

rm

  • 删除文件:
rm text.txt
复制代码
  • 强制删除某个目录及其子目录:
rm -rf testdir/
复制代码

 

展示图片

 

cp

将test1目录复制到test2目录

cp -r /mydata/tes1 /mydata/test2
复制代码

mv

移动或覆盖文件:

mv text.txt text2.txt
复制代码

压缩与解压

tar

  • 将/etc文件夹中的文件归档到文件etc.tar(并不会进行压缩):
tar -cvf /mydata/etc.tar /etc
复制代码
  • 用gzip压缩文件夹/etc中的文件到文件etc.tar.gz:
tar -zcvf /mydata/etc.tar.gz /etc
复制代码
  • 用bzip2压缩文件夹/etc到文件/etc.tar.bz2:
tar -jcvf /mydata/etc.tar.bz2 /etc
复制代码

 

展示图片

 

  • 分页查看压缩包中内容(gzip):
tar -ztvf /mydata/etc.tar.gz |more -c -10
复制代码

 

展示图片

 

  • 解压文件到当前目录(gzip):
tar -zxvf /mydata/etc.tar.gz
复制代码

磁盘和网络管理

df

查看磁盘空间占用情况:

df -hT
复制代码

 

展示图片

 

dh

查看当前目录下的文件及文件夹所占大小:

du -h --max-depth=1 ./*
复制代码

 

展示图片

 

ifconfig

显示当前网络接口状态

 

展示图片

 

netstat

  • 查看当前路由信息:
netstat -rn
复制代码

 

展示图片

 

  • 查看所有有效TCP连接:
netstat -an
复制代码
  • 查看系统中启动的监听服务:
netstat -tulnp
复制代码

 

展示图片

 

  • 查看处于连接状态的系统资源信息:
netstat -atunp
复制代码

wget

从网络上下载文件

 

展示图片

 

软件的安装与管理

rpm

  • 安装软件包:rpm -ivh nginx-1.12.2-2.el7.x86_64.rpm
  • 模糊搜索软件包:rpm -qa | grep nginx
  • 精确查找软件包:rpm -qa nginx
  • 查询软件包的安装路径:rpm -ql nginx-1.12.2-2.el7.x86_64
  • 查看软件包的概要信息:rpm -qi nginx-1.12.2-2.el7.x86_64
  • 验证软件包内容和安装文件是否一致:rpm -V nginx-1.12.2-2.el7.x86_64
  • 更新软件包:rpm -Uvh nginx-1.12.2-2.el7.x86_64
  • 删除软件包:rpm -e nginx-1.12.2-2.el7.x86_64

yum

  • 安装软件包: yum install nginx
  • 检查可以更新的软件包:yum check-update
  • 更新指定的软件包:yum update nginx
  • 在资源库中查找软件包信息:yum info nginx*
  • 列出已经安装的所有软件包:yum info installed
  • 列出软件包名称:yum list nginx*
  • 模糊搜索软件包:yum search nginx

 

...
浏览 : 1526 阅读全文

摘要

本文主要介绍如何使用Maven插件将SpringBoot应用打包为Docker镜像,并上传到私有镜像仓库Docker Registry的过程。Docker命令不熟悉的同学可以先看下这篇开发者必备Docker命令

Docker Registry

Docker Registry 2.0搭建

docker run -d -p 5000:5000 --restart=always --name registry2 registry:2
复制代码

如果遇到镜像下载不下来的情况,需要修改 /etc/docker/daemon.json 文件并添加上 registry-mirrors 键值,然后重启docker服务:

{
  "registry-mirrors": ["https://registry.docker-cn.com"]
}
复制代码

Docker开启远程API

用vim编辑器修改docker.service文件

vi /usr/lib/systemd/system/docker.service
复制代码

需要修改的部分:

ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
复制代码

修改后的部分:

ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock
复制代码

让Docker支持http上传镜像

echo '{ "insecure-registries":["192.168.3.101:5000"] }' > /etc/docker/daemon.json
复制代码

重新启动Docker服务

systemctl stop docker
systemctl start docker
复制代码

开启防火墙的Docker构建端口

firewall-cmd --zone=public --add-port=2375/tcp --permanent
firewall-cmd --reload
复制代码

使用Maven构建Docker镜像

该代码是在mall-tiny-02的基础上修改的。

在应用的pom.xml文件中添加docker-maven-plugin的依赖

<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>1.1.0</version>
    <executions>
        <execution>
            <id>build-image</id>
            <phase>package</phase>
            <goals>
                <goal>build</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <imageName>mall-tiny/${project.artifactId}:${project.version}</imageName>
        <dockerHost>http://192.168.3.101:2375</dockerHost>
        <baseImage>java:8</baseImage>
        <entryPoint>["java", "-jar","/${project.build.finalName}.jar"]
        </entryPoint>
        <resources>
            <resource>
                <targetPath>/</targetPath>
                <directory>${project.build.directory}</directory>
                <include>${project.build.finalName}.jar</include>
            </resource>
        </resources>
    </configuration>
</plugin>
复制代码

相关配置说明:

  • executions.execution.phase:此处配置了在maven打包应用时构建docker镜像;
  • imageName:用于指定镜像名称,mall-tiny是仓库名称,${project.artifactId}为镜像名称,${project.version}为仓库名称;
  • dockerHost:打包后上传到的docker服务器地址;
  • baseImage:该应用所依赖的基础镜像,此处为java;
  • entryPoint:docker容器启动时执行的命令;
  • resources.resource.targetPath:将打包后的资源文件复制到该目录;
  • resources.resource.directory:需要复制的文件所在目录,maven打包的应用jar包保存在target目录下面;
  • resources.resource.include:需要复制的文件,打包好的应用jar包。

修改application.yml,将localhost改为db

可以把docker中的容器看作独立的虚拟机,mall-tiny-docker访问localhost自然会访问不到mysql,docker容器之间可以通过指定好的服务名称db进行访问,至于db这个名称可以在运行mall-tiny-docker容器的时候指定。

spring:
  datasource:
    url: jdbc:mysql://db:3306/mall?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    username: root
    password: root
复制代码

使用IDEA打包项目并构建镜像

注意:依赖的基础镜像需要先行下载,否则会出现构建镜像超时的情况,比如我本地并没有java8的镜像,就需要先把镜像pull下来,再用maven插件进行构建。

  • 执行maven的package命令:
    展示图片
  • 构建成功:
    展示图片
  • 镜像仓库已有该镜像:
    展示图片

运行mall-tiny-docker项目

启动mysql服务

  • 使用docker命令启动:
  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
复制代码
  • 进入运行mysql的docker容器:
docker exec -it mysql /bin/bash
复制代码
  • 使用mysql命令打开客户端:
mysql -uroot -proot --default-character-set=utf8
复制代码

 

展示图片

 

  • 修改root帐号的权限,使得任何ip都能访问:
grant all privileges on *.* to 'root'@'%'
复制代码

 

展示图片

 

  • 创建mall数据库:
create database mall character set utf8
复制代码
  • mall.sql文件拷贝到mysql容器的/目录下:
docker cp /mydata/mall.sql mysql:/
复制代码
  • 将sql文件导入到数据库:
use mall;
source /mall.sql;
复制代码

 

展示图片

 

启动mall-tiny-docker应用服务

  • 使用docker命令启动(--link表示应用可以用db这个域名访问mysql服务):
  docker run -p 8080:8080 --name mall-tiny-docker \
  --link mysql:db \
  -v /etc/localtime:/etc/localtime \
  -v /mydata/app/mall-tiny-docker/logs:/var/logs \
  -d mall-tiny/mall-tiny-docker:0.0.1-SNAPSHOT
复制代码

 

展示图片

 

  • 开启8080端口:
firewall-cmd --zone=public --add-port=8080/tcp --permanent
firewall-cmd --reload
复制代码

项目源码地址

github.com/macrozheng/…

 

...
浏览 : 2311 阅读全文

摘要

上次写过一篇使用Maven插件为SpringBoot应用构建Docker镜像 ,讲述了通过docker-maven-plugin来构建docker镜像的方式,此种方式需要依赖自建的Registry镜像仓库。本文将讲述另一种方式,使用Dockerfile来构建docker镜像,此种方式不需要依赖自建的镜像仓库,只需要应用的jar包和一个Dockerfile文件即可。

Dockerfile常用指令

ADD

用于复制文件,格式:

ADD <src> <dest>
复制代码

示例:

# 将当前目录下的mall-tiny-docker-file.jar包复制到docker容器的/目录下
ADD mall-tiny-docker-file.jar /mall-tiny-docker-file.jar
复制代码

ENTRYPOINT

指定docker容器启动时执行的命令,格式:

ENTRYPOINT ["executable", "param1","param2"...]
复制代码

示例:

# 指定docker容器启动时运行jar包
ENTRYPOINT ["java", "-jar","/mall-tiny-docker-file.jar"]
复制代码

ENV

用于设置环境变量,格式:

ENV <key> <value>
复制代码

示例:

# mysql运行时设置root密码
ENV MYSQL_ROOT_PASSWORD root
复制代码

EXPOSE

声明需要暴露的端口(只声明不会打开端口),格式:

EXPOSE <port1> <port2> ...
复制代码

示例:

# 声明服务运行在8080端口
EXPOSE 8080
复制代码

FROM

指定所需依赖的基础镜像,格式:

FROM <image>:<tag>
复制代码

示例:

# 该镜像需要依赖的java8的镜像
FROM java:8
复制代码

MAINTAINER

指定维护者的名字,格式:

MAINTAINER <name>
复制代码

示例:

MAINTAINER macrozheng
复制代码

RUN

在容器构建过程中执行的命令,我们可以用该命令自定义容器的行为,比如安装一些软件,创建一些文件等,格式:

RUN <command>
RUN ["executable", "param1","param2"...]
复制代码

示例:

# 在容器构建过程中需要在/目录下创建一个mall-tiny-docker-file.jar文件
RUN bash -c 'touch /mall-tiny-docker-file.jar'
复制代码

使用Dockerfile构建SpringBoot应用镜像

编写Dockerfile文件

# 该镜像需要依赖的基础镜像
FROM java:8
# 将当前目录下的jar包复制到docker容器的/目录下
ADD mall-tiny-docker-file-0.0.1-SNAPSHOT.jar /mall-tiny-docker-file.jar
# 运行过程中创建一个mall-tiny-docker-file.jar文件
RUN bash -c 'touch /mall-tiny-docker-file.jar'
# 声明服务运行在8080端口
EXPOSE 8080
# 指定docker容器启动时运行jar包
ENTRYPOINT ["java", "-jar","/mall-tiny-docker-file.jar"]
# 指定维护者的名字
MAINTAINER macrozheng
复制代码

使用maven打包应用

在IDEA中双击package命令进行打包:

展示图片
打包成功后展示:

 

[INFO] --- spring-boot-maven-plugin:2.1.3.RELEASE:repackage (repackage) @ mall-tiny-docker-file ---
[INFO] Replacing main artifact with repackaged archive
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 30.749 s
[INFO] Finished at: 2019-06-16T14:11:07+08:00
[INFO] Final Memory: 43M/306M
[INFO] ------------------------------------------------------------------------
复制代码

将应用jar包及Dockerfile文件上传到linux服务器:

展示图片
展示图片

 

在Linux上构建docker镜像

在Dockerfile所在目录执行以下命令:

# -t 表示指定镜像仓库名称/镜像名称:镜像标签 .表示使用当前目录下的Dockerfile
docker build -t mall-tiny/mall-tiny-docker-file:0.0.1-SNAPSHOT .
复制代码

输出如下信息:

Sending build context to Docker daemon  36.37MB
Step 1/5 : FROM java:8
 ---> d23bdf5b1b1b
Step 2/5 : ADD mall-tiny-docker-file-0.0.1-SNAPSHOT.jar /mall-tiny-docker-file.jar
 ---> c920c9e9d045
Step 3/5 : RUN bash -c 'touch /mall-tiny-docker-file.jar'
 ---> Running in 55506f517f19
Removing intermediate container 55506f517f19
 ---> 0727eded66dc
Step 4/5 : EXPOSE 8080
 ---> Running in d67a5f50aa7d
Removing intermediate container d67a5f50aa7d
 ---> 1b8b4506eb2d
Step 5/5 : ENTRYPOINT ["java", "-jar","/mall-tiny-docker-file.jar"]
 ---> Running in 0c5bf61a0032
Removing intermediate container 0c5bf61a0032
 ---> c3614dad21b7
Successfully built c3614dad21b7
Successfully tagged mall-tiny/mall-tiny-docker-file:0.0.1-SNAPSHOT
复制代码

查看docker镜像:

展示图片

 

运行mysql服务并设置

1.使用docker命令启动:

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
复制代码

2.进入运行mysql的docker容器:

docker exec -it mysql /bin/bash
复制代码

3.使用mysql命令打开客户端:

mysql -uroot -proot --default-character-set=utf8
复制代码

4.修改root帐号的权限,使得任何ip都能访问:

grant all privileges on *.* to 'root'@'%'
复制代码

5.创建mall数据库:

create database mall character set utf8
复制代码

6.将mall.sql文件拷贝到mysql容器的/目录下:

docker cp /mydata/mall.sql mysql:/
复制代码

7.将sql文件导入到数据库:

use mall;
source /mall.sql;
复制代码

运行mall-tiny-docker-file应用

docker run -p 8080:8080 --name mall-tiny-docker-file \
--link mysql:db \
-v /etc/localtime:/etc/localtime \
-v /mydata/app/mall-tiny-docker-file/logs:/var/logs \
-d mall-tiny/mall-tiny-docker-file:0.0.1-SNAPSHOT
复制代码

访问接口文档地址http://192.168.3.101:8080/swagger-ui.html:

展示图片

 

...
浏览 : 1493 阅读全文

使用Docker Compose部署SpringBoot应用

Thu, 18 Jun 2020 05:21:11 GMT

摘要

Docker Compose是一个用于定义和运行多个docker容器应用的工具。使用Compose你可以用YAML文件来配置你的应用服务,然后使用一个命令,你就可以部署你配置的所有服务了。

安装

下载Docker Compose:

curl -L https://get.daocloud.io/docker/compose/releases/download/1.24.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
复制代码

修改该文件的权限为可执行:

chmod +x /usr/local/bin/docker-compose
复制代码

查看是否已经安装成功:

docker-compose --version
复制代码

 

展示图片

 

使用Docker Compose的步骤

  • 使用Dockerfile定义应用程序环境,一般需要修改初始镜像行为时才需要使用;
  • 使用docker-compose.yml定义需要部署的应用程序服务,以便执行脚本一次性部署;
  • 使用docker-compose up命令将所有应用服务一次性部署起来。

docker-compose.yml常用命令

image

指定运行的镜像名称

# 运行的是mysql5.7的镜像
image: mysql:5.7
复制代码

container_name

配置容器名称

# 容器名称为mysql
container_name: mysql
复制代码

ports

指定宿主机和容器的端口映射(HOST:CONTAINER)

# 将宿主机的3306端口映射到容器的3306端口
ports:
  - 3306:3306
复制代码

volumes

将宿主机的文件或目录挂载到容器中(HOST:CONTAINER)

# 将外部文件挂载到myql容器中
volumes:
  - /mydata/mysql/log:/var/log/mysql
  - /mydata/mysql/data:/var/lib/mysql
  - /mydata/mysql/conf:/etc/mysql
复制代码

environment

配置环境变量

# 设置mysqlroot帐号密码的环境变量
environment:
  - MYSQL_ROOT_PASSWORD=root
复制代码

links

连接其他容器的服务(SERVICE:ALIAS)

# 可以以database为域名访问服务名称为db的容器
links:
  - db:database
复制代码

Docker Compose常用命令

构建、创建、启动相关容器:

# -d表示在后台运行
docker-compose up -d
复制代码

停止所有相关容器:

docker-compose stop
复制代码

列出所有容器信息:

docker-compose ps
复制代码

使用Docker Compose 部署应用

编写docker-compose.yml文件

Docker Compose将所管理的容器分为三层,工程、服务及容器。docker-compose.yml中定义所有服务组成了一个工程,services节点下即为服务,服务之下为容器。容器与容器直之间可以以服务名称为域名进行访问,比如在mall-tiny-docker-compose服务中可以通过jdbc:mysql://db:3306这个地址来访问db这个mysql服务。

version: '3'
services:
  # 指定服务名称
  db:
    # 指定服务使用的镜像
    image: mysql:5.7
    # 指定容器名称
    container_name: mysql
    # 指定服务运行的端口
    ports:
      - 3306:3306
    # 指定容器中需要挂载的文件
    volumes:
      - /mydata/mysql/log:/var/log/mysql
      - /mydata/mysql/data:/var/lib/mysql
      - /mydata/mysql/conf:/etc/mysql
    # 指定容器的环境变量
    environment:
      - MYSQL_ROOT_PASSWORD=root
  # 指定服务名称
  mall-tiny-docker-compose:
    # 指定服务使用的镜像
    image: mall-tiny/mall-tiny-docker-compose:0.0.1-SNAPSHOT
    # 指定容器名称
    container_name: mall-tiny-docker-compose
    # 指定服务运行的端口
    ports:
      - 8080:8080
    # 指定容器中需要挂载的文件
    volumes:
      - /etc/localtime:/etc/localtime
      - /mydata/app/mall-tiny-docker-compose/logs:/var/logs
复制代码

注意:如果遇到mall-tiny-docker-compose服务无法连接到mysql,需要在mysql中建立mall数据库,同时导入mall.sql脚本。具体参考使用Dockerfile为SpringBoot应用构建Docker镜像中的运行mysql服务并设置部分。

使用maven插件构建mall-tiny-docker-compose镜像

 

展示图片

 

注意:构建有问题的可以参考使用Maven插件为SpringBoot应用构建Docker镜像

运行Docker Compose命令启动所有服务

先将docker-compose.yml上传至Linux服务器,再在当前目录下运行如下命令:

docker-compose up -d
复制代码

 

展示图片

 

访问接口文档地址http://192.168.3.101:8080/swagger-ui.html:

 

展示图片

 

 

...
浏览 : 1567 阅读全文

10分钟搭建自己的Git仓库

Thu, 18 Jun 2020 05:17:52 GMT

简介

GitLab是一款使用MIT许可证的基于网络的Git仓库管理工具,我们可以使用它来搭建自己的Git仓库,本文将介绍如何使用Gitlab在Linux下快速搭建Git仓库。

Gitlab服务端搭建

在Linux(CenterOS7.6)下我们会以Docker的方式来安装Gitlab,对Docker不了解的朋友可以参考:开发者必备Docker命令

下载Gitlab的Docker镜像

docker pull gitlab/gitlab-ce
复制代码

运行如下命令来启动Gitlab

需要注意的是我们的Gitlab的http服务运行在宿主机的1080端口上,这里我们将Gitlab的配置,日志以及数据目录映射到了宿主机的指定文件夹下,防止我们在重新创建容器后丢失数据。

docker run --detach \
  --publish 10443:443 --publish 1080:80 --publish 1022:22 \
  --name gitlab \
  --restart always \
  --volume /mydata/gitlab/config:/etc/gitlab \
  --volume /mydata/gitlab/logs:/var/log/gitlab \
  --volume /mydata/gitlab/data:/var/opt/gitlab \
  gitlab/gitlab-ce:latest
复制代码

开启防火墙的指定端口

由于Gitlab运行在1080端口上,所以我们需要开放该端口,注意千万不要直接关闭防火墙,否则Gitlab会无法启动。

# 开启1080端口
firewall-cmd --zone=public --add-port=1080/tcp --permanent 
# 重启防火墙才能生效
systemctl restart firewalld
# 查看已经开放的端口
firewall-cmd --list-ports
复制代码

访问Gitlab

  • 访问地址:http://192.168.3.101:1080/
  • 由于Gitlab启动比较慢,需要耐心等待10分钟左右,如果Gitlab没有启动完成访问,会出现如下错误。

 

 

  • 可以通过docker命令动态查看容器启动日志来知道gitlab是否已经启动完成。
docker logs gitlab -f
复制代码

 

 

Gitlab的使用

Gitlab启动完成后第一次访问,会让你重置root帐号的密码

 

 

重置完成后输入帐号密码登录

 

 

选择创建项目、创建组织、创建帐号

 

 

创建组织

首先我们需要创建一个组织,然后在这个组织下分别创建用户和项目,这样同组织的用户就可以使用该组织下的项目了。

 

创建用户并修改密码

找到添加用户的按钮

 

 

输入用户名密码添加用户

 

 

在编辑界面中修改用户密码

 

 

 

 

创建项目并添加README文件

 

 

 

 

将用户分配到组织

 

 

Git客户端安装及使用

下载Git客户端并安装

 

 

clone项目

  • 找到项目clone的地址:

 

 

  • 打开Git命令行工具:

 

 

  • 执行以下命令clone项目到本地:
git clone http://192.168.3.101:1080/macrozheng/hello.git

复制代码

提交代码

进入项目目录,修改一下README.md并提交:

# 进入项目工程目录
cd hello/
# 将当前修改的文件添加到暂存区
git add .
# 提交代码
git commit -m "first commit"
复制代码

推送到远程仓库

git push
复制代码

 

 

拉取远程仓库代码

  • 在Gitlab上修改readme中的文件内容:

 

 

  • 拉取代码:
git pull
复制代码

本地创建并提交分支

# 切换并从当前分支创建一个dev分支
git checkout -b dev
# 将新创建的dev分支推送到远程仓库
git push origin dev
复制代码

 

 

其他常用命令

# 切换到dev分支
git checkout dev
# 查看本地仓库文件状况
git status
# 查看本地所有分支
git branch
# 查看提交记录
git log

作者:MacroZheng
链接:https://juejin.im/post/5d63d600e51d453c135c5af3
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

...
浏览 : 1727 阅读全文

摘要

本文将从虚拟机安装、Linux系统安装、SSH客户端工具使用三方面来详细介绍Linux系统的安装及使用。

虚拟机安装

VirtualBox 是一款开源虚拟机软件,由Sun公司出品,现在则由Oracle进行开发。VirtualBox号称是最强的免费虚拟机软件,它性能优异且简单易用。可虚拟的系统包括Windows、Linux、MacOS、Android等操作系统!本文将使用VirtualBox作为虚拟机来安装Linux系统。

VirtualBox的安装

 

 

  • 中途需要自定义一下安装路径:

 

 

  • 最后点击完成,完成安装。

 

 

创建虚拟机

  • 创建一个Linux虚拟机:

 

 

  • 分配虚拟机内存大小,可以根据自己电脑配置来决定:

 

 

  • 创建虚拟硬盘:

 

 

  • 设置虚拟硬盘文件类型,这里选择DVI格式:

 

 

  • 选择动态分配空间大小,如果你的硬盘空间比较大的话,可以选择固定大小:

 

 

  • 设置虚拟硬盘的位置和大小:

 

 

Linux安装

CentOS(Community Enterprise Operating System)是Linux发行版之一,中文意思为社区企业操作系统。它是来自于商业版 Red Hat Enterprise Linux依照开放源代码规定释出的源代码所编译而成,因此具有高度稳定性且完全开源。本文将以CentOS 7.6为例来介绍Linux系统的安装。

下载

安装

  • 为虚拟机添加虚拟光盘,虚拟光盘指定为我们下载的ISO镜像文件:

 

 

  • 点击启动运行虚拟机:

 

 

  • 运行成功后,选择Install CentOS 7进行安装:

 

 

  • 选择系统安装过程中的语言,建议选择English选项:

 

 

  • 需要进行设置的部分示意图:

 

 

  • 时区设置,地区选择Asia,城市选择Shanghai

 

 

  • 语言支持选择安装英文、简体中文两种语言安装包:

 

 

  • 软件安装设置选择Server with GUI,同时选择如图三种附加环境:

 

 

  • 磁盘分区设置,由于我的虚拟机设置的内存较小,需要创建一个较大的swap分区,内存设置较大的直接选择自动分区即可,这里我们使用手动分区:

 

 

  • 按如图所示进行手动分区操作;

 

 

  • 关于分区的几个目录的说明:

    • /:根分区;
    • swap:交换分区,可以当虚拟内存使用;
    • /boot:存储系统的引导信息和内核信息;
    • /usr:存储系统应用软件安装信息;
    • /var:存储系统日志信息。
  • 网络设置,设置主机名称和进行网络激活操作:

 

 

  • 单击Begin Installation进行安装:

 

 

  • 安装过程中可以设置root用户的密码;

 

 

  • 完成安装后重新启动即可进入系统,第一次启动需要同意协议并完成配置:

 

 

  • 此时宿主机还无法直接访问虚拟机,需要将虚拟机的网络模式改为桥接模式才可以。

 

 

Xshell使用

Xshell是一款SSH连接客户端工具,可以用于远程操作Linux系统。Xshell对于家庭和学校可以免费使用,提供一个有效邮箱,下载链接就会发送到你的的邮箱。

 

 

  • 输入ifconfig命令获取IP地址;

 

 

  • 获取完成后通过Xshell进行连接,并输入账号和密码:

 

 

  • 连接完成后即可远程使用Linux系统了。

 

 

其他相关

修改默认启动模式

如果不想默认启动图形化界面的话,可以修改默认的启动模式,因为图形化界面还是比较占用内存的,使用命令如下。

# 将默认级别修改为多用户文本模式
systemctl set-default multi-user.target
# 将默认级别修改为图形用户界面模式
systemctl set-default graphical.target
# 重启
reboot

作者:MacroZheng
链接:https://juejin.im/post/5ddfd1665188256ec024cb7c
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

...
浏览 : 1555 阅读全文

摘要

本文将从反向代理、文件压缩、地址重写三方面来讲解Nginx在Docker环境下的使用技巧!

在Docker环境下的安装

下载nginx的docker镜像

docker pull nginx:1.10
复制代码

从容器中拷贝nginx配置

  • 先运行一次容器(为了拷贝配置文件):
docker run -p 80:80 --name nginx \
-v /mydata/nginx/html:/usr/share/nginx/html \
-v /mydata/nginx/logs:/var/log/nginx  \
-d nginx:1.10
复制代码
  • 将容器内的配置文件拷贝到指定目录:
docker container cp nginx:/etc/nginx /mydata/nginx/
复制代码
  • 修改文件名称:
mv nginx conf
复制代码
  • 终止并删除容器:
docker stop nginx
docker rm nginx
复制代码

使用docker命令启动

docker run -p 80:80 --name nginx \
-v /mydata/nginx/html:/usr/share/nginx/html \
-v /mydata/nginx/logs:/var/log/nginx  \
-v /mydata/nginx/conf:/etc/nginx \
-d nginx:1.10
复制代码

反向代理

反向代理就是当请求访问你的代理服务器时,代理服务器会对你的请求进行转发,可以转发到静态的资源路径上去,也可以转发到动态的服务接口上去。下面我们以对域名进行代理为例,来讲讲如何进行静态代理和动态代理。

静态代理

静态代理就是将请求代理到不同的静态资源路径上去,这里我们将对docs.macrozheng.com的请求代理到我的文档项目中,对mall.macrozheng.com的请求代理到mall的前端项目中。

  • 首先我们修改下本机的host文件:
192.168.6.132 docs.macrozheng.com
192.168.6.132 mall.macrozheng.com
复制代码
  • 然后将我们的文档项目和mall前端项目上传到nginx的html目录中去,并进行解压操作:

 

 

  • /mydata/nginx/conf/conf.d文件夹中添加配置文件docs.conf对文档项目进行反向代理:
server {
    listen       80;
    server_name  docs.macrozheng.com; #修改域名

    location / {
        root   /usr/share/nginx/html/docs; #代理到docs文件夹中
        index  index.html index.htm;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

}
复制代码
  • /mydata/nginx/conf/conf.d文件夹中添加配置文件mall.conf对mall的前端项目进行反向代理:
server {
    listen       80;
    server_name  mall.macrozheng.com; #修改域名

    location / {
        root   /usr/share/nginx/html/mall; #代理到mall文件夹中
        index  index.html index.htm;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

}
复制代码
  • 重启nginx服务:
docker restart nginx
复制代码
  • 通过docs.macrozheng.com即可访问到我们的文档项目了:

 

 

  • 通过mall.macrozheng.com即可访问到mall的前端项目了:

 

 

动态代理

动态代理就是把代理服务器的请求转发到另一个服务上去,这里我们将对api.macrozheng.com的请求代理到mall-admin的后台服务上去。

  • 首先我们修改下本机的host文件,添加如下规则:
192.168.6.132 api.macrozheng.com
复制代码
  • /mydata/nginx/conf/conf.d文件夹中添加配置文件api.conf对将请求代理到远程的mall-admin服务上去:
server {
    listen       80;
    server_name  api.macrozheng.com; #修改域名

    location / {
    	proxy_pass   http://120.27.63.9:8080; #修改为代理服务地址
        index  index.html index.htm;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

}
复制代码
  • 重启动nginx服务后,通过api.macrozheng.com/swagger-ui.html即可访问到mall-admin的API文档页面了:

 

 

文件压缩

如果我们租用了一个带宽很低的服务器,网站访问速度会很慢,这时我们可以通过让nginx开启GZIP压缩来提高网站的访问速度。这里我们以mall的前端项目为例来演示下它的提速效果。

  • 首先我们对nginx进行限速操作,限制每个连接的访问速度为128K来建立一个比较慢的访问场景;

  • 修改mall.conf配置文件,进行限速操作:

server {
    listen       80;
    server_name  mall.macrozheng.com;
    
    limit_rate 128k; #限制网速为128K

    location / {
        root   /usr/share/nginx/html/mall;
        index  index.html index.htm;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

}
复制代码
  • 对mall的前端项目mall.macrozheng.com进行访问,我们可以发现网站中有个js文件比较大,需要加载12s:

 

 

  • nginx返回请求头信息如下:

 

 

  • 修改/mydata/nginx/conf目录下的nginx.conf配置文件,开启GZIP压缩;
http {

    gzip on; #开启gzip
    gzip_disable "msie6"; #IE6不使用gzip
    gzip_vary on; #设置为on会在Header里增加 "Vary: Accept-Encoding"
    gzip_proxied any; #代理结果数据的压缩
    gzip_comp_level 6; #gzip压缩比(1~9),越小压缩效果越差,但是越大处理越慢,所以一般取中间值
    gzip_buffers 16 8k; #获取多少内存用于缓存压缩结果
    gzip_http_version 1.1; #识别http协议的版本
    gzip_min_length 1k; #设置允许压缩的页面最小字节数,超过1k的文件会被压缩
    gzip_types application/javascript text/css; #对特定的MIME类型生效,js和css文件会被压缩

    include /etc/nginx/conf.d/*.conf;
}

复制代码
  • 再次对mall的前端项目mall.macrozheng.com进行访问,我们可以发现js文件已经被压缩,加载时间缩短到3.88s,提速3倍左右:

 

 

  • nginx返回请求头中添加了Content-Encoding: gzip的信息:

 

 

地址重写

有的时候我们的网站更换了域名,但还有用户在使用老的域名访问,这时可以通过nginx的地址重写来让用户跳转到新的域名进行访问。

  • 比如说原来我们用的docs.macrozheng.com这个域名不用了,现在改成www.macrozheng.com了来访问文档项目了;

  • 修改docs.conf配置文件,将地址带参数重写到新地址:

server {
    listen       80;
    server_name  docs.macrozheng.com; 
    
    rewrite "^/(.*)$" http://www.macrozheng.com/$1; #地址重写到新地址

    location / {
        root   /usr/share/nginx/html/docs; 
        index  index.html index.htm;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

}

 

...
浏览 : 1600 阅读全文

Jenkins的基本使用

关于Jenkins的基本使用可以参考:使用Jenkins一键打包部署SpringBoot应用,就是这么6!

执行脚本准备

首先我们先把需要远程执行的脚本准备好。

  • 脚本文件都存放在了mall项目的/document/sh目录下:

  • 上传脚本前在IDEA中修改所有脚本文件的换行符格式为LF,否则脚本会无法执行;

 

 

  • 将所有脚本文件上传到指定目录,这里我们上传到/mydata/sh目录下;

 

 

  • 将所有脚本文件都修改为可执行文件:
chmod +x ./mall-*
复制代码

 

 

Jenkins中创建任务

接下来我们将通过在Jenkins中创建任务来实现自动化部署。由于我们的mall是个多模块的项目,部署上面和曾经的单模块项目还是有所区别的。

mall-admin

由于各个模块的执行任务的创建都大同小异,下面将详细讲解mall-admin模块任务的创建,其他模块将简略讲解。

  • 首先我们选择构建一个自由风格的软件项目mall-admin,然后配置其Git仓库地址,这里我直接使用了Gitee上面的地址:

 

 

  • 之后我们创建一个构建,构建mall项目中的依赖模块,否则当构建可运行的服务模块时会因为无法找到这些模块而构建失败;
# 只install mall-common,mall-mbg,mall-security三个模块
clean install -pl mall-common,mall-mbg,mall-security -am
复制代码
  • 依赖项目构建示意图:

 

 

  • 再创建一个构建,单独构建并打包mall-admin模块:

 

 

  • 添加一个远程SSH执行任务,去执行mall-admin的运行脚本:

 

 

  • 点击保存,完成mall-admin的执行任务创建。

mall-portal

mall-portal和其他模块与mall-admin创建任务方式基本一致,只需修改构建模块时的pom.xml文件位置和执行脚本位置即可。

  • 我们可以直接从mall-admin模块的任务复制一个过来创建:

 

 

  • 修改第二个构建中的pom.xml文件位置,改为:${WORKSPACE}/mall-portal/pom.xml

 

 

  • 修改第三个构建中的SSH执行脚本文件位置,改为:/mydata/sh/mall-portal.sh

 

 

  • 点击保存,完成mall-portal的执行任务创建。

mall-search

参考mall-admin和mall-portal的创建即可。

任务创建完成

 


作者:MacroZheng
链接:https://juejin.im/post/5e15d7b16fb9a0484f5c3931
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

...
浏览 : 1516 阅读全文

Spring Data Redis 最佳实践!

Thu, 18 Jun 2020 04:49:08 GMT

摘要

Spring Data Redis 是Spring 框架提供的用于操作Redis的方式,最近整理了下它的用法,解决了使用过程中遇到的一些难点与坑点,希望对大家有所帮助。本文涵盖了Redis的安装、Spring Cache结合Redis的使用、Redis连接池的使用和RedisTemplate的使用等内容。

Redis安装

这里提供Linux和Windows两种安装方式,由于Windows下的版本最高只有3.2版本,所以推荐使用Linux下的版本,目前最新稳定版本为5.0,也是本文中使用的版本。

Linux

这里我们使用Docker环境下的安装方式。

  • 下载Redis5.0的Docker镜像;
docker pull redis:5.0
复制代码
  • 使用Docker命令启动Redis容器;
docker run -p 6379:6379 --name redis \
-v /mydata/redis/data:/data \
-d redis:5.0 redis-server --appendonly yes
复制代码

Windows

想使用Windows版本的朋友可以使用以下安装方式。

 

 

  • 下载完后解压到指定目录;

 

 

  • 在当前地址栏输入cmd后,执行redis的启动命令:redis-server.exe redis.windows.conf

 

 

Spring Cache 操作Redis

Spring Cache 简介

当Spring Boot 结合Redis来作为缓存使用时,最简单的方式就是使用Spring Cache了,使用它我们无需知道Spring中对Redis的各种操作,仅仅通过它提供的@Cacheable 、@CachePut 、@CacheEvict 、@EnableCaching等注解就可以实现缓存功能。

常用注解

@EnableCaching

开启缓存功能,一般放在启动类上。

@Cacheable

使用该注解的方法当缓存存在时,会从缓存中获取数据而不执行方法,当缓存不存在时,会执行方法并把返回结果存入缓存中。一般使用在查询方法上,可以设置如下属性:

  • value:缓存名称(必填),指定缓存的命名空间;
  • key:用于设置在命名空间中的缓存key值,可以使用SpEL表达式定义;
  • unless:条件符合则不缓存;
  • condition:条件符合则缓存。

@CachePut

使用该注解的方法每次执行时都会把返回结果存入缓存中。一般使用在新增方法上,可以设置如下属性:

  • value:缓存名称(必填),指定缓存的命名空间;
  • key:用于设置在命名空间中的缓存key值,可以使用SpEL表达式定义;
  • unless:条件符合则不缓存;
  • condition:条件符合则缓存。

@CacheEvict

使用该注解的方法执行时会清空指定的缓存。一般使用在更新或删除方法上,可以设置如下属性:

  • value:缓存名称(必填),指定缓存的命名空间;
  • key:用于设置在命名空间中的缓存key值,可以使用SpEL表达式定义;
  • condition:条件符合则缓存。

使用步骤

  • 在pom.xml中添加项目依赖:
<!--redis依赖配置-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
复制代码
  • 修改配置文件application.yml,添加Redis的连接配置;
spring:
  redis:
    host: 192.168.6.139 # Redis服务器地址
    database: 0 # Redis数据库索引(默认为0)
    port: 6379 # Redis服务器连接端口
    password: # Redis服务器连接密码(默认为空)
    timeout: 1000ms # 连接超时时间
复制代码
  • 在启动类上添加@EnableCaching注解启动缓存功能;
@EnableCaching
@SpringBootApplication
public class MallTinyApplication {

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

}
复制代码
  • 接下来在PmsBrandServiceImpl类中使用相关注解来实现缓存功能,可以发现我们获取品牌详情的方法中使用了@Cacheable注解,在修改和删除品牌的方法上使用了@CacheEvict注解;
/**
 * PmsBrandService实现类
 * Created by macro on 2019/4/19.
 */
@Service
public class PmsBrandServiceImpl implements PmsBrandService {
    @Autowired
    private PmsBrandMapper brandMapper;

    @CacheEvict(value = RedisConfig.REDIS_KEY_DATABASE, key = "'pms:brand:'+#id")
    @Override
    public int update(Long id, PmsBrand brand) {
        brand.setId(id);
        return brandMapper.updateByPrimaryKeySelective(brand);
    }

    @CacheEvict(value = RedisConfig.REDIS_KEY_DATABASE, key = "'pms:brand:'+#id")
    @Override
    public int delete(Long id) {
        return brandMapper.deleteByPrimaryKey(id);
    }

    @Cacheable(value = RedisConfig.REDIS_KEY_DATABASE, key = "'pms:brand:'+#id", unless = "#result==null")
    @Override
    public PmsBrand getItem(Long id) {
        return brandMapper.selectByPrimaryKey(id);
    }

}
复制代码
  • 我们可以调用获取品牌详情的接口测试下效果,此时发现Redis中存储的数据有点像乱码,并且没有设置过期时间;

 

 

存储JSON格式数据

此时我们就会想到有没有什么办法让Redis中存储的数据变成标准的JSON格式,然后可以设置一定的过期时间,不设置过期时间容易产生很多不必要的缓存数据。

  • 我们可以通过给RedisTemplate设置JSON格式的序列化器,并通过配置RedisCacheConfiguration设置超时时间来实现以上需求,此时别忘了去除启动类上的@EnableCaching注解,具体配置类RedisConfig代码如下;
/**
 * Redis配置类
 * Created by macro on 2020/3/2.
 */
@EnableCaching
@Configuration
public class RedisConfig extends CachingConfigurerSupport {

    /**
     * redis数据库自定义key
     */
    public  static final String REDIS_KEY_DATABASE="mall";

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisSerializer<Object> serializer = redisSerializer();
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(serializer);
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(serializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    @Bean
    public RedisSerializer<Object> redisSerializer() {
        //创建JSON序列化器
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(objectMapper);
        return serializer;
    }

    @Bean
    public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
        //设置Redis缓存有效期为1天
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer())).entryTtl(Duration.ofDays(1));
        return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
    }

}
复制代码
  • 此时我们再次调用获取商品详情的接口进行测试,会发现Redis中已经缓存了标准的JSON格式数据,并且超时时间被设置为了1天。

 

 

使用Redis连接池

SpringBoot 1.5.x版本Redis客户端默认是Jedis实现的,SpringBoot 2.x版本中默认客户端是用Lettuce实现的,我们先来了解下Jedis和Lettuce客户端。

Jedis vs Lettuce

Jedis在实现上是直连Redis服务,多线程环境下非线程安全,除非使用连接池,为每个 RedisConnection 实例增加物理连接。

Lettuce是一种可伸缩,线程安全,完全非阻塞的Redis客户端,多个线程可以共享一个RedisConnection,它利用Netty NIO框架来高效地管理多个连接,从而提供了异步和同步数据访问方式,用于构建非阻塞的反应性应用程序。

使用步骤

  • 修改application.yml添加Lettuce连接池配置,用于配置线程数量和阻塞等待时间;
spring:
  redis:
    lettuce:
      pool:
        max-active: 8 # 连接池最大连接数
        max-idle: 8 # 连接池最大空闲连接数
        min-idle: 0 # 连接池最小空闲连接数
        max-wait: -1ms # 连接池最大阻塞等待时间,负值表示没有限制
复制代码
  • 由于SpringBoot 2.x中默认并没有使用Redis连接池,所以需要在pom.xml中添加commons-pool2的依赖;
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>
复制代码
  • 如果你没添加以上依赖的话,启动应用的时候就会产生如下错误;
Caused by: java.lang.NoClassDefFoundError: org/apache/commons/pool2/impl/GenericObjectPoolConfig
	at org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration$LettucePoolingClientConfigurationBuilder.<init>(LettucePoolingClientConfiguration.java:84) ~[spring-data-redis-2.1.5.RELEASE.jar:2.1.5.RELEASE]
	at org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration.builder(LettucePoolingClientConfiguration.java:48) ~[spring-data-redis-2.1.5.RELEASE.jar:2.1.5.RELEASE]
	at org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration$PoolBuilderFactory.createBuilder(LettuceConnectionConfiguration.java:149) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
	at org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration.createBuilder(LettuceConnectionConfiguration.java:107) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
	at org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration.getLettuceClientConfiguration(LettuceConnectionConfiguration.java:93) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
	at org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration.redisConnectionFactory(LettuceConnectionConfiguration.java:74) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
	at org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration$$EnhancerBySpringCGLIB$$5caa7e47.CGLIB$redisConnectionFactory$0(<generated>) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
	at org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration$$EnhancerBySpringCGLIB$$5caa7e47$$FastClassBySpringCGLIB$$b8ae2813.invoke(<generated>) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
	at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.1.5.RELEASE.jar:5.1.5.RELEASE]
	at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
	at org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration$$EnhancerBySpringCGLIB$$5caa7e47.redisConnectionFactory(<generated>) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_91]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_91]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_91]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_91]
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
	... 111 common frames omitted
复制代码

自由操作Redis

Spring Cache 给我们提供了操作Redis缓存的便捷方法,但是也有很多局限性。比如说我们想单独设置一个缓存值的有效期怎么办?我们并不想缓存方法的返回值,我们想缓存方法中产生的中间值怎么办?此时我们就需要用到RedisTemplate这个类了,接下来我们来讲下如何通过RedisTemplate来自由操作Redis中的缓存。

RedisService

定义Redis操作业务类,在Redis中有几种数据结构,比如普通结构(对象),Hash结构、Set结构、List结构,该接口中定义了大多数常用操作方法。

/**
 * redis操作Service
 * Created by macro on 2020/3/3.
 */
public interface RedisService {

    /**
     * 保存属性
     */
    void set(String key, Object value, long time);

    /**
     * 保存属性
     */
    void set(String key, Object value);

    /**
     * 获取属性
     */
    Object get(String key);

    /**
     * 删除属性
     */
    Boolean del(String key);

    /**
     * 批量删除属性
     */
    Long del(List<String> keys);

    /**
     * 设置过期时间
     */
    Boolean expire(String key, long time);

    /**
     * 获取过期时间
     */
    Long getExpire(String key);

    /**
     * 判断是否有该属性
     */
    Boolean hasKey(String key);

    /**
     * 按delta递增
     */
    Long incr(String key, long delta);

    /**
     * 按delta递减
     */
    Long decr(String key, long delta);

    /**
     * 获取Hash结构中的属性
     */
    Object hGet(String key, String hashKey);

    /**
     * 向Hash结构中放入一个属性
     */
    Boolean hSet(String key, String hashKey, Object value, long time);

    /**
     * 向Hash结构中放入一个属性
     */
    void hSet(String key, String hashKey, Object value);

    /**
     * 直接获取整个Hash结构
     */
    Map<Object, Object> hGetAll(String key);

    /**
     * 直接设置整个Hash结构
     */
    Boolean hSetAll(String key, Map<String, Object> map, long time);

    /**
     * 直接设置整个Hash结构
     */
    void hSetAll(String key, Map<String, Object> map);

    /**
     * 删除Hash结构中的属性
     */
    void hDel(String key, Object... hashKey);

    /**
     * 判断Hash结构中是否有该属性
     */
    Boolean hHasKey(String key, String hashKey);

    /**
     * Hash结构中属性递增
     */
    Long hIncr(String key, String hashKey, Long delta);

    /**
     * Hash结构中属性递减
     */
    Long hDecr(String key, String hashKey, Long delta);

    /**
     * 获取Set结构
     */
    Set<Object> sMembers(String key);

    /**
     * 向Set结构中添加属性
     */
    Long sAdd(String key, Object... values);

    /**
     * 向Set结构中添加属性
     */
    Long sAdd(String key, long time, Object... values);

    /**
     * 是否为Set中的属性
     */
    Boolean sIsMember(String key, Object value);

    /**
     * 获取Set结构的长度
     */
    Long sSize(String key);

    /**
     * 删除Set结构中的属性
     */
    Long sRemove(String key, Object... values);

    /**
     * 获取List结构中的属性
     */
    List<Object> lRange(String key, long start, long end);

    /**
     * 获取List结构的长度
     */
    Long lSize(String key);

    /**
     * 根据索引获取List中的属性
     */
    Object lIndex(String key, long index);

    /**
     * 向List结构中添加属性
     */
    Long lPush(String key, Object value);

    /**
     * 向List结构中添加属性
     */
    Long lPush(String key, Object value, long time);

    /**
     * 向List结构中批量添加属性
     */
    Long lPushAll(String key, Object... values);

    /**
     * 向List结构中批量添加属性
     */
    Long lPushAll(String key, Long time, Object... values);

    /**
     * 从List结构中移除属性
     */
    Long lRemove(String key, long count, Object value);
}
复制代码

RedisServiceImpl

RedisService的实现类,使用RedisTemplate来自由操作Redis中的缓存数据。

/**
 * redis操作实现类
 * Created by macro on 2020/3/3.
 */
@Service
public class RedisServiceImpl implements RedisService {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public void set(String key, Object value, long time) {
        redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
    }

    @Override
    public void set(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }

    @Override
    public Object get(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    @Override
    public Boolean del(String key) {
        return redisTemplate.delete(key);
    }

    @Override
    public Long del(List<String> keys) {
        return redisTemplate.delete(keys);
    }

    @Override
    public Boolean expire(String key, long time) {
        return redisTemplate.expire(key, time, TimeUnit.SECONDS);
    }

    @Override
    public Long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    @Override
    public Boolean hasKey(String key) {
        return redisTemplate.hasKey(key);
    }

    @Override
    public Long incr(String key, long delta) {
        return redisTemplate.opsForValue().increment(key, delta);
    }

    @Override
    public Long decr(String key, long delta) {
        return redisTemplate.opsForValue().increment(key, -delta);
    }

    @Override
    public Object hGet(String key, String hashKey) {
        return redisTemplate.opsForHash().get(key, hashKey);
    }

    @Override
    public Boolean hSet(String key, String hashKey, Object value, long time) {
        redisTemplate.opsForHash().put(key, hashKey, value);
        return expire(key, time);
    }

    @Override
    public void hSet(String key, String hashKey, Object value) {
        redisTemplate.opsForHash().put(key, hashKey, value);
    }

    @Override
    public Map<Object, Object> hGetAll(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    @Override
    public Boolean hSetAll(String key, Map<String, Object> map, long time) {
        redisTemplate.opsForHash().putAll(key, map);
        return expire(key, time);
    }

    @Override
    public void hSetAll(String key, Map<String, Object> map) {
        redisTemplate.opsForHash().putAll(key, map);
    }

    @Override
    public void hDel(String key, Object... hashKey) {
        redisTemplate.opsForHash().delete(key, hashKey);
    }

    @Override
    public Boolean hHasKey(String key, String hashKey) {
        return redisTemplate.opsForHash().hasKey(key, hashKey);
    }

    @Override
    public Long hIncr(String key, String hashKey, Long delta) {
        return redisTemplate.opsForHash().increment(key, hashKey, delta);
    }

    @Override
    public Long hDecr(String key, String hashKey, Long delta) {
        return redisTemplate.opsForHash().increment(key, hashKey, -delta);
    }

    @Override
    public Set<Object> sMembers(String key) {
        return redisTemplate.opsForSet().members(key);
    }

    @Override
    public Long sAdd(String key, Object... values) {
        return redisTemplate.opsForSet().add(key, values);
    }

    @Override
    public Long sAdd(String key, long time, Object... values) {
        Long count = redisTemplate.opsForSet().add(key, values);
        expire(key, time);
        return count;
    }

    @Override
    public Boolean sIsMember(String key, Object value) {
        return redisTemplate.opsForSet().isMember(key, value);
    }

    @Override
    public Long sSize(String key) {
        return redisTemplate.opsForSet().size(key);
    }

    @Override
    public Long sRemove(String key, Object... values) {
        return redisTemplate.opsForSet().remove(key, values);
    }

    @Override
    public List<Object> lRange(String key, long start, long end) {
        return redisTemplate.opsForList().range(key, start, end);
    }

    @Override
    public Long lSize(String key) {
        return redisTemplate.opsForList().size(key);
    }

    @Override
    public Object lIndex(String key, long index) {
        return redisTemplate.opsForList().index(key, index);
    }

    @Override
    public Long lPush(String key, Object value) {
        return redisTemplate.opsForList().rightPush(key, value);
    }

    @Override
    public Long lPush(String key, Object value, long time) {
        Long index = redisTemplate.opsForList().rightPush(key, value);
        expire(key, time);
        return index;
    }

    @Override
    public Long lPushAll(String key, Object... values) {
        return redisTemplate.opsForList().rightPushAll(key, values);
    }

    @Override
    public Long lPushAll(String key, Long time, Object... values) {
        Long count = redisTemplate.opsForList().rightPushAll(key, values);
        expire(key, time);
        return count;
    }

    @Override
    public Long lRemove(String key, long count, Object value) {
        return redisTemplate.opsForList().remove(key, count, value);
    }
}

复制代码

RedisController

测试RedisService中缓存操作的Controller,大家可以调用测试下。

/**
 * Redis测试Controller
 * Created by macro on 2020/3/3.
 */
@Api(tags = "RedisController", description = "Redis测试")
@Controller
@RequestMapping("/redis")
public class RedisController {
    @Autowired
    private RedisService redisService;
    @Autowired
    private PmsBrandService brandService;

    @ApiOperation("测试简单缓存")
    @RequestMapping(value = "/simpleTest", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<PmsBrand> simpleTest() {
        List<PmsBrand> brandList = brandService.list(1, 5);
        PmsBrand brand = brandList.get(0);
        String key = "redis:simple:" + brand.getId();
        redisService.set(key, brand);
        PmsBrand cacheBrand = (PmsBrand) redisService.get(key);
        return CommonResult.success(cacheBrand);
    }

    @ApiOperation("测试Hash结构的缓存")
    @RequestMapping(value = "/hashTest", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<PmsBrand> hashTest() {
        List<PmsBrand> brandList = brandService.list(1, 5);
        PmsBrand brand = brandList.get(0);
        String key = "redis:hash:" + brand.getId();
        Map<String, Object> value = BeanUtil.beanToMap(brand);
        redisService.hSetAll(key, value);
        Map<Object, Object> cacheValue = redisService.hGetAll(key);
        PmsBrand cacheBrand = BeanUtil.mapToBean(cacheValue, PmsBrand.class, true);
        return CommonResult.success(cacheBrand);
    }

    @ApiOperation("测试Set结构的缓存")
    @RequestMapping(value = "/setTest", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<Set<Object>> setTest() {
        List<PmsBrand> brandList = brandService.list(1, 5);
        String key = "redis:set:all";
        redisService.sAdd(key, (Object[]) ArrayUtil.toArray(brandList, PmsBrand.class));
        redisService.sRemove(key, brandList.get(0));
        Set<Object> cachedBrandList = redisService.sMembers(key);
        return CommonResult.success(cachedBrandList);
    }

    @ApiOperation("测试List结构的缓存")
    @RequestMapping(value = "/listTest", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<List<Object>> listTest() {
        List<PmsBrand> brandList = brandService.list(1, 5);
        String key = "redis:list:all";
        redisService.lPushAll(key, (Object[]) ArrayUtil.toArray(brandList, PmsBrand.class));
        redisService.lRemove(key, 1, brandList.get(0));
        List<Object> cachedBrandList = redisService.lRange(key, 0, 3);
        return CommonResult.success(cachedBrandList);
    }
}

 

...
浏览 : 2236 阅读全文

摘要

为了提高Redis的存储容量和响应速度,有时候我们需要搭建Redis集群。本文主要讲述Redis集群环境的搭建步骤以及如何在SpringBoot中整合使用Redis集群。

Redis集群搭建

这里我们使用最方便的搭建方式,使用Docker Compose来搭建,对Docker Compose不了解的朋友可以参考下《使用Docker Compose部署SpringBoot应用》。我们将搭建一个6节点的Redis集群,包括3个主节点和3个从节点。

  • 在搭建Redis集群之前,我们需要修改下Redis的配置文件redis.conf,该文件的下载地址:github.com/antirez/red…

  • 需要修改的属性如下,主要是修改了一些集群配置和运行端口,端口号需要按需修改为6391~6396:

# 开启集群功能
cluster-enabled yes
# 设置运行端口
port 6391
# 设置节点超时时间,单位毫秒
cluster-node-timeout 15000
# 集群内部配置文件
cluster-config-file "nodes-6391.conf"
复制代码
  • 然后我们需要编写docker-compose.yml文件用于编排6个Redis容器,具体属性的作用可以参考下面的注释;
version: "3"
services:
  redis-master1:
    image: redis:5.0 # 基础镜像
    container_name: redis-master1 # 容器名称
    working_dir: /config # 切换工作目录
    environment: # 环境变量
      - PORT=6391 # 会使用config/nodes-${PORT}.conf这个配置文件
    ports: # 映射端口,对外提供服务
      - 6391:6391 # redis的服务端口
      - 16391:16391 # redis集群监控端口
    stdin_open: true # 标准输入打开
    tty: true # 后台运行不退出
    network_mode: host # 使用host模式
    privileged: true # 拥有容器内命令执行的权限
    volumes:
      - /mydata/redis-cluster/config:/config #配置文件目录映射到宿主机
    entrypoint: # 设置服务默认的启动程序
      - /bin/bash
      - redis.sh
  redis-master2:
    image: redis:5.0
    working_dir: /config
    container_name: redis-master2
    environment:
      - PORT=6392
    ports:
      - 6392:6392
      - 16392:16392
    stdin_open: true
    network_mode: host
    tty: true
    privileged: true
    volumes:
      - /mydata/redis-cluster/config:/config
    entrypoint:
      - /bin/bash
      - redis.sh
  redis-master3:
    image: redis:5.0
    container_name: redis-master3
    working_dir: /config
    environment:
      - PORT=6393
    ports:
      - 6393:6393
      - 16393:16393
    stdin_open: true
    network_mode: host
    tty: true
    privileged: true
    volumes:
      - /mydata/redis-cluster/config:/config
    entrypoint:
      - /bin/bash
      - redis.sh
  redis-slave1:
    image: redis:5.0
    container_name: redis-slave1
    working_dir: /config
    environment:
      - PORT=6394
    ports:
      - 6394:6394
      - 16394:16394
    stdin_open: true
    network_mode: host
    tty: true
    privileged: true
    volumes:
      - /mydata/redis-cluster/config:/config
    entrypoint:
      - /bin/bash
      - redis.sh
  redis-slave2:
    image: redis:5.0
    working_dir: /config
    container_name: redis-slave2
    environment:
      - PORT=6395
    ports:
      - 6395:6395
      - 16395:16395
    stdin_open: true
    network_mode: host
    tty: true
    privileged: true
    volumes:
      - /mydata/redis-cluster/config:/config
    entrypoint:
      - /bin/bash
      - redis.sh
  redis-slave3:
    image: redis:5.0
    container_name: redis-slave3
    working_dir: /config
    environment:
      - PORT=6396
    ports:
      - 6396:6396
      - 16396:16396
    stdin_open: true
    network_mode: host
    tty: true
    privileged: true
    volumes:
      - /mydata/redis-cluster/config:/config
    entrypoint:
      - /bin/bash
      - redis.sh
复制代码
  • 从docker-compose.yml文件中我们可以看到,我们的Redis容器分别运行在6391~6396这6个端口之上, 将容器中的/config配置目录映射到了宿主机的/mydata/redis-cluster/config目录,同时还以redis.sh脚本作为该容器的启动脚本;

  • redis.sh脚本的作用是根据environment环境变量中的PORT属性,以指定配置文件来启动Redis容器;

redis-server  /config/nodes-${PORT}.conf
复制代码
  • 接下来我们需要把Redis的配置文件和redis.sh上传到Linux服务器的/mydata/redis-cluster/config目录下;

 

 

  • 接下来上传我们的docker-compose.yml文件到Linux服务器,并使用docker-compose命令来启动所有容器;
docker-compose up -d
复制代码
  • 启动过程中会输出如下信息;

 

 

  • 此时进入其中一个Redis容器之中,初始化Redis集群;
# 进入Redis容器
docker exec -it redis-master1 /bin/bash
# 初始化Redis集群命令
redis-cli --cluster create \
192.168.6.139:6391 192.168.6.139:6392 192.168.6.139:6393 \
192.168.6.139:6394 192.168.6.139:6395 192.168.6.139:6396 \
--cluster-replicas 1
复制代码
  • 集群创建过程中会让你确认配置,输入yes确认即可;

 

 

  • Redis集群创建成功后会输出如下信息;

 

 

  • 创建成功后我们可以使用redis-cli命令连接到其中一个Redis服务;
# 单机模式启动
redis-cli -h 127.0.0.1 -p 6391
# 集群模式启动
redis-cli -c -h 127.0.0.1 -p 6391
复制代码
  • 之后通过cluster nodes命令可以查看节点信息,发现符合原来3主3从的预期。

 

 

SpringBoot中使用Redis集群

我们在《Spring Data Redis 最佳实践!》中讲到了在SpringBoot中如何使用Redis,用的是单节点的Redis服务,这次我们讲下如何使用Redis集群服务。

  • 我们在原来代码的基础上进行改造,修改application.yml配置文件,添加Redis集群配置;
spring:
  redis:
#    host: 192.168.6.139 # Redis服务器地址
#    database: 0 # Redis数据库索引(默认为0)
#    port: 6379 # Redis服务器连接端口
    password: # Redis服务器连接密码(默认为空)
    timeout: 3000ms # 连接超时时间
    lettuce:
      pool:
        max-active: 8 # 连接池最大连接数
        max-idle: 8 # 连接池最大空闲连接数
        min-idle: 0 # 连接池最小空闲连接数
        max-wait: -1ms # 连接池最大阻塞等待时间,负值表示没有限制
    cluster:
      nodes:
        - 192.168.6.139:6391
        - 192.168.6.139:6392
        - 192.168.6.139:6393
        - 192.168.6.139:6394
        - 192.168.6.139:6395
        - 192.168.6.139:6396
复制代码
  • 此时我们再次调用获取品牌详情的接口,就会把品牌信息缓存到Redis集群中去了;

  • 由于Redis容器redis-master1redis-slave2互为主从,所以里面都缓存了相同的品牌详情信息。

 


作者:MacroZheng
链接:https://juejin.im/post/5e81fd1ff265da47e84e5e2c
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

...
浏览 : 1751 阅读全文

开发者必备Docker命令

Sat, 20 Jun 2020 07:17:12 GMT

摘要

本文主要讲解Docker环境的安装以及Docker常用命令的使用,掌握这些对Docker环境下应用的部署具有很大帮助。

Docker 简介

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows机器上。使用Docker可以更方便低打包、测试以及部署应用程序。

Docker 环境安装

  • 安装yum-utils:
yum install -y yum-utils device-mapper-persistent-data lvm2
复制代码
  • 为yum源添加docker仓库位置:
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
复制代码
  • 安装docker:
yum install docker-ce
复制代码
  • 启动docker:
systemctl start docker
复制代码

Docker 镜像常用命令

搜索镜像

docker search java
复制代码

 

展示图片

 

下载镜像

docker pull java:8
复制代码

如何查找镜像支持的版本

由于docker search命令只能查找出是否有该镜像,不能找到该镜像支持的版本,所以我们需要通过docker hub来搜索支持的版本。

  • 进入docker hub的官网,地址:hub.docker.com

  • 然后搜索需要的镜像:

    展示图片

     

  • 查看镜像支持的版本:

    展示图片

     

  • 进行镜像的下载操作:

docker pull nginx:1.17.0
复制代码

列出镜像

docker images
复制代码

 

展示图片

 

删除镜像

  • 指定名称删除镜像
docker rmi java:8
复制代码
  • 指定名称删除镜像(强制)
docker rmi -f java:8
复制代码
  • 强制删除所有镜像
docker rmi -f $(docker images)
复制代码

Docker 容器常用命令

新建并启动容器

docker run -p 80:80 --name nginx -d nginx:1.17.0
复制代码
  • -d选项:表示后台运行
  • --name选项:指定运行后容器的名字为nginx,之后可以通过名字来操作容器
  • -p选项:指定端口映射,格式为:hostPort:containerPort

列出容器

  • 列出运行中的容器:
docker ps
复制代码

 

展示图片

 

  • 列出所有容器
docker ps -a
复制代码

 

展示图片

 

停止容器

# $ContainerName$ContainerId可以用docker ps命令查询出来
docker stop $ContainerName(或者$ContainerId)
复制代码

比如:

docker stop nginx
#或者
docker stop c5f5d5125587
复制代码

强制停止容器

docker kill $ContainerName(或者$ContainerId)
复制代码

启动已停止的容器

docker start $ContainerName(或者$ContainerId)
复制代码

进入容器

  • 先查询出容器的pid:
docker inspect --format "{{.State.Pid}}" $ContainerName(或者$ContainerId)
复制代码
  • 根据容器的pid进入容器:
nsenter --target "$pid" --mount --uts --ipc --net --pid
复制代码

 

展示图片

 

删除容器

  • 删除指定容器:
docker rm $ContainerName(或者$ContainerId)
复制代码
  • 强制删除所有容器;
docker rm -f $(docker ps -a -q)
复制代码

查看容器的日志

docker logs $ContainerName(或者$ContainerId)
复制代码

 

展示图片

 

查看容器的IP地址

docker inspect --format '{{ .NetworkSettings.IPAddress }}' $ContainerName(或者$ContainerId)
复制代码

 

展示图片

 

同步宿主机时间到容器

docker cp /etc/localtime $ContainerName(或者$ContainerId):/etc/
复制代码

在宿主机查看docker使用cpu、内存、网络、io情况

  • 查看指定容器情况:
docker stats $ContainerName(或者$ContainerId)
复制代码

 

展示图片

 

  • 查看所有容器情况:
docker stats -a
复制代码

 

展示图片

 

进入Docker容器内部的bash

docker exec -it $ContainerName /bin/bash
复制代码

 

展示图片

 

修改Docker镜像的存放位置

  • 查看Docker镜像的存放位置:
docker info | grep "Docker Root Dir"
复制代码

 

展示图片

 

  • 关闭Docker服务:
systemctl stop docker
复制代码
  • 移动目录到目标路径:
mv /var/lib/docker /mydata/docker
复制代码
  • 建立软连接:
ln -s /mydata/docker /var/lib/docker
复制代码

 

展示图片

 

 

展示图片

 

...
浏览 : 1647 阅读全文