2022年8月

转载自品略图书馆 http://www.pinlue.com/article/2020/04/0611/3510119404305.html

  https为什么比http更安全?学过网络技术的小编来告诉你。

  防止运营商劫持

  如果你要访问.com,不是直接到.com的,需要中间有很多的服务器路由器的转发。

  假设你是可信的,.com也可信,但是中间的节点就未必。

  比如

 

  这11个节点,任何一个都可以串改你的信息和发给你的信息。

  实际上运营商劫持就是这些节点中一些小子为了盈利而修改发给你的html,嵌入他的广告。

  如果是https,这些节点个个都不知道你和.com到底在发些啥,也没有办法改,因为秘钥只有你和.com才有。

  所以,https防止的是中间节点使坏。这在我们的场景下,是非常好有价值的。

  https仅仅只是在传输过程中加密了。

  举个例子:

  A给B写信,写完邮寄给B,但是在邮寄的过程中,邮递员可能会偷偷的把信取出来看完后再放回去,收发室大爷可能也会偷偷取出来看一眼,B收到信的时候,可能在传输过程中已经被很多人看过了。如果信件中有一些银行卡账号密码什么的,可能在传输过程中已经被别人悄悄记下来了。这就是HTTP。

  A和B发现了这个问题,于是他们约定了下次写信要加密,A写信的时候加密,B收到信在解密,加密解密的方法只有A和B知道。同样在寄信的过程中,邮递员、收发室大爷偷偷看了信,但是完全看不懂,信件的内容不会泄露,就安全的多。这就是https。

  所以通常在浏览一般网页的时候,可能不会用https,而在用户登录需要输入密码时,会用https,因为登录肯定要传输用户名密码,不加密可能就会被别人看到。

  用https就告别了运营商劫持。

  什么是运营商劫持?

  运营商会在一些流量大的网站,加上一些小广告来增加收入。有时候你打开百度,会在右下角弹出一个广告,这个广告不是百度加上的,是运营商加的。

  也就像上面例子中,邮递员不但打开看了你的信件,而且在你的信件上加入小广告,让你以为是A加的。如果https加密,邮递员是无法将小广告加密放到你的信中。

  https比http安全指的是数据传输过程,而不是服务器后台的安全防护。https只能防止别人直接监听数据包拿到传输内容而已,对于服务器漏洞或者sql注入之类的,https并没有任何比http高明的地方

  简单点说就是:

  http明文,就是明信片,别人拿到了就可以看到内容。

  https是上锁的保险箱。别人拿到了也开不了锁(就目前的计算机性能来说没办法暴力破解https数据包)


引言

架构生态相对还不是很完善,刚开始搭建也多是自己官网找的jar包启动搭建的环境,经过熟悉阶段后寻docker资源搭建开发环境,管理起来会相对方便一点,其次以下提供的镜像有官方和私人的上传,未能保证其安全性,建议仅开发使用,不建议用于生产.微服务生产环境需要配置相应数据服务保证相应配置重启可用,安装完成后建议执行docker stats 检测CPU和内存占有情况,防止被挂挖矿程序

Docker 环境搭建

#nacos 注册/发现
docker run -d -p 8848:8848  --name=nacos  --e MODE=standalone nacos/nacos-server:latest
#sentinel 熔断器
docker run -d --name sentinel -p 7080:8280   foxiswho/sentinel
#Zipkin 调用链路
docker run -d -p 9411:9411 --name=zipkin  openzipkin/zipkin
#rocketmq
docker run -d -p 9876:9876 -v /usr/docker/rocketmq/data/namesrv/logs:/root/logs -v /usr/docker/rocketmq/data/namesrv/store:/root/store --name rmqnamesrv -e "MAX_POSSIBLE_HEAP=100000000" rocketmqinc/rocketmq:4.4.0 sh mqnamesrv
docker run -d -p 10911:10911 -p 10909:10909 -v  /usr/docker/rocketmq/data/broker/logs:/root/logs -v  /usr/docker/rocketmq/rocketmq/data/broker/store:/root/store -v  /usr/docker/rocketmq/conf/broker.conf:/opt/rocketmq-4.4.0/conf/broker.conf --name rmqbroker --link rmqnamesrv:namesrv -e "NAMESRV_ADDR=namesrv:9876" -e "MAX_POSSIBLE_HEAP=200000000" rocketmqinc/rocketmq:4.4.0 sh mqbroker -c /opt/rocketmq-4.4.0/conf/broker.conf
docker run -e "JAVA_OPTS=-Drocketmq.namesrv.addr=119.137.55.254:9876 -Dcom.rocketmq.sendMessageWithVIPChannel=false" -p 9877:8080 -t pangliang/rocketmq-console-ng
  • /usr/docker/rocketmq/conf/broker.conf 配置文件内容

brokerClusterName = DefaultCluster
brokerName = broker-a
brokerId = 0
deleteWhen = 04
fileReservedTime = 48
brokerRole = ASYNC_MASTER
flushDiskType = ASYNC_FLUSH
#ip地址通过 docker inspect rmqbroker 查看获得  
#由于是本地开发环境,rmqbroker IP是172.17.0.3 但是仍可以使用 ..0.1 因为访问时会映射到端口绑定的容器
brokerIP1 = 172.17.0.1

代码配置

相信看到这篇文章的DevER已经是熟悉这套架构ER,这里就不多赘述,由于整合项目使用的Kotlin SpringBoot版本,即使贴上来也需要大家相应转换可用,不如就参照网上相关教程配置即可

架构使用

  • 首先文档和相应资源多有中文,这点呢比较符合国情,但是英文相对来说也没多大问题,就是看的多花一点时间(针对本人英语还不没有掌握到汉语来说)

  • 架构也逐渐成熟,使用的组件也日益丰富.相信会是未来的主流



作者:Fuuqiu
链接:https://www.jianshu.com/p/f349643a36fc
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


目录


环境介绍#

技术选型SpringCloud&SpringCloud Alibaba&Docker

微服务模块划分

  1. 员工模块:ems-employees

  2. 部门模块:ems-departments

  3. 网关模块:ems-gateway

  4. 公共模块:ems-commons

其他环境

Mysql8.0+、nacos1.3+、JDK1.8

前置准备知识

SpringCloudSpringCloud alibabaDockerDocker-ComposeDockerfile

数据库结构:

一个部门表和一个员工表,员工表里面有个部门ID和部门表主键相关联

数据库sql脚本

use emsSET NAMES utf8mb4;SET FOREIGN_KEY_CHECKS = 0;-- ------------------------------ Table structure for department-- ----------------------------DROP TABLE IF EXISTS `department`;CREATE TABLE `department` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(80) DEFAULT NULL COMMENT '部门名称',
  `created_at` datetime DEFAULT NULL COMMENT '创建时间',  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- ------------------------------ Table structure for employee-- ----------------------------DROP TABLE IF EXISTS `employee`;CREATE TABLE `employee` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(40) DEFAULT NULL,
  `birthday` datetime DEFAULT NULL COMMENT '生日',
  `salary` double(10,2) DEFAULT NULL COMMENT '工资',
  `department_id` int(11) DEFAULT NULL COMMENT '部门信息',  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;SET FOREIGN_KEY_CHECKS = 1;

部署流程#

  1. 先在服务器安装Docker,然后在Docker中安装mysql、nacos镜像,并启动容器

  2. 在员工、部门等微服务模块中指定nacos注册中心地址,使服务注册进去

  3. 把springcloud微服务模块打包成jar包上传至服务器,然后通过Dockerfile构建成镜像

  4. 最后通过docker-compose构建编排项目,将这些微服务镜像打包成一整个项目并启动

环境搭建#

1.Centos7.X安装Docker

网上操作教程很多,略

2.Docker安装mysql、nacos镜像

2.1 安装mysql

1、没有指定版本一般安装的都是最新的8.0+

docker pull mysql

2、docker启动mysql,简单演示就没有创建数据卷了

docker run --name=mysql01 -it -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql

3、启动成功

image-20220102180005212

4、进入mysql容器

docker exec -it  mysql01 /bin/bash

5、登陆mysql

mysql -u root -p

6、授权所有用户可以登录

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'WITH GRANT OPTION;

7、刷新权限  

FLUSH PRIVILEGES;

8、使用客户端连接

image-20220102183304777

2.2 安装nacos
docker pull nacos/nacos-server:1.3.0

1、运行nacos

docker run  --name nacos-quick -e  MODE=standalone -p 8848:8848 -d nacos/nacos-server:1.3.0

2、查看nacos运行日志

docker logs -f b1aacab47d2a

image-20220102184603996

表示启动成功

3、访问成功

image-20220102184738169

默认用户名登录密码都是nacos

3.搭建SpringCloud微服务模块

3.1 搭建父工程模块

image-20220103104841235

image-20220103104929409

image-20220103105150507

父工程的必须遵循以下两点要求:

1.父工程的 packaging 标签的文本内容必须设置为 pom,如果不指定会默认打包成jar包

2.删除src目录

image-20220103105323383

搭建父工程的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.ylc</groupId>
    <artifactId>springcloud-dockerDemo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <mysql.version>8.0.23</mysql.version>
        <spring.cloud.version>Hoxton.SR1</spring.cloud.version>
        <spring.cloud.alibaba.version>2.2.0.RELEASE</spring.cloud.alibaba.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!--spring cloud Hoxton.SR1-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--spring cloud alibaba 2.1.0.RELEASE-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring.cloud.alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build></project>
3.2 搭建员工子模块

image-20220103105744331

image-20220103105854905

点击下一步最后完成

image-20220103110016595

删除一些没用的文件HELP.md、MVNW等等,修改子项目的 pom.xml 文件的继承关系

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <!-- 确认继承关系 -->
    <parent>
        <!--父工程 gropuId-->
        <groupId>com.ylc</groupId>
        <!--父工程 artifactId-->
        <artifactId>springcloud-dockerDemo</artifactId>
        <!--父工程 版本-->
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>ems-employess</artifactId>

    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!--web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--nacos-service-discovery-client-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--druid mysql mybatis-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.6</version>
        </dependency>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.23</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.0</version>
        </dependency>
        <!--远程调用openfegin-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.10.1</version>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.3.4.RELEASE</version>
                <configuration>
                    <fork>true</fork>
                    <addResources>true</addResources>
                </configuration>
            </plugin>
        </plugins>
    </build></project>

在父工程 pom.xml 中 添加子模块标识

image-20220103110152948

开启服务注册中心nacos,并开启远程调用

@EnableFeignClients@EnableDiscoveryClient@SpringBootApplicationpublic class EmsEmploysApplication {    public static void main(String[] args) {
        SpringApplication.run(EmsEmploysApplication.class, args);
    }
}

然后在配置文件application.properties配置nacos的参数、以及数据源配置

server.port=8085spring.application.name=DEPARTMENTSspring.cloud.nacos.server-addr=xxx:8848# datasourcespring.datasource.type=com.alibaba.druid.pool.DruidDataSourcespring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.url=jdbc:mysql://xxxx:3306/ems?useSSL=false&characterEncoding=UTF-8spring.datasource.username=rootspring.datasource.password=123456# mybatismybatis.type-aliases-package=com.ylc.entitymybatis.mapper-locations=classpath:com/ylc/mapper/*.xml# loglogging.level.com.ylc=debug

bootstrap.properties中配置nacos

spring.cloud.nacos.config.server-addr=121.43.33.150:8848spring.cloud.nacos.discovery.server-addr=121.43.33.150:8848

在idea中远程连接mysql

image-20220103160733218

然后利用idea中安装的插件Easycode,根据表去生成service、controller、dao、mapper相关代码

点击这个

image-20220103162655774

module代表生成的模块

package:包名

path:生成的路径

image-20220103163437305

最后生成成功

image-20220103163630949

其中有分页部分爆红的方法,删掉就行了,只简单演示

然后记得添加相关注解@Mapper、@Service、@Repository等等

访问成功

image-20220103181039770

3.3 搭建部门子模块

按照上一个模块流程搭建,pom文件也是相同的,端口改为8086

访问成功

image-20220103183405568

3.4 抽取公共模块

上面两个微服务会有重复代码,抽取公共部分包含项目一些公共的类以及jar包

Department

package com.ylc;import java.io.Serializable;import java.util.Date;/**
 * @author yanglingcong
 * 部门类
 */public class Department implements Serializable {    private static final long serialVersionUID = 279210942586979318L;    private Integer id;    /**
     * 部门名称
     */
    private String name;    /**
     * 创建时间
     */
    private Date createdAt;    private Employee employee;    public Employee getEmployee() {        return employee;
    }    public void setEmployee(Employee employee) {        this.employee = employee;
    }    public Integer getId() {        return id;
    }    public void setId(Integer id) {        this.id = id;
    }    public String getName() {        return name;
    }    public void setName(String name) {        this.name = name;
    }    public Date getCreatedAt() {        return createdAt;
    }    public void setCreatedAt(Date createdAt) {        this.createdAt = createdAt;
    }
}

Employee

package com.ylc;import com.fasterxml.jackson.annotation.JsonProperty;import java.io.Serializable;import java.util.Date;/**
 * (Employee)实体类
 * @author yanglingcong
 */public class Employee implements Serializable {    private static final long serialVersionUID = -87055454147065054L;    private String id;    private String name;    /**
     * 生日
     */
    private Date birthday;    /**
     * 工资
     */
    private String salary;    /**
     * 部门信息
     */
    @JsonProperty("department_id")
    private Integer departmentId;    private Department department;    public Department getDepartment() {        return department;
    }    public void setDepartment(Department department) {        this.department = department;
    }    public String getId() {        return id;
    }    public void setId(String id) {        this.id = id;
    }    public String getName() {        return name;
    }    public void setName(String name) {        this.name = name;
    }    public Date getBirthday() {        return birthday;
    }    public void setBirthday(Date birthday) {        this.birthday = birthday;
    }    public String getSalary() {        return salary;
    }    public void setSalary(String salary) {        this.salary = salary;
    }    public Integer getDepartmentId() {        return departmentId;
    }    public void setDepartmentId(Integer departmentId) {        this.departmentId = departmentId;
    }
}

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <!-- 确认继承关系 -->
    <parent>
        <!--父工程 gropuId-->
        <groupId>com.ylc</groupId>
        <!--父工程 artifactId-->
        <artifactId>springcloud-dockerDemo</artifactId>
        <!--父工程 版本-->
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>ems-employess</artifactId>

    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!--web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--nacos-service-discovery-client-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--druid mysql mybatis-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.6</version>
        </dependency>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.23</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.0</version>
        </dependency>
        <!--远程调用openfegin-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.10.1</version>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.3.4.RELEASE</version>
                <configuration>
                    <fork>true</fork>
                    <addResources>true</addResources>
                </configuration>
            </plugin>
        </plugins>
    </build></project>

公共模块搭建很简单就两个类,然后在其他模块引用公共模块

 <dependencies>
        <!--公共模块-->
        <dependency>
            <groupId>com.ylc</groupId>
            <artifactId>ems-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

到此就完成了

3.5.测试

通过查询员工信息,然后远程调用部门信息

远程接口

@FeignClient("DEPARTMENTS")public interface DepartmentClient {    //部门详细
    @GetMapping("/department/{id}")
     Department detail(@PathVariable("id") Integer id);
}

1、接口定义

/**
 *  查询员工以及部门的详细信息
 * @return List<Employee>
 */

 List<Employee> queryAll();

2、实现类

@Overridepublic List<Employee> queryAll() {
    List<Employee> employees=employeeDao.queryAll();
    employees.forEach(emp->{
        Integer departmentid=emp.getDepartmentId();        Department detail = departmentClient.detail(departmentid);
        emp.setDepartment(detail);
    });    return employees;
}

3、调用方法

    //员工列表
    @GetMapping
    public List<Employee> employees() {        return employeeService.queryAll();
    }

4、测试localhost:8085/employee

image-20220103195635159

3.6 搭建网关子模块

image-20220103201046959

1、开启服务注册发现

@SpringBootApplication@EnableDiscoveryClientpublic class GatewayApplication {    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}

2、网关配置

image-20220103220634321

spring:
  cloud:
    gateway:
      routes: # 用来配置网关路由规则
        - id: employee_route
          uri: lb://EMPLOYESS
          predicates:
            - Path=/ems/employee
          filters:
            - StripPrefix=1

        - id: department_route
          uri: lb://DEPARTMENTS
          predicates:
            - Path=/ems/department
          filters:
            - StripPrefix=1

3、bootstrap.yml

server.port=8888spring.application.name=GATEWAYspring.cloud.nacos.server-addr=121.43.33.150:8848spring.cloud.nacos.config.server-addr=121.43.33.150:8848spring.cloud.nacos.discovery.server-addr=121.43.33.150:8848spring.cloud.nacos.config.enabled=false

4、通过网关访问成功

image-20220103220426218

至此整个项目流程就打通了

部署#

1.本地测试

1、打包之前每个项目都需要有springboot的打包插件,没有的话要在项目中引入

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

安装之后出现这个就可以了

image-20220103221640922

2、先对父项目进行清理(clean)再打包(Package),common公共模块是没主启动类的,这时候把父项目的pom文件的该插件注释调就行了。

   <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

全部打包完成

image-20220103221818398

3、先在本地测试jar是否成功

运行员工模块

image-20220103222146017

运行部门模块

image-20220103222411533

运行网关模块

image-20220103222437716

都成功之后本地访问http://localhost:8888/ems/employee

到这里都没有问题说明本地测试通过了

2.编写Dockerfile

docker中需要有JDK1.8的镜像,安装JDK

docker pull openjdk:8

image-20220103223207189

在idea中编写员工模块Dockerfile

image-20220103225314017

FROM openjdk:8ENV APP_HOME=/appsWORKDIR $APP_HOMECOPY ./ems-employess-1.0-SNAPSHOT.jar ./employess.jarEXPOSE 8086ENTRYPOINT ["java","-jar"]CMD ["employess.jar"]

部门模块Dockerfile

FROM openjdk:8ENV APP_HOME=/appsWORKDIR $APP_HOMECOPY ./ems-departments-0.0.1-SNAPSHOT.jar ./departments.jarEXPOSE 8085ENTRYPOINT ["java","-jar"]CMD ["departments.jar"]

网关模块Dockerfile

FROM openjdk:8ENV APP_HOME=/appsWORKDIR $APP_HOMECOPY ./ems-gateway-1.0-SNAPSHOT.jar ./gateway.jarEXPOSE 8888ENTRYPOINT ["java","-jar"]CMD ["gateway.jar"]

然后在idea 中登录docker所在服务器

image-20220103225516099

3.Dockerfile文件上传

然后把项目的文件上传到服务自己建的ems文件夹中

image-20220103230243686

4.编写docker-compose.yml

直接利用dockerfile文件的路径打包成镜像,最后编排运行

version: "3.8"networks:
  ems:volumes:
  data:services:

  employee:
    build:
      context: ./employee
      dockerfile: Dockerfile
    ports:
      - "8085:8085"
    networks:
      - ems

  department:
    build:
      context: ./department
      dockerfile: Dockerfile
    ports:
      - "8086:8086"
    networks:
      - ems

  gateway:
    build:
      context: ./gateway
      dockerfile: Dockerfile
    ports:
      - "8888:8888"
    networks:
      - ems

  nacos:
    image: nacos/nacos-server:1.3.1
    ports:
      - "8848:8848"
    environment:
      - "MODE=standalone"
    networks:
      - ems


  mysql:
    image: mysql
    ports:
      - "3306:3306" #只写一个端口随机使用宿主机一个端口进行容器端口映射
    environment:
      - "MYSQL_ROOT_PASSWORD=root"
      - "MYSQL_DATABASE=ems"
    volumes:
      - data:/var/lib/mysql
      #- ./ems.sql:/docker-entrypoint-initdb.d/ems.sql
    networks:
      - ems

5.项目启动

在服务器ems文件夹中输入

docker-compose up -d department
docker-compose up -d employee
docker-compose up -d gateway

image-20220103231213593

报错

有个服务报错:Error: Invalid or corrupt jarfile employess.jar

image-20220104001204222

检查了好几遍,重新打包上传还是这样,最后进目录查看发现jar包每次都没有上传完整

image-20220104001321050

文件大小明显不对,因为打包错了里面没有主启动类,我在打包之前就删除这些,添加进来然后重新运行 mvn install即可

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

这下正常了

image-20220104002539137

再次运行因为之前构建的镜像还在,即便重新上传还是运行的之前构建的,没有效果,所以的删除之前构建过的错误镜像,三个都运行成功

image-20220104003902487

部署成功!

image-20220104004009904

总结#

还有很多可以优化的地方,因为本节是着重演示部署流程,细节方面就没有优化了

这就是一整个部署的大概流程,但每次项目代码如果有更改,又需要手动重新生成镜像然后在服务器重新运行,还是不太方便,后续会出Jenkins+Docker自动化部署SpringCloud,实现代码提交自动进行编译打包上传并部署,简化在部署方面的操作。

项目细节难免有纰漏之处,附项目地址:https://gitee.com/yanglingcong/spring-cloud-docker


bus组件:实现远端配置修改自动刷新


实现自动配置刷新

MQ服务主机:47.106.105.80:15672
MQ端口号:15672(web管理界面) 5672(Java)
虚拟主机:ems

1、在springcloud-config-server-3344config服务端引入依赖

<!--引入bus依赖--><dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-bus-amqp</artifactId></dependency>

2、配置config Server配置文件,通过bus连接MQ的配置

server:
  port: 3344spring:
  application:
    name: springcloud-config-server
  # 连接码云远程仓库
  cloud:
    config:
      server:
        git:
          # 注意是https的而不是ssh
          uri: https://gitee.com/luoxiao1104/springcloud-config.git
          # 通过 config-server可以连接到git,访问其中的资源以及配置~
          default-label: master
  #通过bus组件连接到MQ服务
  rabbitmq:
    host: 47.106.105.80 #连接主机
    port: 5672 #连接mq端口
    username: guest #连接mq用户名
    password: guest #连接mq密码
    virtual-host: /#Eureka配置,服务注册到哪里eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
  instance:
    instance-id: springcloud-cofig-server-3344  #修改Eureka默认描述信息

启动springcloud-config-server-3344config服务端查看
image

3、配置微服务config client通过bus连接MQ服务

a.在所有微服务项目中(springcloud-config-client-3355)引入Bus依赖

<!--引入bus依赖--><dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-bus-amqp</artifactId></dependency>

b.在所有的微服务项目中配置MQ配置,即配置远端的配置文件
注意这个bootstrap的配置并不是最终配置,需要通过这里面的配置拉取远端的配置,获取远端配置启动,因此需要将这段配置放入远端的仓库进行管理
image
c.在config客户端bootstrap.yaml添加下面配置
image
d.启动springcloud-config-client-3355config客户端
image
4、在springcloud-config-server-3344config服务中配置application.yaml暴露所有端点
image

现在消息总线和config连接到一起,以后只需要在config Server发一次POST请求,所有的config client配置文件都会发生改变。

指定服务刷新配置实现

集成webhook实现自动刷新

webhooks
根据远程仓库触发对应事件发送一个web请求默认就是POST方式请求

一、在远端仓库中配置webhooks

1、在springcloud-config-server-3344config服务器中添加过滤器(必须要添加,不然后面配置webhooks会报错)

package com.study.springcloud.filters;import org.springframework.stereotype.Component;import javax.servlet.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletRequestWrapper;import javax.servlet.http.HttpServletResponse;import java.io.BufferedReader;import java.io.ByteArrayInputStream;import java.io.IOException;@Componentpublic class UrlFilter  implements Filter {    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
 
    } 
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {        HttpServletRequest httpServletRequest = (HttpServletRequest)request;        HttpServletResponse httpServletResponse = (HttpServletResponse)response; 
        String url = new String(httpServletRequest.getRequestURI()); 
        //只过滤/actuator/bus-refresh请求
        if (!url.endsWith("/bus-refresh")) {
            chain.doFilter(request, response);            return;
        } 
        //获取原始的body
        String body = readAsChars(httpServletRequest);
 
        System.out.println("original body:   "+ body); 
        //使用HttpServletRequest包装原始请求达到修改post请求中body内容的目的
        CustometRequestWrapper requestWrapper = new CustometRequestWrapper(httpServletRequest);
 
        chain.doFilter(requestWrapper, response);
 
    } 
    @Override
    public void destroy() {
 
    } 
    private class CustometRequestWrapper extends HttpServletRequestWrapper {        public CustometRequestWrapper(HttpServletRequest request) {            super(request);
        } 
        @Override
        public ServletInputStream getInputStream() throws IOException {            byte[] bytes = new byte[0];            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes); 
            return new ServletInputStream() {                @Override
                public boolean isFinished() {                    return byteArrayInputStream.read() == -1 ? true:false;
                } 
                @Override
                public boolean isReady() {                    return false;
                } 
                @Override
                public void setReadListener(ReadListener readListener) {
 
                } 
                @Override
                public int read() throws IOException {                    return byteArrayInputStream.read();
                }
            };
        }
    } 
    public static String readAsChars(HttpServletRequest request)
    { 
        BufferedReader br = null;        StringBuilder sb = new StringBuilder("");        try
        {
            br = request.getReader();
            String str;            while ((str = br.readLine()) != null)
            {
                sb.append(str);
            }
            br.close();
        }        catch (IOException e)
        {
            e.printStackTrace();
        }        finally
        {            if (null != br)
            {                try
                {
                    br.close();
                }                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }        return sb.toString();
    }
}

2、在主启动类中添加扫描包注解
image
3、在Gitee仓库中点击管理,再点击webhooks,最后点击添加
image

4、借助内网穿透(把内网地址转化为公网地址)使用natapp https://natapp.cn/

  • a.访问官方网址

  • b.注册 & 实名认证

  • c.购买免费通道

  • d.配置隧道 ==>配置本地端口 config server端口 3344

  • e.下载客户端 antapp.exe

  • f.在cmd命令行打开 启动natapp 输入natapp --authoken=a2164bdbdfe99d11(自己的验证码)
    image

5、输入信息
image
6、添加成功
image

springclou集成webhook实现自动刷新完成!


bus组件:消息总线RabbitMQ安装


bus组件简介

spring cloud bus使用轻量级消息代理将分布式系统的节点连接起来。然后,可以使用它来广播状态更改(例如配置更改)或其他管理指令。AMQP和Kafka broker(中间件)实现包含在项目中。或者,在类路径上找到的任何spring cloud stream绑定器都可以作为传输使用。

bus称之为springcloud中消息总线,主要用来在微服务系统中实现远端配置更新时通过广播形式通知所有客户端刷新配置信息,避免手动重启服务的工作

作用:利用bus 广播特性当一个状态(配置文件)发生改变时通知到bus中所有服务节点更新当前状态(自动更新自身配置)

实现配置刷新原理

image

RabbitMQ安装

1、进入RabbitMQ官网下载环境和安装包:https://www.rabbitmq.com/install-rpm.html#downloads

image

2、把环境和安装包放到linux服务器的root文件夹下

image

3、输入rpm -ivh erlang-22.0.7-1.el7.x86_64.rpm安装RabbitMQ运行环境

image

4、输入yum install -y rabbitmq-server-3.7.18-1.el7.noarch.rpm安装RabbitMQ安装包(需要联网)

image
提示安装完成
image

5、输入yum install socat -y安装socat

6、输入systemctl enable rabbirmq-server设置RabbitMQ开机自启

7、查看RibbitMQ是否安装成功

image

注意:默认安装完成后配置文件模板在:/usr/share/doc/rabbitmq-server-3.7.18/rabbitmq.config.example目录中,需要将配置文件复制到/etc/rabbitmq/目录中,并修改名称为rabbitmq.config

8、复制配置文件

image

9、编辑RabbitMQ的配置文件

进入编辑
image
找到对应位置
image
修改,如果输入:wq 提示文件只读的话,输入:wq!即可
image

10、启动RabbitMQ的web管理界面

image

11、启动RabbitMQ服务

image

12、输入服务ip:15672进入 RabbitMQ web管理界面,与Java TPC通信的端口为:6572

image

13、输入账号:guest 密码:guest ,进入RabbitMQ管理界面

image

14、添加一个RabbitMQ的管理用户

image

15、添加管理的虚拟主机

1、点击Virtaul Hosts
image
2、输入 /ems ,点击Add virtual host
image
3、
image
4、退出到用户管理界面,点击ems
image
5、
image
6、
image

15、不同用户又不同交换机的类型

image