近日在学习springcloud, 为此记录一下如何配置springcloud和注册组件(Nacos、Euraka);
导入SpringCloud依赖
由于是微服务学习, 我这里先创建了一个父maven模块:springcloud, 然后再创建了两个子模块:orderservice和userservice, 目录结构如下:
然后在父模块springcloud的pom文件中进行配置, 你可以在其中添加自己想要的依赖(例如springboot, mysql-driver等依赖), 我这里添加了springboot的相关依赖; 然后在<dependencyManagement></dependencyManagement>中添加springcloud的依赖,
如下:
<properties>
<java.version>17</java.version>
<!-- spring-cloud的版本 -->
<spring.cloud-version>2021.0.6</spring.cloud-version>
<!-- spring-cloud-alibaba的版本 -->
<spring.cloud.alibaba.version>2021.0.1.0</spring.cloud.alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- 引入spring-cloud的依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud-version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--引入阿里巴巴的cloud依赖, 引入spring-cloud-alibaba -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring.cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
我这里引入了spring-cloud的2021.0.6版本, springboot的版本为2.7.9, spring-cloud-alibaba为2021.0.1.0(使用nacos时需要引入此依赖, 如果不使用nacos则不需要引入),不同的版本之间可能会发生冲突, 导致运行不了。上面的版本是可以运行的,不会发生冲突.
然后再在子模块userservice和orderservice中引入springcloud这个父模块即可(springcloud需要在<modules></modules>中指定子模块), 如下:
至此, springcloud的依赖就已经引入了.
Nacos的安装:
去到nacos的官网nacos.io下载nacos, 我下载的版本是1.4.3, 然后再解压nacos,打开nacos的目录, 找到bin目录, 再打开cmd, 输入startup.cmd -m standalone这行命令即可, 正常情况下nacos的服务就会启动.
报错:
Please set the JAVA_HOME variable in your environment, We need java(x64) jdk8 or later
, 可能会出现这个报错, 原因是系统的环境变量中没有JAVA_HOME这个变量, 解决: 在系统的环境变量中添加, 再重新打开cmd,运行上面的命令即可
nacos的服务启动后, 我们可以看到下面的界面, 再去浏览器输入相关地址则可以进入nacos的服务网页.
进入nacos的网页时需要你输入账号和密码, 账号和密码皆为nacos, 登录进去后就可以看到下面的界面
到此, nacos就安装完成了;
将服务注册到Nacos
安装完nacos后则可以将服务注册到nacos中了, 首先在服务(就是orderservice和userservice两个子模块)中引入nacos的依赖, 如下:
<dependencies>
<!-- 加入nacos的依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 在新的springcloud版本中, 由于ribbon不再维护, springcloud使用LoadBalancer作为默认的负载均衡组件
, 所以要引入该依赖
-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
</dependencies>
由于ribbon暂停维护, springcloud在新版本中(我这里的版本较新)已经剔除了ribbon这个实现负载均衡的组件, 使用LoadBalancer作为实现负载均衡的组件, 所以我们要在这里引入loadbalancer的相关依赖, 如果不引入的话可能会报java.net.UnknownHostException这个错误.如果你的springcloud版本较低的话则不需要引入该依赖.
依赖引入完成后, 则开始修改服务的application.yml配置文件, 如下:
spring:
application:
name: userservice #服务的名称
cloud:
nacos:
discovery:
server-addr: localhost:8848 #设置nacos的服务地址
cluster-name: CS #设置集群名称
ephemeral: true #设置是否为临时实例, 默认是true
#namespace: #设置命令空间, 值为命令空间的UUID
加入上面的配置后, 该服务则会注册到nacos中, 此时我们就开始启动服务, 再在nacos的网页中进行查看服务是否已经注册进来了.
报错:
NacosException: Client not connected,current status:STARTING, 这里是alibaba-cloud与spring-cloud,springboot的版本不兼容, 解决: 更换alibaba-cloud的版本, 我上面的版本是可行的, 不会报该兼容问题.
启动后我们就可以在nacos的网页中看到相关的服务信息:
至此, 我们的服务就已经成功的注册到了nacos中了.
当我们在使用RestTemplate实现访问服务提供者的接口时, 我们可以在将RestTemplate交给spring管理时添加@LoadBalanced注解实现负载均衡
当我们使用nacos时, nacos可以指定服务实例的所在的集群, 当同一个集群中有需要的服务实例时, 消费者会优先考虑同一个集群中的服务提供者实例.集群的指定方式已经在上面的配置文件中展示出来了, 即设置spring.cloud.nacos.discovery.cluster-name属性即可。
!!!而springcloud默认的负载均衡方式是轮询负载均衡, 不会考虑是否在同一个集群, 而我们想要当服务消费者需要时首先访问同一个集群中的提供者服务, 此时我们需要指定springcloud得到负载均衡方式为nacos的负载均衡方式.
加入下面的代码即可将springcloud的负载均衡方式改为nacos的负载均衡方式
package com.java.config;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.loadbalancer.NacosLoadBalancer;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import javax.annotation.Resource;
// 指定Nacos的负载均衡算法
// Nacos负载均衡算法会优先使用同一个集群中的服务(有多个相同得的服务则轮询), 如果同一个集群中没有相关服务, 则使用其它集群的服务(多个服务则轮询)
@Configuration
public class NacosLoadBalancerConfig {
@Resource
private NacosDiscoveryProperties nacosDiscoveryProperties;
@Bean
public ReactorLoadBalancer<ServiceInstance> NacosLoadBalancer(Environment environment,
LoadBalancerClientFactory loadBalancerClientFactory) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new NacosLoadBalancer(loadBalancerClientFactory
.getLazyProvider(name, ServiceInstanceListSupplier.class),
name,nacosDiscoveryProperties);
}
}
再在启动类上添加注解告诉springcloud访问哪个服务时需要用到哪个负载均衡方式即可
package com.java;
import com.java.config.NacosLoadBalancerConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@LoadBalancerClients(value = {
// 指定使用哪个服务时使用哪个负载均衡的算法, 这里是指当使用userservice这个服务时使用NacosLoadBalancerConfig的负载均衡算法
@LoadBalancerClient(value = "userservice", configuration = NacosLoadBalancerConfig.class)
// 默认的负载均衡算法
},defaultConfiguration = NacosLoadBalancerConfig.class)
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
到此, 我们就已经将访问userservice这个服务时使用的负载均衡的方式替换为了nacos的负载均衡.
权重
而我们在nacos网页中也可以编辑服务实例的权重, 从而指定哪个实例被访问的几率更大, 假如userservice1的权重为0.1, 而userservice2的权重为1(默认为1), 意味着userservice1这个服务实例被访问的次数为userservice2的十分之一, 为此我们可以为新的服务器指定更大的权重, 而为旧的服务器指定较小的权重降低被访问的频率.
命名空间(namespace)
一个命名空间其实就是一个独立的环境, 只有同一个命名空间下的服务才可以互相访问,
举个例子, 比如orderservice服务需要在内部访问userservice服务的接口,如果userservice与orderservice这个服务在同一个命令空间, orderservice才可以进行访问.如果不是orderservice则会报错, 说找不到userservice这个服务.而nacos默认为我们创建了一个public的命名空间,如果我们没在服务的配置文件中指定命名空间, 则该服务的命名空间默认为public。
当我们在nacos的网页中新建一个命名空间时, 我们就会得到该命名空间的一个UUID
我们可以为服务指定命名空间, 通过application.yml中的spring.cloud.nacos.discovery.namespace指定该服务所属的命名空间, 注意值为命名空间的ID,而不是名称.
集群
我们可以通过application.yml文件中的spring.cloud.nacos.discovery.cluster-name指定该服务所属的集群, 通过nacos的负载均衡则可以发挥集群的作用:服务消费者优先访问同一集群内的服务提供者, 节省访问时间.
在IDEA中为一个服务开启多个实例
学习微服务时, 我们可能需要同一个服务的多个实例, 下面就来介绍如何在IDEA中开启多个实例,
开启多个实例需要注意的是我们不能让多个实例的端口发生冲突.点击编辑服务即可出现下面的画面,
然后进行相关的编辑即可
Eureka组件配置
接下来, 介绍另一个注册组件Eureka, 实现我们需要搭建Eureka的服务端, 我们再注册一个eurekaserver子模块用来搭建EureKa的服务端.目录结构如下
我们再在eurekaserver的pom文件中导入下面的依赖即可:
<!-- eureka服务端依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
只需要这个依赖即可, 不需要导入loadbalancer这个依赖, 因为这个依赖已经包括在eureka中了.
导入依赖后, 我们再在application.yml文件中进行配置即可, 配置如下:
spring:
application:
# 服务名称
name: eurekaserver
server:
port:
10086
eureka:
client:
service-url:
defaultZone: http://localhost:10086/eureka
然后再在启动的类上添加@EnableEurekaServer这个注解即可
@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
至此, eureka服务端已经配置好了, 我们启动项目, 打开 http://localhost:10086即可,打开后看到下面的网页即配置成功了:
Eureka注册:
当我们完成Eureka的服务端搭建后, 我们即可开始将我们的服务注册到该Eureka的服务中了。
在需要进行注册的服务中引入下面的依赖:
<!-- eureka客户端配置 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
然后再在application.yml中添加下面的配置:
spring:
application:
# 服务名称
name: userservice
eureka:
client:
service-url:
defaultZone: http://localhost:10086/eureka
可以看出, eureka的服务搭建和注册几乎差不多. 然后再开始启动服务, 启动完服务后, 再去 http://localhost:10086这个网页查看是否注册成功, 如果出现下面的情况, 则说明已经注册成功了.
到此, springcloud的注册组件nacos和eureka的基本配置和注册已经完成了, 有不足的地方, 还请指出!!!