1.下载地址:
版本:nacos-server-1.4.1.zip windows版本
https://github.com/alibaba/nacos/releases
2.初始化配置
1.登录mysql执行下载中的sql脚本,(**需要注意自己创建数据库**)
2.修改/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
3.启动Nacos服务并访问
startup.cmd -m standalone windows启动nacos命令
./startup.sh -m standalone Linux和mac启动命令
输入http://localhost:8848/nacos地址进行访问,默认帐号密码是nacos/nacos
4.创建父级pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--项目坐标(groupId->01-sca)-->
<groupId>com.jt</groupId>
<artifactId>01-sca</artifactId>
<!--父工程默认的打包方式伟pom方式-->
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<!--这个元素是自动添加的,创建当前工程下的子工程时,会自动添加此元素-->
<modules>
<module>sca-provider</module>
<module>sca-consumer</module>
<module>sca-demos</module>
</modules>
<!--工程中默认定义的或自己定义的属性,例如一些版本信息-->
<properties>
<spring.boot.version>2.3.2.RELEASE</spring.boot.version>
<spring.cloud.version>Hoxton.SR9</spring.cloud.version>
<spring.cloud.alibaba.version>2.2.6.RELEASE</spring.cloud.alibaba.version>
</properties>
<!--dependencyManagement元素用于定义核心依赖的管理,例如依赖的版本-->
<dependencyManagement>
<dependencies>
<!--Spring boot 依赖(微服务基础)-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<!--这里的import表示在其它工程中需要时直接可以引用-->
<scope>import</scope>
<!--假如依赖的scope属性值为scope,则type类型必须为pom-->
<type>pom</type>
</dependency>
<!--Spring Cloud 依赖(定义了微服务规范)-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
<!--Spring Cloud Alibaba依赖(基于spring微服务规范做了具体落地实现)-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring.cloud.alibaba.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
</project>
5.生产者pom文件及配置文件
1.pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>01-sca</artifactId>
<groupId>com.jt</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sca-provider</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!--Web服务-->
<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>
<!--nacos配置中心依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
</dependencies>
</project>
2.核心配置文件(引入nacos服务配置依赖需要修改名字bootstrap.yml)
server:
port: 8081
# tomcat: #ThreadPoolExecutor
# threads:
# max: 300
spring:
application:
name: sca-provider
cloud:
nacos:
discovery: #注册中心
server-addr: localhost:8848
config: #配置中心的配置
server-addr: localhost:8848
file-extension: yml
namespace: 56638dcc-ac08-4cf6-8043-8b3fbcb21adf #dev
#group: DEV_GROUP_51
shared-configs[0]: #共享配置,0表示一个数组下标
data-id: app-common-dev.yml
#group: DEFAULT_GROUP
refresh: true #默认false
# 配置日志(经常变化的数据一般会写到配置中心)
logging:
level:
com.jt: error
6.消费者pom文件及配置文件
1.pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>01-sca</artifactId>
<groupId>com.jt</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sca-consumer</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<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>
<!--当基于feign方式进行服务调用时就需要此依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--限流依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--springboot监控依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
</project>
2.核心配置文件
server:
port: 8090
spring:
application:
name: sca-consumer
cloud:
nacos:
discovery:
server-addr: localhost:8848
sentinel:
transport:
dashboard: localhost:8180
# port: 8719
#feign方式的服务熔断处理
feign:
hystrix: #hystrix 含义是熔断(就相当于服务停止了)或降级
enabled: true
7.resttemplate/loadbalanced方式服务调用
package com.jt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
//@EnableFeignClients注解描述启动类时,用于告诉springboot在启动时,
//扫描启动类所在包或子包中的类,假如接口上有@FeignClient注解描述,则对
//这样的接口创建其实现类,在实现类内部帮我们进行远程服务调用
@EnableFeignClients
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
/**创建RestTemplate对象,然后基于此对象进行远程服务调用
* @Bean 注解用于描述方法,用于告诉spring框架这个方法的返回值交给spring管理,
* spring默认会这个方法返回对象起一个bean的名字(key),默认为方法名.当然也可以
* 对一个bean的名字进行自定义,例如@Bean("自己定义的名字").
* 思考:spring框架中为什么会给出这样的注解,用于描述方法,在方法中构建对象?
* 第一:Spring是一个资源整合框架.
* 第二:何为资源?(内存中对象)
* 第三:所有对象是否都有类型?
* 第四:所有对象的类型都是你自己定义的吗?不一定(有自己,有第三方)
* 第五:第三方的类,我们能在类上直接添加注解描述吗(例如@Component)?不可以
*/
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
@Bean
@LoadBalanced //这个注解描述RestTemplate对象时,系统底层会对RestTemplate对象的请求进行拦截
public RestTemplate loadBalanceRestTemplate(){
return new RestTemplate();
}
@RestController
public class ConsumerController{
@Autowired
private RestTemplate restTemplate;
/**
* @Autowired注解描述属性时,会告诉spring框架,要优先按属性类型进行对象的查找和注入,假如
* 此类型的对象存在多个,此时还会按照属性名进行查找和比对,有相同的则直接注入(DI),没有相同
* 的则出错,当然也可以在属性上添加@Qualifier("bean的名字")注解,指定要注入的具体对象
*/
@Autowired
private RestTemplate loadBalanceRestTemplate;
//负载均衡客户端对象(基于此对象可以从nacos中获取服务列表,并且可以基于一定的算法
//从列表中获取一个服务实例)
@Autowired
private LoadBalancerClient loadBalancerClient;
@Value("${spring.application.name}")
private String appName;
//直接调用(非负载均衡方式)
//http://localhost:8090/consumer/doRestEcho1
@GetMapping("/consumer/doRestEcho1")
public String doRestEcho1(){
String url="http://localhost:8081/provider/echo/"+appName;
return restTemplate.getForObject(url,String.class);
}
//负载均衡方式的调用1
@GetMapping("/consumer/doRestEcho2")
public String doRestEcho2(){
//基于loadBalancerClient方式获取服务实例
String serviceId="sca-provider";//这个名字要在nacos的服务列表中
ServiceInstance choose =
loadBalancerClient.choose(serviceId);
String ip=choose.getHost();
int port=choose.getPort();
//String url="http://"+ip+":"+port+"/provider/echo/"+appName;
String url=String.format("http://%s:%s/provider/echo/%s",ip,port,appName);
return restTemplate.getForObject(url,String.class);
}
//负载均衡应用方式2:@LoadBalance
@GetMapping("/consumer/doRestEcho3")
public String doRestEcho3(){
String serviceId="sca-provider";
String url=String.format("http://%s/provider/echo/%s",serviceId,appName);
//底层在基于loadBalanceRestTemplate对象访问方式,会启动一个拦截器
return loadBalanceRestTemplate.getForObject(url,String.class);
}
}
}
8.feign方式服务调用
1.RemoteProviderServer代码
package com.jt.feign;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
/**
* @FeignClient 注解用于描述远程服务调用接口,这个接口不需要你写实现类,你
* 只需要定义访问规则即可(例如请求方式,请求url,请求参数).
* @FeignClient注解描述的接口的实现类对象会默认交给spring管理,这个bean对象
* 的名字默认就是name属性指定的值,这个name还有一个层面的含义,就是你远程调用的
* 服务名.
* 说明:假如@FeignClient注解中添加了contextId属性,则这个属性值默认
* 会作为当前bean对象的名字,此时name的值仅仅作为要调用的服务名对待,一般
* 推荐contextId的值默认为@FeignClient注解描述的接口的名字(首字母小写)
*/
@FeignClient(name="sca-provider",
contextId = "remoteProviderService",
fallbackFactory = ProviderFallbackFactory.class)
public interface RemoteProviderService {
//@GetMapping表示以get请求方式调用远端服务
//"/provider/echo/{msg}"为远程调用服务的url
@GetMapping("/provider/echo/{msg}")
String echoMessage(@PathVariable("msg") String msg);
}
2.ProviderFallbackFactory.java代码
package com.jt.feign;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
//此对象可以作为Feign方式的远程调用异常处理对象
@Component
public class ProviderFallbackFactory
implements FallbackFactory<RemoteProviderService> {
//当正常远程调用的服务不可用时,系统可以调用此方法进行请求处理
@Override
public RemoteProviderService create(Throwable throwable) {
return new RemoteProviderService() {//匿名内部类
@Override
public String echoMessage(String msg) {
//...通知运维人员(发短信,发邮件,电话)...
return "服务维护中";
}
};
}
}
9.图解调用模式
这张图描述了远程服务调用的几中方式:
第一种:服务比较少,例如就两个服务,一个服务消费,一个服务提供,就不需要注册中心,不需要负载均衡.
第二种:并发比较大,服务服务比较多,我们需要管理服务,就需要注册中心,我们还需要服务间的负载均衡.但代码编写的复杂多相对高一些,我们需要自己获取ip,获取端口,拼接字符串等.
第三种:我们要基于第二种进行代码简化,底层提供了一种拦截器,把基于服务名获取服务实例的过程在拦截器中做了封装,简化了代码的开发.但是加了拦截器多少会在性能少有一点损耗.
第四种方式主要是从代码结构上做一个挑战,我们前面三种基于RestTemplate进行服务调用,本身属于一种远程服务调用业务,能够将这种业务写到一个业务对象中,Feign方式就诞生了,它主要对代码结构的一种优化.
10.Nacos配置管理模型
11.共享配置设计及读取
当同一个namespace的多个配置文件中都有相同配置时,可以对这些配置进行提取,然后存储到nacos配置中心的一个或多个指定配置文件,哪个微服务需要,就在服务的配置中设置读取即可。例如: