Spring Cloud Alibaba 基本上替代了 Spring Cloud netflix。
Nacos:全称Dynamic Naming and Configuration Service
Naming Configuration service(前两个字符na和co,s就是service) 就拼成了nacos得简写。
Nacos官方解释:一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
官方地址:https://nacos.io/zh-cn/index.html
下载地址:https://github.com/alibaba/nacos/releases?page=1
本次使用的Nacos是1.1.4版本。
注意:Beta版本
是用户公开测试版本。
Nacos的使用:
对于项目要引入spring cloud alibaba:
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-dependenciesartifactId>
<version>2.1.0.RELEASEversion>
<type>pomtype>
<scope>importscope>
dependency>
第一步:创建项目,导依赖。
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
第二步:配置application.yml文件。
server:
port: 9001
spring:
application:
name: nacos-payment-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848 # 配置Nacos地址
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/db2019?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true
username: "root"
password: "0818"
management:
endpoint:
web:
exposure:
include: '*'
第三步:创建启动类。不要忘记添加@EnableDiscoveryClient注解。
package com.itholmes.springcloud.alibaba;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* @description: TODO
* @date: 2022/8/5 13:40
*/
@EnableDiscoveryClient
@SpringBootApplication
public class PaymentMain9001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain9001.class,args);
}
}
第四步:查看nacos网站是否有注册。
小技巧:
服务消费者创建流程:
第一步:创建项目,导入依赖。
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
<dependency>
<groupId>com.itholmes.springcloudgroupId>
<artifactId>cloud-api-commonsartifactId>
<version>${project.version}version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
第二步:创建application.yml文件,配置如下:
server:
port: 83
spring:
application:
name: nacos-order-consumer
cloud:
nacos:
discovery:
server-addr: 150.158.199.52:8848 # 配置Nacos地址
# 消费者将要去访问的微服务名称(注册成功进nacos的微服务提供者)
service-url:
nacos-user-service: http://nacos-payment-provider
第三步:创建启动类。
package com.itholmes.springcloud.alibaba;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* @description: TODO
* @date: 2022/8/5 22:04
*/
@EnableDiscoveryClient
@SpringBootApplication
public class OrderNacosMain83 {
public static void main(String[] args) {
SpringApplication.run(OrderNacosMain83.class,args);
}
}
第四步:编写配置类。
package com.itholmes.springcloud.alibaba.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class ApplicationContextConfig {
@Bean
@LoadBalanced // 不要忘记配置负载均衡,没有它启动不起来项目
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
第五步:写个controller,测试测试。
package com.itholmes.springcloud.alibaba.controlller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
/**
* @description: TODO
* @date: 2022/8/5 22:08
*/
@RestController
@Slf4j
public class OrderNacosController {
@Resource
private RestTemplate restTemplate;
@Value("${service-url.nacos-user-service}")
private String serverURL;
@GetMapping(value = "/consumer/payment/nacos/{id}")
public String paymentInfo(@PathVariable("id") Long id) {
return restTemplate.getForObject(serverURL + "/payment/nacos/" + id ,String.class);
}
}
什么是CAP?
Nacos 支持AP 和 CP模式的切换:
可以通过curl发送一个put请求,来切换CP。
URL指令:$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP 。
将nacos作为服务配置中心搭建项目:
第一步:创建项目,导入依赖。
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
第二步:配置bootstrap.yml,application.yml文件。
bootstrap.yml配置:
server:
port: 3377
spring:
application:
name: nacos-config-client
cloud:
nacos:
# 将Nacos作为服务注册中心地址
discovery:
server-addr: localhost:8848
# 将Nacos作为配置中心地址
config:
server-addr: localhost:8848
file-extension: yaml # 指定yaml格式的配置
# ${prefix}-${spring.profiles.active}.${file-extension} 根据公式就如下信息:
# nacos-config-client-dev.yaml
application.yml配置:
spring:
profiles:
active: dev # dev表示开发环境、test表示测试环境、prod表示生产环境,这是标准一点。
第三步:创建主启动类,不要忘记添加注解@EnableDiscoveryClient。
package com.itholmes.springcloud.alibaba;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* @description: TODO
* @date: 2022/8/6 11:00
*/
@EnableDiscoveryClient
@SpringBootApplication
public class NacosConfigClientMain3377 {
public static void main(String[] args) {
SpringApplication.run(NacosConfigClientMain3377.class,args);
}
}
第四步:创建业务类,通过Spring Cloud原生注解,@RefreshScope实现配置的自动更新。
package com.itholmes.springcloud.alibaba.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author: xuyanbo
* @description: TODO
* @date: 2022/8/6 11:14
*/
@RestController
@RefreshScope // 通过Spring Cloud原生注解,@RefreshScope实现配置的自动更新。
public class ConfigClientController {
@Value("${config.info}")
private String configInfo;
@GetMapping(value = "/config/info")
public String getConfigInfo(){
return configInfo;
}
}
第五步:按照规则来,在nacos配置Data ID。
官方给出的Nacos Spring Cloud的Data ID配置格式:
${prefix}-${spring.profiles.active}.${file-extension}
# 读下面图片的介绍,很重要!
nacos新建配置如下:
(注意这里要配置成yaml,不能配置为yml)
详细图:
第六步:编写业务类,测试,并且能够达到动态刷新的效果。
package com.itholmes.springcloud.alibaba.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @description: TODO
* @date: 2022/8/6 11:14
*/
@RestController
@RefreshScope // 通过Spring Cloud原生注解,@RefreshScope实现配置的自动更新。
public class ConfigClientController {
@Value("${config.info}")
private String configInfo;
@GetMapping(value = "/config/info")
public String getConfigInfo(){
return configInfo;
}
}
其实就是下图这样的关系:
默认情况:
场景如下:
默认空间 + 默认分组 + 新建dev和test的两个DataID实现:
通过spring.profile.active属性就能进行多环境下配置文件的读取。
通过这种方式就可以显示一个开发,测试,生产环境的一个替换。
依靠group分组来实现:
新建命名空间:
创建后,在配置列表,会多出创建好的命名空间来:
配置bootstrap和application配置文件:
Nacos要集群化,首先的问题是数据一致性问题,因为nacos存储是嵌入式数据库。
默认Nacos使用嵌入式数据库实现数据derby的存储。
因此,Nacos采用了集中式存储的方式来支持集群化部署
,目前支持MySQL的存储。
切换derby到mysql,通过是用mysql来进行持久化存储。
第一步:在nacos目录下面,有一个conf目录,找到对应的sql脚本。直接按照要求创建一个数据库,执行这些sql脚本。注意:mysql数据库要求5.6.5 + 以上的。
第二步:同样,在nacos服务目录的conf目录下有一个application.properties文件,修改application.properties文件。
第三步:重启Nacos,这样就切换到了mysql数据库存储。
踩坑-注意事项:
org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (Could not create connection to database server. Attempted reconnect 3 times. Giving up.)
at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:81)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:371)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:523)
at com.alibaba.nacos.config.server.service.BasicDataSourceServiceImpl$SelectMasterTask.run(BasicDataSourceServiceImpl.java:317)
at com.alibaba.nacos.config.server.service.BasicDataSourceServiceImpl.reload(BasicDataSourceServiceImpl.java:213)
at com.alibaba.nacos.config.server.service.BasicDataSourceServiceImpl.init(BasicDataSourceServiceImpl.java:131)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
解决方案:
完成上图,切换到nacos/bin目录,执行./startup.sh -m standalone命令,启动服务,就切换成功了。
如果报错是下面错误,是属于连接mysql数据库配置错误,连接mysql8.x需要加上时区)
Caused by: com.mysql.cj.exceptions.InvalidConnectionAttributeException: The server time zone value '???ú±ê×??±??' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61)
at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:85)
at com.mysql.cj.util.TimeUtil.getCanonicalTimezone(TimeUtil.java:132)
at com.mysql.cj.protocol.a.NativeProtocol.configureTimezone(NativeProtocol.java:2234)
at com.mysql.cj.protocol.a.NativeProtocol.initServerSession(NativeProtocol.java:2258)
at com.mysql.cj.jdbc.ConnectionImpl.initializePropsFromServer(ConnectionImpl.java:1319)
at com.mysql.cj.jdbc.ConnectionImpl.connectWithRetries(ConnectionImpl.java:868)
... 95 more
搭建Nacos集群,需要3个或3个以上Nacos节点才能构成集群。
按照上面的配置,切换好mysql持久化。
第一步:复制conf目录下的cluster.conf.example文件,文件名为cluster.conf文件。
第二步:编辑cluster.conf文件。
第三步:编辑startup.sh脚本,添加上能识别-p port端口。
1.先cp startup.sh startup.sh.bk做备份。
2.修改startup.sh脚本,如下信息。
3.接下来就可以通过./startup.sh -p xxxx 来启动定义端口号的nacos。
- 通过使用ps -ef | grep nacos | grep -v grep | wc -l命令来查看是否启动了nacos节点。
命令解释:
# 该命令可以查看我们启动了几台nacos节点
ps -ef | grep nacos | grep -v grep | wc -l
###### 以下对上面命令的解释:
# 查看进程
ps -ef
# 表示只查看包含nacos这个关键字的行内容
grep nacos
# 表示查看除了含有grep内容之外的行内容
grep -v grep
# wc 命令用于计算字数。
wc -l
# wc -c, --bytes:统计字节数。
# wc -m, --chars:统计字符数。
# wc -w, --words:统计字数。
# wc -l, --lines:统计行数。
# wc -L, --max-line-length:统计最长行的长度。
第四步:配置nginx对应nacos的几个端口。
第五步:启动服务,测试效果。