一、Nacos的安装和构建 以及启动
其官网地址如下:
1.安装前提:
第一:确保你电脑已配置JAVA_HOME环境变量(Nacos启动时需要),例如:

第二:确保你的MySQL版本为5.7以上(MariaDB10.5以上、10.3也可以),例如
第三:存放nacos的磁盘的写权限问题(nacos服务启动时会在当前磁盘目录写日志),例如:
2.下载与安装
第一步:Nacos下载与解压
1.可在浏览器直接输入如下地址:
https://github.com/alibaba/nacos/releases
(本电脑上下载的安装包位置 D:\Nacos)
选择对应版本,直接下载,如图所示:

2. 解压Nacos(最好不要解压到中文目录下--我的解压位置D:\Nacos),其解压后目录结构如下:

第二步:导入数据库文件/初始化配置(将sql文件在数据库小黑窗口导入)
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服务的启动与访问
一、DOS窗口启动nacos服务(二选一)
启动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是存在的,还有后面的路径不能有分号“;”.————如下

二、基于idea启动nacos服务(二选一)——推荐
1、
2、


3、


4、启动nacos服务

三、查看nacos是否启动

访问Nacos服务
打开浏览器,输入http://localhost:8848/nacos地址,出现如下登陆页面 即成功:

默认账号密码为nacos/nacos.,登陆后显示下图即成功

二、服务注册与调用
1、服务的注册——服务提供方模块(sca-provider)
1)pom.xml文件:所需依赖的添加(实现Nacos服务注册需要添加什么依赖)
web服务依赖 nacos服务注册、发现的discovery依赖

<dependencies>
<!--依赖一-->
<!--web服务依赖(内嵌一个tomcat服务,底层基于ServerSocket创建服务——————————————————
这个服务内置一个无限循环,会不断等待客户端的连接,并且处理客户端的请求)-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--依赖二-->
<!--nacos 服务注册、发现依赖(此依赖添加后,项目中会启动一个定时任务,这个定时任务会周期性
的向nacos服务器端发送心跳包,用于实现向nacos8848服务器端(浏览器打开的nacos服务)进行注册)-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
2)resources下创建并修改配置文件application.yml(或者application.properties),实现服务注册
#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:88483)创建 服务提供方主启动类(假如已有则无需创建),并运行主启动类


4)主启动类启动成功后,可以打开浏览器中我们的nacos服务进行查看
如果我们关闭idea中的服务器,服务停了,nacos收不到消息;
那么下图中的健康实例数 15s后就会从原本的1变成0
30s后就会把下图中的服务从列表中移除
停掉sca-provider idea里的服务,然后不断刷新浏览器的nacos服务列表,检查服务的健康状态。

测试 服务提供方模块(sca-provider) 是否能对外提供服务/是否生效
测试时 相当于用户直接通过浏览器访问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;
}
2、服务的发现和调用——服务消费方模块(sca-consumer)
1)pom.xml文件:所需依赖的添加(实现Nacos服务注册需要添加什么依赖)
web服务依赖 nacos服务注册、发现的discovery依赖

<dependencies>
<!--依赖一-->
<!--web服务依赖(内嵌一个tomcat服务,底层基于ServerSocket创建服务——————————————————
这个服务内置一个无限循环,会不断等待客户端的连接,并且处理客户端的请求)-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--依赖二-->
<!--nacos 服务注册、发现依赖(此依赖添加后,项目中会启动一个定时任务,这个定时任务会周期性
的向nacos服务器端发送心跳包,用于实现向nacos8848服务器端进行注册)-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
2)resources下创建并修改配置文件application.yml(或者application.properties),实现服务注册
#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:88483)创建 服务消费方主启动类(假如已有则无需创建),并运行主启动类

因为consumer要调用provider,所以主启动类中要用restTemplate调用
(在sca-consumer启动类中添加如下方法,用于创建RestTemplate对象.)

@Bean //bean的名字默认为方法名
public RestTemplate restTemplate(){
return new RestTemplate();
}4)主启动类启动成功后,可以打开浏览器中我们的nacos服务进行查看
如果我们关闭idea中的服务器,服务停了,nacos收不到消息;
那么下图中的健康实例数 15s后就会从原本的1变成0
30s后就会把下图中的服务从列表中移除
停掉sca-provider idea里的服务,然后不断刷新浏览器的nacos服务列表,检查服务的健康状态。

测试 服务消费方模块(sca-consumer) 是否能对外提供服务/是否生效
测试时 相当于用户直接通过浏览器访问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的主启动类(服务)都要开着

3、(服务)调用过程


三.1、Nacos客户端远程服务调用(RPC) 负载均衡 的实现——见下载-微服务中的负载均衡示例代码
一)基于RestTemplate对象 方式实现负载均衡
二)基于Feign的远程服务调用(重点)
day3 pm-1:21:00——day4 pm-2:20:00
规则:谁通过Feign调用其他服务,以下步骤加在谁上
因为comsumer通过Feign调用provider服务,所以以下步骤加在sca-comsumer文件中
(如果provider要通过Feign调用其他服务的话,以下步骤加在sca-provider文件中)
1)在服务消费方sca-comsumer,添加项目依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2)在主启动类上添加@EnableFeignClients注解

3)定义Http请求的service API(远程调用服务)接口——因为有多个,所以创一个service包,在service包下写
(接口的作用就是定义规范,此处的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接口写一个实现类 ,类中写方法,以供远程服务调用不到时来调用/回调

写法1:
写法2:
package com.jt.service.factory;
/**
* 基于此对象处理RemoteProviderService接口调用时出现的服务中断,超时等问题
*/
@Component
public class ProviderFallbackFactory implements FallbackFactory<RemoteProviderService> {
/**
* 此方法会在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主启动类进行服务调用测试


4)创建controller(FeignConsumerController)并添加feign访问
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);
}
}
实际操作:
5)启动消费者服务,在浏览器中直接通过feign客户端进行访问,如图所示(反复刷新检测其响应结果)

三)如何修改sca-consumer端默认的负载均衡策略
方案1:修改sca-consumer配置文件(application.yml),添加如下语句,例如:
sca-provider: #这个是要进行远程调用的服务id(服务名)-----被调用的 服务名
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #负载均衡算法
对于方案1写法,在写的过程没有提示,编写困难,但是将来的可运维性会比较好,我们这部分配置写到配置中心,不需要重启服务即可实现配置的动态发布,动态更新。
方案2:修改sca-consumer的启动类,在启动类中添加如下方法,例如:
@Bean
public IRule ribbonRule() {
return new RandomRule();
}
对于方案2的写法,编写相对简单,编写过程都有提示,但是将来的可运维性比较差,不推荐使用,项目打包以后,我们无法再修改负载均衡算法。
三.2、Idea中Http Client 工具的应用:模拟发起get/post请求,查看服务调用效果(相当于在浏览器输入网址访问)
1、打开HTTP Client中的Test RESTful Web Service——(基于/适用于restful风格:comsumer进行远程服务调用(调用provider服务)时使用)



2、Http Client 工具的使用
1)写url进行模拟请求

多次运行一个相同的url,相当于我们在用浏览器访问url时不断点刷新按钮
2)如果不知道(get/post/json串)格式 写法,有官方提供的例子

3)规则:


4)不小心把如下图 写的窗口关了,不要急着重写——有历史记录

历史记录位置(可以查找和删除不用的)



