SpringCloud之微服务实用篇1

Posted nuist__NJUPT

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringCloud之微服务实用篇1相关的知识,希望对你有一定的参考价值。

今天我们主要学习的内容包含5个部分,分别为认识微服务,分布式服务架构案例,euraka注册中心,Ribbon负载均衡原理,nacos注册中心。

目录

一、微服务

1.1、认识微服务

1.2、服务的拆分及远程调用

1.3、 euraka注册中心

1.4、Ribbon负载均衡原理 

1.5、 nacos注册中心

1.6、Eureka和Nacos对比


一、微服务

1.1、认识微服务

首先我们看一下微服务的架构,首先看一下单体架构,一般适用于小型的项目,将所有业务的功能在一个项目中开发,然后进行打包放到服务器中,客户端就可以进行访问了,这种部署简单,但是代码耦合度较高,不适合大型项目的发布和维护。

对于大型的项目一般采用分布式架构,分布式架构就是根据功能拆分成不同的项目,每个功能对应一个项目,即对应一个服务,分布式架构有利于降低模块之间的耦合性,当然分布式结果也会带来一些问题。

我们可以看到微服务也面临下面几个问题,比如:怎么去拆分,拆分模块的力度怎么把握?对与服务需要集群,集群的地址怎么维护呢?由于服务都是在不同的项目下,如果需要调用别的服务的接口怎么调用呢?为了防止调用坏掉的服务,防止级联失败,怎么去感知服务是否健康呢?

目前常用的是分布式微服务架构,微服务架构特征如下:

包括:单一职责,面向服务,独立,隔离性强;本质上 就是为了实现高内聚和低耦合,降低服务之间的影响范围。

下面我们看一下常用的微服务技术的对比:

我们先了解一下SpringCloud微服务体系,具体如下:
SpringCloud是集成了各种微服务的组件,基于SpringBoot实现了这些组件的自动装配,使得实现了开箱即用的效果。

 下面看一下SpringCloud和SpringBoot的版本兼容介绍,我们学习用的版本是boot版本的。

1.2、服务的拆分及远程调用

1)服务的拆分

在进行服务拆分之前,我们需要注意以下几个问题,首先,需要注意要保证不同的微服务开发不同的业务,防止业务的重复开发;微服务的数据应该独立,应该做到仅访问自己的数据库,不访问其它微服务的数据库;微服务应该可以将自己的业务暴露为接口,供其它微服务调用。

我们使用了一个已有的demo演示服务的拆分和远程调用,首先我们把订单查询和id查询拆分成两个不同的业务,两个数据表去模拟两个不同的数据库。

启动两个微服务,如下有两个运行的微服务,分别是根据id查用户和根据id查订单。

我们现在 浏览器测试一下两个微服务是否能正常工作,如下:

 

2) 服务的远程调用

根据正常的需求要求根据id查询订单同时返回订单消息和用户消息,因为属于不同的服务,那么就需要涉及服务的远程调用了。

 

一般可以使用注册RestTemplate实现服务的远程调用,首先在启动类创建RestTemplate对象,并注入Spring容器。


import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication

public class OrderApplication 

    public static void main(String[] args) 
        SpringApplication.run(OrderApplication.class, args);
    


    @Bean //创建RestTemplate对象,并注入Spring容器
    public RestTemplate restTemplate()
        return new RestTemplate() ;
    



然后就可以在表现层注入RestTemplate对象,并使用该对象发送http请求,实现服务器的远程调用,具体如下:

import cn.itcast.feign.pojo.User;
import cn.itcast.order.pojo.Order;
import cn.itcast.order.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@RequestMapping("order")
public class OrderController 

   @Autowired
   private OrderService orderService;

   @Autowired
   private RestTemplate restTemplate ;

    @GetMapping("orderId")
    public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) 
        // 根据id查询订单并返回
        Order order = orderService.queryOrderById(orderId) ;
        // 利用restTemplate发送http请求,查询用户
        String url = "http://localhost:8081/user/" + order.getUserId();
        //发送http请求实现远程调用
        User user = restTemplate.getForObject(url, User.class);
        // 封装uer对象到order中
        order.setUser(user) ;
        return order;
    

测试结果如下:可以看到在查询用户订单信息,同时把用户信息也查询出来了。

1.3、 euraka注册中心

我们在之前的案例中可以发现order-service是调用user-service,所有前者是服务的消费者,后者是服务的提供者。对于服务可以存在调用和调用的情况,即服务既是消费者又是提供者。

我们看一下Eureka的基本原理,服务提供者会向注册中心注册自己的信息,消费者需要信息时候,直接根据服务名称从注册中心拉去即可。如果服务提供者提供多个服务,一般会根据负载均衡原理从服务列表中挑一个。服务提供者每30s会向注册中心提供一次心跳,这样就可以感知服务的健康状态了,有效地避免了消费者拉去到不健康的服务。

接下来我们进行实践练习一下,该实践一共分为3步,具体如下,首先搭建注册中心,然后将服务都注册到注册中心,最后在order-service中完成服务拉取,通过负载均衡挑选一个服务实现远程调用。

1)搭建注册中心

主要分为三个步骤:1、引入依赖;2、加入启动注解;3、配置eureka地址。

引入依赖:

<?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>cloud-demo</artifactId>
        <groupId>cn.itcast.demo</groupId>
        <version>1.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>eureka-server</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!--eureka服务端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>
</project>

在启动类加入启动注解:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication 
    public static void main(String[] args) 
        SpringApplication.run(EurekaApplication.class, args);
    

配置eureka地址:

server:
  port: 10086 # 服务端口
spring:
  application:
    name: eurekaserver # eureka的服务名称
eureka:
  client:
    service-url:  # eureka的地址信息
      defaultZone: http://127.0.0.1:10086/eureka

在浏览器测试效果如下,即说明搭建注册中心成功。

2)服务注册

服务注册一共两步:导入依赖、配置eureka地址。

将user-service和order-service分别进行注册,具体如下:

在pom.xml配置依赖如下:


        <!--配置eureka客户端依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

在.yml文件种配置地址,当然也可以把服务的名称加上。


eureka:
  client:
    service-url:  # eureka的地址信息
      defaultZone: http://127.0.0.1:10086/eureka

在浏览器测试注册效果如下,可以发现服务均注册到eureka注册中心。

 

另外,可以再次启动user-service服务,模拟多个实例部署,方法如下:

 部署完实例后,启动,可以在浏览器的注册中心看到新注册的实例,一个服务有两个实例,如下:

 3)在order-service中完成服务拉取,通过负载均衡挑选一个服务实现远程调用

只需要将表现层的硬编码获取url方式,改成通过服务名称从注册中心拉取即可,然后需要加上负载 均衡注解。


import cn.itcast.feign.pojo.User;
import cn.itcast.order.pojo.Order;
import cn.itcast.order.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@RequestMapping("order")
public class OrderController 

   @Autowired
   private OrderService orderService;

   @Autowired
   private RestTemplate restTemplate ;

    @GetMapping("orderId")
    public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) 
        // 根据id查询订单并返回
        Order order = orderService.queryOrderById(orderId) ;
        // 利用restTemplate发送http请求,查询用户
        String url = "http://userservice/user/" + order.getUserId();
        //发送http请求实现远程调用
        User user = restTemplate.getForObject(url, User.class);
        // 封装uer对象到order中
        order.setUser(user) ;
        return order;
    

在启动类的远程调用服务对象RestTemplate中加入负载均衡注解即可。


import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication

public class OrderApplication 

    public static void main(String[] args) 
        SpringApplication.run(OrderApplication.class, args);
    


    @LoadBalanced
    @Bean //创建RestTemplate对象,并注入Spring容器
    public RestTemplate restTemplate()
        return new RestTemplate() ;
    



总结:本节主要学习搭建注册中心,注册服务,发现服务(按照负载均衡从注册中心拉去服务)

1.4、Ribbon负载均衡原理 

1)负载均衡流程

我们先看一下负载均衡的流程,具体如下 ,首先是消费服务发送请求到Ribbon,Ribbon向注册中心拉去服务,然后通过负载均衡原理选取一个实例完成服务。

那么Ribbon中做负载均衡的具体流程是什么样?我们看一下,首先Ribbon客户端会使用拦截器拦截请求,交给Dynamic**对象去获取url中的id并从eureka注册中心中拉去服务列表,根据IRule中的负载均衡规则选择某个服务交给Ribbon客户端,由Ribbon客户端选择一个服务完成请求。

 2)负载均衡策略

负载均衡的规则有很多,常见的规则如下所示,有轮循,随机等规则。

既然知道了有上述的规则,那么如何自定义选择实现具体的负载均衡策略呢,如下:

有两种方式,第一种,使用代码的方式,自定义负载均衡的规则,这种是全局方案。

 第二种是针对某一个具体的微服务而言的,直接在配置文件中修改该服务的负载聚恒规则。

3)Ribbon饥饿加载

对于Ribbon的懒加载,第一次加载项目会耗时较大,一般可以配置成饥饿加载的方式。

总结:本节学习了Ribbon负载均衡的原理,主要包含三个方面,第一,负载均衡的规则,第二,负载均衡的定义方式,第三,设置饥饿加载。

1.5、 nacos注册中心

1)认识和安装Nacos

首先Nacos注册中心是阿里的产品,是springcloud的一个组件,使用度还是比较高的,值得学习。

去官网下载即可,下载后解压,在bin目录下,使用命令行启动Nacos,如下:

然后可以通过给出的浏览器地址进行访问,初始的用户名和密码都是nacos,如下:

2)Nacos快速入门

对于Nacos注册中心的使用,首先需要配置主配置文件管理依赖。


            <!--nacos的管理依赖-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.5.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

然后修改原来的user-service中的eureka注册中心依赖换成Nacos注册中心依赖,如下:

    <!-- nacos依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

然后需要在.yml文件中配置nacos的服务器地址,具体如下:

server:
  port: 8081
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/cloud_user?useSSL=false
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver
  application:
        name: userserver # user的服务名称
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #配置nacos服务器地址

mybatis:
  type-aliases-package: cn.itcast.user.pojo
  configuration:
    map-underscore-to-camel-case: true
logging:
  level:
    cn.itcast: debug
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS


#eureka:
#  client:
#   service-url:  # eureka的地址信息
#      defaultZone: http://127.0.0.1:10086/eureka

将order-service注入到nacos中的方法和这个一样,不再赘述。

最后,启动两个服务,在注册中心nacos服务器的业面可以观察到注册的服务,user服务有2个实例,order服务有一个实例。 

3)Nacos服务器分级存储模型

Nacos服务分级存储模型主要包含三级,服务包含多个集群,每个集群中包含若干个实例。

如果像设置服务的集群属性,我们呢首先创建三个user服务,然后需要在.yml文件中进行配置,如下属性,并启动服务,则该服务即属于该集群。

然后就可以在nacos的服务端看到三个实例分布在三个集群中,如下:

我们总结一下NacosRule负载均衡的策略,就是优先选择同一集群的实例,没有找到,才去采用负载均衡挑选实例。

另外,对于负载均衡问题,实际部署的场景中,有些服务器的性能好,一些差,根据服务器性能分配负载任务,即服务器性能好的分配的权重大一些。 

直接在nacos服务端的控制台修改权重就可以了,权重越大,服务被访问的概率越大。

 

4)Nacos环境隔离

Nacos的服务和数据存储最外层都有一个名叫namespace的用来做外层隔离的东西。

在Nacos服务端建立一个命名空间,如下所示:

需要在.yml文件中配置命名空间,主要是根据上面命名空间生成的id进行配置。

然后重启order-service服务,可以在Nacos中发现该服务已经放到新的命名空间dev中,而不是在命名空间public中。

最后,需要注意的是namespace用来做环境隔离,每个namespace都有唯一的id,不同的namespace下服务不可见。

1.6、Eureka和Nacos对比

注册中心Eureka和Nacos都支持服务注册和周期性拉取,都支持用心跳方式做健康检测。

它们俩的区别在于Nacos支持注册检测提供者的健康状态,对于临时实例和非临时实例采用不同检测模式。两个注册中心各有优势。

以上是关于SpringCloud之微服务实用篇1的主要内容,如果未能解决你的问题,请参考以下文章

SpringCloud之微服务实用篇1

SpringCloud之微服务实用篇1

SpringCloud之微服务实用篇2

SpringCloud之微服务实用篇2

SpringCloud之微服务实用篇3-docker

SpringCloud之微服务实用篇3-docker