26、.NET 访问 Coherence 全解析

.NET 访问 Coherence 全解析

1. 配置基础

在 .NET 中访问 Coherence 时,过滤器注册与 Java 非常相似,主要差异在于根元素的命名空间声明和类名的指定方式。在 .NET 客户端,指定类名时,除了要给出完全限定类名,还需包含类所在的程序集名称。例如, PasswordBasedEncryptionFilter 类将从 Coherence.Encryption 程序集中加载。

2. 缓存配置

在 .NET 客户端,只能配置部分缓存方案,这是因为并非集群中所有的缓存方案都适用于 Coherence*Extend 客户端。可配置的方案包括本地、近程和远程缓存方案,以及远程调用服务。以下是一个 .NET 缓存配置文件示例:

<cache-config xmlns="http://schemas.tangosol.com/cache">
  <caching-scheme-mapping>
    <cache-mapping>
      <cache-name>*</cache-name>
      <scheme-name>extend-tcp</scheme-name>
    </cache-mapping>
  </caching-scheme-mapping>
  <caching-schemes>
    <remote-cache-scheme>
      <scheme-name>extend-tcp</scheme-name>
      <service-name>ExtendTcpCacheService</service-name>
      <initiator-config>
        <tcp-initiator>
          <remote-addresses>
            <socket-address>
              <address>localhost</address>
              <port>9099</port>
            </socket-address>
          </remote-addresses>
          <connect-timeout>30s</connect-timeout>
        </tcp-initiator>
        <outgoing-message-handler>
          <heartbeat-interval>1s</heartbeat-interval>
          <heartbeat-timeout>10s</heartbeat-timeout>
          <request-timeout>30s</request-timeout>
        </outgoing-message-handler>
        <use-filters>
          <filter-name>symmetric-encryption</filter-name>
        </use-filters>
      </initiator-config>
    </remote-cache-scheme>
  </caching-schemes>
</cache-config>
3. POF 配置

POF 配置文件除了命名空间声明和类名指定方式的差异外,与 Java 中的配置文件基本相同。以下是一个 POF 配置文件示例:

<pof-config xmlns="http://schemas.tangosol.com/pof">
  <user-type-list>
    <include>
      assembly://Coherence/Tangosol.Config/coherence-pof-config.xml
    </include>
    <user-type>
      <type-id>1000</type-id>
      <class-name>
        BankTerminal.Domain.Account, BankTerminal
      </class-name>
    </user-type>
    <user-type>
      <type-id>1001</type-id>
      <class-name>
        BankTerminal.Domain.Transaction, BankTerminal
      </class-name>
    </user-type>
  </user-type-list>
</pof-config>

重要的是,类型标识符要与集群中配置的标识符相匹配,并且要包含标准的 coherence-pof-config.xml 文件,该文件包含了 Extend 协议或 Coherence API 所需的所有内置 Coherence 类型的定义。

4. Coherence for .NET 的资源加载
4.1 资源抽象

Coherence for .NET 提供了四种 IResource 实现:
| 类名 | 描述 |
| ---- | ---- |
| FileResource | 提供对文件系统中文件的访问,是除 ASP.NET Web 应用程序外所有应用程序的默认资源类型。 |
| WebResource | 提供对 Web 应用程序中文件的访问,是 ASP.NET Web 应用程序的默认资源类型。 |
| EmbeddedResource | 提供对程序集嵌入资源的访问。 |
| UrlResource | 提供对 HTTP 或 FTP 资源的访问。 |

文件资源和 Web 资源虽然都代表磁盘上的物理文件,但在解析路径时行为不同。在 Web 应用程序中,不应使用 FileResource ,因为路径可能无法按预期解析。

4.2 协议和资源加载器

可以根据资源名称的协议部分来确定使用哪种 IResource 实现:
| 协议 | 资源 | 示例 |
| ---- | ---- | ---- |
| file | FileResource | file://config/my-pof-config.xml
file://c:/config/my-cache-config.xml
c:\MyDir\coherence.xml (如果文件是默认类型) |
| web | WebResource | web://config/my-pof-config.xml (相对于当前路径)
web://~/config/my-pof-config.xml (相对于根路径)
~/my-pof-config.xml (如果 Web 是默认类型) |
| assembly、asm | EmbeddedResource | assembly://MyAssembly/My.Name.Space/pof.xml
asm://MyAssembly/My.Name.Space/cache-config.xml |
| http、ftp | UrlResource | http://config.mycompany.com/my-pof-config.xml
ftp://user:pass@ftp.mycompany.com/config/pof.xml |

5. .NET 客户端配置方法

Coherence for .NET 支持三种客户端配置方法:
- 基于约定的配置 :依赖于将具有知名名称的文件放在应用程序目录中,适用于桌面和 ASP.NET Web 应用程序。需要创建以下文件:
- coherence.xml :用于操作描述符。
- coherence-cache-config.xml :用于缓存配置文件。
- coherence-pof-config.xml :用于 POF 配置文件。
Coherence for .NET 客户端库在启动时会自动检测这些文件并使用它们进行配置,除非被其他机制覆盖。
- 显式配置 :在某些情况下,可能需要将配置文件放在网络共享目录中,或使用不同名称的文件。可以通过编程方式或在标准 .NET 配置文件(如 Web.config App.config )中指定配置文件名来实现。以下是在 App.config Web.config 中配置的示例:

<configuration>
  <configSections>
    <section name="coherence"
    type="Tangosol.Config.CoherenceConfigHandler, Coherence"/>
  </configSections>
  <!-- 其他配置 -->
</configuration>
  • 编程式配置 :对于某些应用程序(如 Microsoft Office 插件),上述两种方法可能不适用。可以将配置文件嵌入到插件的程序集中,并在插件初始化时以编程方式配置 Coherence 客户端:
const string baseUrl = "assembly://CoherenceRTD/CoherenceRTD.Config/";
CacheFactory.SetCacheFactoryConfig(baseUrl + "coherence.xml");
CacheFactory.SetCacheConfig(baseUrl + "cache-config.xml");
CacheFactory.SetPofConfig(baseUrl + "pof-config.xml");
6. Coherence 与 Excel 的集成

上述编程式配置示例来自一个将 Coherence 用作数据源的 Excel RTD 服务器的概念验证。当 Coherence 集群中的数据发生变化时,Excel 工作表和图表会实时更新。你可以在 Dave Felcey 的博客(http://blogs.oracle.com/felcey/)上查看最终演示和使用说明。

7. 客户端应用程序实现
7.1 基本缓存操作

要获取命名缓存的引用,需要使用 Tangosol.Net.CacheFactory 类并调用其 GetCache 方法:

INamedCache cache = CacheFactory.GetCache("countries");

获取缓存实例后,可以使用 IDictionary 接口的标准成员(如 Count Add Remove Clear )以及索引器来操作缓存中的数据:

cache.Add("SRB", "Serbia");
cache.Add("USA", "United States");
cache["USA"] = "United States of America";
cache.Remove("SRB");
Console.WriteLine("USA = " + cache["USA"]);
Console.WriteLine("Cache size = " + cache.Count);
cache.Clear();

Add 方法在尝试添加已存在键的对象时会抛出异常,若要替换现有条目,可使用索引器。

也可以使用 Tangosol.Net.ICache 接口中定义的方法:

public interface ICache : IDictionary
{
  object Insert(object key, object value);
  object Insert(object key, object value, long millis);
  void InsertAll(IDictionary dictionary);

  IDictionary GetAll(ICollection keys);
}

前三个方法的行为与 Java 中的 put putAll 方法类似,允许插入新条目并覆盖现有条目,还可以指定条目的过期时间或批量插入多个条目。 GetAll 方法允许在单个网络调用中按键检索多个条目,显著提高读取性能。

7.2 实现数据对象

为了使 Coherence 的大多数功能正常工作,.NET 数据对象必须使用 POF 作为序列化格式,并且可能需要在集群中提供对应的 Java 实现。虽然技术上可以使用 .NET 二进制或 XML 序列化,但在大多数情况下不建议这样做,因为这会使 Coherence 集群节点无法反序列化对象,从而失去集群端的大部分功能。

在 Coherence 3.5 之前,进行集群端处理(如查询、聚合、条目处理器等)绝对需要 Java 类。但现在,即使没有 Java 类,也可以在集群中反序列化对象,甚至可以使用 PofUpdater 直接更新集群中的二进制数据。不过,实现并行类层次结构仍然是最佳方法,原因如下:
- 实现数据亲和性或使用读写穿透方法持久化缓存对象时需要 Java 类。
- 在条目处理器和聚合器中使用强类型的 Java 类比使用二进制数据更容易。
- 集群中存在 Java 类会使调试更加容易。

7.3 实现 IPortableObject 接口

有两种方法可以使对象具有可移植性。第一种是直接在类中实现 Tangosol.IO.POF.IPortableObject 接口:

public class Customer : IPortableObject
{
  // ---- 数据成员 -------------------------------------
  private long     id;
  private String   name;
  private DateTime dateOfBirth;
  // ---- 构造函数 -------------------------------------
  public Customer()
  {
    // 反序列化构造函数
  }
  public Customer(long id, String name, DateTime dateOfBirth)
  {
    // 初始化代码
  }
  // ---- 属性省略以简化代码 -----------------
  // ---- IPortableObject 实现 -------------------
  public virtual void ReadExternal(IPofReader reader)
  {
    id          = reader.ReadInt64(0);
    name        = reader.ReadString(1);
    dateOfBirth = reader.ReadDateTime(2);
  }
  public virtual void WriteExternal(IPofWriter writer)
  {
    writer.WriteInt64(   0, id);
    writer.WriteString(  1, name);
    writer.WriteDateTime(2, dateOfBirth);
  }
  // ---- Equals、GetHashCode 和 ToString 省略 -------
}
7.4 实现外部序列化器

以下是 EnumPofSerializer 的 .NET 实现示例:

public class EnumPofSerializer : IPofSerializer
{
  public void Serialize(IPofWriter writer, object o)
  {
    if (o == null || !o.GetType().IsEnum)
    {
      throw new ArgumentException(
       "EnumPofSerializer can only be used to serialize enum types.");
    }
    writer.WriteString(0, o.ToString());
    writer.WriteRemainder(null);
  }
  public object Deserialize(IPofReader reader)
  {
    IPofContext pofContext = reader.PofContext;
    Type enumType = pofContext.GetType(reader.UserTypeId);
    if (!enumType.IsEnum)
    {
      throw new ArgumentException(
       "EnumPofSerializer can only be used to deserialize enum types.");
    }
    object enumValue = Enum.Parse(enumType, reader.ReadString(0));
    reader.ReadRemainder();
    return enumValue;
  }
}
8. 执行查询

从 Coherence for .NET 客户端执行查询与从 Java 应用程序执行查询非常相似,只需创建一个过滤器并使用 Tangosol.Net.Cache.IQueryCache 接口中定义的方法执行它:

public interface IQueryCache : ICache
{
  object[] GetKeys(IFilter filter);
  // 其他方法
}

排序操作在客户端执行,不会给缓存服务器节点增加额外负载,但 LimitFilter 除外,它需要在集群中进行排序以确定要返回的第一页结果,这在分布式环境中是一项相当昂贵的操作,应尽量避免。如果需要集群端排序,可以考虑使用 Coherence Tools TopAggregator

9. 实现过滤器和值提取器

在定义过滤器时,需要使用值提取器。Coherence for .NET 中包含了所有在查询数据网格时描述的过滤器和值提取器,可以像在 Java 中一样轻松使用。

过滤器和值提取器的执行位置取决于所使用的缓存类型。如果对远程缓存发出查询,过滤器和值提取器会被序列化并传输到代理服务器执行;如果对本地或连续查询缓存(除非仅缓存键而不缓存值)执行查询,则会在客户端直接评估,这可以显著提高性能并减少缓存服务器的负载。

为了使过滤器和值提取器在客户端和集群中都能正常工作,它们必须在 Java 和 .NET 中有并行实现,并且要在相应的 POF 配置文件中使用相同的类型标识符进行正确注册。

10. 在 C# 中实现 PropertyExtractor

内置的 ReflectionExtractor 在 C# 中使用时不太自然,因为它要求根据缓存类型指定不同的访问器方法名称,这可能导致开发过程中更改缓存配置时出现错误。以下是 PropertyExtractor 的 .NET 实现:

public class PropertyExtractor 
        : AbstractExtractor, IValueExtractor, IPortableObject
{
  // ---- 数据成员 -------------------------------------
  private const BindingFlags BINDING_FLAGS =
                                    BindingFlags.Public 
                                    | BindingFlags.Instance 
                                    | BindingFlags.IgnoreCase;
  private String m_propertyName;
  [NonSerialized] 
  private PropertyInfo m_property;
  // ---- 构造函数 -------------------------------------
  public PropertyExtractor()
  {}
  public PropertyExtractor(String propertyName)
         : this(propertyName, VALUE)
  {}
  public PropertyExtractor(String propertyName, int target)
  {
    if (String.IsNullOrEmpty(propertyName))
    {
      throw new ArgumentNullException(             
                     "propertyName", "Property name cannot be null");
    }
    m_propertyName = propertyName;
    m_target       = target;
  }
  // ---- IValueExtractor 实现 -------------------
  public override Object Extract(Object target)
  {
    if (target == null)
    {
      return null;
    }
    Type targetType = target.GetType();
    try
    {
      PropertyInfo property = m_property;
      if (property == null || property.DeclaringType != targetType)
      {
        m_property = property = 
        targetType.GetProperty(m_propertyName, BINDING_FLAGS);
      }
      return property.GetValue(target, null);
    }
    catch (Exception)
    {
      throw new Exception("Property " + m_propertyName +
                       " does not exist in the class " + targetType);
    }
  }
  // ---- IPortableObject 实现 -------------------
  public void ReadExternal(IPofReader reader)
  {
    m_propertyName = reader.ReadString(0);
    m_target       = reader.ReadInt32( 1);
  }
  public void WriteExternal(IPofWriter writer)
  {
    writer.WriteString(0, m_propertyName);
    writer.WriteInt32( 1, m_target);
  }
  // ---- Equals、GetHashCode 和 ToString 省略 -------
}

通过以上步骤和代码示例,你可以在 .NET 环境中全面使用 Coherence 的各项功能,实现高效的数据缓存和处理。

.NET 访问 Coherence 全解析

11. 实现 StartsWithFilter

在 Java 中我们已经实现了 StartsWithFilter ,现在来实现其 .NET 版本。 StartsWithFilter 用于筛选出属性值以指定字符串开头的条目。以下是具体实现:

public class StartsWithFilter : IFilter, IPortableObject
{
    private string m_propertyName;
    private string m_prefix;

    public StartsWithFilter()
    {
    }

    public StartsWithFilter(string propertyName, string prefix)
    {
        m_propertyName = propertyName;
        m_prefix = prefix;
    }

    public bool Evaluate(object o)
    {
        if (o == null)
        {
            return false;
        }
        PropertyExtractor extractor = new PropertyExtractor(m_propertyName);
        object value = extractor.Extract(o);
        if (value is string strValue)
        {
            return strValue.StartsWith(m_prefix);
        }
        return false;
    }

    public void ReadExternal(IPofReader reader)
    {
        m_propertyName = reader.ReadString(0);
        m_prefix = reader.ReadString(1);
    }

    public void WriteExternal(IPofWriter writer)
    {
        writer.WriteString(0, m_propertyName);
        writer.WriteString(1, m_prefix);
    }
}

这个过滤器会根据指定的属性名和前缀,筛选出对象中对应属性值以该前缀开头的对象。

12. 示例应用流程

为了更好地理解如何在实际应用中使用上述功能,下面给出一个完整的示例应用流程:
1. 配置环境
- 创建 coherence.xml coherence-cache-config.xml coherence-pof-config.xml 文件,按照前面介绍的配置方法进行配置。
- 在 coherence-pof-config.xml 中注册自定义的数据对象和过滤器、提取器等。
2. 实现数据对象
- 创建实现 IPortableObject 接口的数据对象,如 Customer 类。
- 或者实现外部序列化器,如 EnumPofSerializer
3. 配置缓存
- 使用 CacheFactory 获取缓存实例,如 INamedCache cache = CacheFactory.GetCache("myCache");
4. 操作缓存数据
- 使用 Insert InsertAll GetAll 等方法操作缓存数据。
- 示例代码如下:

INamedCache cache = CacheFactory.GetCache("myCache");
Customer customer = new Customer(1, "John Doe", DateTime.Now);
cache.Insert(1, customer);
IDictionary result = cache.GetAll(new List<int> { 1 });
  1. 执行查询
    • 创建过滤器,如 StartsWithFilter ,并使用 IQueryCache 接口的方法执行查询。
    • 示例代码如下:
IQueryCache queryCache = (IQueryCache)cache;
StartsWithFilter filter = new StartsWithFilter("name", "J");
object[] keys = queryCache.GetKeys(filter);
13. 性能优化建议

在使用 Coherence for .NET 时,为了获得更好的性能,可以考虑以下几点建议:
- 批量操作 :尽量使用 InsertAll GetAll 方法进行批量插入和读取操作,减少网络开销。例如:

IDictionary data = new Dictionary<int, Customer>();
data.Add(1, new Customer(1, "John", DateTime.Now));
data.Add(2, new Customer(2, "Jane", DateTime.Now));
cache.InsertAll(data);
  • 本地缓存 :对于一些经常访问的数据,可以使用本地缓存,减少对远程缓存的请求。可以通过配置近程缓存方案来实现。
  • 避免不必要的排序 :如前面提到的, LimitFilter 在集群中排序开销较大,尽量避免使用。如果需要排序,可以考虑在客户端进行或者使用 TopAggregator
  • 合理配置超时时间 :在缓存配置文件中,合理配置连接超时、心跳间隔、心跳超时和请求超时等参数,避免因超时设置不合理导致性能问题。例如:
<tcp-initiator>
    <remote-addresses>
        <socket-address>
            <address>localhost</address>
            <port>9099</port>
        </socket-address>
    </remote-addresses>
    <connect-timeout>30s</connect-timeout>
</tcp-initiator>
<outgoing-message-handler>
    <heartbeat-interval>1s</heartbeat-interval>
    <heartbeat-timeout>10s</heartbeat-timeout>
    <request-timeout>30s</request-timeout>
</outgoing-message-handler>
14. 总结

通过以上内容,我们全面了解了在 .NET 环境中访问 Coherence 的各个方面,包括配置、资源加载、数据操作、查询以及过滤器和提取器的实现等。以下是整个过程的流程图:

graph LR
    A[配置环境] --> B[实现数据对象]
    B --> C[配置缓存]
    C --> D[操作缓存数据]
    D --> E[执行查询]
    E --> F[性能优化]

在实际应用中,要根据具体需求选择合适的配置和实现方式,同时注意性能优化,以确保系统的高效运行。通过合理使用 Coherence for .NET,我们可以实现高效的数据缓存和处理,为应用程序提供更好的性能和可扩展性。

希望以上内容能帮助你在 .NET 项目中顺利使用 Coherence,实现强大的数据处理功能。如果你在实践过程中遇到问题,可以根据本文提供的方法和代码进行排查和解决。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值