微服务项目第一天总结

本文探讨了SpringCloudGateway在微服务架构中的应用,对比了与Nginx的区别,强调了两者在安全、性能和流量控制方面的协同作用。同时讨论了实现Serializable接口的原因,以及SpringCloudAlibabaNacos作为注册中心和配置中心的作用,包括服务发现、配置管理和健康检查。文中还涉及了SpringCloudGateway的@EnableDiscoveryClient注解和JWT校验的全局过滤器实现,以及前端项目部署的Nginx配置和Spring框架中的Ordered和GlobalFilter接口使用。
摘要由CSDN通过智能技术生成

用到的技术栈

  • Spring-Cloud-Gateway : 微服务之前架设的网关服务,实现服务注册中的API请求路由,以及控制流速控制和熔断处理都是常用的架构手段,而这些功能Gateway天然支持
  • 运用Spring Boot快速开发框架,构建项目工程;并结合Spring Cloud全家桶技术,实现后端个人中心、自媒体、管理中心等微服务。
  • 运用Spring Cloud Alibaba Nacos作为项目中的注册中心和配置中心
  • 运用mybatis-plus作为持久层提升开发效率
  • 运用Kafka完成内部系统消息通知;与客户端系统消息通知;以及实时数据计算
  • 运用Redis缓存技术,实现热数据的计算,提升系统性能指标
  • 使用Mysql存储用户数据,以保证上层数据查询的高性能
  • 使用Mongo存储用户热数据,以保证用户热数据高扩展和高性能指标
  • 使用FastDFS作为静态资源存储器,在其上实现热静态资源缓存、淘汰等功能
  • 运用Hbase技术,存储系统中的冷数据,保证系统数据的可靠性
  • 运用ES搜索技术,对冷数据、文章数据建立索引,以保证冷数据、文章查询性能
  • 运用AI技术,来完成系统自动化功能,以提升效率及节省成本。比如实名认证自动化
  • PMD&P3C : 静态代码扫描工具,在项目中扫描项目代码,检查异常点、优化点、代码规范等,为开发团队提供规范统一,提升项目代码质量

Gateway 网关和ngix的区别?

Gateway 网关(如Spring Cloud Gateway)和Nginx

共同点: 1. 都可以作为反向代理服务器和API网关使用
不同点:但它们在设计、功能和使用场景上有一些区别:

  1. Spring Cloud Gateway 是一个编程式的API网关,并且是响应式的,基于WebFlux框架。
  2. Nginx 是一个高性能的HTTP服务器和反向代理,使用C语言编写,它是过程式和事件驱动的。Nginx 以其稳定性、高性能和低资源消耗闻名。

Gateway 网关和ngix为什么要一起使用?有什么优势?

  1. 安全性和隔离:

    使用 Nginx 作为最前端的反向代理可以提供额外的安全层。它可以处理外部流量并提供基本的安全防护,如 限流、IP 白名单/黑名单等。
    Spring Cloud Gateway 然后处理内部微服务的路由和其他业务逻辑,这样可以将外部流量与内部服务逻辑分离,增强系统的安全性。

  2. 性能优化:
    Nginx 能够高效地处理静态内容、压缩、缓存等,这可以减轻后端网关和服务的负载。
    Spring Cloud Gateway 可以专注于处理动态路由、服务发现等微服务相关的操作。

  3. 灵活的负载均衡:
    Nginx 可以作为负载均衡器,将流量分发到多个网关实例,实现跨地域的流量管理和灾难恢复。
    Spring Cloud Gateway 可以进一步在微服务层面进行负载均衡,例如基于服务实例的健康状况或响应时间来路由请求。

  4. 简化的SSL管理:

    在 Nginx 层统一管理 SSL 证书,可以简化证书的部署和更新过程。
    Spring Cloud Gateway 可以在内部网络中以纯文本方式运行,减少SSL配置的复杂性。

  5. 协议转换:

    Nginx 可以作为协议转换的网关,例如将外部的 HTTPS 请求转换为内部的 HTTP 请求。
    Spring Cloud Gateway 则处理微服务层面的通信和协议需求。

  6. 缓解冷启动问题:

    在微服务进行部署或重启时,Nginx 可以提供缓存或静态响应,减少系统冷启动时对用户体验的影响。
    Spring Cloud Gateway 在后端服务就绪后再接管流量,确保流量的正确路由。

  7. 分层的流量控制:

    Nginx 可以实现全局的流量控制和防护策略。
    Spring Cloud Gateway 可以根据业务需求实现更细粒度的流量控制和路由策。

    综合来说,将 Nginx 和 Spring Cloud Gateway 一起使用可以更好地利用各自的优势,为系统提供双层的保护和灵活性。不过,这种架构也会增加系统的复杂性,需要更多的运维知识来确保系统的稳定性和性能。因此,是否采取这种架构需要根据实际业务需求和团队能力来决定。

为什么实体类要实现Serializable接口?

实体类通常建议实现Serializable接口的原因在于Java序列化机制。Serializable接口是Java提供的一个标记(marker)接口,它不包含任何方法,当一个类实现了这个接口,这意味着这个类能够将其实例的状态保存为一系列字节,并且可以在之后完全以相同的状态重新构造出来,即实现了序列化和反序列化的功能。

以下是实现Serializable接口的一些常见原因:

1. 持久化存储:
将实体对象存储到磁盘上,如文件、数据库等,实现对象的持久化。序列化后的数据可以在系统关闭后依然存在,并可以在需要的时候反序列化回原有的对象。

2. 网络传输:
在分布式系统中,经常需要在网络中传输对象。序列化可以将对象转换为字节流,从而可以通过网络发送到另一个系统,然后在另一端将字节流反序列化为对象。

3. 深拷贝:
通过序列化和反序列化可以实现对象的深拷贝,即创建一个内容完全相同但是独立的对象副本,这在某些特定场景下非常有用。

4. Java RMI:
Java远程方法调用(RMI)中,当对象需要在JVM之间传输时,这些对象必须实现Serializable接口,以便它们可以被序列化和反序列化。

5. 缓存对象:
在使用缓存框架如Ehcache、Redis等时,如果需要缓存Java对象,这些对象需要是可序列化的,以便将它们存储在缓存中。

实现Serializable接口的类需要提供一个称为serialVersionUID的静态常数。这个ID作为类的版本号,用于验证序列化的对象和对应类的版本是否匹配。如果一个类在序列化后发生了更改,没有相应更新serialVersionUID,那么反序列化时可能会抛出InvalidClassException。

Spring Cloud Alibaba Nacos作为项目中的注册中心和配置中心,Nacos作用是什么?

  1. 服务注册与发现(Service Registry and Discovery):
    作为服务注册中心,Nacos 允许微服务在启动时将自己的地址(IP + 端口)注册到 Nacos 服务器上。
    当服务需要调用其他服务时,它可以查询 Nacos 以获取当前可用的服务实例列表及其地址,从而实现服务之间的动态发现和调用。
    这样可以实现服务间的松耦合和负载均衡,并且在服务实例出现变动时无需手动更新配置。
    2. 动态配置管理(Dynamic Configuration Management):

    Nacos 作为配置中心,可以集中管理应用的配置文件。
    微服务可以在启动时从 Nacos 获取配置信息,并且在配置发生变更时,Nacos 能够实时推送更新的配置到各个服务实例,避免了重新部署服务的需要。
    支持配置的版本管理和回滚,便于跟踪配置变更和快速恢复到旧版本。
    3. 服务健康检查(Service Health Check):

    Nacos 支持服务健康检查,自动检测服务实例的存活状态,并在服务实例不健康时将其从服务列表中剔除,确保服务的可用性和稳定性。

@EnableDiscoveryClient 是什么?

@EnableDiscoveryClient 是一个Spring Cloud提供的注解,用于启用服务发现客户端的功能。当你在Spring Boot应用中添加了这个注解后,应用就具备了服务发现的能力,能够将自己注册到配置好的服务注册中心,比如Eureka、Consul或者Zookeeper等,并且能够从注册中心动态发现其他服务的实例。

服务发现是微服务架构中的一个关键概念,它允许微服务实例在启动时注册到服务注册中心,并在需要时查询其他服务的位置(即IP地址和端口),从而实现服务间的互联互通。这样,服务之间的通信就不再依赖于硬编码的地址,而是基于服务的名称进行动态解析。

以下是一个简单的例子,展示了如何在Spring Boot应用中使用 @EnableDiscoveryClient:

@SpringBootApplication
@EnableDiscoveryClient
public class MyApp {

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

在这个例子中,MyApp 应用将会注册到服务注册中心,并且能够发现其他注册的服务。

全局过滤器实现jwt校验

思路分析:

  1. 用户进入网关开始登陆,网关过滤器进行判断,如果是登录,则路由到后台管理微服务进行登录

  2. 用户登录成功,后台管理微服务签发JWT TOKEN信息返回给用户

  3. 用户再次进入网关开始访问,网关过滤器接收用户携带的TOKEN

  4. 网关过滤器解析TOKEN ,判断是否有权限,如果有,则放行,如果没有则返回未认证错误

  5. 具体实现:

    第一:在认证过滤器中需要用到jwt的解析,所以需要把工具类拷贝一份到网 关微服务
    第二:在网关微服务中新建全局过滤器:

@Component
@Slf4j
public class AuthorizeFilter implements Ordered, GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //1.获取request和response对象
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();

        //2.判断是否是登录
        if(request.getURI().getPath().contains("/login")){
            //放行
            return chain.filter(exchange);
        }
        //3.获取token
        String token = request.getHeaders().getFirst("token");

        //4.判断token是否存在
        if(StringUtils.isBlank(token)){
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        //5.判断token是否有效
        try {
            Claims claimsBody = AppJwtUtil.getClaimsBody(token);
            //是否是过期
            int result = AppJwtUtil.verifyToken(claimsBody);
            if(result == 1 || result  == 2){
                response.setStatusCode(HttpStatus.UNAUTHORIZED);
                return response.setComplete();
            }
        }catch (Exception e){
            e.printStackTrace();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        //6.放行
        return chain.filter(exchange);
    }
    /**
     * 优先级设置  值越小  优先级越高
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }
}

前端项目部署思路

通过nginx来进行配置,功能如下

  • 通过nginx的反向代理功能访问后台的网关资源
  • 通过nginx的静态服务器功能访问前端静态页面

配置nginx
①:解压资料文件夹中的压缩包nginx-1.18.0.zip

②:解压资料文件夹中的前端项目app-web.zip

③:配置nginx.conf文件

upstream  heima-app-gateway{
	
    server localhost:51601;//这指定了应用程序的运行端口为51601。
}
//server:这是Spring Boot应用的服务配置部分。
server {
	listen 8801;
	location / {
		root D:/workspace/app-web/;
		index index.html;
	}
	
	location ~/app/(.*) {
		proxy_pass http://heima-app-gateway/$1;
		proxy_set_header HOST $host;  # 不改变源请求头的值
		proxy_pass_request_body on;  #开启获取请求体
		proxy_pass_request_headers on;  #开启获取请求头
		proxy_set_header X-Real-IP $remote_addr;   # 记录真实发出请求的客户端IP
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  #记录代理信息
	}
}


④ :启动nginx

​ 在nginx安装包中使用命令提示符打开,输入命令nginx启动项目

​ 可查看进程,检查nginx是否启动

​ 重新加载配置文件:nginx -s reload

⑤:打开前端项目进行测试 – > http://localhost:8801

​ 用谷歌浏览器打开,调试移动端模式进行访问

在Spring框架中,Ordered接口和GlobalFilter接口用于不同的目的

  1. Ordered接口:
    Ordered是一个用于定义组件排序顺序的接口。它只有一个方法getOrder(),返回一个整数值表示顺序。在Spring中,多个相同类型的组件(比如Bean、Filter等)可能会同时存在,而它们的执行顺序有时候是很关键的。通过实现Ordered接口,你可以控制这些组件的加载和执行顺序。数值越小,优先级越高,组件就越先执行。

    在Spring Cloud Gateway中,多个网关过滤器(Filter)可能会处理传入的HTTP请求。实现Ordered接口可以帮助你定义这些过滤器的执行顺序。

  2. GlobalFilter接口:
    GlobalFilter是Spring Cloud Gateway中的一个接口,用于创建全局过滤器。全局过滤器会对所有路由的入站请求进行处理。与路由特定的过滤器不同,全局过滤器无需指定特定条件即可应用于所有请求。

    实现GlobalFilter接口的类需要提供filter方法的定义,这个方法定义了过滤器在处理请求时应该执行的逻辑。该方法接收一个ServerWebExchange和一个GatewayFilterChainServerWebExchange封装了HTTP请求和响应的相关信息,而GatewayFilterChain则允许过滤器将处理请求的控制权传递给链中的下一个过滤器。

当你同时实现Ordered和GlobalFilter接口时,你创建的是一个全局过滤器,它会对所有路由生效,并且你可以通过Ordered接口中的getOrder方法来指定其在过滤器链中的执行顺序。

@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 过滤器的逻辑,比如修改请求头
        return chain.filter(exchange); // 继续执行过滤器链
    }

    @Override
    public int getOrder() {
        return -1; // 设置过滤器的优先级,数值越小优先级越高
    }
}

在这个示例中,MyGlobalFilter类定义了一个全局过滤器,并通过实现Ordered接口来指定其执行顺序。在filter方法中,它可以修改HTTP请求或响应,或者执行任何需要对所有请求进行的全局逻辑。

StringUtils.isBlank(token)作用是什么?

     * 如果 token 是 null,返回 true。
     * 如果 token 长度为 0,返回 true。
     * 如果 token 只包含空白字符(如空格、制表符、换行符等),返回 true。
     * 否则,返回 false。
     * isBlank 方法和 isEmpty 方法类似,但 isEmpty 只检查字符串是否为 null 或者长度为 0,并不检查空白字符。

彻底解决Failed to configure a DataSource: ‘url‘ attribute is not specified and no embedded datasource

springboot2启动项目报错,应该是数据库连接的问题,导致无法启动。

错误消息如下:

***************************
APPLICATION FAILED TO START
***************************
 
Description:
 
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
 
Reason: Failed to determine a suitable driver class
 
 
Action:
 
Consider the following:
    If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
    If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).

********************************** 第一种,项目不需要连接数据库,启动报错 ******************************************

解决方法如下:

只要在将@SpringBootApplication修改为@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})就可以启动的时候不需要连接数据库。

@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})

********************************** 第2种,需要连接数据库,启动报错 ******************************************
解决方法如下:

第一种,yml配置示例如下

#在application.properties/或者application.yml文件中没有添加数据库配置信息.
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver

第二种,properties文件示例如下

spring.datasource.url = jdbc:mysql://localhost:3306/test?setUnicode=true&characterEncoding=utf8

第三种,mysql的版本不同,示例如下

#mysql8以下的版本,请检查pom.xml文件种依赖的mysql jar包的版本
driver-class-name: com.mysql.jdbc.Driver
 
#mysql8以下的url写法
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false
 
 
 
 
 
#mysql8的版本写法,多了个cj
driver-class-name: com.mysql.cj.jdbc.Driver
 
#同时mysql8的url也需要加入时区,参照如下
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&tinyInt1isBit=false

第四种,项目没有加载到yml或者properties文件,特别是自己的pom打包是jar的项目,请查看自己的pom.xml文件中的packaging

<packaging>jar</packaging>

第五种,项目使用了**springcloud+nacos**系列,启动项目时候需要手动指定【–spring.profiles.active=test】,那么在resources文件夹下就必须要有bootstrap-test.yml或者application-test.yml文件,同时配置文件中连接的nacos地址里面也必须配置对应的命名空间,和对应服务名称的yml文件,否则也是报错。下面是配置文件的截图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值