【转】 SpringCloudAlibaba--02——nacos
【转】 SpringCloudAlibaba--02——nacos
SpringCloudAlibaba 实际上对SpringCloud 进行了扩展组件,能够完美整合到SpringCloud RPC 远程调用。
1、Nacos 分布式注册中心、分布式配置中心。SpringCloudEureka+Config 组合
2、目的是为了推广阿里云产品,如果使用SpringCloudAlibaba 最好使用阿里云的整个体系的对应的产品。
* Nacos 分布式注册与发现功能 | 分布式配置中心
产生背景:RPC 远程调用中,服务的url 的治理。
* 传统的RPC 远程调用存在哪些问题
1、超时的问题
2、安全的问题
3、服务与服务之间URL 地址管理
这样就造成服务与服务之间依赖关系非常大,URL 地址一但发生改变,还需要人工修改RPC 远程调用地址,这个管理地址是非常复杂的。
那么要想个办法动态的管理治理这个URL 地址,这样就可以实现对服务动态管理,注册与发现、本地负载均衡、容错等等。
方案:
整个微服务架构中最为核心的肯定是 注册中心。不然都没法通讯。。。
注册中心:实际就是存放微服务的地址信息,可以实现动态感知。
注册中心包括:Dubbo(X)依赖Zookeeper、Eureka、Consuler、Nacos等,redis 也可以实现。
注册中心是不会存接口方法名的,什么getUserById、getName什么的,是不会村的,只会村IP 地址+ 端口号
原理实现:
1、生产者启动时候,会把key(服务名称)+value(IP和端口号)注册到微服务的注册中心。--也肯会是一个集群,就是key一样,value不一样,是多个端口。
2、注册存放服务地址的类型:key是唯一的,value是list集合、一个列表。Map<key,List(String)>
3、消费者去注册中心根据 服务名称查询服务地址列表(集合)
4、消费者获取到集群列表后,采用负载均衡器选择一个RPC 远程调用
* Nacos 介绍
分布式服务注册与发现、分布式配置中心框架
官网地址介绍:https://nacos.io/zh-cn/docs/what-is-nacos.html
* Nacos 环境搭建准备
nacos 可以安装linux、windows、mac 版本都可以安装
具体安装地址参考:https://nacos.io/zh-cn/docs/quick-start.html
在 0.版本选择处 选择下载版本,解压,这里选择的版本是1.1.4版本的,这个版本和springboot的版本会有冲突,所以版本不要瞎搞。
默认端口是:8848,也可以在/conf 目录下的application.properties 文件修改端口或其他配置
/bin 目录下:
启动命令:cmd startup.cmd
或者双击startup.cmd运行文件。
关闭服务器: cmd shutdown.cmd
或者双击shutdown.cmd运行文件。
* 测试服务注册与发现
创建SpringBoot 项目,导入依赖:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.0.RELEASE</version> </parent> <dependencies> <!-- springboot 整合web组件--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>0.2.2.RELEASE</version> </dependency> </dependencies>
配置yml 文件配置nacos:
spring:
application:
###服务的名称
name: test-member
cloud:
nacos:
discovery:
###nacos注册地址
server-addr: 127.0.0.1:8848
写个接口,测试写个controller:
@RestController public class MemberService { @Value("${server.port}") private String serverPort; /** * 会员服务提供的接口被订单服务调用 * * @param userId * @return */ @GetMapping("/getUser") public String getUser(Integer userId) { return "端口号为:" + serverPort; } }
启动main方法:
@SpringBootApplication public class AppSpringBoot { public static void main(String[] args) { SpringApplication.run(AppSpringBoot.class); } }
注意:先启动本地的nacos,
然后浏览器访问 127.0.0.1:8848/nacos ,输入用户名密码就行了,默认都是 nacos
然后就可以看到:
* 使用discoveryClient 从注册中心获取接口地址
创建一个子服务当作消费者,进行编写,
yml 配置文件:和提供者一样,修改端口号和服务名称:
spring:
application:
###服务的名称
name: test-order
cloud:
nacos:
discovery:
###nacos注册地址
server-addr: 127.0.0.1:8848
server:
port: 8090
建个service 包,写个模拟的接口:
@RestController public class OrderService { @Autowired private DiscoveryClient discoveryClient; @Autowired private RestTemplate restTemplate; @Autowired private LoadBalancer loadBalancer; /** * 订单服务调用到我们的会员服务接口 * * @return */ @RequestMapping("/orderToMember") public Object orderToMember() { // 1.根据服务名称从 注册中心获取集群列表地址 List<ServiceInstance> instances = discoveryClient.getInstances("test-member"); // 2.列表任意选择一个 实现本地rpc调用 rest 采用我们负载均衡的算法 ServiceInstance srviceInstance = loadBalancer.getSingleAddres(instances); URI rpcMemberUrl = srviceInstance.getUri(); String result = restTemplate.getForObject(rpcMemberUrl + "/getUser", String.class); return "订单调用会员返回结果:" + result; } }
创建main 方法启动类:
@SpringBootApplication public class AppOrder { public static void main(String[] args) { SpringApplication.run(AppOrder.class); } @Bean public RestTemplate restTemplate() { return new RestTemplate(); } }
然后启动,查看浏览器,并新打一个浏览器窗口访问: http://127.0.0.1:8090/orderToMember ip+端口号+接口名
* 手写本地负载均衡轮询算法
模拟 根据访问次数,访问不同的服务器
先避免吧端口号写死,检查提供者的接口,
@Value("${server.port}") private String serverPort;
这个代码,然后配置文件yml 中配置端口号
server:
port: 8081
启动完提供者,把端口号改成8080,再次启动,模拟2 个的集群,查看服务列表
集群模拟完成,开始撸码
建个包写个接口:LoadBalancer
public interface LoadBalancer { /** * 从注册中心集群列表中获取单个地址 * @param serviceInstances * @return */ ServiceInstance getSingleAddres(List<ServiceInstance> serviceInstances); }
然后写个它的实现类:就是访问次数 模于 服务器数量 的值,就去访问第几个服务器
@Component public class RotationLoadBalancer implements LoadBalancer { /** * 0:表示从0开始计数 */ private AtomicInteger atomicInteger = new AtomicInteger(0); @Override public ServiceInstance getSingleAddres(List<ServiceInstance> serviceInstances) { int index = atomicInteger.incrementAndGet() % serviceInstances.size(); return serviceInstances.get(index); } }
ok,然后在那个OrderService 的类里调用,因为这个是类是调用的服务提供者。