一. 注册中心Nacos

1. 微服务架构演变过程

传统架构:即单点应用,也就是ssh/ssm项目,该架构模式没有对业务逻辑实现拆分,所有代码都写入到同一个工程中里,适合小公司开发团队或者个人开发;这种架构模式最大的缺点是如果该系统一个模块出现不可用、会导致整个系统无法使用。

分布式架构:分布式架构模式是基于传统的架构模式演变过来,将传统的单点项目根据业务模块实现拆分、会拆分为会员系统、订单系统、支付系统、秒杀系统等。 从而降低我们项目的耦合度,这种架构模式开始慢慢的适合于互联网公司开发团队。

SOA面向服务架构:SOA架构模式也称作为:面向服务架构模式、俗称面向与接口开发,将共同存在的业务逻辑抽取成一个共同的服务,提供给其他的服务接口实现调用、服务与服务之间通讯采用rpc远程调用技术。SOA架构通讯中,采用XML方式实现通讯、在高并发下通讯过程中协议存在非常大冗余性,所以在最后微服务架构模式中使用JSON格式替代了XML;SOA架构模式实现方案为WebService或者是ESB企业服务总线 底层通讯协议SOAP协议(Http+XML)实现传输。

微服架构务:粒度更加精细,让专业的人去做专业的事情,每个服务与服务之间互不影响,微服务架构中 每个服务必须独立部署、互不影响,微服务架构模式体现轻巧、轻量级、适合于互联网公司开发模式。服务与服务通讯协议采用Http协议,使用restful风格API形式来进行通讯,数据交换格式轻量级json格式通讯,整个传输过程中,采用二进制,所以http协议可以跨语言平台,并且可以和其他不同的语言进行相互的通讯。

2. 服务注册与发现

服务治理概念: 在RPC远程调用过程中,服务与服务之间依赖关系非常大,服务Url地址管理非常复杂,所以这时候需要对我们服务的url实现治理,通过服务治理可以实现服务注册与发现、负载均衡、容错等。

注册中心概念:次调用该服务如果地址直接写死的话,一旦接口发生变化的情况下,需要重新发布版本,所以需要一个注册中心统一管理我们的服务注册与发现。常用的注册中心有eureka、consul、zookeeper、nacos等

服务注册:我们的服务启动的时候,会将当前服务自己的信息地址注册到注册中心,key为服务名称、value为该服务调用地址,该类型为集合类型。

服务发现:消费者从我们的注册中心上获取生产者调用的地址(集合),在使用负载均衡的策略获取集群中某个地址实现本地rpc远程调用。

3. Nacos搭建并整合SpringCloud

Nacos可以实现分布式服务注册与发现/分布式配置中心框架,官网介绍:https://nacos.io/zh-cn/docs/what-is-nacos.html

Nacos可以跨平台安装,支持Linux,Windows,Mac,安装教程地址:https://nacos.io/zh-cn/docs/quick-start.html

【手动注册】

参考官网,可以手动实现服务注册:

http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=app-member&ip=192.168.0.108&port=8080

http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=app-member&ip=192.168.0.108&port=8081

参考官网,可以手动实现服务发现:

http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=app-member,可以查到,是一个集群效果,并且登录nacos(默认用户名和密码都是nacos),进入服务管理 - 服务列表可以看到集群信息。

【整合SpringCloud】

新建聚合项目,springcloud-nacos,新建两个module分别为service-member,service-order,在父模块引入公共依赖:

 <!--  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>

新建service-member和service-order配置文件如下:

spring:
  application:
    # 服务的名称
    name: service-member
  cloud:
    nacos:
      discovery:
        # nacos注册地址
        server-addr: 127.0.0.1:8848
server:
  port: 8080
spring:
  application:
    # 服务的名称
    name: service-order
  cloud:
    nacos:
      discovery:
        # nacos注册地址
        server-addr: 127.0.0.1:8848
server:
  port: 8090

启动类只需加@SpringBootApplication即可,不像eureka还得加入@EnableEurekaServer

①. 手写类似Ribbon效果实现RestTemplate调用

  首先在service-member服务编写getUser接口

@RestController
public class MemberService {
    @Value("${server.port}")
    private String serverPort;
    /**
     * 会员服务提供的接口被订单服务调用
     * @param userId
     * @return
     */
    @GetMapping("/getUser")
    public String getUser(Integer userId) {
        System.out.println(userId);
        return "会员服务-端口号为:" + serverPort;
    }
}

  启动两个member服务,端口分别为8080,8081

  接下来编写service-order服务,首先在启动类把RestTemplate注入到Spring容器中:

@SpringBootApplication
public class AppOrder {
    public static void main(String[] args) {
        SpringApplication.run(AppOrder.class);
    }
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

  编写负载均衡器:

@Component
public class RotationLoadBalancer {
    // 从0开始计数
    private AtomicInteger atomicInteger = new AtomicInteger(0);

    public ServiceInstance getSingleAddres(List<ServiceInstance> serviceInstances) {
        int index = atomicInteger.incrementAndGet() % serviceInstances.size(); // 每次计数器+1
        return serviceInstances.get(index);
    }
}

  编写订单服务,并用RestTemplate调用会员服务

@RestController
public class OrderService {

    @Autowired
    private DiscoveryClient discoveryClient;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private RotationLoadBalancer loadBalancer;

    /**
     * 订单服务调用到会员服务接口
     * @return
     */
    @RequestMapping("/orderToMember")
    public Object orderToMember() {
        // 1.根据服务名称从 注册中心获取集群列表地址
        List<ServiceInstance> instances =
                discoveryClient.getInstances("service-member");
        // 2.列表任意选择一个 实现本地rpc调用 rest 采用我们负载均衡的算法
        ServiceInstance serviceInstance = loadBalancer.getSingleAddres(instances);
        URI rpcMemberUrl = serviceInstance.getUri();
        String result = restTemplate.getForObject(rpcMemberUrl + "/getUser", String.class);
        return "订单调用会员返回结果:" + result;
    }

}

此时浏览器访问order接口orderToMember,会发现轮询调用会员服务

    

【服务下线动态感知】

我们可以手动下线/上线服务,当对8081端口下线后,则订单调会员只会走8080,而重新上线后,则继续轮询,期间不用重启服务,直接点击按钮即可。

  最后,SpringCloud自带了Robbon/LoadBalanced实现了客户端负载均衡效果:

// 加上LoadBalanced 注解就可以实现我们的本地负载均衡
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
    return new RestTemplate();
}
  @RequestMapping("/orderToRibbonMember")
public Object orderToRibbonMember() {
    String result = restTemplate.getForObject("http://service-member/getUser", String.class);
    return "订单调用会员返回结果:" + result;
}

  SpringCloudAlibaba默认继承了Ribbon,直接调用即可,而如果是SpringCloudNetflix,则需要引入依赖如下:

<!-- 负载均衡  ribbon -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>

  

 

 

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐