CloudAlibaba
Nacos
Nacos注册中心
nacos手册:https://nacos.io/zh-cn/docs/what-is-nacos.html
依赖:
<!--添加nacos客户端-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>${latest.version}</version>
</dependency>
yaml配置:
spring:
cloud:
nacos:
discovery:
server-addr: ${NacosServerIP:Port}
通过 Spring Cloud 原生注解 @EnableDiscoveryClient
开启服务注册发现功能:
@SpringBootApplication
//开启服务发现
@EnableDiscoveryClient
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
Nacos配置中心
- 项目添加依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
-
配置文件优先级讲解
- 不能使用原先的application.yml, 需要使用bootstrap.yml作为配置文件
- 配置读取优先级 bootstrap.yml > application.yml
-
配置实操
- 订单服务迁移配置
- 增加bootstrap.yml
spring: application: name: xdclass-order-service cloud: nacos: config: server-addr: 127.0.0.1:8848 #Nacos配置中心地址 file-extension: yaml #文件拓展格式 profiles: active: dev
启动微服务服务验证
- 测试是否可以获取配置
浏览器访问 http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=xdclass-order-service-dev.yaml&group=DEFAULT_GROUP
Nacos动态配置下发
-
什么是动态刷新配置
- 我们修改了配置,程序不能自动更新
- 动态刷新就可以解决这个问题
-
配置实战
- 增加Nacos增加测试配置
- 编写代码
@RefreshScope public class OrderController { @Value("${video.title}") private String videoTitle; }
负载均衡
常⻅的负载均衡策略(看组件的⽀持情况)
节点轮询
简介:每个请求按顺序分配到不同的后端服务器
weight 权重配置
简介:weight和访问⽐率成正⽐,数字越⼤,分配 得到的流量越⾼
固定分发
简介:根据请求按访问ip的hash结果分配,这样每 个⽤户就可以固定访问⼀个后端服务器
AlibabaCloud集成Ribbon实现负载均衡
@SpringBootApplication
//开启服务发现
@EnableDiscoveryClient
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
@Bean
//开启负载均衡
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
负载均衡组件Open-Feign
官方文档:https://spring.io/projects/spring-cloud-openfeign
<!--引入feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>${latest.version}</version>
</dependency>
启动类增加@EnableFeignClients
@SpringBootApplication
//开启服务发现
@EnableDiscoveryClient
//开启Feign支持
@EnableFeignClients
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
调用方增加⼀个接⼝
src/main/java/net/xdclass/service/VideoService.java
@FeignClient(value = "xdclass-video-service",fallback = VideoServiceFallback.class)
public interface VideoService {
@GetMapping("api/v1/video/find_by_id")
Video findById(@RequestParam("videoId") int videoId);
@PostMapping("api/v1/video/save")
int save(@RequestBody Video video);
}
被调用方
src/main/java/net/xdclass/controller/VideoController.java
@RestController
@RequestMapping("api/v1/video")
public class VideoController {
@Autowired
private VideoService videoService;
@RequestMapping("find_by_id")
public Object findById(int videoId, HttpServletRequest request) {
Video video = videoService.findById(videoId);
//注入IP
video.setServeInfo(request.getServerName() + ":" + request.getServerPort());
return video;
}
@PostMapping("save")
public int save(@RequestBody Video video) {
System.out.println(video.getTitle());
return 1;
}
}
CAP理论
Sentinle
- sentinel介绍
- 阿里巴巴开源的分布式系统流控工具
- 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性
- 丰富的应用场景:消息削峰填谷、集群流量控制、实时熔断下游不可用应用等
- 完备的实时监控:Sentinel 同时提供实时的监控功能
- 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合
- 官网:https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D
- Sentinel版本:2.2.1
- 核心概念:
- 资源:是 Sentinel 中的核心概念之一,可以是java程序中任何内容,可以是服务或者方法甚至代码,总结起来就是我们要保护的东西
- 规则:定义怎样的方式保护资源,主要包括流控规则、熔断降级规则等
依赖引入和控制台搭建
-
Sentinel 分为两个部分
- 核心库(Java 客户端)不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo、Spring Cloud 等框架也有较好的支持。
- 控制台(Dashboard)基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器。
-
微服务引入Sentinel依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> <version>${latest.version}</version> </dependency>
-
Sentinel控制台搭建
-
控制台包含如下功能:
- 查看机器列表以及健康情况:收集 Sentinel 客户端发送的心跳包,用于判断机器是否在线。
- 监控 (单机和集群聚合)通过 Sentinel 客户端暴露的监控 API,定期拉取并且聚合应用监控信息,最终可以实现秒级的实时监控。
- 规则管理和推送:统一管理推送规则。
- 鉴权:生产环境中鉴权非常重要。这里每个开发者需要根据自己的实际情况进行定制。
注意:Sentinel 控制台目前仅支持单机部署
//启动 Sentinel 控制台需要 JDK 版本为 1.8 及以上版本,
//-Dserver.port=8080 用于指定 Sentinel 控制台端口为 8080
//默认用户名和密码都是 sentinel
java -jar sentinel-dashboard-1.8.0.jar
多个微服务接入sentinel
spring:
cloud:
sentinel:
transport:
dashboard: 127.0.0.1:8080
port: 9999
#dashboard: 8080 控制台端口
#port: 9999 本地启的端口,随机选个不能被占用的,与dashboard进行数据交互,会在应用对应的机器上启动一个 Http Server,该 Server 会与 Sentinel 控制台做交互, 若被占用,则开始+1一次扫描
流量控制
-
流量控制(flow control)
- 原理是监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。
-
两种规则
- 基于统计并发线程数的流量控制
并发数控制用于保护业务线程池不被慢调用耗尽 Sentinel 并发控制不负责创建和管理线程池,而是简单统计当前请求上下文的线程数目(正在执行的调用数目) 如果超出阈值,新的请求会被立即拒绝,效果类似于信号量隔离。
- 基于统计QPS的流量控制
当 QPS 超过某个阈值的时候,则采取措施进行流量控制
-
控制面板介绍
- 资源名:默认是请求路径,可自定义
- 针对来源:对哪个微服务进行限流,默认是不区分来源,全部限流,这个是针对 区分上游服务进行限流, 比如 视频服务 被 订单服务、用户服务调用,就可以针对来源进行限流
-
流量控制的效果包括以下几种:
- 直接拒绝:默认的流量控制方式,当QPS超过任意规则的阈值后,新的请求就会被立即拒绝
- Warm Up:冷启动/预热,如果系统在此之前长期处于空闲的状态,我们希望处理请求的数量是缓步的增多,经过预期的时间以后,到达系统处理请求个数的最大值
-
匀速排队:严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法,主要用于处理间隔性突发的流量,如消息队列,想象一下这样的场景,在某一秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求
- 注意:
- 匀速排队等待策略是 Leaky Bucket 算法结合虚拟队列等待机制实现的。
- 匀速排队模式暂时不支持 QPS > 1000 的场景
- 注意:
-
流控文档
熔断降级
Sentinel熔断降级规则
-
备注:如果 簇点链路 没数据,刷多几次接口
-
熔断降级(虽然是两个概念,基本都是互相配合)
- 对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一
- 对不稳定的弱依赖服务调用进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩
- 熔断降级作为保护自身的手段,通常在客户端(调用端)进行配置
-
什么是Sentinel降级规则
- 文档:https://github.com/alibaba/Sentinel/wiki/熔断降级
- 就是配置一定规则,然后满足之后就对服务进行熔断降级
-
Sentinel 熔断策略
-
慢调用比例(响应时间): 选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用
- 比例阈值:修改后不生效-目前已经反馈给官方那边的bug
- 熔断时长:超过时间后会尝试恢复
- 最小请求数:熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断
-
异常比例:当单位统计时长内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断
- 比例阈值
- 熔断时长:超过时间后会尝试恢复
- 最小请求数:熔断触发的最小请求数,请求数小于该值时,即使异常比率超出阈值也不会熔断
-
异常数:当单位统计时长内的异常数目超过阈值之后会自动进行熔断
-
异常数:
-
熔断时长:超过时间后会尝试恢复
-
最小请求数:熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断
-
-
熔断状态和恢复
-
服务熔断一般有三种状态
-
熔断关闭(Closed)
- 服务没有故障时,熔断器所处的状态,对调用方的调用不做任何限制
-
熔断开启(Open)
- 后续对该服务接口的调用不再经过网络,直接执行本地的fallback方法
-
半熔断(Half-Open)
- 所谓半熔断就是尝试恢复服务调用,允许有限的流量调用该服务,并监控调用成功率
-
-
熔断恢复:
- 经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态)尝试恢复服务调用,允许有限的流量调用该服务,并监控调用成功率。
- 如果成功率达到预期,则说明服务已恢复,进入熔断关闭状态;如果成功率仍旧很低,则重新进入熔断状态
Sentinel自定义异常降级
- 默认降级返回数据问题
- 限流和熔断返回的数据有问题-
- 微服务交互基本都是json格式,如果让自定义异常信息
- AlibabCloud版本升级,不兼容问题
- v2.1.0到v2.2.0后,Sentinel里面依赖进行了改动,且不向下兼容
- 自定义降级返回数据
- 【旧版】实现UrlBlockHandler并且重写blocked方法
@Component
public class XdclassUrlBlockHandler implements UrlBlockHandler {
@Override
public void blocked(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws IOException {
//降级业务处理
}
}
- 【新版】实现BlockExceptionHandler并且重写handle方法
public class XdclassUrlBlockHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
//降级业务处理
}
}
-
异常种类
FlowException //限流异常 DegradeException //降级异常 ParamFlowException //参数限流异常 SystemBlockException //系统负载异常 AuthorityException //授权异常
-
【新版】实现BlockExceptionHandler并且重写handle方法
-
代码路径:src/main/java/net/xdclass/config/XdclassBlockExceptionHandler.java
@Component
public class XdclassUrlBlockHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws IOException {
Map<String,Object> backMap=new HashMap<>();
if (e instanceof FlowException){
backMap.put("code",-1);
backMap.put("msg","限流-异常啦");
}else if (e instanceof DegradeException){
backMap.put("code",-2);
backMap.put("msg","降级-异常啦");
}else if (e instanceof ParamFlowException){
backMap.put("code",-3);
backMap.put("msg","热点-异常啦");
}else if (e instanceof SystemBlockException){
backMap.put("code",-4);
backMap.put("msg","系统规则-异常啦");
}else if (e instanceof AuthorityException){
backMap.put("code",-5);
backMap.put("msg","认证-异常啦");
}
// 设置返回json数据
httpServletResponse.setStatus(200);
httpServletResponse.setHeader("content-Type","application/json;charset=UTF-8");
httpServletResponse.getWriter().write(JSON.toJSONString(backMap));
}
}
使用Feign整合Sentinel配置实战
整合步骤
- 加入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
- 开启Feign对Sentinel的支持
feign:
sentinel:
enabled: true
- 创建容错类, 实现对应的服务接口, 记得加注解 @Service
@Service
public class VideoServiceFallback implements VideoService {
@Override
public Video findById(int videoId) {
Video video = new Video();
video.setTitle("熔断降级数据");
return video;
}
@Override
public Video saveVideo(Video video) {
return null;
}
}
- 配置feign容错类
@FeignClient(value = "xdclass-video-service", fallback = VideoServiceFallback.class)
Gateway
微服务的网关和应用场景
-
什么是网关
-
API Gateway,是系统的唯一对外的入口,介于客户端和服务器端之间的中间层,处理非业务功能 提供路由请求、鉴权、监控、缓存、限流等功能
-
统一接入
- 智能路由
- AB测试、灰度测试
- 负载均衡、容灾处理
- 日志埋点(类似Nignx日志)
-
流量监控
- 限流处理
- 服务降级
-
安全防护
- 鉴权处理
- 监控
- 机器网络隔离
-
-
主流的网关
- zuul:是Netflix开源的微服务网关,和Eureka,Ribbon,Hystrix等组件配合使用,依赖组件比较多,性能教差
- kong: 由Mashape公司开源的,基于Nginx的API gateway
-
nginx+lua:是一个高性能的HTTP和反向代理服务器,lua是脚本语言,让Nginx执行Lua脚本,并且高并发、非阻塞的处理各种请求
-
springcloud gateway: Spring公司专门开发的网关,替代zuul
-
注意:AlibabaCloud全家桶还没对应的网关,暂用SpringCloud官方推荐的Gateway
SpringCloud Gateway
-
Spring官方出品,基于Spring5+Reactor技术开发的网关
-
性能强劲基于Reactor+WebFlux、功能多样
-
基于springboot2.x, 直接可以jar包方式运行
-
官方文档
Gateway项目创建和依赖添加
创建Gateway项目
- 添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
配置
server:
port: 8888
spring:
application:
name: api-gateway
cloud:
gateway:
routes: #数组形式
- id: order-service #路由唯一标识
uri: http://127.0.0.1:8000 #想要转发到的地址
order: 1 #优先级,数字越小优先级越高
predicates: #断言 配置哪个路径才转发
- Path=/order-server/**
filters: #过滤器,请求在传递过程中通过过滤器修改
- StripPrefix=1 #去掉第一层前缀
#访问路径 http://localhost:8888/order-server/api/v1/video_order/list
#转发路径 http://localhost:8000/order-server/api/v1/video_order/list
#需要过滤器去掉前面第一层
Gateway整合Nacos
-
原先存在的问题
- 微服务地址写死
- 负载均衡没做到
-
添加Nacos服务治理配置
- 网关添加naocs依赖
<!--添加nacos客户端--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
- 启动类开启支持
@EnableDiscoveryClient
- 修改配置文件
server: port: 8888 spring: application: name: api-gateway cloud: nacos: discovery: server-addr: 127.0.0.1:8848 gateway: routes: #数组形式 - id: order-service #路由唯一标识 #uri: http://127.0.0.1:8000 #想要转发到的地址 uri: lb://xdclass-order-service # 从nacos获取名称转发,lb是负载均衡轮训策略 predicates: #断言 配置哪个路径才转发 - Path=/order-server/** filters: #过滤器,请求在传递过程中通过过滤器修改 - StripPrefix=1 #去掉第一层前缀 discovery: locator: enabled: true #开启网关拉取nacos的服务 ## 访问路径 http://localhost:8888/order-server/api/v1/video_order/list
内置路由断言
-
Gateway路由断言
- Predicate 来源于Java8,接受输入参数,返回一个布尔值结果
- Spring Cloud Gateway 中 Spring 利用 Predicate 的特性实现了各种路由匹配规则
- 转发的判断条件,SpringCloud Gateway支持多种方式,常见如:Path、Query、Method、Header等
- 支持多个
Predicate
请求的转发是必须满足所有的Predicate
后才可以进行路由转发
-
内置路由断言介绍 RoutePredicateFactory 接口实现类
-
参数编写规则 XXXRoutePredicateFactory,使用XXX作为参数配置, 例如下面
predicates:
- Host=
- Path=
- Method=
- Header=
- Query=
- Cookie=
-
需求:接口需要在指定时间进行下线,过后不可以在被访问
- 使用Before ,只要当前时间小于设定时间,路由才会匹配请求
- 东8区的2020-09-11T01:01:01.000+08:00后,请求不可访问
- 为了方便测试,修改时间即可
predicates: - Before=2020-09-09T01:01:01.000+08:00
过滤器
-
什么是网关的过滤器
-
过滤器生命周期
- PRE: 这种过滤器在请求被路由之前调用,一般用于鉴权、限流等
- POST:这种过滤器在路由到微服务以后执行,一般用于修改响应结果,比如增加header信息、打点结果日志
-
网关过滤器分类
- 局部过滤器GatewayFilter:应用在某个路由上,每个过滤器工厂都对应一个实现类,并且这些类的名称必须以 GatewayFilterFactory 结尾
- 全局过滤器:作用全部路由上,
-
内置很多局部过滤器,顶级接口 GatewayFilterFactory,
- 内置很多全局过滤器,顶级接口 GlobalFilter
过滤器实现用户鉴权
代码路径:src/main/java/net/xdclass/filter/UserGlobalFilter.java
@Component
public class UserGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//业务逻辑
String token = exchange.getRequest().getHeaders().getFirst("token");
if (StringUtils.isBlank(token)){
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
//继续往下执行
return chain.filter(exchange);
}
//数字越⼩,优先级越高
@Override
public int getOrder() {
return 0;
}
}
Zipking
Ecs容器化部署
服务部署
# docker拉取镜像
docker pull nacos/nacos-server
# 查看镜像
docker images
# 启动Nacos
docker run --env MODE=standalone --name xdclass-nacos -d -p 8848:8848 ef8e53226440 (镜像id)
# 查看日志
docker logs -f
http://公网ip:8848/nacos
# 登录密码默认nacos/nacos
# docker拉取镜像
docker pull openzipkin/zipkin:latest
# 查看镜像
docker images
# 启动Nacos
docker run --name xdclass-zipkin -d -p 9411:9411 镜像id
#访问zipkin
http://公⽹ip:9411/zipkin/
# docker拉取镜像
docker pull openzipkin/zipkin:latest
# 查看镜像
docker images
# 启动Nacos
docker run --name sentinel -d -p 8858:8858 镜像id
http://公⽹ip:8858
# 登录密码默认sentinel/sentinel
微服务本地镜像打包配置
- 父项目springboot版本依赖
<properties>
<java.version>11</java.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring.boot.version>2.3.3.RELEASE</spring.boot.version>
</properties>
- 每个子模块项目添加依赖
<properties>
<!--配置文件增加-->
<docker.image.prefix>xdclass-cloud</docker.image.prefix>
</properties>
<build>
<finalName>alibaba-cloud-video</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.10</version>
<configuration>
<repository>${docker.image.prefix}/${project.artifactId}</repository>
<buildArgs>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
</plugins>
</build>
- Spotify 的 docker-maven-plugin 插件是用maven插件方式构建docker镜像的
${project.build.finalName} 产出物名称,缺省为
${project.artifactId}-${project.version}
镜像打包脚本Dockerfile
- 创建Dockerfile,默认是根目录,(可以修改为src/main/docker/Dockerfile,如果修则需要制定路径)
- 什么是Dockerfile
- 由一系列命令和参数构成的脚本,这些命令应用于基础镜像, 最终创建一个新的镜像
FROM adoptopenjdk/openjdk11:ubi
VOLUME /tmp
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
FROM <image>:<tag> 需要一个基础镜像,可以是公共的或者是私有的,
后续构建会基于此镜像,如果同一个Dockerfile中建立多个镜像时,可以使用多个FROM指令
VOLUME 配置一个具有持久化功能的目录,主机 /var/lib/docker 目录下创建了一个临时文件,并链接到容器的/tmp。改步骤是可选的,如果涉及到文件系统的应用就很有必要了。
/tmp目录用来持久化到 Docker 数据文件夹,因为 Spring Boot 使用的内嵌 Tomcat 容器默认使用/tmp作为工作目录
ARG 设置编译镜像时加入的参数, JAR_FILE 是设置容器的环境变量(maven里面配置的)
COPY : 只支持将本地文件复制到容器 ,还有个ADD更强大但复杂点
ENTRYPOINT 容器启动时执行的命令
EXPOSE 8080 暴露镜像端口
- 构建镜像( 去到子模块pom文件下)
mvn install '-Dmaven.test.skip=true' dockerfile:build
阿里云私有镜像仓库
镜像加速器
https://cr.console.aliyun.com/cn-shenzhen/instances/mirrors
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://hhp6jcc1.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
镜像操作
docker login --username=caichuanliang001 registry.cn-shenzhen.aliyuncs.com
docker tag 8d8ddf384e5e registry.cn-shenzhen.aliyuncs.com/xdclass-ccl-cloud/cloud-order:v1.0
docker push registry.cn-shenzhen.aliyuncs.com/xdclass-ccl-cloud/cloud-order:v1.0
docker pull registry.cn-shenzhen.aliyuncs.com/xdclass-ccl-cloud/cloud-order:v1.0
docker tag db884f16b7ea registry.cn-shenzhen.aliyuncs.com/xdclass-ccl-cloud/cloud-gateway:v1.0
docker push registry.cn-shenzhen.aliyuncs.com/xdclass-ccl-cloud/cloud-gateway:v1.0
docker pull registry.cn-shenzhen.aliyuncs.com/xdclass-ccl-cloud/cloud-gateway:v1.0
docker tag aae2b626b4c8 registry.cn-shenzhen.aliyuncs.com/xdclass-ccl-cloud/cloud-video:v1.0
docker push registry.cn-shenzhen.aliyuncs.com/xdclass-ccl-cloud/cloud-video:v1.0
docker pull registry.cn-shenzhen.aliyuncs.com/xdclass-ccl-cloud/cloud-video:v1.0
docker run --name xdclass-video -d -p 9000:9000 aae2b626b4c8
docker run --name xdclass-order -d -p 8001:8001 8d8ddf384e5e
docker run --name xdclass-gateway -d -p 8888:8888 db884f16b7ea