12-2108微服务课上问题分析及总结

文章目录

  • Day01~微服务架构入门
    • 核心知识点
    • 常见问题分析
    • 常见Bug分析
    • 课堂练习
    • 课后作业
  • Day02~Nacos注册中心入门
    • 核心知识点
    • 常见问题分析
    • 常见Bug分析
    • 课堂小技巧
    • 课后作业
  • Day03~基于Nacos实现服务发现与调用
    • 核心知识点
    • 常见问题分析
    • 常见Bug分析
    • 课堂练习
    • 课后作业
  • Day04~基于Feign方式的服务调用实践
    • 核心知识点
    • 常见问题分析
    • 常见Bug分析
    • 课上技巧
    • 课上练习
    • 课后作业
  • Day05~Nacos配置中心应用实践
    • 核心知识点
    • 常见问题分析
    • 常见Bug分析
    • 课后作业

Day01~微服务架构入门

核心知识点

  • 微服务架构诞生的背景(软件即服务,将一个大型软件,拆成若干个小系统;分而治之~北京一个火车站到多个火车站)
  • 微服务架构解决方案(大厂基本自研~自己研发各种组件,Spring Cloud ~Netflix,Alibaba,…)
  • 微服务架构下Maven聚合项目的创建方式?(Maven聚合项目~资源复用:extends,import,简化编译,打包,部署方式)
  • 微服务架构入门聚合项目创建?(01-sca,sca-consumer,sca-provider,sca-gateway,sca-common)
  • 微服务中聚合工程之间的引用设计?(将一个工程作为依赖添加到其它工程~重点是坐标)

常见问题分析

  • 为什么需要微服务?(对系统分而治,解决因并发访问过大带来的系统复杂性(例如:业务,开发,测试,升级,可靠性等)
  • 微服务设计的特点?(单一职责,独立进程,开发测试效率高,可靠性高,升级难度小,但会带来一定的维护成本)
  • 微服务解决方案有哪些?(大厂自研,中小企业采用开源Spring Cloud Alibaba,Spring Cloud Netfix等 )
  • 微服务设计中需要哪些关键组件(服务的注册,发现,配置,限流降级,访问入口管理,分布式事务管理等)
  • 创建聚合工程的目的?(实现工程之间资源的的共享,简化工程管理)
  • 如何修改聚合工程中项目的编译和运行版本?(pom.xml:build->plugins->plugin->maven-compiler-plugin)
  • maven工程中build元素的作用?(定义项目的编译,打包方式)
  • maven父工程的packaging元素内的值是什么?(父工程默认打包方式为pom方式)
  • maven父工程中dependencyManagement元素的作用是什么?(项目依赖的版本,当前工程或子工程不需要再指定版本)
  • Maven父工程中如何统一定义JDK编译和运行版本?(配置maven编译插件:maven-compiler-plugin)

常见Bug分析

  • 依赖无法下载或加载?(本地库冲突,网络不好,maven镜像配置,指定版本在远程服务器不存在,清idea缓存后重启)

  • 项目的pom.xml文件有删除线?(idea/setting/build,Execution,Deployment/build Tools/maven/ignore Files)
    12-2108微服务课上问题分析及总结_第1张图片

  • 项目单元测试失败,提示找不到@SpringBootConfiguration,例如:
    12-2108微服务课上问题分析及总结_第2张图片

  • 当项目中出现了多个启动类时,在项目启动或单元测试时会出现如下问题,例如:
    12-2108微服务课上问题分析及总结_第3张图片

  • 单元测试依赖添加的有问题或者单元测试类写错了位置,例如:
    12-2108微服务课上问题分析及总结_第4张图片

  • 方法调用错误,例如:
    12-2108微服务课上问题分析及总结_第5张图片

  • 空指针异常,例如:
    12-2108微服务课上问题分析及总结_第6张图片

课堂练习

练习一:公共工程设计及实现

第一步:创建01-sca工程的子工程,工程模块名sca-common,例如:
12-2108微服务课上问题分析及总结_第7张图片
第二步:在sca-common模块工程中创建一个工具类com.jt.common.util.StringUtils,并在类中添加一个判断字符串是否为空的静态方法。

package com.jt.common.util;

public class StringUtils {
     
    /**
     * 通过此方法判定传入的字符串是否为空
     * @param str
     * @return
     */
    public static boolean isEmpty(String str){
     
        return str==null||"".equals(str);
    }
}

第三步:将sca-common工程以依赖的方式添加到sca-provider工程中?

<dependencies>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    
    <dependency>
        <groupId>com.jtgroupId>
        <artifactId>sca-commonartifactId>
        <version>1.0-SNAPSHOTversion>
    dependency>
dependencies>

第四步:在sca-provider工程中添加一个springboot启动类,类名为com.jt.ProviderApplication

package com.jt;
import com.jt.common.cache.DefaultCache;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class ProviderApplication{
     
    public static void main(String[] args) {
     
        SpringApplication.run(ProviderApplication.class,args);
    }
}

第五步:在sca-provider工程中写一个单元测试类,类全名为com.jt.util.StringTests,并添加单元测试方法,在这个单元测试方法中使用sca-common工程中写的StringUtils类,测试一个字符串是否为空.

package com.jt.util;
import com.jt.common.util.StringUtils;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class StringTests {
     
    @Test //org.junit.jupiter.api.Test
    void testStringEmpty(){
     
         String str="";
         boolean empty = StringUtils.isEmpty(str);
         System.out.println(empty);
    }
}

练习二:熟悉工程中对象的管理以及测试

第一步:在sca-common工程中定义一个com.jt.common.cache.DefaultCache类型.

package com.jt.common.cache;
public class DefaultCache {
     
}

第二步:在sca-provider工程将DefaultCache类型的对象交给spring管理,写到启动类即可。

package com.jt;
import com.jt.common.cache.DefaultCache;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class ProviderApplication{
     
    @Bean
    public DefaultCache defaultCache(){
     //将DefaultCache对象交给spring管理
        return new DefaultCache();
    }
    public static void main(String[] args) {
     
        SpringApplication.run(ProviderApplication.class,args);
    }
}

第三步:在sca-provider工程中定义个单元测试类DefaultCache,并且在类中定义一个
单元测试方法,输出DefaultCache对象的toString方法的返回值。

package com.jt.util;

import com.jt.common.cache.DefaultCache;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class DefaultCacheTests {
     
    @Autowired //DI
    private DefaultCache defaultCache;
    @Test
    void testDefaultCache(){
     
        System.out.println(defaultCache.toString());
    }
}

课后作业

  • 总结课上知识点(养成好习惯)
  • 完成自己电脑中JAVA_HOME环境变量的配置。(JDK必须是8并且64Bit的)
  • 确保自己电脑中的mysql为5.7以上或者mariadb10.5以上版本并基于这个版本执行课前资料中的nacos-mysql.sql
  • 预习04-Nacos注册服务注册中心应用实践。

Day02~Nacos注册中心入门

核心知识点

  • 服务注册中心诞生背景? (服务多了,需要统一管理,例如所有公司需要在工商局进行备案)
  • 服务注册中心的选型?(社区活跃度,稳定性,功能,性能,学习成本)
  • 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管理)

常见Bug分析

  • JAVA_HOME环境变量定义错误,例如:
    在这里插入图片描述
    说明,这里一定要注意JAVA_HOME单词的拼写,JAVA_HOME中定义的JDK是存在的,还有后面的路径不能有分号“;”.

  • MySQL版本比较低(建议mysql5.7或mariadb10.5及以上版本),例如:
    当执行nacos-mysql.sql文件时,出现如下错误:
    在这里插入图片描述

  • sql文件不存在,例如
    12-2108微服务课上问题分析及总结_第8张图片

  • SQL文件应用错误,例如:
    在这里插入图片描述

  • Nacos的application.properties配置文件中,连接数据库的配置错误.
    在这里插入图片描述

  • 服务启动时,端口被占用了。例如:
    在这里插入图片描述

  • 服务注册时,服务名不正确,格式不正确,配置文件名字不正确,或者没有配置文件,例如:
    在这里插入图片描述

  • 基于Nacos实现服务注册失败,例如
    加粗样式

  • 客户端500异常,例如
    在这里插入图片描述

  • 服务调用时,连接异常,例如:
    在这里插入图片描述

  • 服务调用时底层404问题,例如:
    在这里插入图片描述

课堂小技巧

  • 基于idea启动nacos,例如:
    12-2108微服务课上问题分析及总结_第9张图片
  • 基于idea链接database数据库,例如:
    第一步:打开DataSource,找到mysql,例如:
    12-2108微服务课上问题分析及总结_第10张图片
    第二步:配置连接的数据库,例如:
    12-2108微服务课上问题分析及总结_第11张图片

课后作业

  • 总结课堂知识点
  • 完成基于nacos的服务注册
  • 完成基于RestTemplate对象实现服务调用。
  • 预习负载均衡方式的服务发现及调用。

Day03~基于Nacos实现服务发现与调用

核心知识点

  • 负载均衡诞生背景.(网络中有一组可以提供相同服务的计算机~类似银行的各个营业点)
  • 客户端负载均衡&服务端负载均衡的不同?(browser->nginx->…;sca-consumer->sca-provider)
  • 基于LoadBalancerClient 对象从注册中心获取服务列表(服务发现)
  • 基于Ribbon(一个负载均衡组件,这个组件中提供一套负载均衡算法)实现负载均衡
  • @Loadbalanced注解的应用(描述RestTemplate对象,为此对象的远程调用进行赋能)

常见问题分析

  • 为什么负载均衡?(通过多个服务实例均衡处理客户端的请求,生活中有一种说法叫不患寡而患不均)
  • 如何理解服务发现?(服务发现就是从注册中心获取服务信息,例如从nacos获取服务实例信息)
  • LoadBalancerClient的作用?(从nacos注册中心获取服务实例列表,然后本地基于负载均衡算法获取具体服务实例)
  • @Loadbalanced注解作用?(描述RestTemplate对象,让系统底层为RestTemplate对象赋能,对请求过程进行拦截)
  • 你了解哪些负载均衡策略?(基于IRule接口去查看,快捷键ctrl+h)
  • 我们如何修改负载均衡策略?(配置文件->例如application.yml,配置类->例如启功类)

常见Bug分析

  • NullPointerException,例如:
    12-2108微服务课上问题分析及总结_第12张图片
  • 端口被占用,例如
    12-2108微服务课上问题分析及总结_第13张图片
  • UnknownHostException,例如
    12-2108微服务课上问题分析及总结_第14张图片

课堂练习

  • 修改sca-consumer端默认的负载均衡策略?(自己查资料实现)
    方案1:修改sca-consumer配置文件(application.yml),添加如下语句,例如:
sca-provider: #这个是要进行远程调用的服务id(服务名)
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #负载均衡算法

对于方案1写法,在写的过程没有提示,缩写编写苦难,但是将来的可运维性会比较好,我们这部分配置写到配置中心,不需要重启服务即可实现配置的动态发布,动态更新。

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

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

对于方案2的写法,编写相对简单,编写过程都有提示,但是将来的可运维性比较差,项目打包以后,我们无法再修改
负载均衡算法。

课后作业

  • 总结课上知识点(重点总结核心知识点,遇到了什么问题,如何解决的)。
  • 同学之间相互挖些坑,提高分析问题和解决问题的能力。(404,500,…)
  • 预习并尝试实现一个基于feign方式的服务调用(一定要去做)。

Day04~基于Feign方式的服务调用实践

核心知识点

  • Feign 诞生的背景
  • Feign 方式远程服务调用实践
  • Feign 接口对应的Bean对象命名
  • Feign 方式远程服务调用时熔断处理方案
  • Feign 方式调用原理分析

常见问题分析

  • 为什么使用Feign方式的服务调用?(优化结构,简化服务调用过程代码的编写、)
  • 如何基于feign方式实现远程服务调用?(依赖,配置,feign接口定义)
  • @EnableFeignCleints 注解的作用是什么?(描述配置类,例如启动类)
  • @FeignClient注解的作用是什么?(告诉Feign Starter,在项目启动时,为此注解描述的接口创建实现类-代理类)
  • 如何理解基于Feign方式的远程服务调用?声明式远程服务调用,底层封装了服务调用过程。
  • Feign方式如何实现负载均衡?(底层基于ribbon组件实现)
  • Feign接口指向的对象是谁?
    12-2108微服务课上问题分析及总结_第15张图片
  • 常用服务发现、服务调用方式有哪些?
    12-2108微服务课上问题分析及总结_第16张图片

常见Bug分析

  • Fien接口对象依赖注入异常,例如:
    12-2108微服务课上问题分析及总结_第17张图片

  • 服务访问时的404异常,例如:
    12-2108微服务课上问题分析及总结_第18张图片

  • Feign接口方法中@PathVariable注解参数定义问题,例如:
    12-2108微服务课上问题分析及总结_第19张图片

  • 读数据超时,例如:
    12-2108微服务课上问题分析及总结_第20张图片

  • 依赖注入异常,例如:
    12-2108微服务课上问题分析及总结_第21张图片

课上技巧

  • Idea中Http Client 工具的应用?(基于此工具进行restful风格的请求测试)
    12-2108微服务课上问题分析及总结_第22张图片
    12-2108微服务课上问题分析及总结_第23张图片

课上练习

  • Feign方式远程调用超时配置,例如
feign:
  hystrix:
    enabled: false #false,true表示启动超时熔断机制
  client:
    config:
     default: #表示所有服务均采用此配置,也可以指定具体服务名(remoteProviderService)。
        connectTimeout: 20000 #连接超时
        readTimeout: 20000 #读取数据超时
  • 简易tomcat应用实践,了解服务创建,服务通讯过程,例如:

第一步:构建一个简易tomcat对象(了解)

package com.jt.common.net;

import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 通过java代码实现一个简易Tomcat对象
 */
public class Tomcat {
     
    public static void main(String[] args) throws IOException {
     
       //1.构建一个ServerSocket对象(java网络编程中的服务对象),并在指定端口进行监听
        ServerSocket server=new ServerSocket(9000);
        System.out.println("server start ...");
       //2.等待客户端连接(可以循环处理多个客户端的请求)
        while(true){
     
            Socket client = server.accept();//阻塞式方法
            OutputStream out = client.getOutputStream();
            //基于http协议格式构建响应数据
            byte[] data=("HTTP/1.1 200 OK \n\r" +
                    "Content-Type: text/html;charset=utf-8 \n\r" +
                    "\n\r" +
                    "hello client").getBytes();
            out.write(data);
            out.flush();
        }//http
    }
}

第二步:构建一个简易Browser对象,例如

package com.jt.common.net;

import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;

/**
 * 模拟浏览器
 */
public class Browser {
     
    public static void main(String[] args) throws IOException {
     
        //1.构建网络客户端对象Socket,并通过此对象对远端服务进行连接
        Socket socket=new Socket("127.0.0.1", 9000);
        //2.获取流对象
        InputStream in = socket.getInputStream();
        byte[] buf=new byte[1024];
        int len=in.read(buf);
        System.out.println("server say:"+new String(buf,0,len));
        //3.释放资源
        socket.close();
    }
}

第三步:启动tomcat服务,Browser服务进行访问测试分析。

课后作业

  • 总结课上知识点
  • 强化Feign方式的服务调用
  • 尝试基于Feign方式实现Post方式的服务调用
  • 阅读ruoyi项目中的Feign方式应用
  • 预习Nacos配置中心应用实践。

Day05~Nacos配置中心应用实践

核心知识点

  • 配置中心诞生背景。
  • 市场上主流的配置中心。
  • Nacos配置中心简介。
  • Nacos配置中心入门实践。
  • Nacos配置中心的配置管理模型。

常见问题分析

  • 什么是配置中心?(存储项目配置信息的一个服务,这个服务可以实现配置的动态发布和更新)
  • 为什么要使用配置中心?(集中管理配置信息,动态发布配置信息)
  • 市场上有哪些主流的配置中心?(Apollo,nacos,……)
  • 配置中心一般都会配置什么内容?(可能会经常变化的配置信息,例如连接池,日志、线程池、限流熔断规则)
  • 什么信息一般不会写到配置中心?(服务端口,服务名,服务的注册地址,配置中心地址)
  • 项目中为什么要定义bootstrap.yml文件?(此文件被读取的优先级比较高,可以在服务启动时读取配置中心的数据)
  • Nacos配置中心宕机了,我们的服务还可以读取到配置信息吗?(可以从服务的本地内存读取)
  • 微服务应用中客户端如何感知配置中心数据变化?(1.4.x版本的nacos客户端会基于长轮询机制从nacos获取配置信息)
  • 服务启动后没有从配置中心获取我们的配置数据是什么原因?(依赖,bootstrap.yml,配置单词,格式,配置模型)
  • 你项目中使用的日志规范是什么?(SLF4J~门面模式)
  • 你了解项目中的日志级别吗?(debug,info,warn,error可以基于日志级别控制日志的输出)
  • Nacos配置管理模型的背景?(环境不同配置不同)
  • Nacos配置中的管理模型是怎样的?(namespace>group>service/data-id)
  • Nacos客户端(微服务)是否可以读取共享配置?(可以)

常见Bug分析

  • mysql中没有配置中心数据,例如:
    12-2108微服务课上问题分析及总结_第24张图片
  • 包导入错误,例如:
    12-2108微服务课上问题分析及总结_第25张图片
  • 配置中心配置格式不正确,例如:
    12-2108微服务课上问题分析及总结_第26张图片
  • 程序中服务读取配置时,找不到配置,例如:
    12-2108微服务课上问题分析及总结_第27张图片

课后作业

  • 总结课上知识点
  • 尝试完成一个简易本地cache的应用。
  • 预习sentinel组件如何实现服务限流操作。

你可能感兴趣的