如今微服務架構已經被炒的如火如荼,網際網路公司況且不說,連我接觸的一個國企現在都開始往微服務分布式架構發展。因此,我會通過最近幾篇博客介紹目前比較流行的一些微服務組件,其實微服務並沒有那麼難。如果在跑項目過程中,想要知道整個項目的所有依賴pom文件或者任何疑問,直接聯繫我即可。
(二)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/
(三)NacosNacos是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實現服務註冊發現中心4.1 服務註冊Nacos通過簡單的註解,就可以快速註冊服務,首先Nacos依賴:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>在application.properties中配置nacos的地址、用戶名以及密碼:
server.port=8081
spring.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:8848
spring.cloud.nacos.username=nacos
spring.cloud.nacos.password=nacos接著在啟動類中增加一個開啟註解
@EnableDiscoveryClient //開啟服務註冊發現在這裡實現一個最簡單的接口:
@RestController
public class IndexController {
@GetMapping("/{name}")
public String index(@PathVariable("name") String name){
return "provider "+name;
}
}啟動服務後就可以在Nacos的管理頁面中看到注入的服務
服務註冊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 //負載均衡
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}然後在代碼中直接通過服務名稱調用即可
@Slf4j
@RestController
public 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
@RestController
public class TestController {
@Autowired
private TestService testService;
@GetMapping("/feign/{str}")
public String etIndex3(@PathVariable("str")String string){
return testService.index(string);
}
}
4.3 在代碼中獲取Nacos服務的數據有時候在業務邏輯中需要獲取到Nacos中服務的列表以及詳細信息,可以通過DiscoveryClient來實現
@Slf4j
@RestController
public 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提供用於存儲配置和其他元數據的key/value存儲,為分布式系統中的外部化配置提供伺服器端和客戶端支持。Nacos-config的核心依賴是:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>首先在配置中心新建一行配置
具體內容如下:
如果在SpringBoot項目中要使用配置中心的話,需要新建一個bootstrap.properties配置文件,在配置文件中配置相關信息:
server.port=8084
spring.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:8848
spring.cloud.nacos.config.server-addr=192.168.78.128:8848
#如果需要使用yaml格式的,需要在配置文件中進行文件類型擴展
#spring.cloud.nacos.config.file-extension=yaml接著就可以在代碼中使用配置文件了,具體如何使用配置文件方式和使用本地配置文件一樣,這裡介紹一種:
@RestController
public 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.profiles.active}.${file-extension}文件了。
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中的數據默認是保存在內嵌資料庫中的,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=UTC
db.user.0=root
db.password.0=123456配置完成後所有的數據都會放在外部的Mysql中了。
(七)總結至此,你已經可以將Nacos放到具體的項目中使用了。等真正在項目中用過一段時間後,再去探究它的源碼,將會更加簡單。你會累是因為你在走上坡路,我是魚仔,我們下期再見!