ServiceComb/CSE常见问题处理(190110)

一、Tomcat重复加载war包问题

问题现象

有同事开发了一个demo服务,服务包含前端页面和ServiceComb开发的REST后端服务两部分。打成war包部署在Tomcat中,发现这个服务会在服务中心注册两个地址相同的实例。观察日志,发现Spring Context加载了两遍,并且Tomcat的webapps目录下存在一个与war包同名的目录和一个ROOT目录,两个目录中的内容是相同的。

问题原因

Tomcat在启动时会将webapps目录下的war包解压到一个同名目录下,将其作为一个context加载。而在Tomcat的conf/server.xml文件中,又额外定义了一个Context:

<Context path="/" reloadable="true" docBase="${war包的名字}"/>

于是该war包会作为root context 又被加载一次。

解决方案

删掉conf/server.xml文件中定义的context,把拷贝到webapps目录下的war包改名为ROOT.war。Tomcat启动时会自动将war包解压作为root context加载。

二、CSE/ServiceComb JAVA SDK如何配置业务处理线程池

CSE JAVA SDK的线程池模型比较复杂,对于tomcat场景,以及Edge Service的vert.x场景,都有一个业务处理线程池(Edge Service的场景默认在reactive模式,是没有业务线程池的)。CSE设置的默认线程池的线程个数为2 * CPU个数。如果部分服务处理比较慢(比如评价时延>50ms),那么建议要设置一个较大的业务线程池,以提升吞吐量。如果所有接口都处理的很快,则不需要设置非常大的业务线程池,过多线程反而会因为线程调度,增加处理时延。如果一个微服务,有少量的几个接口处理非常耗时,需要考虑将这些接口放到独立的线程池执行(线程池隔离),防止访问慢的接口,影响访问快的接口。 

线程池配置 (可以适当的抽时间学习下线程模型:https://bbs.huaweicloud.com/blogs/0a1a862f412611e89fc57ca23e93a89f

  1.        通过配置项servicecomb.executors.default给业务接口制定执行线程池。配置项的的缺省值为servicecomb.executor.groupThreadPool,这个值是Bean的ID,CSE缺省的几个Bean ID如下:

1

2

3

4

5

  <bean id="cse.executor.groupThreadPool" class="org.apache.servicecomb.core.executor.FixedThreadExecutor"/>

  <alias name="cse.executor.groupThreadPool" alias="cse.executor.default"/>

  <alias name="cse.executor.groupThreadPool" alias="servicecomb.executor.groupThreadPool"/>

  <bean id="cse.executor.reactive" class="org.apache.servicecomb.core.executor.ReactiveExecutor"/>

  <alias name="cse.executor.reactive" alias="servicecomb.executor.reactive"/>

2.       通过servicecomb.executors.Provider.[servicename.schemaid.operationId]给某个具体的接口指定不同的线程池。

三、服务端定义一个空schema,客户端抛出异常

错误异常如下:

2019-01-05 11:17:33.882 [pool-1-thread-1] ERROR o.a.s.s.consumer.MicroserviceVersions Line:163 ----------------> Failed to setInstances, appId=ippc, microserviceName=service-acceptance-dhc-quyq.

java.lang.NullPointerException: null

at org.apache.servicecomb.swagger.SwaggerUtils.validateSwagger(SwaggerUtils.java:80)

at org.apache.servicecomb.core.definition.SchemaUtils.parseSwagger(SchemaUtils.java:49)

at org.apache.servicecomb.core.definition.schema.ConsumerSchemaFactory.loadSwagger(ConsumerSchemaFactory.java:77)

at org.apache.servicecomb.core.definition.schema.ConsumerSchemaFactory.createSchema(ConsumerSchemaFactory.java:54)

at org.apache.servicecomb.core.definition.schema.ConsumerSchemaFactory.createSchema(ConsumerSchemaFactory.java:33)

at org.apache.servicecomb.core.definition.schema.AbstractSchemaFactory.getOrCreateSchema(AbstractSchemaFactory.java:65)

at org.apache.servicecomb.core.definition.schema.ConsumerSchemaFactory.createConsumerSchema(ConsumerSchemaFactory.java:47)

at org.apache.servicecomb.core.definition.MicroserviceVersionMeta.<init>(MicroserviceVersionMeta.java:40)

at org.apache.servicecomb.core.definition.MicroserviceVersionMetaFactory.create(MicroserviceVersionMetaFactory.java:38)

at org.apache.servicecomb.serviceregistry.consumer.MicroserviceVersions.lambda$setInstances$0(MicroserviceVersions.java:182)

at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660)

at org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx.computeIfAbsent(ConcurrentHashMapEx.java:56)

at org.apache.servicecomb.serviceregistry.consumer.MicroserviceVersions.setInstances(MicroserviceVersions.java:180)

at org.apache.servicecomb.serviceregistry.consumer.MicroserviceVersions.safeSetInstances(MicroserviceVersions.java:160)

at org.apache.servicecomb.serviceregistry.consumer.MicroserviceVersions.pullInstances(MicroserviceVersions.java:155)

at org.apache.servicecomb.serviceregistry.consumer.MicroserviceVersions.submitPull(MicroserviceVersions.java:127)

at org.apache.servicecomb.serviceregistry.consumer.MicroserviceManager.lambda$getOrCreateMicroserviceVersions$0(MicroserviceManager.java:55)

at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660)

at org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx.computeIfAbsent(ConcurrentHashMapEx.java:56)

at org.apache.servicecomb.serviceregistry.consumer.MicroserviceManager.getOrCreateMicroserviceVersions(MicroserviceManager.java:53)

at org.apache.servicecomb.serviceregistry.consumer.MicroserviceManager.getOrCreateMicroserviceVersionRule(MicroserviceManager.java:79)

at org.apache.servicecomb.serviceregistry.consumer.AppManager.getOrCreateMicroserviceVersionRule(AppManager.java:59)

at org.apache.servicecomb.core.provider.consumer.ReferenceConfig.<init>(ReferenceConfig.java:37)

at org.apache.servicecomb.core.provider.consumer.ConsumerProviderManager.createReferenceConfig(ConsumerProviderManager.java:56)

at org.apache.servicecomb.core.provider.consumer.ConsumerProviderManager.createReferenceConfig(ConsumerProviderManager.java:87)

at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660)

at org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx.computeIfAbsent(ConcurrentHashMapEx.java:56)

at org.apache.servicecomb.core.provider.consumer.ConsumerProviderManager.getReferenceConfig(ConsumerProviderManager.java:91)

at org.apache.servicecomb.core.SCBEngine.getReferenceConfigForInvoke(SCBEngine.java:293)

at org.apache.servicecomb.provider.pojo.Invoker.findReferenceConfig(Invoker.java:119)

at org.apache.servicecomb.provider.pojo.Invoker.createInvokerMeta(Invoker.java:88)

at org.apache.servicecomb.provider.pojo.Invoker.invoke(Invoker.java:129)

at com.sun.proxy.$Proxy170.findAllByApplyId(Unknown Source)

at com.dhc.ippc.state.controller.sync.SyncCntrController.getCntrNAndBlNs(SyncCntrController.java:316)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:498)

at org.apache.servicecomb.swagger.engine.SwaggerProducerOperation.doInvoke(SwaggerProducerOperation.java:160)

at org.apache.servicecomb.swagger.engine.SwaggerProducerOperation.syncInvoke(SwaggerProducerOperation.java:148)

at org.apache.servicecomb.swagger.engine.SwaggerProducerOperation.invoke(SwaggerProducerOperation.java:115)

at org.apache.servicecomb.core.handler.impl.ProducerOperationHandler.handle(ProducerOperationHandler.java:40)

at org.apache.servicecomb.core.Invocation.next(Invocation.java:151)

问题原因:

服务端定义了一个接口, 没有任何方法,比如:

@RestSchema(schemaid="hello")

public class Hello{

}

解决方法:删除这个接口。或者增加一个REST接口定义。

四、CSE JAVA SDK: java.lang.IllegalStateException: Response is closed 原因和定位

当有些业务处理比较耗时的时候,日志里面经常打印如下异常:

2019-01-09 10:42:22,890 [ntloop-thread-0] ERROR Unhandled exception [io.vertx.core.impl.ContextImpl.lambda$wrapTask$2(ContextImpl.java:345)]

java.lang.IllegalStateException: Response is closed

at io.vertx.core.http.impl.HttpServerResponseImpl.checkValid(HttpServerResponseImpl.java:548)

at io.vertx.core.http.impl.HttpServerResponseImpl.end0(HttpServerResponseImpl.java:401)

at io.vertx.core.http.impl.HttpServerResponseImpl.end(HttpServerResponseImpl.java:319)

at org.apache.servicecomb.foundation.vertx.http.VertxServerResponseToHttpServletResponse.internalFlushBuffer(VertxServerResponseToHttpServletResponse.java:122)

at org.apache.servicecomb.foundation.vertx.http.VertxServerResponseToHttpServletResponse.lambda$flushBuffer$0(VertxServerResponseToHttpServletResponse.java:112)

at io.vertx.core.impl.ContextImpl.lambda$wrapTask$2(ContextImpl.java:339)

at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)

at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404)

at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:463)

at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884)

at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)

at java.lang.Thread.run(Thread.java:745)

这个异常表示的是在给请求返回结果的时候,写结果发现连接已经关闭。这种情况通常发生在业务处理比较长的情况。这个日志在服务端打印(服务端是相对的)。和这个问题相关的配置由如下几个:

客户端:

cse.rest.client.connection.idleTimeoutInSeconds(缺省值30s)

服务端:

cse.rest.server.connection.idleTimeoutInSeconds(缺省值30s)

如果业务处理时间超过这两个值的最小值,那么服务端就会报告这个异常。 

猜你喜欢

转载自blog.csdn.net/looook/article/details/86287123