# (一)前言 {#一-前言}
如今微服务架构已经被炒的如火如荼,互联网公司况且不说,连我接触的一个国企现在都开始往微服务分布式架构发展。因此,我会通过最近几篇博客介绍目前比较流行的一些微服务组件,其实微服务并没有那么难。如果在跑项目过程中,想要知道整个项目的所有依赖pom文件或者任何疑问,直接联系我即可。
# (二)SpringCloudAlibaba {#二-springcloudalibaba}
以前一直听人说SpringCloud,现在又冒出来一个Spring Cloud Alibaba,其实Spring Cloud Alibaba是Spring Cloud下的一个子项目。Spring Cloud不是一个新的框架,而是一系列框架的集合 ,Spring Cloud Alibaba同样如此。按照官方的说法,Spring Cloud Alibaba为分布式应用程序开发提供了一站式解决方案,它包含开发分布式应用程序所需的所有组件,使您可以轻松地使用Spring Cloud开发应用程序,总结一句话,Spring Cloud Alibaba可以让分布式开发更加简单,并且他提供的开源组件也经历了双十一的洗礼,绝对是如今分布式系统开发的首要选择。
SpringCloudAlibaba中的开源组件有:Nacos Discovery、Nacos Config、Sentinel、RocketMQ、Dubbo Spring Cloud。
官网如下:https://spring.io/projects/spring-cloud-alibaba/
# (三)Nacos {#三-nacos}
Nacos是alibaba开源的一个动态服务发现、配置管理和服务管理平台,Nacos约等于eureka+springcloudconfig。
所谓服务发现,其实就是指服务的提供者将服务注册到一个统一的平台,服务的消费者从这个统一的平台中获取服务进行调用。
Nacos就提供了这样一个服务注册中心的平台,而且基于SpringBoot开发,十分简单。
所谓配置中心,就是将项目中的一系列配置(那些原本写在application.properties配置),放到一个统一的平台,就不需要给每个微服务都重新配置,也更加方便管理。
以上两点就是Nacos的功能,了解Nacos能做什么之后,接下来就是代码实践了。在此之前先安装Nacos,我用的是linux版本。
给出Nacos的下载地址:我下载的是最新的1.4.1版本
https://github.com/alibaba/nacos/releases
上传到linux系统上后,先部署:
tar -zxvf nacos-server-1.4.1.tar.gz -C /usr/local/
进到/usr/local/,启动服务,单机环境下需要加上参数-m standalone
./startup.sh -m standalone
可以通过启动的sh文件看到原因:不加standalone参数情况下启动的是集群服务
if [[ "${MODE}" == "standalone" ]]; then
echo "nacos is starting with standalone"else
echo "nacos is starting with cluster"fi
启动后访问:http://ip:8848/nacos/ 即可进入nacos管理页面,默认登陆名和密码都是nacos
# (四)Nacos实现服务注册发现中心 {#四-nacos实现服务注册发现中心}
# 4.1 服务注册 {#_4-1-服务注册}
Nacos通过简单的注解,就可以快速注册服务,首先Nacos依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>
在application.properties中配置nacos的地址、用户名以及密码:
server.port=8081spring.application.name=nacos-discovery-provider
## 单机环境下
spring.cloud.nacos.discovery.server-addr=192.168.78.128:8848#集群环境下,地址逗号分开
#spring.cloud.nacos.discovery.server-addr=192.168.78.128:8848,192.168.78.129:8848spring.cloud.nacos.username=nacos
spring.cloud.nacos.password=nacos
接着在启动类中增加一个开启注解
@EnableDiscoveryClient //开启服务注册发现
在这里实现一个最简单的接口:
@RestControllerpublic class IndexController {
@GetMapping("/{name}")
public String index(@PathVariable("name") String name){
return "provider "+name;
}}
启动服务后就可以在Nacos的管理页面中看到注入的服务
# 4.2 调用服务 {#_4-2-调用服务}
前面已经把一个服务注册到Nacos,接下来需要用另外一个服务去调用它,调用方式有很多,这里主要介绍两种:由于调用中会用到feign和ribbon,先引入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId></dependency><dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId></dependency>
通过RestTemplate调用 首先在启动类中将RestTemplate注入到Bean容器中:
@LoadBalanced //负载均衡@Beanpublic RestTemplate restTemplate(){
return new RestTemplate();}
然后在代码中直接通过服务名称调用即可
@Slf4j@RestControllerpublic class TestController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/rest/{name}")
public String etIndex2(@PathVariable("name")String name){
String url="http://nacos-discovery-provider/"+name;
return restTemplate.getForObject(url,String.class);
}}
通过feign调用
在启动类时开启注解**@EnableFeignClients**
使用方式也很简单,三个步骤
建立对应于服务提供者的接口:
@FeignClient(name = "nacos-discovery-provider",fallback = TestServiceFallback.class,configuration = FeignConfiguration.class)public interface TestService {
@GetMapping("/{name}")
String index(@PathVariable("name") String string);}
TestServiceFallback对应于报错回调
public class TestServiceFallback implements TestService{
@Override
public String index(String string) {
return null;
}}
FeignConfiguration将回调类注入到Bean容器中
public class FeignConfiguration {
@Bean
public TestServiceFallback testServiceFallback(){
return new TestServiceFallback();
}}
最后在Controller中调用Feign接口:
@Slf4j@RestControllerpublic class TestController {
@Autowired
private TestService testService;
@GetMapping("/feign/{str}")
public String etIndex3(@PathVariable("str")String string){
return testService.index(string);
}}
# 4.3 在代码中获取Nacos服务的数据 {#_4-3-在代码中获取nacos服务的数据}
有时候在业务逻辑中需要获取到Nacos中服务的列表以及详细信息,可以通过DiscoveryClient来实现
@Slf4j@RestControllerpublic class TestController {
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("/services/{services}")
public Object getService(@PathVariable("services")String services){
log.info(String.valueOf(discoveryClient.getServices()));
return discoveryClient.getInstances(services);
}}
注意点:如果Nacos服务宕机了,以前已经调用过的接口依旧可以被调用,因为Nacos客户端会缓存调用信息。
# (五)Nacos作为配置中心 {#五-nacos作为配置中心}
Nacos提供用于存储配置和其他元数据的key/value存储,为分布式系统中的外部化配置提供服务器端和客户端支持。Nacos-config的核心依赖是:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency>
首先在配置中心新建一行配置
具体内容如下:
如果在SpringBoot项目中要使用配置中心的话,需要新建一个bootstrap.properties配置文件,在配置文件中配置相关信息:
server.port=8084spring.application.name=nacos-discovery-config
spring.cloud.nacos.username=nacos
spring.cloud.nacos.password=nacos
spring.cloud.nacos.discovery.server-addr=192.168.78.128:8848spring.cloud.nacos.config.server-addr=192.168.78.128:8848#如果需要使用yaml格式的,需要在配置文件中进行文件类型扩展
#spring.cloud.nacos.config.file-extension=yaml
接着就可以在代码中使用配置文件了,具体如何使用配置文件方式和使用本地配置文件一样,这里介绍一种:
@RestControllerpublic class TestController {
@Value("${user.name}")
private String name;
@Value("${user.addr}")
private String addr;
@GetMapping("/config")
public String config(){
return name+"----------"+addr;
}}
# 配置中心的多环境版本 {#配置中心的多环境版本}
在之前使用springboot时,我们会新建多个配置文件,如application-dev.properties、application-test.properties ,然后使用spring.profiles.active=dev去激活对应的配置文件。
在Nacos中,同样也可以这样操作,新建一个dev的配置文件:注意命名需要加后缀,不然获取不到
bootstrap.properties中去激活:
spring.profiles.active=dev
这样访问的就是${spring.application.name}-${spring.profiles.active}.${file-extension}文件了。
# Nacos服务配置数据模型 {#nacos服务配置数据模型}
Nacos的配置中心在权限隔离上有三个概念,命名空间、组(Group)、Data ID,这三个概念都是用来隔离区分的,可以在代码中指定对应的命名空间、组和Data ID,来获取到唯一的配置文件。
在代码中可以配置命名空间、组信息,从而选择适合该应用的配置文件。
#配置组
spring.cloud.nacos.config.group=My_GROUP#配置命名空间
spring.cloud.nacos.config.namespace=9464c719-e93b-414f-a904-2f21ec540178
# (六)Nacos数据持久化 {#六-nacos数据持久化}
Nacos中的数据默认是保存在内嵌数据库中的,0.7版本后增加了mysql数据库的支持。新建一个数据库,我这里命名为nacos_config,然后执行官方的sql语句:
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*//******************************************//* 数据库全名 = nacos_config *//* 表名称 = config_info *//******************************************/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 '2010-05-05 00:00:00' COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
`src_user` text COMMENT 'source user',
`src_ip` varchar(20) 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 '2010-05-05 00:00:00' COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
`src_user` text COMMENT 'source user',
`src_ip` varchar(20) 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 '2010-05-05 00:00:00' COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
`src_user` text COMMENT 'source user',
`src_ip` varchar(20) 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 '2010-05-05 00:00:00' COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' 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 '2010-05-05 00:00:00',
`gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00',
`src_user` text,
`src_ip` varchar(20) 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 '2010-05-05 00:00:00' COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' 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,
constraint uk_username_role UNIQUE (username,role));CREATE TABLE permissions (
role varchar(50) NOT NULL,
resource varchar(512) NOT NULL,
action varchar(8) NOT NULL,
constraint uk_role_permission UNIQUE (role,resource,action));INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');
执行完成后会创建一系列的表,接下来在nacos的配置文件(conf/application.properties)中配置数据库连接:
spring.datasource.platform=mysql
### Count of DB:db.num=1### Connect URL of DB:db.url.0=jdbc:mysql://192.168.199.170:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTCdb.user.0=root
db.password.0=123456
配置完成后所有的数据都会放在外部的Mysql中了。
# (七)总结 {#七-总结}
至此,你已经可以将Nacos放到具体的项目中使用了。等真正在项目中用过一段时间后,再去探究它的源码,将会更加简单。你会累是因为你在走上坡路,我们下期再见!