最近在用opensips(3.3.10)版本支持信创和国产数据库,因为是使用源码编译构建,所以arm版本编译很顺利,在支持国产数据库的过程中遇到一些问题,现对这些问题做个总结。
1. 尽量少用数据库
2. 在无法避免使用数据库时,使用轻量模块(数据读)
3. 使用odbc模块(数据读写)
1. 尽量少用数据库
opensips的大部分模块比如usrloc, dialog, cluster, rtpengine等这些是支持nodb模式的,所以我们是构建项目尽量少用组件,服务越简单,越可靠。opensips当然还有些模块比如dispatcher必须要用db模式,此时就必须要考虑以下两种方式了。
2. 使用轻量模块
2.1 db_text
db_text是opensips提供的轻量级文件处理模块,此模块需要注意三点:
1. 无法像mysql一样生成自增id,所以对于这样的字段可以去掉。
2. 它把数据存在内存中,只有在服务死掉时才同步到文件,所以如果想用db_text
存储acc,那么内存会有写爆的风险。
3. db_text的表数据类型可能会和mysql中的表类型不一致。我指的是mysql的int到db_text有可能是str,所以实际可根据错误来修改(这应该是db_text的bug)。
opensips认为db_text也是一种数据库,所以需要version表,以dispatcher为例,那么就需要两个表:version和dispatcher
version:
table_name(str) table_version(int) acc:7 active_watchers:12 address:5 b2b_entities:2 b2b_logic:4 b2b_sca:1 cachedb:2 carrierfailureroute:2 carrierroute:3 cc_agents:3 cc_calls:3 cc_cdrs:2 cc_flows:2 closeddial:1 clusterer:4 cpl:2 dbaliases:2 dialog:11 dialplan:5 dispatcher:8 domain:3 domainpolicy:3 dr_carriers:3 dr_gateways:6 dr_groups:2 dr_partitions:1 dr_rules:4 emergency_report:1 emergency_routing:1 emergency_service_provider:1 fraud_detection:1 freeswitch:1 globalblacklist:2 grp:3 imc_members:2 imc_rooms:2 jwt_profiles:1 jwt_secrets:1 load_balancer:3 location:1013 missed_calls:5 presentity:5 pua:9 qr_profiles:1 rc_clients:1 rc_demo_ratesheet:1 rc_ratesheets:1 rc_vendors:1 registrant:3 re_grp:2 rls_presentity:1 rls_watchers:2 route_tree:2 rtpengine:1 rtpproxy_sockets:0 silo:6 sip_trace:5 smpp:1 speed_dial:3 subscriber:8 tcp_mgm:1 tls_mgm:3 uri:2 userblacklist:2 usr_preferences:3 watchers:4 xcap:4
- dispatcher
id(int,auto) setid(int) destination(str) socket(str,null) state(int) weight(str) priority(int) attrs(str) description(str)
1:1:sip\:192.168.9.124\:5261::0:1:0:pstn=100:test
opensips.cfg中的配置方式:
loadmodule "db_text.so"
modparam("dispatcher", "db_url", "text:///data/sbc/text")
/data/sbc/text目录下:
/data/sbc/text
[root@sbc-lb text]# ll
total 8
-rw-r--r-- 1 root root 207 Dec 6 17:44 dispatcher
-rw-r--r-- 1 root root 911 Dec 6 16:25 version
2.2 db_http
opensips提供了一种http的方式,可以把数据通过http的方式发送给server。
http Server可以接收数据写数据库。这个我没有实际实践过,看了官方文档,应该是可行的。
2.3 db_sqlite
sqlite是大部分服务不能对接国产数据库,但必须使用数据库的唯一方式。
但是由于sqlite在高并发下,性能不强。
而且它存储数据在本地文件夹下,opensips在做主备方案时,主备只能各存各的,数据不一致。
3. 使用odbc模块
在以上的方式都不能满足的条件下,必须要使用数据库,比如acc。
当然acc也有db_flatstore模块支持快速写,但是这个也是和写文件一样,存储在本地,opensips主备模式,不太适用。
此时只能用odbc来对接国产数据库了,进入今天的主题。
参考文章:https://www.cnblogs.com/itschen/p/14831048.html
3.1 准备知识
达梦,高斯,OceanBase这些数据库都是有"模式"的概念,这个模式对应的是schema。
但是此参数在odbc配置数据库信息时,所有的数据库都是不提供的,另外达梦的schema要带引号。
这个"模式"其实和mysql的数据库名是差不多一个概念。
opensips的sql语句都是未带库名,只有表名。
3.2 odbc对接
3.2.1 达梦
- 使用参照文章 https://www.cnblogs.com/itschen/p/14831048.html 安装unixodbc
- 把达梦的libdodbc.so相关的so库(这个库需要注册达梦官方网站,找他们的客服要),放到/usr/local/odbc/lib/下(自己定义,直接放到/usr/local/lib下也行)。
- export LD_LIBRARY_PATH=/usr/local/odbc/lib:/usr/local/lib:$LD_LIBRARY_PATH,
- ldd libdodbc.so,看看是否缺库,缺啥安装啥。
odbcinst.ini
[DM8 ODBC DRIVER] Description = ODBC DRIVER FOR DM8 DRIVER = /usr/local/odbc/lib/libdodbc.so
odbc.ini
[DM8] Description = ODBC DRIVER FOR DM8 Driver = DM8 ODBC DRIVER SERVER = 172.16.6.224 DATABASE = sbc UID = test PWD = test123 TCP_PORT = 5238
然后
isql -v dm8
正常就连上了dm数据库了。
opensips如何配置呢:
- opensips的Makefile.conf.templete里的exclude_modules去掉db_unixodbc。
db_url: unixodbc://test:test123@172.16.6.224:5238/dm8
小技巧:docker-compose.yaml里如果密码带有$符号,那么怎么才能使用此$,不被转义呢? 答案是再加个$,比如密码是test12#$, 那么docker-compose.yaml配置时为:test12#$$
这些只能是连上了数据库,但是在执行sql出错,还是schema的问题。
3.2.2 高斯
高斯和达梦的对接方式差不多,区别
- odbc.init的配置
- 高斯的schema不用加引号
- gsqlowdbcw.so库需要glibc2.28的版本,所以要提前安装好
gsqlowdbcw.so 要去华为的官网上找。
odbcinst.ini
[GaussMPP] Description = ODBC DRIVER FOR GaussDB Driver64 = /usr/local/odbc/lib/gsqlodbcw.so setup = /usr/local/odbc/lib/gsqlodbcw.so
odbc.ini
[gb] Driver = GaussMPP Servername = 172.16.6.223 Database = sbc Username = huaweibase Password = Huaweibase123 Port = 26000 Sslmode = allow
只是能连接上,如要正确使用sql要改源码。
3.2.3 OceanBase
由于oceanBase兼容mysql比较好,所以直接使用mysql驱动就行,不用使用odbc方式,当然使用odbc也行。
另外由于oceanBase的mysql在配置的时候,用户名会带有'@'字符,opensips会报错,要改源码。opensips需要改的源码位置为:db/db_id.c,具体可参考kamailio的来。
4 如何处理schema?
由于此模式也就相当于opensips在执行sql时,前面指定schema,又或者这样
select table_version from xing_sbc.version where table_name = 'dialog';
所以为避免改动过多,我采用的策略是在表名前加schema前缀,需要改动db/db.c里的代码。
小技巧: 在docker-compose.yaml里,对接达梦时,要传双引号,可采用如下配置:
unixodbc://dmtest:kdbase#@172.16.4.112:5236/dm8?Schema=\\"opensips\\"
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。