自行百度安装教程:
安装完成以后启动nacos-server;在nacos.bin目录下面CMD输入启动命令如下:
startup.cmd -m standalone # 单例模式运行nacos,非集群(高可用)模式
前提:父工程cloud-demo引入Spring Cloud Alibaba的依赖
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>Greenwich.SR1version>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-dependenciesartifactId>
<version>2.1.4.RELEASEversion>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
步骤一:引入nacos依赖;这里以Order服务为例,其余的服务按照这个步骤集成即可
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
步骤二:编写nacos-client客户端的配置
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
测试:打开游览器访问nacos控制台http://localhost:8848/nacos/
定义:同一个服务会存在多个节点;一部分节点的服务器存于上海,一部分节点的数据存于广州等,每个节点都属于特定的区域或者机房内(也可简称本地集群服务器)。
解决的问题:服务调用尽可能有限选择本地集群服务,跨集群服务调用延迟高,只有本地集群不可用时,才会尝试去请求别的区域的其他服务集群。
在配置文件中配置当前服务节点属于的集群名称(cluster-name):比如Order服务我设置的集群名为HZ,Product和User设置的是SH。
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
cluster-name: HZ # 指明其属于哪一个集群
控制台查看集群服务器:
负载均衡:Spring Cloud Alibaba默认还是使用ribbon的轮询规则(微服务调用章节有提到过);如下如果是有三台User服务节点,则order发起服务远程调用时,就会进行轮询调用,但是user1是和order一个地区的,user2和user3是SH地区的服务器,order如果轮询调用到他们了就是跨集群调用了,这是非常影响服务性能的。所以我们需要更改负载策略,使得order服务节点发起的请求优先路由到跟它同一个集群中的user节点(即下图中的user1)。
修改Ribbon负载均衡策略:即将默认轮询的规则换成NacosRule,这样会优先调用本地集群中的生产者服务节点,只有本地服务节点全部挂掉了才会去跨集群调用别的集群节点。
userservice:
ribbon:
NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule
权重负载:nacos提供了权重配置来控制访问频次;权重越大的节点被访问的频次越高;一般生产环境中性能配置更好的服务器分配到的负载权重会大一些。具体配置步骤就是:nacos控制台 -> 编辑 -> 更改权重;如果权重设置为0,则不会有请求路由过来此节点,一般这种情况可以用作线上服务器平滑更新云端系统。
spring:
cloud:
nacos:
discovery:
namespace: 命名空、间id
定义:实现配置更改热更新,远程读取云端配置并重启服务
控制台创建远程配置文件:控制台 -> 配置管理 -> 新加配置(名字,内容,分组,描述)
微服务读取配置文件流程:
bootstrap.yml文件 :读取优先级最高,一般存放服务名称、开发环境、nacos配置地址、远程配置文件等应用级别信息。
nacos控制台创建order-service-local.yaml文件:
student:
name: zahngsan
age: 23
sex: man
引入nacos-config依赖:
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
dependency>
配置bootstrap.yml:会通过spring.application.name + profiles.active + nacos.config.file-extension = order-service-local.yaml文件名来拉取云端的远程配置文件。
server:
port: 8081
spring:
application:
name: order-service
profiles:
active: local
datasource:
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 123456
url: jdbc:mysql://localhost:3306/mc_mall?useSSL=false&useUnicode=true&characterEncoding=utf-8
type: com.alibaba.druid.pool.DruidDataSource
initialSize: 50 #初始化时建立物理连接的个数
minIdle: 30 #最小连接池数量
maxActive: 200 #最大连接池数量
maxWait: 60000 #获取连接时最大等待时间
timeBetweenEvictionRunsMillis: 60000 #Destory线程检测连接的间隔时间
minEvictableIdleTimeMillis: 300000 #连接保持空闲而不被驱逐的最长时间
redis:
host: localhost
port: 6379
password: 123456
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
cluster-name: HZ # 指明其属于哪一个集群
config:
file-extension: yaml #配置文件后缀
#eureka:
# client:
# fetch-registry: true
# register-with-eureka: true
# service-url:
# defaultZone: http://127.0.0.1:10081/eureka/
feign:
client:
config:
default:
loggerLevel: FULL # 日志等级
httpclient:
enabled: true # 开启feign对Apache HttpClient的支持
max-connections: 200 # 最大的连接数
max-connections-per-route: 50 # 每个路径的最大连接数
验证远程配置是否生效: 新增getStudent接口
@RestController
@RequestMapping("order")
public class OrderController {
private static final Logger logger = LoggerFactory.getLogger(OrderController.class);
@Autowired
private RestTemplate restTemplate;
@Autowired
private UserClient userClient;
@Value("${student.name}")
private String studentName;
@Value("${student.age}")
private int studentAge;
@Value("${student.sex}")
private String studentSex;
@GetMapping("getStudent")
public StudentVO getStudent(){
StudentVO studentVO = new StudentVO();
studentVO.setName(studentName);
studentVO.setAge(studentAge);
studentVO.setSex(studentSex);
return studentVO;
}
}
测试结果:成功拿到远程配置
如果配置属性是@Value标签进行注入:在属性注入类上面加上@RefreshScope标签
package com.acx.controller;
import com.acx.client.UserClient;
import com.acx.pojo.vo.ActorInfoVO;
import com.acx.pojo.vo.OrderInfoVO;
import com.acx.pojo.vo.StudentVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@RequestMapping("order")
@RefreshScope //远程配置热更新注解
public class OrderController {
private static final Logger logger = LoggerFactory.getLogger(OrderController.class);
@Autowired
private RestTemplate restTemplate;
@Autowired
private UserClient userClient;
@Value("${student.name}")
private String studentName;
@Value("${student.age}")
private int studentAge;
@Value("${student.sex}")
private String studentSex;
@GetMapping("getStudent")
public StudentVO getStudent(){
StudentVO studentVO = new StudentVO();
studentVO.setName(studentName);
studentVO.setAge(studentAge);
studentVO.setSex(studentSex);
return studentVO;
}
}
如果配置是使用@ConfigurationProperties标签进行注入:不需要加上@RefreshScope标签即可实现热更新
package com.acx.pojo.vo;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "student")
public class StudentVO {
private String name;
private int age;
private String sex;
}
package com.acx.controller;
import com.acx.client.UserClient;
import com.acx.pojo.vo.ActorInfoVO;
import com.acx.pojo.vo.OrderInfoVO;
import com.acx.pojo.vo.StudentVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@RequestMapping("order")
public class OrderController {
private static final Logger logger = LoggerFactory.getLogger(OrderController.class);
@Autowired
private RestTemplate restTemplate;
@Autowired
private UserClient userClient;
@Autowired
private StudentVO studentVO;
@GetMapping("getStudent")
public StudentVO getStudent(){
return studentVO;
}
}
集群架构:这里配置的操作系统是windows环境
搭建步骤:
下载nacos:https://github.com/alibaba/nacos/tags
初始化数据库:创建一个名为nacos的数据库,然后初始化表sql;初始化表sql在/nacos/conf/文件下面的nacos-mysql.sql文件里面。拿到sql语句以后再mysql里面执行初始化sql命令。
nacos配置:
### Default web server port: nacos端口
server.port=8845
### If user MySQL as datasource: 使用的持久层数据库类型
spring.datasource.platform=mysql
### Count of DB: 数据库数量,mysql单机这个值就=1
db.num=1
### Connect URL of DB: 数据库连接配置
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=123456
127.0.0.1:8845
127.0.0.1:8846
127.0.0.1:8847
启动三台nacos:
Nginx反向代理:
upstream nacos-cluster {
server 127.0.0.1:8845;
server 127.0.0.1:8846;
server 127.0.0.1:8847;
}
server {
listen 8848;
server_name localhost;
location /nacos {
proxy_pass http://nacos-cluster;
}
}
测试结果:访问http://localhost:8848/nacos/ 能够访问nacos控制台