tarscloud / tarsjava Goto Github PK
View Code? Open in Web Editor NEWJava language framework rpc source code implementation
License: Other
Java language framework rpc source code implementation
License: Other
快速上手,服务端部署war包报 com.qq.tars.server.startup.Main not found
Caused by: java.lang.ClassNotFoundException: com.qq.tars.server.startup.Main not found in gnu.gcj.runtime.SystemClassLoader{urls=[file:/usr/local/app/tars/tarsnode/data/demo.HelloServer/bin//WEB-INF/classes/], parent=gnu.gcj.runtime.ExtensionClassLoader{urls=[], parent=null}}
at java.net.URLClassLoader.findClass(libgcj.so.10)
at java.lang.ClassLoader.loadClass(libgcj.so.10)
at java.lang.ClassLoader.loadClass(libgcj.so.10)
at gnu.java.lang.MainThread.run(libgcj.so.10)
程式是通过com.qq.tars.server.startup.Main来启动的吗? SystemClassLoader的路径在哪里配置?
tars文件
module TestApp
{
struct TestRecursive
{
0 optional int value;
1 optional TestRecursive testRecursive;
};
};
做序列化的时候会有栈溢出的问题
at com.qq.tars.protocol.util.TarsHelper.getStructInfo(TarsHelper.java:294)
at com.qq.tars.protocol.util.TarsHelper.isStruct(TarsHelper.java:491)
at com.qq.tars.protocol.util.TarsHelper.getParameterStamp(TarsHelper.java:207)
at com.qq.tars.protocol.util.TarsHelper.getStructInfo(TarsHelper.java:294)
at com.qq.tars.protocol.util.TarsHelper.isStruct(TarsHelper.java:491)
at com.qq.tars.protocol.util.TarsHelper.getParameterStamp(TarsHelper.java:207)
at com.qq.tars.protocol.util.TarsHelper.getStructInfo(TarsHelper.java:294)
We prefer selecting one invoker even all invokers are not available for the following reasons:
tryTimesInterval
expired.We plan to use tars-java to build up service framework, and prefer select one invoker anyway.
I found a "TODO" annotation on loadbalance implement related to what we want it to be, so maybe we can take it into consideration
no main manifest attribute, in HelloClient.war
Error: A JNI error has occurred, please check your installation and try again Exception in thread "main" java.lang.NoClassDefFoundError: com/qq/tars/rpc/protocol/tars/support/TarsAbstractCallback at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:756) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:468) at java.net.URLClassLoader.access$100(URLClassLoader.java:74) at java.net.URLClassLoader$1.run(URLClassLoader.java:369) at java.net.URLClassLoader$1.run(URLClassLoader.java:363) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:362) at java.lang.ClassLoader.loadClass(ClassLoader.java:418) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352) at java.lang.ClassLoader.loadClass(ClassLoader.java:351) at java.lang.Class.getDeclaredMethods0(Native Method) at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) at java.lang.Class.privateGetMethodRecursive(Class.java:3048) at java.lang.Class.getMethod0(Class.java:3018) at java.lang.Class.getMethod(Class.java:1784) at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544) at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526) Caused by: java.lang.ClassNotFoundException: com.qq.tars.rpc.protocol.tars.support.TarsAbstractCallback at java.net.URLClassLoader.findClass(URLClassLoader.java:382) at java.lang.ClassLoader.loadClass(ClassLoader.java:418) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352) at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ... 19 more
mv /usr/local/app/tars/tarsnode/tmp/download/BatchPatchingLoad/tarsjava.HelloService/tarsjava.HelloService.tgz /usr/local/app/tars/tarsnode/tmp/download/BatchPatchingLoad/tarsjava.HelloService/tarsjava.HelloService.war;unzip -oq /usr/local/app/tars/tarsnode/tmp/download/BatchPatchingLoad/tarsjava.HelloService/tarsjava.HelloService.war -d /usr/local/app/tars/tarsnode/tmp/download/BatchPatching/tarsjava.HelloService/HelloService,error!
quickstart-server发布正常运行了,配置:
TestApp.HelloServer.HelloObj
tcp -h 127.0.0.1 -t 60000 -p 18601
quickstart-client proxy的设置:
TestApp.HelloServer.HelloObj@tcp -h 127.0.0.1 -p 18601 -t 60000
no main manifest attribute, in HelloClient.war
Error: A JNI error has occurred, please check your installation and try again Exception in thread "main" java.lang.NoClassDefFoundError: com/qq/tars/rpc/protocol/tars/support/TarsAbstractCallback at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:756) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:468) at java.net.URLClassLoader.access$100(URLClassLoader.java:74) at java.net.URLClassLoader$1.run(URLClassLoader.java:369) at java.net.URLClassLoader$1.run(URLClassLoader.java:363) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:362) at java.lang.ClassLoader.loadClass(ClassLoader.java:418) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352) at java.lang.ClassLoader.loadClass(ClassLoader.java:351) at java.lang.Class.getDeclaredMethods0(Native Method) at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) at java.lang.Class.privateGetMethodRecursive(Class.java:3048) at java.lang.Class.getMethod0(Class.java:3018) at java.lang.Class.getMethod(Class.java:1784) at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544) at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526) Caused by: java.lang.ClassNotFoundException: com.qq.tars.rpc.protocol.tars.support.TarsAbstractCallback at java.net.URLClassLoader.findClass(URLClassLoader.java:382) at java.lang.ClassLoader.loadClass(ClassLoader.java:418) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352) at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ... 19 more
求大佬帮忙看下,谢谢!
application.yml配置如下:
eureka:
client:
serviceUrl:
#服务注册中心的地址
defaultZone: http://localhost:8761/eureka/
#客户端不需要向spring cloud主控注册
register-with-eureka: false
报错:
Description:
Disconnected from the target VM, address: '127.0.0.1:56002', transport: 'socket'
Field clientProperties in com.qq.tars.register.eureka.EurekaRegisterHandler required a bean of type 'com.qq.tars.spring.config.TarsClientProperties' that could not be found.
Action:
Consider defining a bean of type 'com.qq.tars.spring.config.TarsClientProperties' in your configuration.
issue和pr都多久没review了,今天收到一个接受的pr竟然是作者自己提的。
由同一个Communicator获取不同servant的proxy,调用servant的超时时间都是相同的。现在,想实现每个servant能够有各自的超时时间,为了减少创建的Communicator数量,使用同一个Communicator获取proxy,通过stringToProxy(Class<T> clazz, ServantProxyConfig servantProxyConfig)
中的ServantProxyConfig来为每个servant设置不同的超时参数。
ServantProxyConfig默认的SetDivision值为“”(空字符串),并且setSetDivision方法无法将值设置为null。在ObjectProxyFactory.getObjectProxy
中,通过判断SetDivision是否为null来确定如何设置赋值,这就导致了通过上述stringToProxy接口来获取proxy时,SetDivision一定得设置。
有几个问题:
1、是否可以提个PR将ServantProxyConfig的SetDivision默认值改为null,或者将ObjectProxyFactory.getObjectProxy中对SetDivision的判断改为isEmpty判断,或者修改setSetDivision使其允许将值设置null;
2、除了创建多个Communicator,是否有其他推荐的做法来到达不同servant设置不同超时的效果;
Communicator#initCommunicator中不需要lock,直接inited.cas就行了
Our team uses tars as our rpc framework and we are trying to adopt the sprint-boot version of tars.
In general, we use tars console and ConfigHelper to manage our config files. In tars spring boot, the server template use java -jar rather than -cp to run the spring boot application, such that the class path configuration is ignored.
ConfigHelper will load files into {basepath}/conf, so this path should be added to resources location in tars-spring-boot-starter.
改造一个老项目,很多依赖应用用的http协议,好像tars c++是支持的
实现中,是用一个线程定时去轮询 ticks,500ms轮询一次,导致异步超时,当超时时间小于500ms的时候,检测不到,没有触发exipire的逻辑.
能否追加注册中心consul和etcd?
tars & vertx 如何一起使用有demo吗
在使用中出现过Selector空转的bug,希望能有netty、grizzly这样的重建Selector的规避方案。
在Logger的这个方法,如果在写入日志文件发生异常,代码就会走到后面一段,即从queue里poll出日志然后System.out.print输出,然后Tars的日志系统把System的out/err都冲定向到这个LoggingOutputstream,而这个流的flush方法,就是调用Logger的info方法,最终就是offer一个日志到这个queue里,然后发生死循环,一边offer一边poll。
private void writeAllToLocal(String file) {
boolean succ = false;
if (file != null) {
BufferedWriter bw = null;
try {
if (!logQueue.isEmpty()) {
bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file + "." + Utils.getDateSimpleInfo(System.currentTimeMillis()), true), "UTF-8"));
LogItem item = null;
while ((item = logQueue.poll()) != null) {
bw.write(item.toString());
}
}
succ = true;
} catch (IOException ex) {
} finally {
if (bw != null) {
try {
bw.close();
} catch (IOException e) {
}
}
}
}
if (!succ) {
LogItem item = null;
while ((item = logQueue.poll()) != null && !STDOUT_LOG.equals(name)) {
System.out.print("\t" + item.toString());
}
}
}
我想在日志里,将请求串联起来,应该怎么弄
还是说要结合 :https://github.com/TarsCloud/TarsJava/blob/master/docs/tars_tracing.md 这个才可以使用。我要怎么get到 traceid,打印在日志里?
在各个AppContext进行载入servant时,捕获了可能发生的异常,然后打印了日志。
如果一台服务器上一个端口被其他servant占用,再load这个servant时候,绑定配置的端口时就会发生异常,然后被捕获。但是控制台检测时应该只是检测了端口是否监听,然后显示服务active,实际上该服务并没有起来(而是另一个已经起来的相同端口的servant),如果这时候客户端调用,就会返回-4,没有这个servant(显然,因为根本没起来)。
请考虑直接在启动时把异常抛出来,能够快速发现问题而不是在调用时才发现,毕竟我们发布一个服务时希望所有的servant都可用而不是部分可用,而发布时候已然错误地显示成功。
private void loadAppServants(ApplicationContext applicationContext) {
Map<String, ServantConfig> servantMap = applicationContext.getBeansOfType(ServantConfig.class);
for (Map.Entry<String, ServantConfig> entry : servantMap.entrySet()) {
try {
ServantHomeSkeleton skeleton = loadServant(entry.getValue());
skeletonMap.put(skeleton.name(), skeleton);
appServantStarted(skeleton);
} catch (Exception e) {
System.err.println("init a service failed");
e.printStackTrace();
}
}
}
在tars的NodeServer模块源码CommandPatch.h里execute这个函数404行可以看到在发布时对war包执行的操作
if (_serverObjectPtr->getServerType() == "tars_java") //如果是tars_java,使用war 方法
{
sLocalTgzFile_bak=TC_Common::replace(sLocalTgzFile,".tgz",".war");
cmd +=" mv "+sLocalTgzFile+" "+sLocalTgzFile_bak+";";
cmd += "unzip -oq " + sLocalTgzFile_bak+ " -d "+ sLocalExtractPach+"/"+sServerName;
}
是覆盖原来的WEB-INF下,不是清除后再覆盖,所以会保留原来的旧版本包,在启动时可能加载
的是旧的jar包。生产不应该让用户去手动删除WEB-INF这个包吧?希望框架能改一下实现。全量发布先清除原目录再解压、发布。
When will SSL communication be supported?
如题.
Taf2JavaMojo插件,去生成struct对应的java类时,没有实现 toString方法.
带来问题:接口打印请求参数的时候,没办法打印整个对象的参数
In tar-spring-boot-starter, ManageServiceListener is added to spring.factories to init server configuration.
public class ManageServiceListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
System.out.println("[TARS] init manage service");
Server.loadServerConfig();
Server.initCommunicator();
Server.configLogger();
Server.startManagerService();
}
}
Generally, this code works fine. But when we involve some spring cloud components, BootstrapApplicationListener will build another BootstrapApplicationContext during application startup, which causes the ManageServiceListener constructed and run twice.
But the listener is intended to run only once and it will throw exception if run twice.
com.qq.tars.rpc.exc.TarsException: PropertyReporter|setPropertyInfo method should be called once at most at com.qq.tars.support.property.PropertyReportHelper.setPropertyInfo(PropertyReportHelper.java:127) ~[tars-core-1.6.1.jar:na] at com.qq.tars.support.om.OmServiceMngr.initAndStartOmService(OmServiceMngr.java:53) ~[tars-core-1.6.1.jar:na] at com.qq.tars.server.core.Server.startManagerService(Server.java:80) ~[tars-core-1.6.1.jar:na] at com.qq.tars.spring.bean.ManageServiceListener.onApplicationEvent(ManageServiceListener.java:31) ~[tars-spring-boot-starter-1.6.1.jar:na] at com.qq.tars.spring.bean.ManageServiceListener.onApplicationEvent(ManageServiceListener.java:23) ~[tars-spring-boot-starter-1.6.1.jar:na]
文档描述有误:
在服务器 tasnode/data/服务名/conf 目录下
应该是:
在服务器 tarsnode/data/服务名/conf 目录下
The default value of ServantInvokerAliveStat.lastRetryTime is 0. When the Invoker
marked as inactive first time, the value of lastRetryTime is still 0.
The loadbalance would still add it into candidate Invoker due to LastRetryTime
is 0 so that the candition would always be true when first time an Invoke
marked as inactive.
(stat.getLastRetryTime() + (config.getTryTimeInterval() * 1000)) < System.currentTimeMillis()
It works not what we expected, especially when we set frequenceFailInvoke
to 1.
ServantProxyFactory用了concurrentHashMap,为什么还要加个lock?
我看TarsInputStream里面有read方法。但是必须要指定一个Tag和flag。
而读取一个对象的时候的时候(Struct.readFrom()?)只需要read其中readStrcut的那部分,如下
TarsStructInfo info = TarsHelper.getStructInfo(WebSocketCommand.class);
Object result = CommonUtils.newInstance(Object.class);
List<TarsStrutPropertyInfo> list = info.getPropertyList();
if (!CommonUtils.isEmptyCollection(list)) {
for (TarsStrutPropertyInfo propertyInfo : list) {
Object value = tarsInputStream.read(propertyInfo.getStamp(), propertyInfo.getOrder(), propertyInfo.isRequire());
BeanAccessor.setBeanValue(result, propertyInfo.getName(), value);
}
}
而TarsStructBase有一个readFrom的Abstract方法,要自己手动实现。。。那注解的意义何在
为什么不弄一个default方法(JDK 8 interface)或者直接实现它呢。。
还是说我没找到正确的操作方式?java的文档太少啦,
springboot example项目,启动服务报错 [alarm] activating,pid not exist
跟随tarsJava快速入门,执行mvn package
后,准备将war包发布到web管理平台上。
跟随tarsJava发布执行后,服务无法开启,始终处于inactive状态:
请问是什么原因?谢谢!
在插件代码TarsBuildMojo.java
line381
File servicesXMLFile = new File(war, "WEB-INF" + File.separator + "servants.xml");
会去WEB-INF下找servants.xml,否则执行tars:build时会报错。
但是在应用启动时,是在classpath下查找servants.xml的,见XmlContext.java
XMLConfigFile cfg = new XMLConfigFile();
cfg.parse(getClass().getClassLoader().getResource("servants.xml").openStream());
应该只需要统一在classpath查找servant的配置就行了吧,没必要维护两份一模一样的文件。
ERROR tars-log | config error: locator and objName can't be empty.
各位大佬,tars-spring-boot-server运行时报错。看起来像是按tars协议处理了,应该是走非tars协议才对。求帮忙看下,谢谢!
代码:
`package com.qq.tars.quickstart.server;
import com.qq.tars.server.core.ContextManager;
import com.qq.tars.spring.annotation.EnableTarsServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.qq.tars.spring.annotation.TarsHttpService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@EnableTarsServer
@TarsHttpService("HttpObj")
@RestController
public class QuickStartApplication {
public static void main(String[] args) {
SpringApplication.run(QuickStartApplication.class, args);
}
@RequestMapping(path = "/test")
public String test() {
return "hello world";
}
}`
启动时有报这个错,但能正常启动,端口监听也正常。
Exception in thread "ServantThreadPool-exec-null-1" java.lang.NoClassDefFoundError: com/qq/tars/server/core/ContextManager at com.qq.tars.server.core.TarsServantProcessor.process(TarsServantProcessor.java:180) at com.qq.tars.net.core.nio.WorkThread.run(WorkThread.java:80) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Caused by: java.lang.ClassNotFoundException: com.qq.tars.server.core.ContextManager at java.net.URLClassLoader.findClass(URLClassLoader.java:382) at java.lang.ClassLoader.loadClass(ClassLoader.java:418) at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:92) at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ... 5 more
收到http请求后,服务报的错如下。看起来像是按tars协议处理了,应该是走非tars协议才对。
com.qq.tars.net.protocol.ProtocolException: the length header of the package must be between 0~10M bytes. data length:504f5350 at com.qq.tars.rpc.protocol.tars.TarsCodec.decodeRequest(TarsCodec.java:254) at com.qq.tars.net.core.nio.TCPSession.readRequest(TCPSession.java:119) at com.qq.tars.net.core.nio.TCPSession.read(TCPSession.java:97) at com.qq.tars.net.core.nio.TCPAcceptor.handleReadEvent(TCPAcceptor.java:77) at com.qq.tars.net.core.nio.Reactor.dispatchEvent(Reactor.java:183) at com.qq.tars.net.core.nio.Reactor.run(Reactor.java:104)
org.springframework.context.ApplicationContextException: Failed to start bean 'eurekaAutoServiceRegistration'; nested exception is java.lang.ClassCastException: com.netflix.discovery.DiscoveryClient cannot be cast to org.springframework.cloud.netflix.eureka.CloudEurekaClient
不知道是不是使用的springcloud版本不兼容,我是用的cloud版本为Greenwich.RELEASE,boot版本2.1.3,tars的版本1.6.1,1.6.2,1.7.0都试过,一样的错误
能否用TarsJava中的net库来做普通的IM长连接服务器,像Netty一样
不明白为什么要获取TarsStructInfo。如果是自动生成的代码,那么已经有生成好的readFrom(TarsInputStream)方法,直接通过反射获取到readFrom方法,然后invoke不就好了?
获取TarsStructInfo反而会造成有tars里面如果定义的结构有嵌套,在这边直接死循环。
//省略验证以及HeadData那部分
T result = CommonUtils.newInstance(e::class.java);
Method readFrom = e.getClass().getDeclaredMethod("readFrom",TarsInputStream.class);
readFrom.invoke(result, jis);
return result;
查看1.5.0 TarsJava源码,发现CommunicatorConfig中refreshEndpointInterval不起作用,没有任何代码引用此参数,按官方文档的意思是,refreshEndpointInterval是“定时去registry刷新配置的时间间隔”。是不是此处有问题,按代码里的逻辑,应该最终将refreshEndpointInterval参数设置到ServantProxyConfig的refreshInterval参数里,但是没看到设置。
说实话刷新默认时间设置成1分钟,也太长了,难道服务还得等1分钟才能调用,不让就超时或失败,希望今后加入准实时感应服务节点变更情况,比如像zookeeper主动通知服务变更机制。
配置如下:
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
register-with-eureka: false
tars:
client:
async-invoke-timeout: 10000
locator: http://localhost:8761/eureka/
报错:
Description:
Field clientProperties in com.qq.tars.register.eureka.EurekaRegisterHandler required a bean of type 'com.qq.tars.spring.config.TarsClientProperties' that could not be found.
如果使用自己实现的Logger,在程序里面很难控制这块的处理,而且目前看下来,可能是因为要做remote logging所以自己做了实现?
这块应该可以有更好的处理方案吧,比如使用常用的日志框架和实现,并增加自定义appender?
如何在一台机器上部署多个tars springboot 实例?springboot在启动的时候必须指定http端口,如果要在一台机器部署同样的服务的多个springboot实例,应该怎么配置呢?目的是为了高效的利用机器资源。
tars官方给的指引,是用maven来管理项目的,如果使用gradle,是否有对应的tars2java插件?或者有什么方式能够在gradle项目中使用tars2java?
When the Java Client use "oneway" mode to call another server, it uses async call with a null callback. When the call happens, a ticket with the callback wrapper will be created and will be checked periodically to see if the call timeout.
Though the callback is null, the callback wrapper will never be null. So since oneway call never gets response, the client will always consider this as timeout and report to StatServer. And this produces false timeout report.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.