1. spring cloud概述
1.1 系统架构的演变
- 单体架构
所有业务模块都藕合在一个war包里,例如一个电商系统中,用户管理,商品管理等业务都部署在一个web容器中运行。
问题:代码藕合(代码修改难度大)、迭代困难(功能变更和修改bug困难)、扩展受限(只能整体性的进行扩展)、技术债务(需求变更和人员更迭导致技术债务堆积)
- 分布式架构
将原来一个项目应用按照业务逻辑进行拆分,提高系统整体性能。
问题:各模块之间存在重叠业务
- soa架构
将业务拆分成服务层和表现层并独立部署
问题:抽取粒度大,服务方和消费方藕合度高(必须先启动付服务方在启动消费方)
- 微服务
微服务的特征:
1.单一职责:微服务拆分粒度更小,做到单一职责
2.面向服务:微服务对外暴露Restful等轻量协议的接口
1.2 spring cloud
- 什么是spring cloud?
spring cloud是一套微服务开发的全家桶,spring cloud没有重复造轮子,只是基于springboot将其他公司(Netflix)的服务框架组合起来。
- 什么是spring cloud alibaba?
spring cloud = springboot + Netflix spring cloud alibaba = springboot + alibaba
-
springcloud、springcloud alibaba、springboot版本关系
Spring Boot和Spring Cloud的版本号如下:
Spring Boot版本号:https://spring.io/projects/spring-boot#learn
Spring Cloud版本号:https://spring.io/projects/spring-cloud#learn
Spring Cloud Alibaba版本号:https://spring.io/projects/spring-cloud-alibaba#learn
下表为按时间顺序发布的 Spring Cloud Alibaba 以及对应的适配 Spring Cloud 和 Spring Boot 版本关系:
Spring Cloud Alibaba Version | Spring Cloud Version | Spring Boot Version |
---|---|---|
2021.0.1.0 | Spring Cloud 2021.0.1 | 2.6.3 |
2.2.7.RELEASE | Spring Cloud Hoxton.SR12 | 2.3.12.RELEASE |
2021.1 | Spring Cloud 2020.0.1 | 2.4.2 |
2.2.6.RELEASE | Spring Cloud Hoxton.SR9 | 2.3.2.RELEASE |
2.1.4.RELEASE | Spring Cloud Greenwich.SR6 | 2.1.13.RELEASE |
2.2.1.RELEASE | Spring Cloud Hoxton.SR3 | 2.2.5.RELEASE |
2.2.0.RELEASE | Spring Cloud Hoxton.RELEASE | 2.2.X.RELEASE |
2.1.2.RELEASE | Spring Cloud Greenwich | 2.1.X.RELEASE |
2.0.4.RELEASE(停止维护,建议升级) | Spring Cloud Finchley | 2.0.X.RELEASE |
1.5.1.RELEASE(停止维护,建议升级) | Spring Cloud Edgware | 1.5.X.RELEASE |
2. 注册中心和配置中心nacos
2.1 nacos介绍
- 什么是nacos?
Nacos是阿里巴巴的一个注册中心,配置中心组件。
- nacos的启动器
spring-cloud-starter-alibaba-nacos-discovery
spring-cloud-starter-alibaba-nacos-config
2.2 nacos的安装和启动
1. 上传并解压
cd /usr/upload
tar -zxvf nacos-server-1.4.1.tar.gz -C /usr/local
2. 启动和关闭
启动:
cd /usr/local/nacos/bin
./startup.sh -m standalone
关闭:
cd /usr/local/nacos/bin
./shutdown.sh
3、测试
浏览器访问:http://192.168.209.129:8848/nacos
默认用户名/密码为:nacos/nacos
2.3 nacos注册中心(服务的ip和端口)
- 服务提供者:nacos_provider
<!--pom.xml文件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--nacos客户端-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.sanjin</groupId>
<artifactId>springcloud_common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--application.yml-->
server:
port: 8090
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.204.129:8848
application:
name: nacos-provider
@SpringBootApplication
@EnableDiscoveryClient//向注册中心注册该服务,并可以获取其他服务的调用地址
public class ProviderApp {
public static void main(String[] args) {
SpringApplication.run(ProviderApp.class);
}
}
- 服务消费者:nacos_consumer
<!--pom.xml文件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--nacos客户端-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.sanjin</groupId>
<artifactId>springcloud_common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--application.yml-->
server: 80
port:
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.204.129:8848
application:
name: nacos-consumer
@SpringBootApplication
@EnableDiscoveryClient//向注册中心注册该服务,并可以获取其他服务的调用地址
public class ConsumerApp {
public static void main(String[] args) {
SpringApplication.run(ConsumerApp.class);
}
}
- 测试
@RestController
@RequestMapping(value = "/consumer")
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
@RequestMapping(value="/getUserById/{id}")
public User getUserById(@PathVariable Integer id){
//获取nacos中注册的所有服务信息
List<String> serviceList = discoveryClient.getServices();
for (String service : serviceList) {
System.out.println(service);
}
//获取nacos中注册的指定服务信息
ServiceInstance instance = discoveryClient.getInstances("nacos-provider").get(0);
String serviceUrl = instance.getHost() + ":" + instance.getPort();
String url = "http://"+serviceUrl+"/provider/getUserById/"+id;
return restTemplate.getForObject(url, User.class);
}
}
2.4 nacos配置中心
- 集中管理配置文件
1. pom.xml
<!--pom.xml-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
2. bootstrap.yml
注:客户端配置文件的名称必须为bootstrap.yml
bootstrap.yml
比 applicaton.yml
优先加载,应用于系统级别参数配置,一般不会变动;
application.yml
应用于SpringBoot项目的自动化配置;
// bootstrap.yml
spring:
cloud:
nacos:
config: #(系统级别的配置)
server-addr: 192.168.204.129:8848 #配置中心的地址
prefix: nacos-config #默认值是spring.application.name
file-extension: yaml #默认值是properties
3. APP
// 启动类
@SpringBootApplication
@EnableDiscoveryClient // 向注册中心注册该服务并发现其他服务
public class NacosConfigApplication {
public static void main(String[] args) {
SpringApplication.run(NacosConfigApplication.class,args);
}
}
4. 在nacos中新建配置文件
Data Id:${spring.cloud.nacos.config.prefix}.${spring.cloud.nacos.config.file-extension}
5. controller测试
package com.bjpowernode.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;
@RestController
@RefreshScope //重新从BeanFactory获取一个新的实例(该实例使用新的配置)
public class ConfigController {
@Value("${spring.datasource.driver-class-name}")
private String driverClassName;
@Value("${spring.datasource.url}")
private String url;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
@Value("${spring.datasource.type}")
private String type;
@GetMapping("/config/info")
public String getConfigInfo() {
System.out.println(this);
String configInfo = driverClassName+"<br>"+url+"<br>"+username+"<br>"
+password+"<br>"+type;
return configInfo;
}
}
- 实时更新最新配置
利用上文中的controller进行测试
注意:添加logback.xml
原理:nacos监听MD5
- 配置隔离
Namespace: 代表不同的环境的配置隔离, 如: 开发、测试, 生产等
Group: 可以代表某个项目, 如XX医疗项目, XX电商项目
DataId: 每个项目下往往有若干个工程, 每个配置集(DataId)是一个工程的主配置文件
获取配置集需要指定:
nacos服务地址,必须指定
namespace,如不指定默认public
group,如不指定默认 DEFAULT_GROUP
dataId,必须指定
1. namespace隔离
1.1 新建namespace
1.2 克隆配置文件
1.3 读取配置文件
spring:
cloud:
nacos:
config:
server-addr: 192.168.204.129:8848
file-extension: yaml
prefix: nacos-config
namespace: dev(新建的namespace名称) #开发环境
2. group隔离
2.1 新建配置文件并修改Group名
2.2 不同的配置分组下可以有相同的配置
2.3 读取配置文件
spring:
cloud:
nacos:
config:
server-addr: 192.168.204.129:8848
file-extension: yaml
prefix: nacos-config
namespace: dev
group: springcloud_parent #nacos项目
3. 服务隔离
在服务中的application.yml文件添加namespace和group配置项即可
2.5 Nacos持久化
- 为什么要持久化?
nacos有自带嵌入式数据库derby,如果搭建集群则每台nacos的配置文件都不一样,导致数据不统一。
- 持久化
1. 切换数据库
vim /usr/local/nacos/conf/application.properties:
### If use MySQL as datasource:
spring.datasource.platform=mysql### Count of DB:
db.num=1### Connect URL of DB:
db.url.0=jdbc:mysql://192.168.75.132:3306/nacos? characterEncoding=utf8&connectTimeout=10000&socketTimeout=30000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=root
db.password.0=root
2. 建库建表
①新建nacos数据库
②初始化数据库
找到/usr/local/nacos/conf/nacos-mysql.sql并在Navicat执行
3. 测试
①重启nacos
②上传配置文件,观察是否写到了mysql
2.6 nacos集群
- 问题
1)如何把请求平均分配?nginx
2)为什么是3台?投票选举 leader
3)如何同步数据?leader
- nacos集群搭建
1) 修改nacos的cluster.conf,配置3台nacos的通讯地址
cd /usr/local/nacos/conf
cp cluster.conf.example cluster.conf
vim cluster:
192.168.204.129:8848
192.168.204.129:8849
192.168.204.129:8850
2) 复制3台nacos
cd /usr/local
mkdir nacos_cluster
cp -r nacos nacos_cluster/nacos_8848
cp -r nacos nacos_cluster/nacos_8849
cp -r nacos nacos_cluster/nacos_8850
3) 修改3台nacos的port
vim /usr/local/nacos_cluster/nacos_8849/conf/application.properties:
server.port=8849
vim /usr/local/nacos_cluster/nacos_8849/conf/application.properties:
server.port=8849
4) 启动集群
cd /usr/local/nacos_cluster/nacos_8848/bin
./startup
cd /usr/local/nacos_cluster/nacos_8849/bin
./startup
cd /usr/local/nacos_cluster/nacos_8850/bin
./startup
- 搭建nginx
1) 安装c语言环境
yum -y install gcc pcre pcre-devel zlib zlib-devel openssl openssl-devel
2) 下载nginx
cd /usr/upload
wget -c https://nginx.org/download/nginx-1.12.0.tar.gz
3) 解压
tar -zxvf nginx-1.12.0.tar.gz
4) 配置安装路径
cd nginx-1.12.0
./configure --prefix=/usr/local/nginx
5) 编译并安装
make && make install
6) 启动和关闭
启动:
cd /usr/local/nginx/sbin
./nginx
关闭:
cd /usr/local/nginx/sbin
./nginx -s stop
7) 配置nginx代理nacos集群
upstream nacos {
server 192.168.209.129:8848;
server 192.168.209.129:8849;
server 192.168.209.129:8850;
}server {
location / {
proxy_pass http://nacos;
}
}
2.7 nacos开机自启动
- 添加开机自启动文件
vim /lib/systemd/system/nacos.service:
[Unit]
Description=nacos
After=network.target[Service]
Type=forking
ExecStart=/usr/local/nacos/bin/startup.sh -m standalone
ExecReload=/usr/local/nacos/bin/shutdown.sh
ExecStop=/usr/local/nacos/bin/shutdown.sh
PrivateTmp=true[Install]
WantedBy=multi-user.target
- 修改nacos的startup.sh
vim /usr/local/nacos/bin/startup.sh:
原:[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=$HOME/jdk/java
改:[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=/usr/local/jdk1.8.0_191
#[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=/usr/java
#[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=/opt/taobao/java
#[ ! -e "$JAVA_HOME/bin/java" ] && unset JAVA_HOME
- 设置开启执行nacos.service
systemctl daemon-reload #重新加载服务配置
systemctl start nacos.service #启动nacos服务
systemctl status nacos.service #查看nacos服务的状态
systemctl enable nacos.service #设置为开机启动