You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET客户端检索Apache Ignite C++复杂类型触发网格映射请求失败异常

问题背景

使用Apache Ignite 2.14.0 Java服务端,搭配.NET Core 6.0 ASP.NET Core WebAPI及C++、C# Worker程序,已按跨平台互操作与序列化文档定义WorkerStatus类。两类客户端均可向缓存写入WorkerStatus数据,但.NET客户端仅能读取C#写入的数据,读取C++写入的数据时触发异常:

Apache.Ignite.Core.Binary.BinaryObjectException: Requesting mapping from grid failed for [platformId=1, typeId=959909104]

服务端配置的BinaryConfiguration如下:

<property name="binaryConfiguration">
    <bean class="org.apache.ignite.configuration.BinaryConfiguration">
        <property name="compactFooter" value="false"/>

        <property name="idMapper">
            <bean class="org.apache.ignite.binary.BinaryBasicIdMapper">
                <property name="lowerCase" value="true"/>
            </bean>
        </property>
            
        <property name="nameMapper">
            <bean class="org.apache.ignite.binary.BinaryBasicNameMapper">
                <property name="simpleName" value="true"/>
            </bean>
        </property>
    </bean>
</property>

已尝试简化WorkerStatus类、调整包结构、移除可疑属性,怀疑C#与C++的TypeId计算不一致,现咨询三个问题:

  1. .NET Core 6.0与C++的跨平台兼容性是否可行?
  2. 是否有更复杂的跨平台序列化示例?
  3. 采用SQL方案能否规避该序列化问题?

问题解答

1. .NET Core 6.0与C++的跨平台兼容性完全可行

Apache Ignite原生支持多平台互操作,只要保证类型Id、字段映射、序列化配置完全一致,就能实现跨平台数据读写。你遇到的问题核心是C和.NET端的WorkerStatus类型Id计算不匹配,导致.NET客户端无法识别C写入的数据类型。

需要重点对齐以下配置:

  • 两端的BinaryBasicIdMapper规则:C++和.NET端都要启用lowerCase=true,确保类型名称的大小写处理统一。
  • C++端的类型名称指定:通过IGNITE_BINARY_TYPE_NAME宏设置的类型名称,必须和.NET端类名经BinaryBasicNameMapper处理后的结果完全一致。
  • 字段名称映射:两端字段名经BinaryBasicNameMapper(simpleName=true)处理后要一一对应,大小写规则统一。

2. 复杂跨平台序列化示例

以包含嵌套对象、枚举、集合的WorkerTask类型为例,各端实现如下:

Java服务端配置

显式注册类型并对齐映射规则:

BinaryConfiguration binaryCfg = new BinaryConfiguration();
binaryCfg.setCompactFooter(false);
binaryCfg.setIdMapper(new BinaryBasicIdMapper(true));
binaryCfg.setNameMapper(new BinaryBasicNameMapper(true));

BinaryTypeConfiguration taskTypeCfg = new BinaryTypeConfiguration("WorkerTask");
taskTypeCfg.addFieldConfiguration(new BinaryFieldConfiguration("Id"));
taskTypeCfg.addFieldConfiguration(new BinaryFieldConfiguration("Name"));
taskTypeCfg.addFieldConfiguration(new BinaryFieldConfiguration("Status"));
taskTypeCfg.addFieldConfiguration(new BinaryFieldConfiguration("SubTasks"));
binaryCfg.setTypeConfigurations(Collections.singletonList(taskTypeCfg));
.NET端实现
[BinaryTypeName("WorkerTask")]
public class WorkerTask
{
    public int Id { get; set; }
    public string Name { get; set; }
    public TaskStatus Status { get; set; }
    public List<SubTask> SubTasks { get; set; }
}

public enum TaskStatus
{
    Pending,
    Running,
    Completed
}

[BinaryTypeName("SubTask")]
public class SubTask
{
    public int SubTaskId { get; set; }
    public string Description { get; set; }
}
C++端实现
enum TaskStatus
{
    PENDING,
    RUNNING,
    COMPLETED
};

class SubTask
{
public:
    int subTaskId;
    std::string description;

    IGNITE_BINARY_TYPE(SubTask)
    {
        ignite::binary::BinaryType<SubTask>::SetTypeName("SubTask");
        ignite::binary::BinaryType<SubTask>::SetIdMapper(ignite::binary::BinaryBasicIdMapper(true));
        ignite::binary::BinaryType<SubTask>::SetNameMapper(ignite::binary::BinaryBasicNameMapper(true));
        
        ignite::binary::BinaryType<SubTask>::RegisterField<int>("subTaskId", &SubTask::subTaskId);
        ignite::binary::BinaryType<SubTask>::RegisterField<std::string>("description", &SubTask::description);
    }
};

class WorkerTask
{
public:
    int id;
    std::string name;
    TaskStatus status;
    std::vector<SubTask> subTasks;

    IGNITE_BINARY_TYPE(WorkerTask)
    {
        ignite::binary::BinaryType<WorkerTask>::SetTypeName("WorkerTask");
        ignite::binary::BinaryType<WorkerTask>::SetIdMapper(ignite::binary::BinaryBasicIdMapper(true));
        ignite::binary::BinaryType<WorkerTask>::SetNameMapper(ignite::binary::BinaryBasicNameMapper(true));
        
        ignite::binary::BinaryType<WorkerTask>::RegisterField<int>("id", &WorkerTask::id);
        ignite::binary::BinaryType<WorkerTask>::RegisterField<std::string>("name", &WorkerTask::name);
        ignite::binary::BinaryType<WorkerTask>::RegisterField<TaskStatus>("status", &WorkerTask::status);
        ignite::binary::BinaryType<WorkerTask>::RegisterField<std::vector<SubTask>>("subTasks", &WorkerTask::subTasks);
    }
};

核心要求:各端类型名称、字段名称、映射规则完全统一,枚举类型的数值与名称对应一致。

3. 采用SQL方案可以规避序列化问题

使用Ignite SQL读写数据时,无需依赖二进制类型的序列化映射,只需将缓存配置为SQL表,通过列形式操作数据,各平台客户端用SQL语句访问,直接绕过类型Id不匹配的问题。

具体实现步骤:

  1. Java服务端配置缓存为SQL表:
<bean id="workerStatusCacheCfg" class="org.apache.ignite.configuration.CacheConfiguration">
    <property name="name" value="WorkerStatusCache"/>
    <property name="queryEntities">
        <list>
            <bean class="org.apache.ignite.cache.QueryEntity">
                <property name="keyType" value="java.lang.Long"/>
                <property name="valueType" value="WorkerStatus"/>
                <property name="fields">
                    <map>
                        <entry key="id" value="java.lang.Long"/>
                        <entry key="workerName" value="java.lang.String"/>
                        <entry key="status" value="java.lang.String"/>
                        <entry key="lastUpdateTime" value="java.util.Date"/>
                    </map>
                </property>
                <property name="tableName" value="WORKER_STATUS"/>
            </bean>
        </list>
    </property>
</bean>
  1. .NET端SQL查询示例:
var sqlQuery = new SqlQuery(typeof(WorkerStatus), "SELECT id, workerName, status FROM WORKER_STATUS WHERE id = ?", 1L);
var results = cache.Query(sqlQuery).ToList();
  1. C++端SQL操作示例:
ignite::SqlFieldsQuery query("SELECT id, workerName, status FROM WORKER_STATUS WHERE id = ?");
query.AddArgument(1L);

ignite::FieldsQueryCursor cursor = cache.QueryFields(query);
for (ignite::FieldsRow row : cursor)
{
    int64_t id = row.Get<int64_t>(0);
    std::string workerName = row.Get<std::string>(1);
    std::string status = row.Get<std::string>(2);
    // 处理数据
}

这种方式下,各平台无需关心二进制序列化细节,按SQL表字段结构读写即可。


内容的提问来源于stack exchange,提问作者osmedd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 03:55:20