其官网地址如下:
Nacos官网
第一:确保你电脑已配置JAVA_HOME环境变量(Nacos启动时需要),例如:
第二:确保你的MySQL版本为5.7以上(MariaDB10.5以上、10.3也可以),例如
第三:存放nacos的磁盘的写权限问题(nacos服务启动时会在当前磁盘目录写日志),例如:
1.可在浏览器直接输入如下地址:
https://github.com/alibaba/nacos/releases
(本电脑上下载的安装包位置 D:\Nacos)
选择对应版本,直接下载,如图所示:
2. 解压Nacos(最好不要解压到中文目录下--我的解压位置D:\Nacos),其解压后目录结构如下:
1.登陆mysql,执行老师发给同学们的sql脚本(数据库表)。
1)例如,我们可以使用mysql自带客户端,在命令行首先登录mysql(mysql -uroot -proot)
2)然后执行如下指令:(nacos-mysql.sql 是老师给的sql文件,我存在了D盘里----不要用nacos D:\Nacos\nacos\conf 中自带的这个nacos-mysql.sql,有问题)
source d:/nacos-mysql.sql
执行成功以后,会创建一个nacos_config数据库,打开数据库会看到一些表,例如;
常见bug
1
注意:在执行此文件时,要求mysql的版本大于5.7版本(MariaDB最好10.5.11),否则会出现如下错误:
2
sql文件不存在,例如
3
SQL文件应用错误,例如:
2.在解压后的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://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=root #数据库名
db.password.0=root #数据库密码
常见bug
1
Nacos的application.properties配置文件中,连接数据库的配置错误.
2
数据库的名字配置错误,例如:
3
nacos配置文件application.properties配置错误,例如:
启动Nacos服务——在解压后的Nacos文件夹中 bin目录打开DOS窗口,根据系统执行如下命令
Linux/Unix/Mac 系统 启动命令(standalone代表着单机模式运行,非集群模式)用:
./startup.sh -m standalone
Windows 系统 启动命令(standalone代表着单机模式运行,非集群模式)用:
startup.cmd -m standalone
假如所有的配置都正确,还连不上,检查一下你有几个数据库(mysql,…)
常见bug
JAVA_HOME环境变量定义错误,例如:
说明,这里一定要注意JAVA_HOME单词的拼写,JAVA_HOME中定义的JDK是存在的,还有后面的路径不能有分号“;”.————如下
2、
3、
4、启动nacos服务
打开浏览器,输入http://localhost:8848/nacos地址,出现如下登陆页面 即成功:
默认账号密码为nacos/nacos.,登陆后显示下图即成功
web服务依赖 nacos服务注册、发现的discovery依赖
org.springframework.boot
spring-boot-starter-web
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
#web 服务启动时所需要的端口————8081 #web 服务向nacos进行服务注册的名字————sca-provider #web 服务向nacos进行服务注册的地址(此处是本机)————8848
#web 服务启动时所需要的端口
server:
port: 8081
#web 服务向nacos进行服务注册的名字
spring:
application:
name: sca-provider
#web 服务向nacos进行服务注册的地址(此处是本机)
cloud:
nacos:
discovery:
server-addr: localhost:8848
如果我们关闭idea中的服务器,服务停了,nacos收不到消息;
那么下图中的健康实例数 15s后就会从原本的1变成0
30s后就会把下图中的服务从列表中移除
停掉sca-provider idea里的服务,然后不断刷新浏览器的nacos服务列表,检查服务的健康状态。
测试时 相当于用户直接通过浏览器访问sca-provider;——此处仅为测试
(实际中 用户要先访问sca-comsumer,再到sca-provider)
/**构建controller对象,用于处理用户(客户端)的请求——对外提供一些服务
* 即在这里写一些方法以供调用*/
动态为属性赋值
/*从项目配置文件中读取server.port的值,然后赋值给serverPort属性,
* 冒号 右边的8080是我们设置的一个默认值,假如从配置文件读取不到server.port,
* 就会将默认值赋值给属性serverPort*/
@Value("${server.port:8080}")
private String serverPort;
/*自己写的一个 调用的服务例子*/
//http://localhost:8081/product/echo/nacos
@GetMapping("/product/echo/{msg}")
public String doRestEcho1(@PathVariable("msg") String msg){
return serverPort + "say hello" + msg;
}
web服务依赖 nacos服务注册、发现的discovery依赖
org.springframework.boot
spring-boot-starter-web
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
#web 服务启动时所需要的端口————要和sca-provider中的端口不同 8090 #web 服务向nacos进行服务注册的名字—————sca-consumer #web 服务向nacos进行服务注册的地址(此处是本机)————8848
#web 服务启动时所需要的端口
server:
port: 8090
#web 服务向nacos进行服务注册的名字
spring:
application:
name: sca-consumer
#web 服务向nacos进行服务注册的地址(此处是本机)
cloud:
nacos:
discovery:
server-addr: localhost:8848
因为consumer要调用provider,所以主启动类中要用restTemplate调用
(在sca-consumer启动类中添加如下方法,用于创建RestTemplate对象.)
@Bean //bean的名字默认为方法名
public RestTemplate restTemplate(){
return new RestTemplate();
}
如果我们关闭idea中的服务器,服务停了,nacos收不到消息;
那么下图中的健康实例数 15s后就会从原本的1变成0
30s后就会把下图中的服务从列表中移除
停掉sca-provider idea里的服务,然后不断刷新浏览器的nacos服务列表,检查服务的健康状态。
测试时 相当于用户直接通过浏览器访问sca-consumer;——此处仅为测试
(实际中 用户要先访问sca-comsumer,再到sca-provider)
/**@Autowired
private RestTemplate restTemplate;
Spring中不推荐这种方式构造注入,@Autowired下会有波浪线,
而且restTemplate此时也是灰暗色,表明Spring不推荐此种注入方式*/
/**Spring推荐使用构造注入——如下:写一个构造方法,通过构造方法为属性赋个值*/
private RestTemplate restTemplate;
@Autowired
public ConsumerController(RestTemplate restTemplate){
this.restTemplate = restTemplate;
}
@Value("${server.port:8090}")
private String serverPort;
//http://localhost:8090/consumer/doRestEcho1
@GetMapping("/consumer/doRestEcho1")
public String doRestEcho1(){
//在这里调用sca-provider服务 provider的端口我们设的是8081
//这里写的地址不正确会出现调用404异常(此处的url地址要和ProviderController里的地址一样)
String url = "http://localhost:8081/product/echo/8090";
return restTemplate.getForObject(url, String.class,serverPort);
//远端的url地址 响应结果的类型(此处是String)
}
此时provider和consumer的主启动类(服务)都要开着
day3 pm-1:21:00——day4 pm-2:20:00
规则:谁通过Feign调用其他服务,以下步骤加在谁上
因为comsumer通过Feign调用provider服务,所以以下步骤加在sca-comsumer文件中
(如果provider要通过Feign调用其他服务的话,以下步骤加在sca-provider文件中)
org.springframework.cloud
spring-cloud-starter-openfeign
(接口的作用就是定义规范,此处的API接口用于声明 我们要调用哪个服务和要访问服务中的什么资源),基于此API借助OpenFeign(Feign之后改的名字)访问其他(比如此处四访问sca-provider)服务——我们把此API定义在service层,因为controller层调用service层
package com.jt.consumer.service;
@FeignClient(name/value="sca-provider")//sca-provider为服务提供者名称
public interface RemoteProviderService{
//方法上要声明访问的服务中的哪个url(资源)——("/provider/echo/{string}")
@GetMapping("/provider/echo/{string}")//前提是远端sca-provider 的ProviderController里需要有这个服务
public String echoMessage(@PathVariable("string") String string);
}
@FeignClient 作用:
1、声明要调用/访问的(远端)服务是服务名sca-provider
2、/*当前接口对应的实现类交给Spring管理时,Bean的名字——当然,如果我们不想让value属性的值作为bean对象的名字,可以通过contextId属性指定一个名字
例:@FeignClient(value="sca-provider" ,contextId = "remoteProviderService" )*/
实际操作:
*********************************************************************************************
**1、多个调用接口情况:**
以上3)的写法是服务消费方基于同一个服务提供方写了一个serviceAPI服务调用接口
实际中特殊的普遍的情况:服务消费方基于同一个服务提供方写了很多serviceAPI服务调用接口
理解:一个服务提供方通常会提供很多资源服务,服务消费方基于同一个服务提供方写了很多服务调用接口,此时假如没有指定contextId,服务
启动就会失败,例如,假如在服务消费方再添加一个如下接口,消费方启动时就会启动失败;例如:
@FeignClient(name="sca-provider")
public interface RemoteOtherService {
@GetMapping("/doSomeThing")
public String doSomeThing();
}
其启动异常如下:
The bean 'optimization-user.FeignClientSpecification', defined in null, could not be registered. A bean with that name has already been defined in null and overriding is disabled.
解决方式:
此时我们需要为第二/三....个service远程调用服务接口指定一个contextId属性,作为远程调用服务的唯一标识(这个标识是Bean对象的名字)即可,例如:
@FeignClient(name="sca-provider",contextId="remoteProviderService")//sca-provider为服务提供者名称
interface RemoteProviderService{
@GetMapping("/provider/echo/{string}")//前提是远端需要有这个服务
public String echoMessage(@PathVariable("string") String string);
}
******************************************************************************************
**2、解决service API接口调用时出现的服务中断,超时等问题
系统出现问题后(远程服务调用不到:service调不到provider时——因为有的时候我们没有运行远端provider服务的主启动类,只运行了consumer服务的主启动类),不能让用户看到如下图的页面否则用户体验不好;必须要有回滚/回调fallback措施**
解决方式:fallbackFactory
我们需要为 每个service API远端调用添加以下步骤
步骤1:在service包下 我们写的service API远程调用服务接口指定fallbackFactory属性
@FeignClient(name="sca-provider",contextId="remoteProviderService",fallbackFactory="")
interface RemoteProviderService{
@GetMapping("/provider/echo/{string}")//前提是远端需要有这个服务
public String echoMessage(@PathVariable("string") String string);
}
步骤2:创建要回调的方法(在service包下,自己为service API接口写一个实现类 ,类中写方法,以供远程服务调用不到时来调用/回调
写法2:
package com.jt.service.factory;
/**
* 基于此对象处理RemoteProviderService接口调用时出现的服务中断,超时等问题
*/
@Component
public class ProviderFallbackFactory implements FallbackFactory {
/**
* 此方法会在RemoteProviderService接口服务调用时,出现了异常后执行.
* @param throwable 用于接收异常
*/
@Override
public RemoteProviderService create(Throwable throwable) {
return (msg)->{
return "服务维护中,稍等片刻再访问";
};
}
}
步骤3:完善步骤一
@FeignClient(name="sca-provider",contextId="remoteProviderService",fallbackFactory=ProviderFallbackFactory.class)
interface RemoteProviderService{
@GetMapping("/provider/echo/{string}")//前提是远端需要有这个服务
public String echoMessage(@PathVariable("string") String string);
}
步骤4:配置文件中启用熔断机制(在sca-consumer的application.yml配置文件中开启熔断机制)
#熔断机制默认是false 关闭,我们要打开变为true
feign:
hystrix:
enabled: true
步骤5:在服务提供方provider对应的调用方法中添加Thread.sleep(5000)模拟耗时操作,然后启动consumer主启动类进行服务调用测试
package com.jt.consumer.controller;
@RestController
public class FeignConsumerController {
@Autowired
private RemoteProviderService remoteProviderService;
/**基于feign方式的服务调用*/
@GetMapping("/comsumer/echo/{msg}")
public String doFeignEcho(@PathVariable String msg){
//基于feign方式进行远端服务调用(前提是服务必须存在)
return remoteProviderService.echoMessage(msg);
}
}
sca-provider: #这个是要进行远程调用的服务id(服务名)-----被调用的 服务名
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #负载均衡算法
对于方案1写法,在写的过程没有提示,编写困难,但是将来的可运维性会比较好,我们这部分配置写到配置中心,不需要重启服务即可实现配置的动态发布,动态更新。
@Bean
public IRule ribbonRule() {
return new RandomRule();
}
对于方案2的写法,编写相对简单,编写过程都有提示,但是将来的可运维性比较差,不推荐使用,项目打包以后,我们无法再修改负载均衡算法。
多次运行一个相同的url,相当于我们在用浏览器访问url时不断点刷新按钮
历史记录位置(可以查找和删除不用的)