SpringCloud-Alibaba全家桶


来源:Nacos服务注册中心应用实践

Nacos注册中心简介

需求:在微服务中,首先需要面对的问题就是如何查找服务(软件即服务),其次,就是**如何在不同的服务之间进行通信?**如何更好更方便的管理应用中的每一个服务,如何建立各个服务之间联系的纽带,由此注册中心诞生(例如淘宝网卖家提供服务,买家调用服务)。

市面上常用注册中心有Zookeeper(雅虎Apache),Eureka(Netfix),Nacos(Alibaba),Consul(Google),那他们分别都有什么特点,我们如何进行选型呢?我们主要从社区活跃度,稳定性,功能,性能等方面进行考虑即可.本次微服务的学习,我们选择Nacos,它很好的支持了阿里的双11活动,不仅可以做注册中心,还可以作为配置中心,稳定性和性能都很好。

Nacos概述

Nacos(DynamicNaming and Configuration Service)是一个应用于服务注册与发现、配置管理的平台。
官方网址:

https://nacos.io/zh-cn/docs/quick-start.html

安装与配置

第一:确保你电脑已配置JAVA_HOME环境变量(Nacos启动时需要),例如:
在这里插入图片描述
第二:确保你的MySQL版本为5.7以上(MariaDB10.5以上),例如
在这里插入图片描述

下载与安装

第一步:Nacos下载,可在浏览器直接输入如下地址:
下载连接
第二步:选择对应版本,直接下载,如图所示:
在这里插入图片描述
第三步:解压Nacos(最好不要解压到中文目录下),其目录结构如下
在这里插入图片描述
初始化配置
第一步:登陆mysql,执行老师发给同学们的sql脚本。例如,我们可以使用mysql自带客户端,在命令行首先登录mysql,然后执行如下指令

source d:/nacos-mysql.sql 

执行成功以后,会创建一个nacos_config数据库,打开数据库会看到一些表,例如;
在这里插入图片描述
说明:在执行此文件时,要求mysql的版本大于5.7版本(MariaDB最好10.5.11),否则会出现如下错误:
在这里插入图片描述
第二步:打开/conf/application.properties里打开默认配置,并基于你当前环境配置要连接的数据库,连接数据库时使用的用户名和密码(假如前面有"#"要将其去掉):

### If use MySQL as datasource:
spring.datasource.platform=mysql

### Count of DB:
db.num=1

### Connect URL of DB:
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=root
db.password.0=root

服务启动与访问

第一步:启动Nacos服务。 在nacos/bin下启动,或者在外面配置环境变量

Linux/Unix/Mac启动命令(standalone代表着单机模式运行,非集群模式):

./startup.sh -m standalone

Windows启动命令(standalone代表着单机模式运行,非集群模式):

startup.cmd -m standalone

说明:
1)执行执行令时要么配置环境变量,要么直接在nacos/bin目录下去执行.
2)nacos启动时需要本地环境变量中配置了JAVA_HOME(对应jdk的安装目录),
3)一定要确保你连接的数据库(nacos_config)是存在的.
4)假如所有的配置都正确,还连不上,检查一下你有几个数据库(mysql,…)
第二步:访问Nacos服务。
打开浏览器,输入http://localhost:8848/nacos地址,出现如下登陆页面:
在这里插入图片描述
其中,默认账号密码为nacos/nacos.

服务注册与调用入门(重点)

业务描述
创建两个项目Module分别为服务提供者和服务消费者,两者都要注册到NacosServer中(这个server本质上就是一个web服务,端口默认为8848),然后服务提供者可以为服务消费者提供远端调用服务(例如支付服务为服务提供方,订单服务为服务消费方),如图所示:
在这里插入图片描述

怎么注册的?

服务注册之后,每五秒会发送一次心跳包,15秒没没收到说明不健康,当30秒后没收到消息说明服务已经死掉或者听了。

生产者服务创建及注册

第一步:创建服务提供者工程(module名为sca-provider,假如已有则无需创建),继承parent工程(01-sca),其pom.xml文件内容如下

<?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>01-sca</artifactId>
        <groupId>com.jt</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>sca-provider</artifactId>
    <dependencies>
        <!--Web服务-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--服务的注册和发现(我们要讲服务注册到nacos)-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
    </dependencies>
</project>

第二步:创建并修改配置文件application.yml(或者application.properties),实现服务注册,关键代码如下:

server:
   port: 8081
spring:
  application:
    name: sca-provider #进行服务注册必须配置服务名
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848

**注意:**服务名不要使用下划线(“_”),应使用横杠(“-”),这是规则。
第三步:创建启动类(假如已有则无需定义),关键代码如下:

package com.cy;

@SpringBootApplication
public class ProviderApplication {

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

第四步:启动启动类,然后刷先nacos服务,检测是否服务注册成功,如图所示:
在这里插入图片描述
第六步:打开浏览器,输入http://localhost:8081/provider/echo/msa,然后进行访问测试。

消费者服务发现及调用

第一步: 在sca-provider项目中创建服务提供方对象,基于此对象对外提供服务,例如:

    package com.jt.provider.controller;
    /**定义Controller对象(这个对象在spring mvc中给他的定义是handler),
     * 基于此对象处理客户端的请求*/
    @RestController
    public class ProviderController{
        //@Value默认读取项目配置文件中配置的内容
        //8080为没有读到server.port的值时,给定的默认值
        @Value("${server.port:8080}")
        private String server;
        //http://localhost:8081/provider/echo/tedu
        @GetMapping("/provider/echo/{msg}")
        public String doRestEcho1(@PathVariable String msg){
            return server+" say hello "+msg;
        }
    }

第二步:创建服务消费者工程(module名为sca-consumer,假如已有则无需创建),继承parent工程(01-sca),其pom.xml文件内容如下:

<?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>01-sca</artifactId>
        <groupId>com.jt</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>sca-consumer</artifactId>
    
   <dependencies>
    <!--Web服务-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--服务的注册和发现(我们要讲服务注册到nacos)-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    </dependencies>
</project>

第三步:修改配置文件application.yml,关键代码如下:

server:
  port: 8090
spring:
  application:
    name: sca-consumer #服务注册时,服务名必须配置
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #从哪里去查找服务

第四步:创建消费端启动类并实现服务消,关键代码如下:

package com.cy;
@SpringBootApplication
public class ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class,args);
    }
}

第五步:在启动类中添加如下方法,用于创建RestTemplate对象.

@Bean
public RestTemplate restTemplate(){//基于此对象实现远端服务调用
    return new RestTemplate();
}

第六步:定义服务消费端Controller,在此对象方法内部实现远端服务调用

package com.jt.consumer.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;


/**
 * 定义服务消费端Controller,在这个Controller对象
 * 的方法中实现对远端服务sca-provider的调用
 */
@RestController
public class ConsumerController {
    /**
     * 从spring容器获取一个RestTemplate对象,
     * 基于此对象实现远端服务调用
     */
    @Autowired
    private RestTemplate restTemplate;
    /**
     * 在此方法中通过一个RestTemplate对象调用远端sca-provider中的服务
     * @return
     * 访问此方法的url: http://localhost:8090/consumer/doRestEcho1
     */
    @GetMapping("/consumer/doRestEcho1")
    public String doRestEcho01(){
        //1.定义要调用的远端服务的url
        String url="http://localhost:8081/provider/echo/8090";
        //2.基于restTemplate对象中的相关方法进行服务调用
        return restTemplate.getForObject(url, String.class);
    }

}

第七步:启动消费者服务,并在浏览器输入http://localhost:8090/consumer/doRestEcho1地址进行访问,假如访问成功会出现,如图所示效果:
在这里插入图片描述

核心知识点

服务注册中心诞生背景? (服务多了,需要统一管理,例如所有公司需要在工商局进行备案)
服务注册中心的选型?(社区活跃度,稳定性,功能,性能,学习成本)
Nacos下载,安装,配置,启动,访问(http://ip:port/nacos)
基于Nacos实现服务的注册?(添加依赖,服务配置,启动服务并检查)
基于RestTemplate实现服务的简易调用?(服务消费方调用服务提供方)

常见问题分析

如何理解服务注册中心?(存储服务信息的一个服务)
服务注册中心诞生的背景? (服务多了,需要对服务进行更好管理)
市场上常用的注册中心?(Zookeeper,Eureka,Nacos,Consul)
如何对注册中心进行选型?(社区活跃度,稳定性,功能,性能,学习成本)
Nacos 是什么?(是Alibaba公司基于SpringBoo技术实现的一个注册中心,本质上也是一个web服务)
Nacos 的基本架构?(Client/Server架构)
Nacos 主要提供了什么核心功能?(服务的注册,发现,配置)
Nacos 服务启动需要什么前置条件?(配置JDK的JAVA_HOME目录,安装MySQL5.7以上版本,配置连接的数据库)
Nacos 服务单机模式,window平台下启动时的指令是什么?(startup.cmd -m standalone)
实现Nacos服务注册需要添加什么依赖?(两个:web,discovery)
实现Nacos服务注册时,必须做哪些配置?(服务名,假如是本机服务注册可以省略服务地址)
Nacos如何检查服务状态?(通过心跳包实现,服务启动时会定时向nacos发送心跳包-BeatInfo)
服务之间进行服务调用时,使用了什么API?(RestTemplate,用此对象之前要先创建这个对象并交给spring管理)

小节面试分析

为什么要将服务注册到nacos?(为了更好的查找这些服务)
在Nacos中服务提供者是如何向Nacos注册中心(Registry)续约的?(5秒心跳)
对于Nacos服务来讲它是如何判定服务实例的状态?(检测心跳包,15,30)
服务启动时如何找到服务启动注册配置类?(NacosNamingService)
服务消费方是如何调用服务提供方的服务的?(RestTemplate)

基于idea启动nacos

-m standalone

在这里插入图片描述

基于idea链接database数据库

第一步:打开DataSource,找到mysql,例如:
在这里插入图片描述
第二步:配置连接的数据库,需要导入MySQL的本地架包 例如:

jdbc:mysql://localhost:3306/nacos_config?serverTimezone=Asia/Shanghai&characterEncoding=utf8

在这里插入图片描述

服务负载均衡设计及实现(重点)

业务描述
一个服务实例可以处理请求是有限的,假如服务实例的并发访问比较大,我们会启动多个服务实例,让这些服务实例采用一定策略均衡(轮询,权重,随机,hash等)的处理并发请求,在Nacos中服务的负载均衡(Nacos客户端负载均衡)是如何应用的?

核心知识点

负载均衡诞生背景.
基于LoadBalancerClient 对象实现服务发现及负载均衡(choose)
@Loadbalanced注解的作用以及应用分析
基于Feign方式的远程服务调用实践

常见问题分析

为什么负载均衡?(通过多个服务实例均衡处理客户端的请求)
如何理解服务发现?(服务发现就是从注册中心获取服务信息,例如从nacos获取服务实例信息)
LoadBalancerClient的作用?(从nacos注册中心获取服务实例列表,然后本地基于负载均衡算法获取服务实例)
@Loadbalanced注解作用?(描述RestTemplate对象,让系统底层为RestTemplate对象赋能)
你了解哪些负载均衡策略?(基于IRule接口去查看)
我们如何修改负载均衡策略?(配置文件,配置类)
Feign是什么?(Spring Cloud微服务规范中的一组远程调用API)
为什么使用Feign?(优化服务调用结构)
如何使用Feign实现服务调用?(依赖,@EnableFeignClients,@FeignClient)
Feign方式的服务调用原理是怎样的?(底层基于代理对象实现)
常用服务发现、服务调用方式有哪些?
在这里插入图片描述

常见Bug分析

NullPointerException,例如:

在这里插入图片描述

端口被占用,例如

在这里插入图片描述

UnknownHostException,例如

在这里插入图片描述

修改sca-consumer端默认的负载均衡策略?

方案1:修改sca-consumer配置文件(application.yml),添加如下语句,例如:

sca-provider:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

方案2:修改sca-consumer的启动类,在启动类中添加如下方法,例如:

@Bean
public IRule ribbonRule() {
    return new RandomRule();
}

LoadBalancerClient应用

LoadBalancerClient对象是springcloud提供的!ServiceInstance也是。
LoadBalancerClient对象可以从nacos中基于服务名获取服务实例,然后在工程中基于特点算法实现负载均衡方式的调用,案例实现如下:
第一步:修改ConsumerController类,注入LoadBalancerClient对象,并添加doRestEcho2方法,然后进行服务访问.


  @Autowired
  private LoadBalancerClient loadBalancerClient;
   
  @GetMapping("/consumer/doRestEcho02")
 public String doRestEcho02(){
     ServiceInstance serviceInstance = loadBalancerClient.choose("sca-provider");
     String url = String.format("http://%s:%s/provider/echo/%s",serviceInstance.getHost(),serviceInstance.getPort(),appName);
     System.out.println("request url:"+url);
     return restTemplate.getForObject(url, String.class);
     }
 }

第二步:打开Idea服务启动配置,如图所示:
在这里插入图片描述
第三步:修改并发运行选项(假如没有找到这个选项我们需要通过搜索引擎基于组合查询的方法,去找到对应的解决方案,例如搜索 idea allow parallel run),如图所示:
在这里插入图片描述
第四步:修改sca-provider的配置文件端口,分别以8081,8082端口方式进行启动。

server:
  port: 8082
spring:
  application:
    name: sca-provider
  cloud:
    nacos:
      server-addr: localhost:8848

启动成功以后,访问nacos的服务列表,检测服务是否成功注册,如图所示:
在这里插入图片描述
第四步:启动sca-consumer项目模块,打开浏览器,输入如下网址进行反复服务访问:
http://localhost:8090/consumer/doRestEcho02
然后会发现sca-provider的两个服务都可以处理sca-consumer的请求。
在这里插入图片描述
这里多个实例并发提供服务的方式为负载均衡,这里的负载均衡实现默认是因为Nacos集成了Ribbon来实现的,Ribbon配合RestTemplate,可以非常容易的实现服务之间的访问。Ribbon是Spring Cloud核心组件之一,它提供的最重要的功能就是客户端的负载均衡(客户端可以采用一定算法,例如轮询访问,访问服务端实例信息),这个功能可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡方式的服务调用。

@LoadBalanced

当使用RestTemplate进行远程服务调用时,假如需要负载均衡,可以在RestTemplate对象构建时,使用@LoadBalanced对构建RestTemplate的方法进行修饰,例如在ConsumerApplication中构建名字为loadBalancedRestTemplate的RestTemplate对象:

@Bean
@LoadBalanced
public RestTemplate loadBalancedRestTemplate(){
    return new RestTemplate();
}

在需要RestTemplate实现负载均衡调用的地方进行依赖注入.例如在ConsumerController类中添加loadBalancedRestTemplate属性

@Autowired
private RestTemplate loadBalancedRestTemplate;

接下来,可以在对应的服务端调用方的方法内,基于RestTemplate借助服务名进行服务调用, 例如:

@GetMapping("/consumer/doRestEcho3")
public String doRestEcho03(){
    String url=String.format("http://%s/provider/echo/%s","sca-provider",appName);
    //向服务提供方发起http请求,获取响应数据
    return loadBalancedRestTemplate.getForObject(
            url,//要请求的服务的地址
            String.class);//String.class为请求服务的响应结果类型
}

RestTemplate在发送请求的时候会被LoadBalancerInterceptor拦截,它的作用就是用于RestTemplate的负载均衡,LoadBalancerInterceptor将负载均衡的核心逻辑交给了loadBalancer,核心代码如下所示(了解):

public ClientHttpResponse intercept(final HttpRequest request, 
    final byte[] body, final ClientHttpRequestExecution execution) throws IOException {
	final URI originalUri = request.getURI();
	String serviceName = originalUri.getHost();
	return this.loadBalancer.execute(serviceName, 
    requestFactory.createRequest(request, body, execution));
}

@LoadBalanced注解是属于Spring,而不是Ribbon的,Spring在初始化容器的时候,如果检测到Bean被@LoadBalanced注解,Spring会为其设置LoadBalancerInterceptor的拦截器。

Ribbon负载均衡策略(了解)

基于Ribbon方式的负载均衡,Netflix默认提供了七种负载均衡策略,对于SpringCloud Alibaba解决方案中又提供了NacosRule策略,默认的负载均衡策略是轮训策略。如图所示:
在这里插入图片描述
当系统提供的负载均衡策略不能满足我们需求时,我们还可以基于IRule接口自己定义策略.

小节面试分析

@Bean注解的作用?(一般用于配置类内部,描述相关方法,用于告诉spring此方法的返回值要交给spring管理,bean的名字默认为方法名,假如需要指定名字可以@Bean(“bean的名字”),最多的应用场景是整合第三方的资源-对象)
@Autowired注解的作用?(此注解用于描述属性,构造方法,set方法等,用于告诉spring框架,按找一定的规则为属性进行DI操作,默认按属性,方法参数类型查找对应的对象,假如只找到一个,则直接注入,类型多个时还会按照属性名或方法参数名进行值的注入,假如名字也不同,就出报错.)
Nacos中的负责均衡底层是如何实现的?(通过Ribbon实现,Ribbon中定义了一些负载均衡算法,然后基于这些算法从服务实例中获取一个实例为消费方法提供服务)
Ribbon 是什么?(Netflix公司提供的负载均衡客户端,一般应用于服务的消费方法)
Ribbon 可以解决什么问题? (基于负载均衡策略进行服务调用, 所有策略都会实现IRule接口)
Ribbon 内置的负载策略都有哪些?(8种,可以通过查看IRule接口的实现类进行分析)
@LoadBalanced的作用是什么?(描述RestTemplate对象,用于告诉Spring框架,在使用RestTempalte进行服务调用时,这个调用过程会被一个拦截器进行拦截,然后在拦截器内部,启动负载均衡策略。)
我们可以自己定义负载均衡策略吗?(可以,基于IRule接口进行策略定义,也可以参考NacosRule进行实现)

基于Feign的远程服务调用(重点)

背景分析

服务消费方基于rest方式请求服务提供方的服务时,一种直接的方式就是自己拼接url,拼接参数然后实现服务调用,但每次服务调用都需要这样拼接,代码量复杂且不易维护,此时Feign诞生。

Feign是什么

Feign 是一种声明式Web服务客户端,底层封装了对Rest技术的应用,通过Feign可以简化服务消费方对远程服务提供方法的调用实现。如图所示:
在这里插入图片描述
Feign 最早是由 Netflix 公司进行维护的,后来 Netflix 不再对其进行维护,最终 Feign 由一些社区进行维护,更名为 OpenFeign。

Feign应用实践(掌握)

第一步:在服务消费方,添加项目依赖(SpringCloud团队基于OpenFeign研发了starter),代码如下:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

第二步:在启动类上添加@EnableFeignClients注解,代码如下:

@EnableFeignClients
@SpringBootApplication
public class ConsumerApplication {}

第三步:定义Http请求API,基于此API借助OpenFeign访问远端服务,代码如下:

package com.jt.consumer.service;
@FeignClient(name="sca-provider")//sca-provider为服务提供者名称
public interface RemoteProviderService{
    @GetMapping("/provider/echo/{string}")//前提是远端需要有这个服务
    public String echoMessage(@PathVariable("string") String string);
}

其中,@FeignClient描述的接口底层会为其创建实现类。
第四步:创建FeignConsumerController中并添加feign访问,代码如下:

 package com.jt.consumer.controller;
@RestController
@RequestMapping("/consumer/ ")
public class FeignConsumerController {
    @Autowired
    private RemoteProviderService remoteProviderService;
    /**基于feign方式的服务调用*/
    @GetMapping("/echo/{msg}")
    public String doFeignEcho(@PathVariable  String msg){
        //基于feign方式进行远端服务调用(前提是服务必须存在)
        return remoteProviderService.echoMessage(msg);
    }
}


第五步:启动消费者服务,在浏览器中直接通过feign客户端进行访问,如图所示(反复刷新检测其响应结果):
在这里插入图片描述

基于idea运行sentinet

-Dserver.port=8180
-Dcsp.sentinel.dashboard.server=localhost:8180
-Dproject.name=sentinel-dashboard
-jar
E:/devcloud/sentinel/sentinel-dashboard-1.8.1.jar

在这里插入图片描述

整合网关sso-gateway

http://localhost:9000/sso/oauth/token?username=admin&password=123456&client_id=gateway-client&grant_type=password&client_secret=123456
在这里插入图片描述

get

http://localhost:9000/sso/
基于网关进行资源访问测试,例如:
在这里插入图片描述
在这里插入图片描述
Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2Mzg3NjAxNzksInVzZXJfbmFtZSI6ImFkbWluIiwiYXV0aG9yaXRpZXMiOlsic3lzOnJlczpjcmVhdGUiLCJzeXM6cmVzOmxpc3QiLCJzeXM6cmVzOmRlbGV0ZSJdLCJqdGkiOiI3MjYyZDQ5ZS03NmU1LTRhZjMtODMwMC0zNDI3N2M2OGQzZDgiLCJjbGllbnRfaWQiOiJnYXRld2F5LWNsaWVudCIsInNjb3BlIjpbImFsbCJdfQ.4B2s8nu45rWJWanulBQlbHj-ccpnf0lV1wpQf4sD51g

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值