本文已参与「新人创作礼」活动,一起开启掘金创作之路。
多线程JNI使用TUXEDO客户端问题
测试的时候,报文正常通过,一段时间之后,出现报文全部卡死,之后所有报文都不能正常通讯。(顶不住压力,交易量大就死)
1、重启平台之后,通讯暂时恢复,一段时间之后有卡死。
2、最开始怀疑,内存未回收,jni的变量和tuxedo的变量未回收,检查是否都tpfree和release掉。
3、跟踪jni的程序,发现进入jni函数之后,tpinit出现阻塞,导致之后所有交易都卡到,进jni的c程序之后。
4、去掉tpinit之后,发现程序都阻塞到了,tpcall里面。不tpinit,tpcall自动tpinit。
5、设置tuxedo 客户端,多会话模式,问题解决。
TPINIT * tpinfo = NULL ;
tpinfo = (TPINIT *)tpalloc("TPINIT", NULL, TPINITNEED(32));
if(tpinfo != NULL) {
// 设置多会话模式,适配多线程模式
tpinfo->flags = TPMULTICONTEXTS;
} else {
printf("tpalloc(TPINIT)失败\n");
return -1;
}
if ( tpinit(tpinfo) == -1 ) {
printf("tpinit err\n");
tpfree((char *)tpinfo);
return -1;
}
tpfree((char *)tpinfo);
tuxedo 客户端使用多线程时 在初始化时设置多上下文
当客户端准备好加入应用程序时,指定tpinit()并设置TPMULTICONTEXTS标志
tpinitbuf = tpalloc(TPINIT, NULL, TPINITNEED(0));
tpinitbuf->flags = TPMULTICONTEXTS;
if(tpinit(tpinitbuf)== -1){
ERROR_PROCESSING_CODE
}
tuxedo客户端,应该变成如下代码
#include <stdio.h>
#include "atmi.h" /* TUXEDO Header File */
#include "TuxedoJNI.h"
#define DATALEN 2048
/*void main() */
JNIEXPORT jint JNICALL
Java_TuxedoJNI_tuxedo_1send(JNIEnv *env, jclass jc)
{
char *sendbuf, *rcvbuf;
long sendlen, rcvlen;
int ret,iLen=0,lLen=0;
putenv("WSNADDR=//192.168.1.11:8000");
/* Attach to System/T as a Client Process */
if (tpinit((TPINIT *) NULL) == -1) {
(void) fprintf(stderr, "Tpinit failed\n");
exit(1);
}
/* Allocate STRING buffers for the request and the reply */
if((sendbuf = (char *) tpalloc("CARRAY", NULL, DATALEN+1)) == NULL) {
(void) fprintf(stderr,"Error allocating send buffer\n");
tpterm();
exit(1);
}
if((rcvbuf = (char *) tpalloc("CARRAY", NULL, DATALEN+1)) == NULL) {
tpinitbuf = tpalloc(TPINIT, NULL, TPINITNEED(0));
tpinitbuf->flags = TPMULTICONTEXTS;
if(tpinit(tpinitbuf)== -1){
ERROR_PROCESSING_CODE
}
}
/* orgnize the package */
sendlen = Pack_buf(sendbuf);//发包自己实现
/* Request the service IPPSRV, waiting for a reply */
ret = tpcall("zhcx", (char *)sendbuf, sendlen, (char **)&rcvbuf, &rcvlen, (long)0);
if(ret == -1 && tperrno==TPESYSTEM) {
tpterm();
ret = tpcall("zhcx", (char *)sendbuf, sendlen, (char **)&rcvbuf, &rcvlen, (long)0);
}
if(ret == -1) {
(void) fprintf(stderr, "Can't send request to service IPPSRV\n");
(void) fprintf(stderr, "Tperrno = %d\n", tperrno);
tpfree(sendbuf);
tpfree(rcvbuf);
tpterm();
exit(1);
}
unPack_buf(rcvbuf,rcvlen); //收包自己实现
/* Free Buffers & Detach from System/T */
tpfree(sendbuf);
tpfree(rcvbuf);
tpterm();
}