ABP微服务架构中网关层NullReferenceException问题解析与HTTP配置优化

一、网关层System.NullReferenceException问题解析

1.1 问题现象与原因分析

在ABP微服务架构开发过程中,网关层启动后调用微服务接口时出现以下异常:

System.NullReferenceException: Object reference not set to an instance of an object.

异常堆栈指向网关层控制器中的某一行代码,通常是在调用微服务接口的位置。进一步分析发现,该异常是由于网关层控制器中依赖的服务接口实例为null导致的。

1.2 关键代码场景

public class ProdcutController : AbpController, IProductService
{public IProductService ProductService { get; set; } // 属性注入,实例为null[HttpGet]public async Task<PagedResultDto<ProductDto>> GetListAsync([FromQuery] PagedAndSortedResultRequestDto pagedAndSortedResultRequestDto){return await ProductService.GetListAsync(pagedAndSortedResultRequestDto); // 此处引发异常}
}

1.3 为什么注释app.UseConfiguredEndpoints()可以解决问题

在ABP框架中,app.UseConfiguredEndpoints(); 方法用于注册和启用应用程序的路由系统,包括控制器路由的注册和依赖注入容器的初始化。当注释掉该方法后:

  1. 路由系统未启用:网关层的控制器不会被注册到路由系统中,请求不再由网关层的控制器处理
  2. Ocelot直接代理请求:请求被Ocelot直接捕获并转发到微服务,绕过了网关层的控制器
  3. 依赖注入问题被绕过:由于网关层控制器不再处理请求,依赖注入失败导致的空引用异常不再触发
// 原启动配置
app.UseConfiguredEndpoints(); // 启用路由系统,会触发控制器依赖注入检查
app.UseOcelot().Wait(); // 启用Ocelot代理// 修改后配置(注释掉UseConfiguredEndpoints)
// app.UseConfiguredEndpoints(); // 注释掉,不启用网关层路由系统
app.UseOcelot().Wait(); // Ocelot直接处理所有请求

1.4 本质原因与隐患

这种解决方案本质上是绕过了问题而非解决了问题,存在以下隐患:

  1. 网关层的自定义控制器功能失效
  2. 网关层的中间件和过滤器不再对请求生效
  3. 无法利用ABP框架的依赖注入和控制器特性

正确的解决方案应该是修复依赖注入配置,而不是绕过路由系统。

二、ABP微服务架构中HTTPS转HTTP配置指南

2.1 为什么需要将HTTPS改为HTTP

在开发环境中,HTTPS配置可能会遇到以下问题:

  1. 证书配置复杂,需要信任开发证书
  2. 本地调试时HTTPS可能引发连接问题
  3. 微服务间通信使用HTTP更便捷

2.2 网关层Ocelot配置修改

2.2.1 修改Ocelot配置文件

找到网关层的ocelot.json配置文件,将所有DownstreamSchemehttps改为http,并调整端口:

{"Routes": [{"UpstreamPathTemplate": "/api/productservice/{everything}","DownstreamPathTemplate": "/api/productservice/{everything}","DownstreamScheme": "http", // 关键修改:从https改为http"DownstreamHostAndPorts": [{"Host": "localhost","Port": 50383 // 改为HTTP端口,与微服务的HTTP端口一致}],// 其他配置保持不变...}],"GlobalConfiguration": {"BaseUrl": "http://localhost:44376" // 改为http}
}
2.2.2 修改网关层启动配置

在网关层的Program.csStartup.cs中,修改Kestrel配置为HTTP:

builder.WebHost.UseKestrel(options =>
{options.ListenAnyIP(44376, listenOptions =>{listenOptions.UseHttp(); // 关键修改:使用HTTP});
});

2.3 微服务层配置修改

2.3.1 修改微服务launchSettings.json

找到微服务的Properties/launchSettings.json,修改端口为HTTP:

{"iisSettings": {"iisExpress": {"applicationUrl": "http://localhost:50383", // 改为http"sslPort": 0 // 移除HTTPS端口配置}},"profiles": {"ProductService": {"commandName": "Project","launchBrowser": true,"applicationUrl": "http://localhost:50383", // 改为http"environmentVariables": {"ASPNETCORE_ENVIRONMENT": "Development"}}}
}
2.3.2 修改微服务Kestrel配置

在微服务的Program.cs中,修改Kestrel配置为HTTP:

builder.WebHost.UseKestrel(options =>
{options.ListenAnyIP(50383, listenOptions =>{listenOptions.UseHttp(); // 关键修改:使用HTTP});
});
2.3.3 修改微服务appsettings.json

将微服务的appsettings.json中的SelfUrl改为HTTP:

{"App": {"SelfUrl": "http://localhost:50383", // 改为http"ClientUrl": "http://localhost:4200","CorsOrigins": "http://*.ProductService.com,http://localhost:4200"},// 其他配置保持不变...
}

2.4 认证与授权配置调整

如果使用了认证授权服务,需要修改相关配置为HTTP:

// 网关层appsettings.json
{"AuthServer": {"Authority": "http://localhost:50399", // 改为http和认证服务的HTTP端口"RequireHttpsMetadata": false,"SwaggerClientId": "WebSite_Gateway_Swagger"},// 其他配置保持不变...
}

2.5 验证HTTP配置

  1. 启动微服务,确认控制台输出为HTTP端口:
Now listening on: http://localhost:50383
Application started.
  1. 使用Postman测试微服务接口:
http://localhost:50383/api/productservice/product
  1. 测试网关转发:
http://localhost:44376/api/productservice/product

三、网关层依赖注入问题的正确解决方案

虽然注释app.UseConfiguredEndpoints();可以暂时解决空引用异常,但这不是正确的解决方案。正确的做法是修复依赖注入配置:

3.1 使用构造函数注入

public class ProductController : AbpController
{private readonly IProductService _productService;// 构造函数注入确保服务实例被正确初始化public ProductController(IProductService productService){_productService = productService;}[HttpGet]public async Task<PagedResultDto<ProductDto>> GetListAsync([FromQuery] PagedAndSortedResultRequestDto pagedAndSortedResultRequestDto){return await _productService.GetListAsync(pagedAndSortedResultRequestDto);}
}

3.2 注册服务到依赖注入容器

在网关层模块中注册远程服务代理:

public override void ConfigureServices(ServiceConfigurationContext context)
{// 注册远程服务代理context.Services.AddProxy<ProductService.Contracts.IProductService>(remoteServiceName: "ProductService",proxyUrl: "http://localhost:50383");
}

3.3 启用路由系统

恢复app.UseConfiguredEndpoints();并确保其在Ocelot之前调用:

app.UseRouting();
app.UseConfiguredEndpoints(); // 启用路由系统
app.UseOcelot().Wait(); // 启用Ocelot代理

四、总结与最佳实践

4.1 问题解决思路总结

  1. System.NullReferenceException在网关层通常是由于依赖注入失败导致的,注释app.UseConfiguredEndpoints();只是绕过了问题,而非解决问题
  2. 将HTTPS改为HTTP可以简化开发环境的配置,但生产环境应使用HTTPS保证安全
  3. 正确的解决方案是修复依赖注入配置,使用构造函数注入并正确注册服务

4.2 开发环境最佳实践

  1. 依赖注入:始终使用构造函数注入,避免属性注入
  2. 路由配置:正确配置网关层和微服务的路由,确保请求正确转发
  3. HTTPS/HTTP:开发环境可使用HTTP简化配置,生产环境必须使用HTTPS
  4. 日志记录:启用详细日志,便于问题排查
  5. 异常处理:添加全局异常处理,避免应用崩溃

仅供参考

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/87637.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/87637.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/87637.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

啊啊啊啊啊啊啊啊code

前序遍历和中序遍历构建二叉树 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, TreeNod…

【算法 day06】LeetCode 454.四数相加II | 15. 三数之和 | 18. 四数之和

454.四数相加II 题目链接 | 文档讲解 |视频讲解 : 链接 1.思路&#xff1a; 0.定义一个count&#xff0c;计算最终出现的次数 1.先遍历nums1和nums2,求出两者的和&#xff0c;map的key是和&#xff0c;value是出现的次数 2.再遍历nums3和nums4&#xff0c;求出0-两者的和 3…

【项目实训】【项目博客#09】HarmonySmartCodingSystem系统后端智能API检索与代码助手实现(6.2-6.15)

【项目实训】【项目博客#09】HarmonySmartCodingSystem系统后端智能API检索与代码助手实现&#xff08;6.2-6.15&#xff09; 文章目录 【项目实训】【项目博客#09】HarmonySmartCodingSystem系统后端智能API检索与代码助手实现&#xff08;6.2-6.15&#xff09;项目博客概述一…

【JVM】- 类加载与字节码结构3

类加载阶段 1. 加载 加载&#xff1a;将类的字节码载入方法区中&#xff0c;内部采用C的instanceKlass描述java类。如果这个类的父类还没加载&#xff0c;则先加载父类加载和链接可能是交替运行的 通过全限定名获取字节码 从文件系统&#xff08;.class 文件&#xff09;、JA…

Qt蓝图式技能编辑器状态机模块设计与实现

设计概述 这个模块是一个基于Qt的蓝图式技能编辑器状态机&#xff0c;主要用于游戏开发中的技能状态管理。核心功能包括&#xff1a; 状态节点&#xff08;开始、结束、普通状态&#xff09;的可视化 状态间连线的绘制与管理 状态转换逻辑的可视化编辑 动作选择与配置 核…

Unity AR识别物体的内容语音读取+使用说明功能

因之前一直在开发项目&#xff0c;断断续续写了一点博客&#xff0c;最后统一写了一下博客记录学习内容。 可以看到我的工作一直在进行。 目录 一、识别内容语音读取 二、点击齿轮按钮弹出使用说明界面 开发步骤 1. 创建齿轮按钮 UI 2. 创建使用说明面板 UI 3. 编写控制…

Unable to start embedded Tomcat

通常是由于xml文件配置错误导致 1. mapper 指向错误 <resultMap id"Waybill" type"c.Waybill"> 2. 字段类型错误 <result column"wstatus" property"stus" javaType"TINYINT"/>TINYINT 是数据库类型<resu…

Mac电脑 充电限制保护工具 AlDente Pro

AlDente Pro一款充电限制保护工具&#xff0c;是可以限制最大充电百分比来保护电池的工具。 锂离子和聚合物电池&#xff08;如 MacBook 中的电池&#xff09;在40&#xff05; 至 80&#xff05; 之间运行时&#xff0c;使用寿命最长。 始终将电池电量保持在 100&#xff05…

KungfuBot——基于物理约束和自适应运动追踪的人形全身控制PBHC,用于学习打拳或跳舞(即RL下的动作模仿和运控)

前言 昨天618&#xff0c;我司「七月在线」同事朝阳为主力&#xff0c;我打杂&#xff0c;折腾了整整一天&#xff0c;终于可以通过VR摇操宇树G1了——当然&#xff0c;摇操是为了做训练数据的采集&#xff0c;从而方便 下一步的模型(策略)训练&#xff0c;最终实现机器人自主…

Kafka多副本机制

副本和副本因子 Kafka 会为每个 Partition 创建多个副本。这些副本分布在不同的 Broker 上。副本确保了数据的冗余存储&#xff0c;即使某个 Broker 宕机或失效&#xff0c;其他副本可以继续提供服务。 副本因子指的是每个 Partition 有多少个副本。副本因子的设置决定了一个…

Vue3类似百度风格搜索框组件

Vue3百度风格搜索框组件&#xff0c;使用vue3进行设计&#xff0c;亦有vue3TS的版本。 vue3组件如下&#xff1a; <template><!-- 搜索组件容器 --><div class"search-container"><!-- 百度Logo - 新样式 --><div class"logo-conta…

智净未来:华为智选IAM以科技巧思优化家庭健康饮水体验

在中国家庭中&#xff0c;净水器早已成为厨房标配&#xff0c;但传统净水设备的使用体验却远未达到理想状态。根据《2023年中国家庭净水器使用调研报告》显示&#xff0c;超过65%的用户对传统净水器存在不满&#xff0c;主要痛点集中在功能单一、操作复杂、维护麻烦、噪音大、废…

细说STM32单片机SPI-Flash芯片的FatFS移植

目录 一、SPI-Flash芯片硬件电路 二、CubeMX项目基础设置 1、RCC、SYS、Code Generator、USART6、NVIC 2、RTC 3、SPI2 4、GPIO 5、FatFS模式 6、FatFS参数设置概述 &#xff08;1&#xff09;Version组 &#xff08;2&#xff09;Function Parameters组 1&#x…

ubuntu 22.04 安装部署logstash 7.10.0详细教程

安装部署logstash 7.10.0详细教程 一、下载并安装二、新建配置文件三、赋权文件权限四、检测文件grok语法是否异常五、启动服务六、安装启动常见问题 【背景】 整个elk安装是基于ubuntu 22.04和jdk 11环境。logstash采用 *.deb方式安装&#xff0c;需要服务器能联网。ubuntu 22…

JVM对象创建与内存分配机制深度剖析

对象创建的主要流程 类加载检查 在创建对象之前&#xff0c;JVM 首先会检查该类是否已经加载、解析并初始化&#xff1a; 如果没有&#xff0c;则会通过类加载机制加载类元信息&#xff08;Class Metadata&#xff09;到方法区。 这个过程包括&#xff1a;加载&#xff08;load…

Navicat 技术指引 | TiDB 的 AI 查询交互功能

目前&#xff0c;Navicat 两款工具支持对 TiDB 数据库的管理开发功能&#xff1a;一款是旗舰款 Navicat Premium&#xff0c;另一款是其轻量化功能的 Navicat Premium Lite&#xff08;官方轻量级免费版&#xff09;。Navicat 自版本 17.1 开始支持 TiDB 7。它支持的系统有 Win…

以list为输入条件,查询数据库表,java中的mapper层和mybatis层应该怎么写?

根据一个 List 中的两个字段 rangeCode 和 unitcd&#xff0c;查询数据库表 model_engineering_spatial_unit。这个需求在 Java MyBatis 项目中非常常见&#xff0c;下面我将为你详细写出 Mapper 接口&#xff08;Java&#xff09; 和 MyBatis XML 映射文件 的写法。 ✅ 前提…

pyspark 创建DataFrame

from pyspark.sql import SparkSession from pyspark.sql import StructType, StructField, IntegerType,StringType spark SparkSession.builder.appName(test).getOrCreate() 1、 从列表中创建DataFrame data [(1,"alice"),(2,Blob),(3,Charlie)] columns [&qu…

Vim:从入门到进阶的高效文本编辑器之旅

目录 一、Vim简介 二、Vim的基础操作 2.1 进入和退出Vim 2.2 Vim的三种模式 2.3 基础移动 三、Vim的高效编辑技巧 3.1 文本编辑 3.2 文本删除与修改 3.3 复制与粘贴 四、Vim的进阶使用 4.1 搜索与替换 4.2 寄存器与宏 4.3 插件与配置 五、结语 在编程界&#xff0…

Docker基础理论与阿里云Linux服务器安装指南

文章目录 一、Docker核心概念二、阿里云环境准备三、Docker安装与配置四、核心容器部署示例五、开发环境容器化六、运维管理技巧七、安全加固措施 一、Docker核心概念 容器化本质&#xff1a; 轻量级虚拟化技术&#xff0c;共享主机内核进程级隔离&#xff08;cgroups/namespac…