Couchbase php / .Net客户端不兼容问题


Couchbase php / .Net client incompatibility Issue

我们正在尝试将couchbase客户端用于PHP和.NET。 当我们使用 C# 设置值然后使用 PHP 读取它时,我们收到错误。 在远程登录到服务器时,我们没有任何问题,可以向另一个方向或读取值。 有谁知道为什么我们会收到错误?

php 'get' 调用会导致以下错误:

警告:Couchbase::get() [couchbase.get]:无法解压缩第 5 行 D:''inetpub''Webadvisor''its''test''couchbase.php 中的值(错误内容)

该错误来自 github 上 php-ext-couchbase 存储库中的 couchbase.c。https://github.com/couchbase/php-ext-couchbase/blob/master/convert.c#L213

C# 代码:(这工作正常)

Couchbase.Configuration.CouchbaseClientConfiguration config = new Couchbase.Configuration.CouchbaseClientConfiguration();
config.Urls.Add(new Uri("http://127.0.0.1:8091/pools"));
CouchbaseClient client = new CouchbaseClient(config);
client.Store(StoreMode.Set, "foo", "bar");
client.Dispose();

PHP代码:

$cb = new Couchbase("127.0.0.1", "", "", "default");
var_dump($cb->get("foo"));

我认为这是因为 php 扩展默认使用php序列化程序,以允许在 PHP 中无缝序列化更广泛的对象。以下是示例配置的摘录,解释了可用选项: https://github.com/couchbase/php-ext-couchbase/blob/master/example/couchbase.ini#L44-L52

; Specify the serializer to use to store objects in the Couchbase cluster.
;
; Legal values:
;   php        - Use the standard php serializer
;   json       - Use the php JSON encoding
;   json_array - Same as json, but decodes into arrays
;   igbinary   - This option is only available if the extension is build
;                with igbinary support
couchbase.serializer = php

在您的情况下,我认为您应该改用json序列化程序。

事实证明,.NET 和 PHP 客户端不兼容的问题归结为客户端将 memcache 标志设置为什么。这些标志用于告诉客户端存储的值的类型。.NET 的标志基于 Type.GetTypeCode() 方法。 因此,例如,当 .NET 客户端写入字符串以缓存时,它将标志设置为 274,但是 PHP 对 .NET 类型方案一无所知,也不知道如何处理该值,因此它尝试解压缩该值,这会引发错误。 当 PHP 写入字符串以缓存时,它将标志设置为 0。

我们找到了针对该问题的两种不同的修复方法。 第一个更像是一种解决方法。 如果将 PHP Couchbase 选项设置为 true COUCHBASE_OPT_IGNOREFLAGS,它将开始工作。

$cb = new Couchbase("127.0.0.1", "", "", "default");
$cb->setOption(COUCHBASE_OPT_IGNOREFLAGS,true);

我们最终采用的第二个解决方案是重载.NET Transcoder(Enyim.Caching.Memcached.ITranscoder)并设置标志以匹配PHP标志。

public class PHPTranscoder : ITranscoder
{
    ...
    public static uint TypeCodeToFlag(TypeCode code)
    {
        switch (code)
        {
            case TypeCode.String: return 0;
            case TypeCode.Int16: return 1;
            case TypeCode.Int32: return 1;
            case TypeCode.Int64: return 1;
            case TypeCode.UInt16: return 1;
            case TypeCode.UInt32: return 1;
            case TypeCode.UInt64: return 1;
            case TypeCode.Decimal: return 2;
            case TypeCode.Boolean: return 3;
            default: return 0; //default to string
        }
        // THE FOLLOWING IS COUCHBASE'S ORGINAL CODE
        // return (uint)((int)code | 0x0100);
    }
    ...
}