这是我的第一篇博客,这篇博客是对B站上的一个关于微服务视频的阶段性总结,目前我完成了前105p内容的学习.期间碰到了各种各样的问题,收获也很丰富.
这篇博客的主要内容是使用spring cloud netflix和docker搭建分布式微服务的持续集成环境,使用的服务器都是操作系统都是Ubuntu.其中依赖服务都使用自己搭建的私服或者使用云厂商的私服服务.其中除了项目开发在个人pc上,其他服务都运行于虚拟机或者云服务器上.如果你只使用虚拟机运行,你的宿主机内存需要16g内存及以上.
这篇博客默认读者了解linux,docker和docker-compose,以及springboot.
想要运行gitlab请确保内存大于3g.
首先要确认你的docker-compose的版本.
docker-compose version
注意这一项:docker-py version: 3.7.3
,版本号的前两位将在docker-compose的配置用到.
新建一个docker-compose.yml
文件,添加以下内容:
version: '3.7' # docker-py的版本
services:
web:
image: 'twang2218/gitlab-ce-zh:11.0.5' # 中文翻译的gitlab镜像
container_name: gitlab
restart: always
hostname: '192.168.0.114' # 主机ip
environment:
TZ: 'Asia/Shanghai'
GITLAB_OMNIBUS_CONFIG: |
external_url 'http://192.168.0.114:80'
gitlab_rails['gitlab_shell_ssh_port'] = 2222 # 通过ssh操作的端口
gitlab_rails['gitlab_email_enabled'] = true # 开启邮箱服务
gitlab_rails['gitlab_email_from'] = '邮箱服务器地址(邮箱地址)'
gitlab_rails['gitlab_email_display_name'] = 'gitlab admin' # 邮件发信人
gitlab_rails['gitlab_email_reply_to'] = '回复邮箱地址'
gitlab_rails['gitlab_email_subject_suffix'] = '[gitlab]' # 邮件标题后缀
gitlab_rails['smtp_enable'] = true # 开启smtp服务
gitlab_rails['smtp_address'] = "smtp.qq.com" # smtp服务器
gitlab_rails['smtp_port'] = 465 # smtp端口
gitlab_rails['smtp_user_name'] = "邮箱服务器用户登录名(也可以是邮箱地址)"
gitlab_rails['smtp_password'] = "三方登录的校验码"
gitlab_rails['smtp_domain'] = "qq.com"
gitlab_rails['smtp_authentication'] = "login" # smtp认证方式
gitlab_rails['smtp_enable_starttls_auto'] = true # 开启starttls加密
gitlab_rails['smtp_tls'] = true
unicorn['port'] = 8888 # unicorn端口
nginx['listen_port'] = 80 # nginx监听端口
ports:
- '80:80'
- '8443:443'
- '2222:22'
volumes:
- /usr/local/docker/gitlab/config:/etc/gitlab
- /usr/local/docker/gitlab/data:/var/opt/gitlab
- /usr/local/docker/gitlab/logs:/var/log/gitlab
以上配置利用了qq邮箱作为邮箱服务器,关于qq邮箱开启smtp服务请百度.
然后运行以下命令
docker-compose up -d && docker logs gitlab -f
因为镜像文件有1.61G,所以在部分操作系统上可能存在/var/lib/docker空间不足的问题.(Ubuntu16.04 LTS没有这个问题).
等待启动完成后访问配置中的external_url,会进入root用户密码初始化的页面,输入两次密码并确认,然后可以使用root作为用户名,输入的密码作为密码登录gitlab进行管理.
成功登录之后在右上角头像点击setting设置你的ssh密钥,并更改默认的邮箱地址.
密钥对生成:
ssh-keygen -t rsa -C "[email protected]"
默认私钥和公钥会保存在$home/.ssh/目录下
内存要求至少2g.
docker-compose.yml:
version: '3.7'
services:
nexus:
restart: always
image: sonatype/nexus3
container_name: nexus
ports:
- 8081:8081
volumes:
- ./data:/nexus-data
mkdir data
chmod -hR 200 data
docker-compose up -d && docker logs -f nexus
启动时如果出现权限问题可以使用:chmod 666 ./data
赋予数据卷目录可读可写的权限.
启动后,使用admin作为账号登录,密码在usr/local/docker/nexus/data
目录下的admin.password文件中.
登陆后重新设置密码,勾选Allow anonymous users to access the server .
在本地的maven工具的settings.xml文件中,在servers标签下增加:
<server>
<id>nexus-releasesid>
<username>adminusername>
<password>密码password>
server>
<server>
<id>nexus-snapshotsid>
<username>adminusername>
<password>密码password>
server>
不要忘记将密码改成你修改后的密码.
并且在你要进行部署的项目中增加:
<distributionManagement>
<repository>
<id>nexus-releasesid>
<name>Nexus Release Repositoryname>
<url>http://ip:port/repository/maven-releases/url>
repository>
<snapshotRepository>
<id>nexus-snapshotsid>
<name>Nexus Snapshot Repositoryname>
<url>http://ip:port/repository/maven-snapshots/url>
snapshotRepository>
distributionManagement>
ip和port就是你部署nexus的ip和端口.
登录并开通仓库服务,按照使用指南添加配置.
我在后面采用了阿里云的maven私服.
1g内存也能运行.请保证足够的带宽,否则在镜像push的时候会非常慢.
docker-compose.yml:
version: '3.7'
services:
registry:
image: registry
restart: always
container_name: registry
ports:
- 5000:5000
volumes:
- /usr/local/docker/registry/data:/var/lib/registry
docker-compose up -d
在你的/etc/docker/daemon.json
中,配置如下:
{
"registry-mirrors": [
"默认拉取镜像的仓库地址"
],
"insecure-registries": [
"私服仓库地址:5000"
]
}
默认拉取镜像的仓库地址可以配置成阿里云的镜像加速器.
重启守护线程和docker
systemctl daemon-reload
systemctl restart docker
配置完成后可以测试是否生效
docker pull alpine
docker tag alpine 私服仓库地址:5000/alpine:latest
docker push 私服仓库地址:5000/alpine:latest
查看私服中的全部镜像
curl -XGET http://192.168.75.133:5000/v2/_catalog
拉取镜像只要通过仓库地址:端口/镜像名:版本号
就可以从你的私服仓库拉取镜像了.
登录阿里云容器镜像服务,点击管理控制台,以此添加命名空间和镜像仓库,代码源选择本地仓库.按这种方式可以创建一个镜像仓库的私服.完成后点镜像名,进入管理,查看仓库的基本信息,按照操作指南登录阿里云镜像仓库,如果报连接超时,这是网络问题.这个私服的网络比较慢,不是很推荐使用,如果说你有更高的带宽可以尝试.
相比之下,我们可以使用镜像加速器加快我们pull镜像的速度.在控制台左侧导航选择镜像加速器,就可以看到加速器地址.把这个地址配置到/etc/docker/daemon.json
中的registry-mirrors
里面,然后按照之前的流程重启docker,然后输入docker info
查看镜像加速器是否生效.
因为网络问题我没有选择阿里云的私人镜像仓库.
点搜索栏旁边的加号,选择新建一个群组.然后新建五个项目如图.
dependencies是项目依赖管理,config是分布式配置中心,eureka是服务注册发现,admin是服务监控,zipkin是链路追踪,zuul是网关,有相关经验的应该都会了解这几个组件.
在你开发的电脑上将这几个项目都拉取下来
打开你的开发工具,这里使用的是intellj idea.
通过file>open将项目添加到idea,现在这几个还没有我们的项目代码.
我们从itoken-dependencies开始新建我们的项目.
在itoken-dependencies下新建pom.xml.
pom.xml文件配置如下:
<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.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.1.6.RELEASEversion>
parent>
<groupId>com.wymc.cloudgroupId>
<artifactId>itoken-dependenciesartifactId>
<version>0.0.1-SNAPSHOTversion>
<packaging>pompackaging>
<name>itoken-dependenciesname>
<inceptionYear>2019-NowinceptionYear>
<properties>
<java.version>1.8java.version>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
<spring-cloud.version>Greenwich.SR2spring-cloud.version>
<spring-boot-admin.version>2.1.6spring-boot-admin.version>
<spring-boot-alibaba-druid.version>1.1.10spring-boot-alibaba-druid.version>
<spring-boot-mapper.version>2.1.5spring-boot-mapper.version>
<spring-boot-pagehelper.version>1.2.5spring-boot-pagehelper.version>
<zipkin.version>2.10.1zipkin.version>
<mysql.version>5.1.47mysql.version>
<lombok.version>1.16.18lombok.version>
<guava.version>25.1-jreguava.version>
<nekohtml.version>1.9.22nekohtml.version>
<jackson.version>2.9.6jackson.version>
<feign-form.version>3.3.0feign-form.version>
<swagger2.version>2.8.0swagger2.version>
properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druid-spring-boot-starterartifactId>
<version>${spring-boot-alibaba-druid.version}version>
dependency>
<dependency>
<groupId>tk.mybatisgroupId>
<artifactId>mapper-spring-boot-starterartifactId>
<version>${spring-boot-mapper.version}version>
dependency>
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelper-spring-boot-starterartifactId>
<version>${spring-boot-pagehelper.version}version>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>${spring-cloud.version}version>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>de.codecentricgroupId>
<artifactId>spring-boot-admin-starter-serverartifactId>
<version>${spring-boot-admin.version}version>
dependency>
<dependency>
<groupId>de.codecentricgroupId>
<artifactId>spring-boot-admin-starter-clientartifactId>
<version>${spring-boot-admin.version}version>
dependency>
<dependency>
<groupId>io.zipkin.javagroupId>
<artifactId>zipkinartifactId>
<version>${zipkin.version}version>
dependency>
<dependency>
<groupId>io.zipkin.javagroupId>
<artifactId>zipkin-serverartifactId>
<version>${zipkin.version}version>
dependency>
<dependency>
<groupId>io.zipkin.javagroupId>
<artifactId>zipkin-autoconfigure-uiartifactId>
<version>${zipkin.version}version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>${mysql.version}version>
<scope>runtimescope>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>${lombok.version}version>
dependency>
<dependency>
<groupId>com.google.guavagroupId>
<artifactId>guavaartifactId>
<version>${guava.version}version>
dependency>
<dependency>
<groupId>net.sourceforge.nekohtmlgroupId>
<artifactId>nekohtmlartifactId>
<version>${nekohtml.version}version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>${jackson.version}version>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger2artifactId>
<version>${swagger2.version}version>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger-uiartifactId>
<version>${swagger2.version}version>
dependency>
dependencies>
dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<configuration>
<showWarnings>trueshowWarnings>
configuration>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-jar-pluginartifactId>
<configuration>
<archive>
<addMavenDescriptor>falseaddMavenDescriptor>
archive>
configuration>
<executions>
<execution>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>trueaddDefaultImplementationEntries>
<addDefaultSpecificationEntries>trueaddDefaultSpecificationEntries>
<addClasspath>trueaddClasspath>
manifest>
archive>
configuration>
execution>
executions>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-resources-pluginartifactId>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-install-pluginartifactId>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-clean-pluginartifactId>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-antrun-pluginartifactId>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-dependency-pluginartifactId>
plugin>
plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-javadoc-pluginartifactId>
<executions>
<execution>
<phase>prepare-packagephase>
<goals>
<goal>jargoal>
goals>
execution>
executions>
plugin>
<plugin>
<groupId>net.alchim31.mavengroupId>
<artifactId>yuicompressor-maven-pluginartifactId>
<version>1.5.1version>
<executions>
<execution>
<phase>prepare-packagephase>
<goals>
<goal>compressgoal>
goals>
execution>
executions>
<configuration>
<encoding>UTF-8encoding>
<jswarn>falsejswarn>
<nosuffix>truenosuffix>
<linebreakpos>30000linebreakpos>
<force>trueforce>
<includes>
<include>**/*.jsinclude>
<include>**/*.cssinclude>
includes>
<excludes>
<exclude>**/*.min.jsexclude>
<exclude>**/*.min.cssexclude>
excludes>
configuration>
plugin>
plugins>
pluginManagement>
<resources>
<resource>
<directory>src/main/javadirectory>
<excludes>
<exclude>**/*.javaexclude>
excludes>
resource>
<resource>
<directory>src/main/resourcesdirectory>
resource>
resources>
build>
<distributionManagement>
<repository>
<id>rdc-releasesid>
<url>releases仓库地址url>
repository>
<snapshotRepository>
<id>rdc-snapshotsid>
<url>snapshots仓库地址url>
snapshotRepository>
distributionManagement>
<repositories>
<repository>
<id>rdc-releasesid>
<name>releases仓库名name>
<url>releases仓库urlurl>
<releases>
<enabled>trueenabled>
releases>
repository>
<repository>
<id>rdc-snapshotsid>
<name>snapshots仓库名name>
<url>snapshots仓库urlurl>
<snapshots>
<enabled>trueenabled>
snapshots>
repository>
repositories>
<pluginRepositories>
<pluginRepository>
<id>rdc-releasesid>
<name>snapshots仓库名name>
<url>snapshots仓库urlurl>
<releases>
<enabled>trueenabled>
releases>
pluginRepository>
<pluginRepository>
<id>aliyun-reposid>
<name>Aliyun Repositoryname>
<url>http://maven.aliyun.com/nexus/content/groups/publicurl>
<releases>
<enabled>trueenabled>
releases>
<snapshots>
<enabled>falseenabled>
snapshots>
pluginRepository>
pluginRepositories>
project>
需要修改pom.xml文件中必要的配置.并且在右侧的sidebar上找到maven,点击+将pom添加到maven插件管理.
新建.gitignore文件:
target/
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### JRebel ###
rebel.xml
### MAC ###
.DS_Store
### Other ###
logs/
temp/
完成后就可以将项目部署到maven私服了
mvn clean deploy
第二步搭建配置中心.
同样新建pom.xml文件,然后新建src/main/java和src/mian/resources文件夹,.gitignore文件.
pom.xml文件配置:
<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.0modelVersion>
<parent>
<groupId>com.wymc.cloudgroupId>
<artifactId>itoken-dependenciesartifactId>
<version>0.0.1-SNAPSHOTversion>
<relativePath>../itoken-dependencies/pom.xmlrelativePath>
parent>
<artifactId>itoken-configartifactId>
<name>itoken-configname>
<inceptionYear>2019-NowinceptionYear>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-tomcatartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-zipkinartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-config-serverartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
dependency>
<dependency>
<groupId>org.jolokiagroupId>
<artifactId>jolokia-coreartifactId>
dependency>
<dependency>
<groupId>de.codecentricgroupId>
<artifactId>spring-boot-admin-starter-clientartifactId>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<mainClass>com.wymc.cloud.ConfigApplicationmainClass>
configuration>
plugin>
plugins>
build>
project>
新建一个包com.wymc.cloud
,新建一个类
package com.wymc.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
* @author 无以铭川
* @date 2019/7/24:下午 10:04
*/
@EnableEurekaClient
@EnableConfigServer
@SpringBootApplication
public class ConfigApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigApplication.class,args);
}
}
在resources下新建bootstrap.yml
不能使用application.yml,因为优先级问题会导致指定配置中心ip和端口无效.
spring:
# 应用配置
application:
name: itoken-config
cloud:
# 配置中心
config:
label: master
server:
git:
uri: http://ip/spring-cloud-itoken/itoken-config.git
search-paths: 配置文件夹 # 其他项目将从这个文件夹查找配置文件
username: gitlab账号
password: gitlab密码
zipkin:
base-url: http://localhost:9411
# 端口
server:
port: 8888
# 服务注册客户端配置
eureka:
instance:
hostname: localhost
ip-address: 127.0.0.1
prefer-ip-address: true
instance-id: 127.0.0.1:${server.port}
client:
serviceUrl:
defaultZone: http://api:[email protected]:8761/eureka/
# 服务监控配置
management:
endpoint:
health:
show-details: always
endpoints:
web:
exposure:
include: health,info
上面的步骤完成后,在你的项目下配置文件夹:
结果应该如图:
这里,src/main/java/resources/config是我的配置文件夹
docker文件夹和.gitlab-ci.yml都将在之后说明.
在配置文件夹下新建一个测试用的yml文件,例如test-dev.yml
,在里面写上一些配置信息
spring:
application:
name: test
server:
port: 8080
访问http://localhost:8888/test/dev/master
,程序正常运行可以得到一个xml结构的配置信息.
在上面的链接中,路径是/服务名/profile/分支
.
pom.xml:
<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.0modelVersion>
<parent>
<groupId>com.wymc.cloudgroupId>
<artifactId>itoken-dependenciesartifactId>
<version>0.0.1-SNAPSHOTversion>
<relativePath>../itoken-dependencies/pom.xmlrelativePath>
parent>
<artifactId>itoken-eurekaartifactId>
<version>0.0.1-SNAPSHOTversion>
<packaging>jarpackaging>
<name>itoken-eurekaname>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-securityartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-zipkinartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-configartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
dependency>
<dependency>
<groupId>org.jolokiagroupId>
<artifactId>jolokia-coreartifactId>
dependency>
<dependency>
<groupId>de.codecentricgroupId>
<artifactId>spring-boot-admin-starter-clientartifactId>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<mainClass>com.wymc.cloud.EurekaApplicationmainClass>
configuration>
plugin>
plugins>
build>
project>
src/main/java/com.wymc.cloud.config.SecurityConfiguration:
package com.wymc.cloud.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
/**
* @author 无以铭川
* @date
*/
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);
http.csrf()
.disable()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic();
}
}
src/main/java/com.wymc.cloud.EurekaApplication:
package com.wymc.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* @author 无以铭川
*/
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
src/main/resources/bootstrap.yml:
spring:
cloud: # 配置中心客户端配置
config:
uri: http://localhost:8888
name: itoken-eureka
label: master
profile: dev
security: # 服务安全认证
user: # 认证用户
name: api
password: node
roles: SERVICE_NODE
显然,只是这样配置还不够,我们要在配置中心新建我们的配置文件.
在itoken-config的配置文件夹下新建一个name-profile-label.yml
的配置文件,这里是itoken-eureka-dev-master.yml
在itoken-config
的配置文件夹下新建文件,我这里是src/main/resources/config/itoken-eureka-dev-master.yml:
spring:
application:
name: itoken-admin
zipkin:
base-url: http://localhost:9411
server:
port: 8084
management:
endpoints:
web:
exposure:
include: health,info
endpoint:
health:
show-details: always
eureka:
instance:
hostname: localhost
ip-address: localhost
prefer-ip-address: true
instance-id: localhost:${server.port}
client:
service-url:
defaultZone: http://api:node@localhost:8761/eureka
在这个注册中心应用中,采用了spring security保障注册中心的安全,SecurityConfiguration
配置类关闭了csrf避免服务被阻拦无法注册到注册中心.
==每次修改itoken-config的配置文件夹中的配置文件,都应该推送到仓库.==因为配置文件其实是从gitlab上拉取的,如果你没有push,其他服务将得不到你更改后的配置.
先启动配置中心,启动完成后访问http://localhost:8888/itoken-eureka/dev/master
,有xml配置回应代表服务端正常.
然后启动eureka,在启动日志的前几行就会显示从配置中心拉取了配置.
访问http://localhost:8761/
,输入你在配置文件中加入的user的name和password即可查看服务列表.
pom.xml:
<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.0modelVersion>
<parent>
<groupId>com.wymc.cloudgroupId>
<artifactId>itoken-dependenciesartifactId>
<version>0.0.1-SNAPSHOTversion>
<relativePath>../itoken-dependencies/pom.xmlrelativePath>
parent>
<groupId>com.wymc.cloudgroupId>
<artifactId>itoken-adminartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>admin-demoname>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>de.codecentricgroupId>
<artifactId>spring-boot-admin-starter-serverartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-zipkinartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-configartifactId>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<mainClass>com.wymc.cloud.AdminApplicationmainClass>
configuration>
plugin>
plugins>
build>
project>
src/main/java/com.wymc.cloud.AdminApplication:
package com.wymc.cloud;
import de.codecentric.boot.admin.server.config.EnableAdminServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
* @author 无以铭川
* @date 2019/7/25:上午 8:53
*/
@SpringBootApplication
@EnableEurekaClient
@EnableAdminServer
public class AdminApplication {
public static void main(String[] args) {
SpringApplication.run(AdminApplication.class, args);
}
}
src/main/resources/bootstrap.yml:
spring:
cloud:
config:
uri: http://localhost:8888
name: itoken-admin
label: master
profile: dev
同样,你需要在配置中心增加itoken-admin-dev.yml
:
spring:
application:
name: itoken-admin
zipkin:
base-url: http://localhost:9411
server:
port: 8084
management:
endpoints:
web:
exposure:
include: health,info
endpoint:
health:
show-details: always
eureka:
instance:
hostname: localhost
ip-address: localhost
prefer-ip-address: true
instance-id: localhost:${server.port}
client:
service-url:
defaultZone: http://api:node@localhost:8761/eureka
如果你有看视频你会发现我的服务监控的pom.xml去掉了一些配置,在如今这个版本之前的配置会发生一个奇怪的错误,虽然启动,但是访问是没有监控到任何服务的,并且会出现控制台持续报tomcat找不到方法的错误.
同样,服务监控也要求配置中心先启动,在之后的所有服务启动前都应该先启动配置中心才能到gitlab去拉取配置文件.
启动后访问http://localhost:8084/
可以进入服务监控页.正常运行的情况下,我们可以看到服务的状态.
admin在注册到注册中心后可以从注册中心上拉取服务信息,从而监控服务,但是这种方法在注册中心宕机后就无法监控其他服务,想要保证注册中心宕机也能监控服务你需要增加配置项spring.boot.admin.client.url
.
pom.xml
<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.0modelVersion>
<parent>
<groupId>com.wymc.cloudgroupId>
<artifactId>itoken-dependenciesartifactId>
<version>0.0.1-SNAPSHOTversion>
<relativePath>../itoken-dependencies/pom.xmlrelativePath>
parent>
<artifactId>itoken-zipkinartifactId>
<packaging>jarpackaging>
<name>itoken-zipkinname>
<inceptionYear>2019-NowinceptionYear>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-tomcatartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-zipkinartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-configartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
dependency>
<dependency>
<groupId>org.jolokiagroupId>
<artifactId>jolokia-coreartifactId>
dependency>
<dependency>
<groupId>de.codecentricgroupId>
<artifactId>spring-boot-admin-starter-clientartifactId>
dependency>
<dependency>
<groupId>io.zipkin.javagroupId>
<artifactId>zipkinartifactId>
dependency>
<dependency>
<groupId>io.zipkin.javagroupId>
<artifactId>zipkin-serverartifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-log4j2artifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>io.zipkin.javagroupId>
<artifactId>zipkin-autoconfigure-uiartifactId>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<mainClass>com.wymc.cloud.ZipKinApplicationmainClass>
configuration>
plugin>
plugins>
build>
project>
在这个pom文件中会有日志实现的冲突需要排除一个.
src/main/java/com.wymc.cloud.ZipKinApplication:
package com.wymc.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import zipkin.server.internal.EnableZipkinServer;
/**
* @author 无以铭川
* @date 2019/7/25:上午 8:35
*/
@SpringBootApplication
@EnableEurekaClient
@EnableZipkinServer
public class ZipKinApplication {
public static void main(String[] args) {
SpringApplication.run(ZipKinApplication.class, args);
}
}
src/main/resources/bootstrap.yml
spring:
main:
allow-bean-definition-overriding: true
cloud:
config:
uri: http://localhost:8888
name: itoken-zipkin
label: master
profile: dev
因为原因未知的bean定义冲突,并且是在拉取配置前就发生了,所以只能配置在bootstrap.yml中.
配置中心的itoken-zipkin-dev.yml
:
spring:
application:
name: itoken-zipkin
main:
allow-bean-definition-overriding: true
zipkin:
base-url: http://localhost:9411
server:
port: 9411
eureka:
instance:
hostname: localhost
ip-address: localhost
prefer-ip-address: true
instance-id: localhost:${server.port}
client:
serviceUrl:
defaultZone: http://api:node@localhost:8761/eureka/
management:
endpoint:
health:
show-details: always
endpoints:
web:
exposure:
include: health,info
metrics:
web:
server:
auto-time-requests: false
启动后访问http://localhost:9411/
,点一下find traces,下面出现访问记录代表正常.详细链路追踪的使用可以查看谷歌或者百度.
pom.xml
<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.0modelVersion>
<parent>
<groupId>com.wymc.cloudgroupId>
<artifactId>itoken-dependenciesartifactId>
<version>0.0.1-SNAPSHOTversion>
<relativePath>../itoken-dependencies/pom.xmlrelativePath>
parent>
<artifactId>itoken-zuulartifactId>
<packaging>jarpackaging>
<name>itoken-zuulname>
<inceptionYear>2019-NowinceptionYear>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-tomcatartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-zipkinartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-configartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-zuulartifactId>
dependency>
<dependency>
<groupId>org.jolokiagroupId>
<artifactId>jolokia-coreartifactId>
dependency>
<dependency>
<groupId>de.codecentricgroupId>
<artifactId>spring-boot-admin-starter-clientartifactId>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<mainClass>com.wymc.cloud.ZuulApplicationmainClass>
configuration>
plugin>
plugins>
build>
project>
src/main/java/com.wymc.cloud.ZuulApplication:
package com.wymc.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
/**
* @author 无以铭川
* @date 2019/7/25:上午 9:08
*/
@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
src/main/resources/bootstrap.yml:
spring:
cloud:
config:
uri: http://localhost:8888
name: itoken-zuul
label: master
profile: dev
itoken-zuul-dev.yml
:
spring:
application:
name: itoken-zuul
zipkin:
base-url: http://localhost:9411
server:
port: 8769
eureka:
instance:
hostname: localhost
ip-address: localhost
prefer-ip-address: true
instance-id: localhost:${server.port}
client:
serviceUrl:
defaultZone: http://api:node@localhost:8761/eureka/
management:
endpoint:
health:
show-details: always
endpoints:
web:
exposure:
include: health,info
服务网关的增加一点配置:
zuul:
routes:
itoken-eureka:
path: /eureka
url: http://localhost:8761/
推送到仓库后重启itoken-zuul
访问http://localhost:8769/eureka
,如果出现eureka页面代表成功.
找个文件夹放如下内容.其中config是将要被挂载的数据卷,config目录和下面的内容不需要新建.environment是我们构建我们需要的gitlab-runner的镜像的文件夹.
docker-compose.yml:
version: '3.7'
services:
gitlab-runner:
build: environment
restart: always
container_name: gitlab-runner
privileged: true
volumes:
- /usr/local/docker/runner/config:/etc/gitlab-runner
- /var/run/docker.sock:/var/run/docker.sock
environment/apache-maven-3.5.3-bin.tar.gz,这个是maven的压缩包,从官网下载上传的,因为curl或者wget在构建镜像的时候下载太慢,所以我选择了直接上传复制解压.同样,下面的docker-compose是1.24版本的,以及jdk都是下载后上传的文件.
在这里的maven需要你先解压后,修改settings.xml增加前面提到的配置项,然后打包压缩,否则在使用的时候会出现未认证的错误.
daemon.json:
{
"registry-mirrors": [
"镜像加速器"
],
"insecure-registries": [
"私服仓库地址"
]
}
镜像加速器可以使用阿里云的.因为私服仓库是http,但是docker在push的时候默认是用https,所以需要配置insecure-registries.尽管这个私服仓库可以push,但因为带宽问题(云服务器),push是非常耗时的,你可以选择虚拟机,在局域网内的镜像仓库是速度快很多的.
Dockerfile:
FROM gitlab/gitlab-runner:v11.0.2
MAINTAINER 作者名 <作者邮箱>
# 修改软件包仓库
RUN echo "deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted universe multiverse" > /etc/apt/sources.list && \
echo "deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted universe multiverse" >> /etc/apt/sources.list && \
echo "deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted universe multiverse" >> /etc/apt/sources.list && \
echo "deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse" >> /etc/apt/sources.list && \
apt-get update -y && \
apt-get clean
# 安装 Docker
RUN apt-get -y install apt-transport-https ca-certificates curl software-properties-common && \
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | apt-key add - && \
add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" && \
apt-get update -y && \
apt-get install -y docker-ce
COPY daemon.json /etc/docker/daemon.json
# 安装 Docker Compose
COPY docker-compose /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-compose
# 安装 Java
RUN mkdir -p /usr/local/java
WORKDIR /usr/local/java
COPY ./jdk-8u211-linux-x64.tar.gz /usr/local/java
RUN tar -zxvf jdk-8u211-linux-x64.tar.gz && \
rm -fr jdk-8u211-linux-x64.tar.gz
# 安装 Maven
RUN mkdir -p /usr/local/maven
WORKDIR /usr/local/maven
COPY apache-maven-3.5.3-bin.tar.gz /usr/local/maven
RUN tar -zxvf apache-maven-3.5.3-bin.tar.gz && \
rm -fr apache-maven-3.5.3-bin.tar.gz
# 配置环境变量
ENV JAVA_HOME=/usr/local/java/jdk1.8.0_211 \
MAVEN_HOME=/usr/local/maven/apache-maven-3.5.3 \
PATH=$PATH:/usr/local/java/jdk1.8.0_211/bin:/usr/local/maven/apache-maven-3.5.3/bin
WORKDIR /
上面的准备工作完成后,在runner目录下docker-compose up -d就可以启动gitlab-runner了.
如果任何步骤失败,在修改镜像构建需要使用的文件后,你可以使用docker-compose up --build -d来重新启动.
等待启动成功后,我们要把我们的项目注册到gitlab-runner.
在每个项目页面,设置–>CI/CD–>Runners设置,展开找到Setup a specific Runner manually
,其下会有url和一个注册令牌.
# 交互方式启动gitlab-runner的注册
docker exec -it gitlab-runner gitlab-runner register
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
输入你的url
Please enter the gitlab-ci token for this runner:
输入项目的注册令牌
下面两步可以enter跳过
最后输入的是脚本的执行器,输入shell
每个项目都注册到gitlab-runner之后,我们就可以使用gitlab-runner了.
每次push都将触发pipeline,或者称之为流水线,一个流水线就是一次任务流程的定义,由一个或多个stage构成
stage是流水线中的任务单元,所有stage顺序执行,只有前一个执行成功后一个才会开始,任何stage失败,pipeline都会失败
stage可以拥有一个或多个job,多个job之前并行执行,任何job失败,这个stage就会失败.
简单示例:
stages:
- stage1
- stage2
job1:
stage: stage1
script:
- echo "stage1 job1"
job2:
stage: stage2
script:
- echo "stage2 job2"
job3:
stage: stage1
script:
- echo "stage1 job3"
在上面这个示例中,将先并行执行stage1的两个job:job1和job3,然后执行stage2的job2.
关键词 | 必须 | 描述 |
---|---|---|
script | 是 | 定义由Runner执行的shell脚本 |
Image | 否 | 使用Docker镜像,使用Docker Images进行了介绍 |
services | 否 | 使用Docker服务,使用Docker Images |
stage | 否 | 定义一个工作阶段(默认:test) |
type | 否 | 别名为 stage |
variables | 否 | 在作业级别定义作业变量 |
Only | 否 | 定义一列git分支,并为其创建job |
except | 否 | 定义一列git分支,不创建job |
tags | 否 | 定义用于选择Runner的标记列表 |
allow_failure | 否 | 允许job失败。失败的job不影响commit状态 |
When | 否 | 定义何时运行作业。可以是on_success,on_failure,always或者manual |
Dependencies | 否 | 定义作业所依赖的其他作业,以便您可以在它们之间传递工件 |
Artifacts | 否 | 定义作业工件列表 用于指定成功后应附加到作业的文件和目录列表。 作业成功完成后,工件将被发送到 GitLab,并可在GitLab UI中下载。 |
Cache | 否 | 定义后续运行之间应缓存的文件列表 |
before_script | 否 | 重写在作业之前执行的一组命令 |
after_script | 否 | 重写作业后执行的一组命令 |
Environment | 否 | 定义此作业完成部署的环境名称 |
Coverage | 否 | 定义给定作业的代码覆盖率设置 |
Retry | 否 | 定义在发生故障时可以自动重试作业的次数 |
上表原博
从依赖管理开始在项目路径下新建.gitlab-ci.yml:
stages:
- deploy
deploy:
stage: deploy
script:
- /usr/local/maven/apache-maven-3.5.3/bin/mvn clean deploy
将他push到仓库,gitlab-runner将为我们自动部署依赖管理.
其他项目都是可运行的,我们可以在push之后直接用gitlab-runner来完成构建镜像,启动运行的操作.
配置中心的.gitlab-ci.yml:
stages:
- build
- run
- clean
build:
stage: build
script:
- /usr/local/maven/apache-maven-3.5.3/bin/mvn clean package
- cp target/itoken-config-0.0.1-SNAPSHOT.jar docker/
- cd docker
- docker build -t 镜像仓库ip:5000/itoken-config
run:
stage: run
script:
- cd docker
- docker-compose down
- docker-compose up -d
clean:
stage: clean
script:
- docker image prune -f
这将完成项目的打包,镜像构建,运行,和镜像清理的作业.而如何构建镜像和运行我们需要先定义好,所以需要在项目目录下新建docker文件夹,新建Dockerfile和docker-compose.yml.
Dockerfile:
FROM openjdk:8-jre
MAINTAINER 作者名 <作者email>
# 新建存放项目文件的文件夹
RUN mkdir /app
# 项目版本
ENV APP_VERSION 0.0.1-SNAPSHOT
# 复制项目jar包
COPY itoken-config-${APP_VERSION}.jar /app/app.jar
# 运行项目
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app/app.jar", "--spring.profiles.active=prod"]
#暴露端口
EXPOSE 8888
因为这个时候的项目已经是开发完成了,使用gitlab-runner来运行到测试或者生产环境上,所以上面的配置激活的profile是prod,你需要在配置中心增加对应的配置文件,主要修改一下其中的ip就可以了.
docker-compose.yml:
version: "3.7"
services:
itoken-config: # 名称,不同项目不重复即可
image: 镜像仓库ip:5000/itoken-config # 镜像名需要修改
restart: always
container_name: itoken-config # 容器名需要修改
ports:
- 8888:8888 # 端口需要修改
networks:
- network_config # 使用的网卡需要修改
networks:
network_config: # 新建网卡需要修改
这里会新建network_config网卡并使用,其他项目也需要修改networks的配置,如果不修改将会使用默认的docker_default网卡,这将会发生冲突.
其他项目的Dockerfile略有不同
itoken-eureka
的Dockerfile:
FROM openjdk:8-jre
MAINTAINER wymc
ENV APP_VERSION 0.0.1-SNAPSHOT
ENV DOCKERIZE_VERSIONP v0.6.1
# 下载dockerize
RUN wget https://github.com/jwilder/dockerize/releases/download/${DOCKERIZE_VERSIONP}/dockerize-linux-amd64-${DOCKERIZE_VERSIONP}.tar.gz \
&& tar -C /usr/local/bin -xzvf dockerize-linux-amd64-${DOCKERIZE_VERSIONP}.tar.gz \
&& rm dockerize-linux-amd64-${DOCKERIZE_VERSIONP}.tar.gz
RUN mkdir /app
COPY 项目名-${APP_VERSION}.jar /app/app.jar
# 利用dockerize等待配置中心响应配置后启动
ENTRYPOINT ["dockerize", "-timeout", "5m", "-wait", "http://配置中心的ip:8888/itoken-config/prod/master", "java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app/app.jar", "--spring.profiles.active=prod"]
EXPOSE 端口
上面中文都是必要修改的地方.
这里使用了一个dockerrize插件,让注册中心等待配置中心启动完成后,返回了正确的配置信息后才会启动.
其他项目同理,Dockerfile只要修改一下COPY上的项目名以及下面的EXPOSE的端口,docker-compose.yml只要修改项目名和端口配置和网卡的设置.
最终每个项目都应该有如下的结构(除了配置中心多个配置文件夹和依赖管理外):
配置中心的配置文件夹:
在开发环境下push的以-dev.yml
结尾的文件我们不需要集成,所以可以添加如下配置:
job:
except:
changes:
- boostrap.yml
- "*-dev.yml"
注意只有当前job会跳过,所以需要在所有的job中都配置上.
END