Docker 下的 Nacos 环境开发,mysql 联合索引原理
基础镜像,使用 alpine 操作系统,openjkd 使用 8u201
FROM openjdk:8u201-jdk-alpine3.9
#作者
MAINTAINER BolingCavalry zq2599@gmail.com
#系统编码
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8
#path
ENV PATH /opt/conda/bin:$PATH
#安装必要的软件
#RUN apt-get update --fix-missing && apt-get install -y wget
RUN apk update && apk add wget
#下载下来的压缩文件名称
ENV NACOS_FILE_NAME nacos-server-1.1.0.tar.gz
#把启动时用到的文件准备好
COPY ./docker-entrypoint.sh /docker-entrypoint.sh
#解压后的文件夹名称
ENV NACOS_FOLDER_NAME nacos
RUN wget https://github.com/alibaba/nacos/releases/download/1.1.0/nacos-server-1.1.0.tar.gz -O ~/$NACOS_FILE_NAME && \
tar -zxf ~/$NACOS_FILE_NAME -C ~/ && \
rm ~/$NACOS_FILE_NAME && \
chmod a+x /docker-entrypoint.sh
ENTRYPOINT ["/docker-entrypoint.sh"]
EXPOSE 8848
从 Dockerfile 内容中可见,先去 nacos 的 github 下载安装包,然后解压,再复制 docker-entrypoint.sh 到镜像中,最后将 nacos 的 8848 端口暴露出来;
再来看看 docker-entrypoint.sh 文件的内容,该文件在容器启动时会被执行,内容很简单,就是进入 nacos 的 bin 目录,执行启动文件,再将 start.out 输出到控制台:
#!/bin/sh
echo "Starting nacos"n && \
cd ~/nacos/bin && \
./startup.sh -m standalone && \
cd ../logs && \
tail -f start.out
有两个重要信息需要注意:
nacos 的官方参考启动命令是./startup.sh -m standalone,这个命令会将 jvm 的输出重定向到 start.out 文件,也就是说 nacos 的 JVM 进程是在后台运行的,不会占用控制台(相比之下,spring boot 应用使用 java -jar 启动时会占用控制台),对于 docker 来说,容器内的进程如果不占用控制台,docker 就认为该容器已经结束工作,就会停止该容器,所以,为了避免 nacos 在 docker 刚刚启动就退出,需要用 tail -f start.out 来占领控制台;
用 tail -f start.out 来占领控制台可以避免容器刚刚启动就退出,但也有个弊端,就是容器中有了多个进程,并且 nacos 进程的 PID 不是 1,所以在执行 docker stop 命令时,结束进程的信号量不会到 nacos 进程,而是去了 PID 等于 1 的进程,所以 nacos 进程不会立即退出,只能等到 30 秒后被强制 kill,这个问题最好的解法是修改 nacos 的 startup.sh,让 nacos 进程始终保持在控制台,不要重定向到后台,但这样就导致 Dockerfile 不好处理了,每次下载和解压了 nacos 安装包后,都要用本地的 startup.sh 去替换原有的,这样做的话,如果 nacos 升级版本,这边本地的 startup.sh 也要随之更新,很是麻烦…
[](
)构建镜像
Dockerfile 和 docker-entrypoint.sh 文件准备好之后放在同一个目录,执行以下命令构建镜像:
docker build -t bolingcavalry/nacossimpleprovider:1.0-SNAPSHOT
如果您在 hub.docker.com 已经注册,可以执行以下命令将本地镜像上传到 hub.docker.com ,这样任何人都可以下载使用该镜像了:
docker push bolingcavalry/nacossimpleprovider:1.0-SNAPSHOT
Nacos 镜像的制作已经完成,接下来制作一个 java 应用的镜像:服务提供者;
[](
)java 应用的父工程
接下来要开发的 simple-provider 和 simple-consumer 两个应用都是 java 应用,为了管理方便,做一个基于 maven 的父工程,再将 simple-provider 和 simple-consumer 以 module 的形式加入到这个父工程中;
基于 maven 创建父工程,名为 nacosdemo,其 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<modules>
<module>simpleconsumer</module>
<module>simpleprovider</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
</parent>
<groupId>com.bolingcavalry</groupId>
<artifactId>nacosdemo</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring.boot.version>2.0.5.RELEASE</spring.boot.version>
<spring.cloud.version>Finchley.SR1</spring.cloud.version>
<spring.cloud.alibaba.version>0.2.2.RELEASE</spring.cloud.alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework
.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring.cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
可见这是个普通的父工程,里面对 spring cloud 和 spring cloud alibaba 的版本做了控制,避免子工程还要各种指定版本的繁琐操作;
[](
)制作服务提供者镜像
simple-provider 是个 java web 应用,使用了 spring cloud alibaba 的依赖库之后可以使用 Nacos 的注册发现服务,整个工程的开发步骤如下:
基于 maven 创建工程,其 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>nacosdemo</artifactId>
<groupId>com.bolingcavalry</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>simpleprovider</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>1.3.0</version>
<configuration>
<from>
<image>openjdk:8u201-jdk-alpine3.9</image>
</from>
<to>
<!--镜像名称和 tag,使用了 mvn 内置变量{project.version}-->
<image>bolingcavalry/nacos{project.version}</image>
</to>
<container>
<jvmFlags>
<jvmFlag>-Xms1g</jvmFlag>
<jvmFlag>-Xmx1g</jvmFlag>
</jvmFlags>
</container>
</configuration>
</plugin>
</plugins>
</build>
</project>
上述内容有两点需要注意:
a. 依赖 spring-cloud-starter-alibaba-nacos-discovery,这样可以用上 spring cloud nacos 的服务;
b. 使用了 maven 插件 jib-maven-plugin,用于将应用构建成 docker 镜像,此插件相关的详情请参考[《Docker 与 Jib(maven 插件版)实战》](
);
2. 配置文件 application.properties,配置应用名称和 nacos 地址,注意这里 nacos 地址配置的是 nacoshost,对应的是后面 docker-compose.yml 中的 link 参数:
spring.application.name=simple-provider
spring.cloud.nacos.discovery.server-addr=nacoshost:8848
应用启动类 SimpleProviderApplication ,配置了注解 EnableDiscoveryClient,用于启动注册发现服务:
package simpleprovider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class SimpleProviderApplication {
public static void main(String[] args) {
SpringApplication.run(SimpleProviderApplication.class, args);
}
}
增加一个提供 http 服务的 controller 类 ProviderController:
package simpleprovider.controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
@Description: 提供 web 服务的 controller
@author: willzhao E-mail: zq2599@gmail.com
@date: 2019/7/28 11:08
*/
@RestController
public class ProviderController {
@RequestMapping(value = "/hello/{name}", method = RequestMethod.GET)
public String hello(@PathVariable("name") String name){
return "hello " + name + ", " + new SimpleDateFormat("yyyy-mm-dd HH:mm:ss").format(new Date());
}
}
以上就是 simple-provider 的所有源码了,在 pom.xml 所在目录执行以下命令,即可构建 docker 镜像,存入本地仓库:
mvn compile jib:dockerBuild
[](
)制作服务消费者镜像
simple-consumer 是个 java web 应用,启动后对外提供 http 服务,响应的时候,通过 nacos 取得 simple-provider 的地址,然后向 simple-provider 发请求,将响应返回给浏览器:
基于 maven 创建工程,其 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>nacosdemo</artifactId>
<groupId>com.bolingcavalry</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>simpleconsumer</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
评论