本文共 7245 字,大约阅读时间需要 24 分钟。
安装包:
下载nacos-server-$version.zip包,Windows下载解压后(.zip),直接点击bin/startup.cmd就可以了。默认启动端口是8848,可以在conf下找到application.properties文件,对server.port进行修改。
可视化控制台:http://localhost:8848/nacos, 默认的用户名和密码都是nacos。
nacos.zip解压,绿色版,启动服务。注意:解压路径一定不要有中文或括号之类的字符,包括(x86),否则可能无法启动。
因为解压到了D:\Program Files (x86)下,解压路径不能包含括号,移到D:\Program Files下完美解决。
解决方案:
执行startup.cmd -m standalone
如果不喜欢以命令的方式启动,可以通过修改D:\Program Files\nacos\bin\startup.cmd文件, 然后我们将原来的set MODE="cluster"集群改为set MODE="standalone"单机 ,然后在直接鼠标点击startup.cmd启动即可。在父工程路径下创建子工程,让子工程继承父工程的环境依赖,子工程pom.xml 中添加 nacos 发现组件(可以放在父pom,当项目庞大起来,子工程越来越多,此时继承父pom即可,避免重复代码)。
pom.xml配置
com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery
application.yml 中配置,项目启动时是否会注册,取决于spring.application.name的配置
或者不使用application.yml ,直接在主类上使用@EnableDiscoveryClient。server: port: 8081spring: cloud: nacos: discovery: # 指定nacos server地址,不用写http://,不配置默认是本机localhost:8848 server-addr: localhost:8848 application: # 指定提供者的名字,注册服务的关键因素,注释掉name就不会再注册 name: my-provider
项目启动就会自动在注册中心注册一个实例,如图所示:
小提示:idea可以启动同一个项目多次,在run 配置中勾选Allow parallel run即可启动多个实例,记得修改端口再启动哦。
子项目(消费者)
第一步:添加依赖; 第二步:使用DiscoveryClient来获取提供者列表; 第三步:使用RestTemplate进行服务调用,但是RestTemplate没有被纳入Spring管理,无法直接使用注解,可以自己实现一个配置类,将RestTemplate纳入Spring管理,pom.xml 添加 discovery,完成服务发现。
com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery
DiscoveryClient是专门负责服务注册和发现的,我们可以通过它获取到注册到注册中心的所有服务
RestTemplate是专门进行服务调用的
添加一个配置类,使用@Bean将RestTemplate纳入Spring容器管理,业务层就可用@Autowired直接依赖使用。
package com.gs.consumer.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.client.RestTemplate;@Configurationpublic class ConsumerConfig { @Bean public RestTemplate restTemplate(){ return new RestTemplate(); }}
通过 discoveryClient 发现注册到 nacos 中的 provider 服务,再通过RestTemplate 进行服务调用。
整合:这种方式比较麻烦,而且随机数的生成也不合理,稍后介绍更便捷用法-Ribbon。package com.gs.consumer.controller;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cloud.client.ServiceInstance;import org.springframework.cloud.client.discovery.DiscoveryClient;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;import java.util.List;import java.util.concurrent.ThreadLocalRandom;@RestControllerpublic class ConsumerController { @Autowired private RestTemplate restTemplate; // 前提:RestTemplate 纳入Spring容器管理 @Autowired private DiscoveryClient discoveryClient; @GetMapping("/instances") public Listinstances(){ List provider = discoveryClient.getInstances("my-provider"); return provider; } @GetMapping("/consumer") public String test1() { // 获取提供者实例 List provider = discoveryClient.getInstances("my-provider"); // 根据提供者个数生成随机数,随机调用提供者 // 整合:这种方式比较麻烦,而且随机数的生成也不合理,稍后介绍更便捷用法-Ribbon。 int index = ThreadLocalRandom.current().nextInt(provider.size()); // 调用提供者实例的index方法 String url = provider.get(index).getUri() + "/index"; return "consumer随机远程调用provier:" + this.restTemplate.getForObject(url, String.class); }}
使用Ribbon优化上述的DiscoveryClient 和 RestTemplate 用法。
在配置类上使用@Bean + @LoadBalanced注解,将RestTemplate纳入Spring容器管理。 注意:使用Ribbon负载均衡的时候服务名中不能使用下划线,不然会找不到服务。package com.gs.consumer.config;import org.springframework.cloud.client.loadbalancer.LoadBalanced;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.client.RestTemplate;@Configurationpublic class ConsumerConfig { @Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); }}
在调用时不需要再使用DiscoveryClient进行服务列表的获取,不需要自行生成随机数来进行负载分发,将一切交给Ribbon。
我们只需要提供url,形如http://serviceId/api@RestControllerpublic class ConsumerController { @Autowired private RestTemplate restTemplate; @GetMapping("/consumer") public String index(){ return "consumer随机远程调用provier:" + this.restTemplate.getForObject("http://my-provider/index", String.class); }}
负载均衡,默认策略是随机,权重1:1
测试: 小提示:idea可以启动同一个项目多次,在run 配置中勾选Allow parallel run即可启动多个实例,记得修改端口再启动哦。随机(默认)
server: port: 8081my-provider: ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
自定义策略,继承AbstractLoadBalancerRule,重写choose方法
package com.gs.provider.config;import com.alibaba.cloud.nacos.NacosDiscoveryProperties;import com.alibaba.cloud.nacos.ribbon.NacosServer;import com.alibaba.nacos.api.exception.NacosException;import com.alibaba.nacos.api.naming.NamingService;import com.alibaba.nacos.api.naming.pojo.Instance;import com.netflix.client.config.IClientConfig;import com.netflix.loadbalancer.AbstractLoadBalancerRule;import com.netflix.loadbalancer.BaseLoadBalancer;import com.netflix.loadbalancer.Server;import org.springframework.beans.factory.annotation.Autowired;/** * Nacos 自定义负载策略 */public class BalanceWeightRule extends AbstractLoadBalancerRule { @Autowired private NacosDiscoveryProperties discoveryProperties; @Override public Server choose(Object o) { // 获取负载均衡的对象 BaseLoadBalancer baseLoadBalancer = (BaseLoadBalancer) getLoadBalancer(); // 获取当前调用的微服务的名称 String serviceName = baseLoadBalancer.getName(); // 获取Nocas服务发现的相关组件API NamingService namingService = discoveryProperties.namingServiceInstance(); try { // 获取一个基于 nacos client 实现权重的负载均衡算法 Instance instance = namingService.selectOneHealthyInstance(serviceName); System.out.println("选择的实例是port={" + instance.getPort() + "},instance={" + instance + "}"); // 返回一个nacos的server return new NacosServer(instance); } catch (NacosException e) { e.printStackTrace(); return null; } } @Override public void initWithNiwsConfig(IClientConfig iClientConfig) { }}
package com.gs.provider.config;import com.netflix.loadbalancer.IRule;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class RibbonConfig { @Bean public IRule getRule() { // 实现带有权重的负载均衡策略 return new BalanceWeightRule(); }}
server: port: 8082spring: application: # 注册服务的关键因素,注释掉name就不会再注册 name: my-provider# 针对此服务设置负载策略my-provider: ribbon: NFLoadBalancerRuleClassName: com.gs.provider.config.BalanceWeightRule
转载地址:http://lzqgn.baihongyu.com/