微服务:分布式架构(把服务做拆分,拆分中产生的问题需要解决,springcloud仅仅解决了服务拆分的治理问题,然后再部署在不同的的机器上去)的一种。根据业务功能,将单体架构的项目拆分一个一个的独立项目(即服务)。
技术栈
微服务治理
异步通信技术
缓存技术
搜索技术
持续集成
Dubbo | SpringCloud | SpringCloudAlibaba | |
---|---|---|---|
注册中心 | zookeeper、redis | Eureka、Consul | Nacos、Eureka |
远程调用(接口约定、协议等) | Dubbo协议 | Feign(http协议,restful) | Dubbo、Fegin |
配置中心 | 无 | SpringCloudConfig | SpringCloudConfig、Nacos |
服务网关 | 无 | SpringCloudGateway、Zuul | SpringCloudGateway、Zuul |
服务监控和保护 | dubbo-admin | Hystrix | Sentinel |
技术体系:SpringCloudAlibaba+Fegin 性价比高。
补充:REST实质:URL中只使用名词来定位资源,用HTTP协议里的动词(GET、POST、PUT、DELETE)来实现资源的增删改查操作。
RESTful 风格:
RESTFUL是一种网络应用程序的设计风格和开发方式,基于HTTP,可以使用 XML 格式定义或 JSON 格式定义。最常用的数据格式是JSON。由于JSON能直接被JavaScript读取,所以,使用JSON格式的REST风格的API具有简单、易读、易用的特点。
(14条消息) RESTful 风格(详细介绍 + 案例实现)_Yan Yang的博客-CSDN博客_restful风格
服务拆分:1、不同微服务,不要重复开发相同非业务;2、微服务数据独立,不要访问其他服务数据库;3、微服务可以将自己的业务接口暴露。
远程调用:本质是如何利用java发出对应的http请求。
步骤
提供者与消费者
提供者:提供被调用的接口的服务;消费者:调用其他服务接口的服务
一个服务既可以是提供者也可以是消费者
1、作用
1)解决消费者如何获取提供者信息。
2)解决多个提供者,消费则如何选择。
3)解决消费者如何感知提供者状态。
2、基本概念和原理
eureka角色分为服务端和客户端
3、eureka使用三步走 (eureka-server和eureka-client同理)
1)依赖
父工程中配置springboot版本支持的springcloud版本
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
<java.version>1.8java.version>
<spring-cloud.version>Hoxton.SR10spring-cloud.version>
<mysql.version>5.1.47mysql.version>
<mybatis.version>2.1.1mybatis.version>
properties>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
dependency>
2)注解启动:标注在主配置类下
@EnableEurekaServer
server:
port: 10086 #服务端口
spring:
application:
name: euraka-server #服务名称
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka #注册地址 eureka-server本身也是一个服务因此需要进行注册(自己注册自己),后面集群时需要多个服务端进行相互注册注册
4、eureka-client 拉取服务远程调用和负载均衡
修改负载均衡策略
第一种方法:全局配置,在当前服务下,不管当前服务远程调用哪一个服务均采用此策略。
第二种方法:可以选择对哪一个远程调用的服务采用此策略。
配置文件中修改
eureka-client-user: #远程调用的服务名称
ribbon: #负载均衡器
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #设置负载均衡策略
饥饿加载
基于上述的负载均衡执行流程,Ribbon在默认配置下采用懒加载,在第一次访问时才去创建LoadBalancerClient对象,请求时间长。
饥饿加载会在项目启动时创建。
配置:
ribbon:
eager-load:
clients: #指定饥饿加载服务名称
- eureka-client-user
enabled: true #开启饥饿加载
基本介绍:nacos是阿里巴巴的产品现在是springcloud中的一个组件,eureka2.x版本不再维护(没诞生),使用的1.x版本依旧在更新。
对于eureka来说nacos的服务端是独立于项目启动,只需要在客户端配置服务端的主机地址和端口即可。又因为nacos遵循springcloud的通用接口所以在代码层面上不需要做改动,只需要修改配置文件即可。
使用三步走
1)启动nacos
2)添加依赖
父工程中添加nacos整体版本信息
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-dependenciesartifactId>
<version>2.2.5.RELEASEversion>
<type>pomtype>
<scope>importscope>
dependency>
子工程中引入nacos客户端依赖(如果项目中还使用了eureka依赖,则需要注释掉)
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
3)配置配置文件(包括nacos服务地址+端口,如果存在eureka配置则需要注释掉)
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 #nacos注册中心(server端)地址+端口
注:如果在你的应用启动程序启动类加了@EnableEurekaClient
,需将其修改为@EnableDiscoveryClient
,或者索性删除。
服务分级模型
nacos中把原来一个服务对应多实例的结构多加了一个集群做划分变成一个服务可以有多个集群,每个集群下对应多个实例。这样做的目的是因为:假设将一个服务在不同地方做部署的话,用户访问不同地方的服务实例可能会出现延迟高等问题,这时将不同地方的服务的多个实例作为集群进行划分,不同地区的用户只访问当前地区集群下的服务实例,只有该集群中所有的服务实例挂掉后才去访问其他地区的集群中的服务实例,这样就把延迟降低了。
图示
服务分级模型的使用(降低不同地区远程调用服务延迟)
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 #nacos注册中心(server端)地址+端口
cluster-name: CQ #CQ代表该集群实在重庆
2)将不同地区部署的调用者设置集群(同上)
3)调用者调整负载均衡策略,使用Nacos的负载均衡策略(如果不使用Nacos的负载均衡策略,采用轮询或者随机都不能使集群生效)
userservice: #服务名
ribbon:
NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule #服务策略
注:如果本地集群全挂掉,跨集群访问nacos会给出警告信息
负载均衡:ribbon采用nacos负载均衡策略,有两种
环境隔离:不同于服务集群的不同,环境隔离是nacos提供的,其中服务和数据存储的最外层都有一个叫namespace的东西做隔离。
图示
不同命名空间下的服务无法访问
服务提供者检测机制不同:nacos对每个服务实例默认为临时实例,nacos对于临时实例与eureka一样采用30s发送心跳消息的心跳检测机制;对于非临时服务实例,nacos注册中心会主动询问其健康状态。
消费者服务列表更新方式不同:eureka让消费者每30s拉取一次服务列表;nacos除了采用该方式外,一旦注册中心发现有服务挂掉之后,立马通知消费者更新服务列表。
配置临时实例与非临时实例
spring:
cloud:
nacos:
discovery:
ephemeral: false #是否是临时实例,默认为true
统一配置管理:为了解决不同服务在升级或者需求变更情况下配置文件的修改问题,假如需要手动修改服务配置文件并生效,需要先关停服务、修改配置文件、重启服务,假如需要修改多个服务则此过程需要重复多次,整个流程下来耗时长且用户体验不好。因此统一配置管理可以把一些核心的配置、需要热更新(不用暂停服务)的配置进行统一管理,一旦配置完成重新发布,再由服务拉取配置即可。
使用步骤
1)在nacos服务端添加配置(Data ID命名规则:服务名+环境名.yaml),
并发布
2)服务拉取配置
2.1)在服务拉取配置时,服务是先从nacos获取配置(例:上文中的eureka-client-user-dev.yaml)再合并本地的配置(一边来说是application.xml中的配置),所以需要再读取本地配置前想办法获取nacos中配置。解决办法是利用bootstrap.yml,该配置文件的读取优先级是高于application的,可以把服务的地址、端口以及nocas的注册中心的地址和端口等拉取所需信息配置到bootstrap.yml中。
2.2)引入依赖
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
dependency>
2.3)配置bootstrap.yml(注意服务名称、环境要与Data Id一致,nacos注册中心地址+端口)
spring:
application:
name: eureka-client-user #服务名称
profiles:
active: dev #环境
cloud:
nacos:
discovery:
server-addr: localhost:8848 #nacos服务端地址+端口
ephemeral: false
cluster-name: CQ
config:
file-extension: yaml #文件后缀名
3)配置自更新:两种方式
4)多环境共享配置:nacos Data Id配置命名:服务名.yml即可
5)补充: 可以使用spring.cloud.nacos.config.enabled =false,来关闭Spring Cloud Nacos Config 配置功能。
物理内存小于启动时nacos的虚拟机内存设置
确保startup.sh/cmd启动脚本中JDK路径设置正确
MySql版本问题
本机nacos+nginx集群,服务注册不起问题
解决办法:1)如果是系统是windows首先查看本机hosts文件,看看有没有开启127.0.0.1 localhost本机域名解析。如果没有开启那么cluster-conf与nginx中的配置均采用本机真实的ip地址,否则会出现服务注册失败的情况(微服务的服务发现配置无论是使用本机真实ip还是loclahost都不行)。如果你是采用127.0.0.1/localhost进行配置的话,所以要么修改配置文件中信息为真实ip,要么修改hosts文件开启本机域名解析。
解决办法:2)查看nacos下的cluster-conf下是否多出了一个地址,然后查看该IP地址是不是你电脑的真实IP地址,如果不是,查看是不是你的虚拟网卡地址并禁用。
nacos注册服务的时候报错server is DOWN now, please try again later!
nacos服务从单机到集群转换时,本地服务注册失败
本质是一个http客户端用来替代RestTemplate发出请求。
解决RestTemplate:url复杂可读性差;请求参数难以维护。
feign集成了Rabbon
使用步骤:
Feign的优化
Feign的最佳实践
网关作用:1、用户身份认证、权限校验;2、将用户请求路由到微服务,并实现负载均衡;3、给用户请求做限流。
问题:以前spring/springboot不是有安全框架做身份、权限验证吗?:现在是把业务流程按功能拆分成一个个的微服务,不能将所有的微服务都放开进行公共访问,所以安全验证统一交由网关去做去查看当前请求是否符合规范,网关身份相当于springmvc中的dispatchservlet对所有请求进行管理。
使用三步走:
Gateway断言(predicates)配置详解
路由过滤器
全局路由过滤器
简介:
定义一个全局过滤器
//@Order(-1) //设置当前过滤器执行优先级,值越小优先级越高
@Component //组件注册
public class AuthorizeFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//1 获取请求参数
ServerHttpRequest request = exchange.getRequest();
MultiValueMap<String, String> queryParams = request.getQueryParams();
//2.判断参数
String authorized = queryParams.getFirst("authorized");
//3
if(authorized != null && authorized.equals("admin"))
return chain.filter(exchange);//放行
else {//拦截
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.UNAUTHORIZED);//设置响应头
return response.setComplete();
}
}
@Override //同Order注解作用一样
public int getOrder() {
return -1;
}
}
过滤器执行顺序:之前我们学过的过滤器最终会转化成Gatewayfilter再进行排序。
跨域问题:出现在浏览器,微服务之间远程调用并没有问题。浏览器禁止请求发起者与服务端发生跨域ajax请求,被浏览器拦截。
同源策略:域名+端口一致。
解决办法:cors:浏览器先询问(询问即发出option请求,默认也是被拦截的)下服务端让不让这个请求跨域访问。
CentOS7安装DockerCompose:
Linux下需要通过命令下载:
# 安装
curl -L https://github.com/docker/compose/releases/download/1.23.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
如果下载速度较慢,或者下载失败,可以使用资料提供的docker-compose文件:
上传到宿主机/usr/local/bin/
目录。
修改文件权限:
# 修改权限
chmod +x /usr/local/bin/docker-compose
2.3.Base自动补全命令:
# 补全命令
curl -L https://raw.githubusercontent.com/docker/compose/1.29.1/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose
如果这里出现错误,需要修改自己的hosts文件:
#1、
echo "199.232.68.133 raw.githubusercontent.com" >> /etc/hosts
#2、
curl -L https://raw.githubusercontent.com/docker/compose/1.29.1/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose -k #-k表示不进行证书检查,这样就可以直接下载了
安装docker-compose:
虚拟机准备:virtualbox+vagrant下的centos7,最新版docker
1)IP构建
nacos服务名 | IP地址 | 端口 |
---|---|---|
my-gateway | 宿主机真实ip(192.168.56.10) | 10086 |
order-service | 192.168.56.10 | 8088 |
user-service | 192.168.56.10 | 8089 |
nacos节点 | IP地址 | 节点端口 |
---|---|---|
nacos1 | 宿主机真实ip(192.168.56.10) | 8845 |
nacos2 | 192.168.56.10 | 8846 |
nacos3 | 192.168.56.10 | 8847 |
nginx | IP地址:localhost | 监听端口:81 |
---|
2)准备基本容器
nacos2.0.2
docker pull nacos/nacos-server:2.0.2
nginx最新版
docker pull nginx
mysql8
docker pull mysql:5.7.33
3)创建挂载目录:
在/home目录下创建三个目录,用于挂载 docker 容器的数据卷。
mkdir -p /home/mysql
mkdir -p /home/nacos
mkdir -p /home/nacos-nginx
4)mysal nacos数据初始化(数据库名:naocs 用户:root 密码:123456)这里省略了mysql容器创建过程,但是后面我补充了如何使用docker-compose的编排文件启动容器。
CREATE TABLE `config_info` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(255) DEFAULT NULL,
`content` longtext NOT NULL COMMENT 'content',
`md5` varchar(32) DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`src_user` text COMMENT 'source user',
`src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
`app_name` varchar(128) DEFAULT NULL,
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
`c_desc` varchar(256) DEFAULT NULL,
`c_use` varchar(64) DEFAULT NULL,
`effect` varchar(64) DEFAULT NULL,
`type` varchar(64) DEFAULT NULL,
`c_schema` text,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = config_info_aggr */
/******************************************/
CREATE TABLE `config_info_aggr` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(255) NOT NULL COMMENT 'group_id',
`datum_id` varchar(255) NOT NULL COMMENT 'datum_id',
`content` longtext NOT NULL COMMENT '内容',
`gmt_modified` datetime NOT NULL COMMENT '修改时间',
`app_name` varchar(128) DEFAULT NULL,
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfoaggr_datagrouptenantdatum` (`data_id`,`group_id`,`tenant_id`,`datum_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='增加租户字段';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = config_info_beta */
/******************************************/
CREATE TABLE `config_info_beta` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
`content` longtext NOT NULL COMMENT 'content',
`beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps',
`md5` varchar(32) DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`src_user` text COMMENT 'source user',
`src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_beta';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = config_info_tag */
/******************************************/
CREATE TABLE `config_info_tag` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
`tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
`tag_id` varchar(128) NOT NULL COMMENT 'tag_id',
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
`content` longtext NOT NULL COMMENT 'content',
`md5` varchar(32) DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`src_user` text COMMENT 'source user',
`src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_tag';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = config_tags_relation */
/******************************************/
CREATE TABLE `config_tags_relation` (
`id` bigint(20) NOT NULL COMMENT 'id',
`tag_name` varchar(128) NOT NULL COMMENT 'tag_name',
`tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
`tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
`nid` bigint(20) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`nid`),
UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`),
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_tag_relation';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = group_capacity */
/******************************************/
CREATE TABLE `group_capacity` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID,空字符表示整个集群',
`quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
`usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
`max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
`max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数,,0表示使用默认值',
`max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
`max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_group_id` (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='集群、各Group容量信息表';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = his_config_info */
/******************************************/
CREATE TABLE `his_config_info` (
`id` bigint(64) unsigned NOT NULL,
`nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`data_id` varchar(255) NOT NULL,
`group_id` varchar(128) NOT NULL,
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
`content` longtext NOT NULL,
`md5` varchar(32) DEFAULT NULL,
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`src_user` text,
`src_ip` varchar(50) DEFAULT NULL,
`op_type` char(10) DEFAULT NULL,
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
PRIMARY KEY (`nid`),
KEY `idx_gmt_create` (`gmt_create`),
KEY `idx_gmt_modified` (`gmt_modified`),
KEY `idx_did` (`data_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='多租户改造';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = tenant_capacity */
/******************************************/
CREATE TABLE `tenant_capacity` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID',
`quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
`usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
`max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
`max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数',
`max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
`max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='租户容量信息表';
CREATE TABLE `tenant_info` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`kp` varchar(128) NOT NULL COMMENT 'kp',
`tenant_id` varchar(128) default '' COMMENT 'tenant_id',
`tenant_name` varchar(128) default '' COMMENT 'tenant_name',
`tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc',
`create_source` varchar(32) DEFAULT NULL COMMENT 'create_source',
`gmt_create` bigint(20) NOT NULL COMMENT '创建时间',
`gmt_modified` bigint(20) NOT NULL COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info';
CREATE TABLE `users` (
`username` varchar(50) NOT NULL PRIMARY KEY,
`password` varchar(500) NOT NULL,
`enabled` boolean NOT NULL
);
CREATE TABLE `roles` (
`username` varchar(50) NOT NULL,
`role` varchar(50) NOT NULL,
UNIQUE INDEX `idx_user_role` (`username` ASC, `role` ASC) USING BTREE
);
CREATE TABLE `permissions` (
`role` varchar(50) NOT NULL,
`resource` varchar(255) NOT NULL,
`action` varchar(8) NOT NULL,
UNIQUE INDEX `uk_role_permission` (`role`,`resource`,`action`) USING BTREE
);
INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);
INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');
5)使用nacos编排文件(可选也可参照网络手动启动)注意:#后的内容是注释。
version: "3"
services:
nacos1:
container_name: nacos-server01
hostname: nacos-server01
image: nacos/nacos-server:2.0.2
environment:
- MODE=cluster
- PREFER_HOST_MODE=hostname
- NACOS_SERVERS=nacos-server01:8848 nacos-server02:8848
- SPRING_DATASOURCE_PLATFORM=mysql
- MYSQL_SERVICE_HOST=192.168.56.10
- MYSQL_SERVICE_PORT=3306
- MYSQL_SERVICE_USER=root
- MYSQL_SERVICE_PASSWORD=123456
- MYSQL_SERVICE_DB_NAME=nacos
- JVM_XMS=128m
- JVM_XMX=128m
- JVM_XMN=128m
volumes:
- /home/nacos2/cluster-logs/nacos-server01:/home/nacos/logs
- /home/nacos2/init.d:/home/nacos/init.d
ports:
- 8845:8848 #使用docker根据镜像创建,没办法更改默认application.properties
# nacos会默认在当前naocs的端口上偏移1000和1001开启两个新端口,所以不能给nacos服务端配两个连续的端口。
- 9848:9848 #9845 客户端gRPC请求服务端端口,用于客户端向服务端发起连接和请求,
- 9849:9849 #9846 服务端gRPC请求服务端端口,用于服务间同步等
restart: on-failure
#为什么nacos1和2都是相同的端口?
#可能原因:1)在容器启动时,容器内的文件会被容器外的文件覆盖掉,从而配置失效。
#解决办法,使用命令手动启动一个单机版,拷贝单机的application,properties并修改其中的端口号为你像设定的端口(假设为8846),最后使用命令启动nacos容器再命令中把拷贝文件的目录进行挂载,同时还要指定端口为8846这样才能按照指定端口启动。
nacos2:
container_name: nacos-server02
hostname: nacos-server02
image: nacos/nacos-server:2.0.2
environment:
- MODE=cluster
- PREFER_HOST_MODE=hostname
- NACOS_SERVERS=nacos-server01:8848 nacos-server02:8848
- SPRING_DATASOURCE_PLATFORM=mysql
- MYSQL_SERVICE_HOST=192.168.56.10
- MYSQL_SERVICE_PORT=3306
- MYSQL_SERVICE_USER=root
- MYSQL_SERVICE_PASSWORD=123456
- MYSQL_SERVICE_DB_NAME=nacos
- JVM_XMS=128m
- JVM_XMX=128m
- JVM_XMN=128m
volumes:
- /home/nacos/cluster-logs/nacos-server02:/home/nacos/logs
- /home/nacos/init.d:/home/nacos/init.d
ports:
- 8847:8848
restart: on-failure
6)查看日志启动成功:
6)Nginx 的部署
Nginx 的部署与其他服务部署略有不同,我们需要先启动一个 Nginx 容器实例,然后从容器事例中拷贝出 Nginx 的配置文件到指定目录,之后我们将复制出的配置文件与 Nginx 容器的数据卷进行挂载,从而达到可以在容器外部修改配置文件的目的。这么做是因为,如果直接挂载,那么容器实例中的的目录将会被外部的挂载所覆盖(nacos同理)。这是官方 Nginx 镜像的一个小缺陷,注意一下就行了。
运行 Nginx 容器
$ docker run --name temp-nginx -p 8080:8080 -d nginx:1.21.1
在宿主机创建 Nginx 的挂载目录
# 实际创建时以自己的机器环境为准
$ mkdir -p <宿主机挂载目录>
拷贝容器中的配置到宿主机的挂载目录
$ docker cp :/etc/nginx/ <宿主机挂载目录>
#例如:docker cp :/etc/nginx/ /home/docker/nginx/
停止并删除容器实例
$ docker stop
$ docker rm
修改 Nginx 配置文件
位置:<宿主机挂载目录>/conf.d/default.conf
配置文件主要修改两个部分,一个是新增 upstream,通过负载均衡来配置 Nacos 服务的节点;第二个是修改 server 下的 location,在其中添加反向代理配置。另外,如果你的 Nginx 没有配置过 server_name,那么还需要修改 server 下的 server_name 配置。
下面给出两种配置:
-----------------------------------1、----------------------------------------
# 添加负载均衡配置
#因为上面nacos配置的都是8848端口所以这里也都使用8848
upstream nacos-cluster {
server nacos-server01:8848 weight=1 max_fails=2 fail_timeout=10s;
server nacos-server01:8848 weight=1 max_fails=2 fail_timeout=10s;
}
server {
#80端口可能会被其他应用占用保险起见还是改为81,当如如果80没用被占用仍可使用。
listen 81;
#listen [::]:80;
# 修改为宿主机的 IP地址
server_name 172.16.1.180;
#access_log /var/log/nginx/host.access.log main;
location / {
# 添加代理配置
proxy_pass http://nacos;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
add_header X-Cache $upstream_cache_status;
add_header Cache-Control no-cache;
#root /usr/share/nginx/html;
#index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
-------------------------------------2、--------------------------------------
#新增,为了演示,故不配置权重
upstream cluster {
server nacos-server01:8848;
server nacos-server02:8848;
}
server {
listen 81;
server_name 192.168.56.10;
#新增,配置nginx的日志级别debug
#error_log /var/log/nginx/debug.log debug;
#新增,转向集群配置
location /nacos {
proxy_pass http://cluster;
}
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
Nginx编排文件
version: "3"
services:
nacos-nginx:
container_name: nacos-nginx
image: nginx:1.21.1
volumes:
- /home/docker/nginx/nginx:/etc/nginx/
- /home/docker/nginx/www:/usr/share/nginx
ports:
- 8840:81
restart: on-failure
#重要说明:
#数据卷挂载 - 本例中分别将 Nginx 的配置文件目录和静态文件资源目录挂载到了宿主机,如果不需要#提供静态资源访问,可以不用挂载此目录。
#端口 - 本例中,为了避免与其他 Nginx 端口冲突,我们暴露的端口为 8840,其中 81 端口为容器#内部端口。
打来浏览器输入:http://
,如果显示如下界面,则说明部署成功。
7)微服务部署
修改application/bootsratp.yml中包含naccos服务发现配置(宿主机地址+nginx映射端口)
打包配置和Dockerfile文件
<build>
<finalName>appfinalName>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
将打包好的jar包复制到宿主机的指定目录下,并编写Dockerfile
Dockerfile:
FROM openjdk:8-alpine
COPY ./app.jar /tmp/app.jar
ENTRYPOINT java -jar /tmp/app.jar
进入/tmp/dockertest/my-gateway/下,运行Dockerfile构建新镜像:
docker build -t my-gateway:1.0 .
运行镜像:
docker run --name my-gateway01 up my-gateway:1.0
启动成功:
docker run -it \
--net=host \
--name nacos-8846 \
-e NACOS_SERVER_PORT=8846 \
-e NACOS_SERVERS="nacos-8846:8846 nacos-8850:8850" \
-e MODE=cluster \
-e SPRING_DATASOURCE_PLATFORM=mysql \
-e MYSQL_SERVICE_HOST=192.168.56.10 \
-e MYSQL_SERVICE_PORT=3306 \
-e MYSQL_SERVICE_DB_NAME=nacos \
-e MYSQL_SERVICE_USER=root \
-e MYSQL_SERVICE_PASSWORD=123456 \
-e JVM_XMS=256m \
-e JVM_XMX=256m \
-e JVM_XMN=256m \
-p 8846:8846 \
nacos/nacos-server:2.0.2
-v /home/docker/nacos/conf:/home/nacos/conf \
-v /home/docker/nacos/logs:/home/nacos/logs \
-v /home/docker/nacos/data:/home/nacos/data \
docker cp 容器名:/home/nacos/conf 宿主机目录(比如/home/docker/nacos/conf)
3)修改/home/docker/nacos/conf下的application.properties中的端口
4)挂载启动
docker run -it \
--net=host \
--name nacos-8846 \
-e NACOS_SERVER_PORT=8846 \
-e NACOS_SERVERS="nacos-8846:8846 nacos-8850:8850" \
-e MODE=cluster \
-e SPRING_DATASOURCE_PLATFORM=mysql \
-e MYSQL_SERVICE_HOST=192.168.56.10 \
-e MYSQL_SERVICE_PORT=3306 \
-e MYSQL_SERVICE_DB_NAME=nacos \
-e MYSQL_SERVICE_USER=root \
-e MYSQL_SERVICE_PASSWORD=123456 \
-e JVM_XMS=256m \
-e JVM_XMX=256m \
-e JVM_XMN=256m \
-p 8846:8846 \
-v /home/docker/nacos/conf:/home/nacos/conf \
-v /home/docker/nacos/logs:/home/nacos/logs \
-v /home/docker/nacos/data:/home/nacos/data \
nacos/nacos-server:2.0.2
容器日志查看是否成功:docker logs -f nacos-8846
mysql编排文件(可选)
version: "3"
services:
mysql:
container_name: mysql5
image: mysql:5.7.33
environment:
- MYSQL_ROOT_PASSWORD=ok
volumes:
- /home/mysql/conf:/etc/mysql
- /home/mysql/logs:/var/log/mysql
- /home/mysql/data:/var/lib/mysql
restart: on-failure
ports:
- 3306:3306
privileged: true
stdin_open: true
tty: true
使用编排部署 Nacos 集群(可选):
docker-compose -f <编排文件路径> up -d
踩坑1
成功安装了docker-compose,但是一直提示command not found…:
解决办法:
//(1)sudo curl -L https://github.com/docker/compose/releases/download/1.21.0/docker-compose-( u n a m e − s ) − (uname -s)-(uname−s)−(uname -m) -o /usr/local/bin/docker-compose
//(2)sudo chmod +x /usr/local/bin/docker-compose
(3)sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
(4) docker-compose --version
踩坑2
nacos-sever:v1.4.1和1.4.4运行不了:查看日志提示(Failed to bind properties under ‘server.tomcat.basedir’ to java.io.File)
只能采用手动启动:
docker run -d \
--net=host \
--restart=unless-stopped \
--name nacos-server-1.4 \
--env PREFER_HOST_MODE=hostname \
--env MODE=cluster \
--env NACOS_SERVERS=nacos-server01:8840,nacos-server02:8841 \
--env NACOS_SERVER_IP=192.168.56.10 \
--env SPRING_DATASOURCE_PLATFORM=mysql \
--env MYSQL_SERVICE_HOST=192.168.56.10 \
--env MYSQL_SERVICE_DB_NAME=nacos \
--env MYSQL_SERVICE_USER=root \
--env MYSQL_SERVICE_PASSWORD=123456 \
-p 8840:8840 \
nacos/nacos-server:1.4.1
踩坑3
nacos在运行时不能把其配置文件进行挂载否则会出错。
搭建私有仓库镜像
1)简单搭建
Docker官方的Docker Registry是一个基础版本的Docker镜像仓库,具备仓库管理的完整功能,但是没有图形化界面。
搭建方式比较简单,命令如下:
docker run -d \
--restart=always \
--name registry \
-p 5000:5000 \
-v registry-data:/var/lib/registry \
registry
命令中挂载了一个数据卷registry-data到容器内的/var/lib/registry 目录,这是私有镜像库存放数据的目录。
访问http://YourIp:5000/v2/_catalog 可以查看当前私有镜像服务中包含的镜像
2)带有图形化界面版本
使用DockerCompose部署带有图象界面的DockerRegistry,命令如下:
version: '3.0'
services:
registry:
image: registry
volumes:
- ./registry-data:/var/lib/registry
ui:
image: joxit/docker-registry-ui:static
ports:
- 8180:80
environment:
- REGISTRY_TITLE=我的私有仓库
- REGISTRY_URL=http://registry:5000
depends_on:
- registry
配置Docker信任地址
我们的私服采用的是http协议,默认不被Docker信任,所以需要做一个配置:
# 打开要修改的文件
vi /etc/docker/daemon.json
# 添加内容:
"insecure-registries":["http://192.168.56.10:8180"]
# 重加载
systemctl daemon-reload
# 重启docker
systemctl restart docker