阿里云OSS线程增长问题分析
線上出現(xiàn)運(yùn)行幾個(gè)小時(shí)后,阿里云OSS無(wú)法進(jìn)行操作問(wèn)題,分析發(fā)現(xiàn)線程數(shù)線性增長(zhǎng),很快到達(dá)最大線程數(shù),最后分析代碼/查找OSS文檔發(fā)現(xiàn)是使用OSSObject時(shí)沒有close導(dǎo)致的,因?yàn)镺SSObject封裝了inputStream,未關(guān)閉會(huì)導(dǎo)致http連接一直處于open狀態(tài),無(wú)法進(jìn)行回收,最后到達(dá)最大連接,徹底無(wú)法訪問(wèn)OSS。
隨后對(duì)OSSClient代碼進(jìn)行分析,看下為何會(huì)線程線性增長(zhǎng);
1,查看OSSClient定義
public OSSClient(String endpoint, CredentialsProvider credsProvider, ClientConfiguration config) {this.credsProvider = credsProvider;config = config == null ? new ClientConfiguration() : config;if (config.isRequestTimeoutEnabled()) {this.serviceClient = new TimeoutServiceClient(config);} else {//新建DefaultServiceClient對(duì)象this.serviceClient = new DefaultServiceClient(config);}initOperations();setEndpoint(endpoint);}2,查看DefaultServiceClient,定義了httpclient包里的PoolingHttpClientConnectionManager(http連接池管理器),并單獨(dú)起線程進(jìn)行連接回收策略
public DefaultServiceClient(ClientConfiguration config) {super(config);//使用了httpClient包里的連接管理器,重點(diǎn)看這里this.connectionManager = createHttpClientConnectionManager();this.httpClient = createHttpClient(this.connectionManager);RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();//連接超時(shí)時(shí)間requestConfigBuilder.setConnectTimeout(config.getConnectionTimeout());requestConfigBuilder.setSocketTimeout(config.getSocketTimeout());requestConfigBuilder.setConnectionRequestTimeout(config.getConnectionRequestTimeout());//。。。。。省略代碼this.requestConfig = requestConfigBuilder.build();} protected HttpClientConnectionManager createHttpClientConnectionManager() {//。。。。省略代碼Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create().register(Protocol.HTTP.toString(), PlainConnectionSocketFactory.getSocketFactory()).register(Protocol.HTTPS.toString(), sslSocketFactory).build();//使用httpclient的http連接池管理器PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);//設(shè)置最大連接,默認(rèn)1024connectionManager.setDefaultMaxPerRoute(config.getMaxConnections());connectionManager.setMaxTotal(config.getMaxConnections());connectionManager.setValidateAfterInactivity(config.getValidateAfterInactivity());connectionManager.setDefaultSocketConfig(SocketConfig.custom().setSoTimeout(config.getSocketTimeout()).setTcpNoDelay(true).build());if (config.isUseReaper()) {//起新線程執(zhí)行連接回收策略,重點(diǎn)關(guān)注IdleConnectionReaper.setIdleConnectionTime(config.getIdleConnectionTime());IdleConnectionReaper.registerConnectionManager(connectionManager);}return connectionManager;}3,連接回收策略,定時(shí)去遍歷連接管理器,然后調(diào)用httpclient的連接回收策略。
public void run() {while (true) {if (shuttingDown) {getLog().debug("Shutting down reaper thread.");return;}//每次休眠五秒try {Thread.sleep(REAP_INTERVAL_MILLISECONDS);} catch (InterruptedException e) {}try {List<HttpClientConnectionManager> connectionManagers = null;synchronized (IdleConnectionReaper.class) {connectionManagers = (List<HttpClientConnectionManager>)IdleConnectionReaper.connectionManagers.clone();}//遍歷所有連接管理器for (HttpClientConnectionManager connectionManager : connectionManagers) {try {//調(diào)用httpclient的回收連接方法,回收過(guò)期連接與超時(shí)空閑連接connectionManager.closeExpiredConnections();connectionManager.closeIdleConnections(idleConnectionTime, TimeUnit.MILLISECONDS);} catch (Exception ex) {getLog().warn("Unable to close idle connections", ex);}}} catch (Throwable t) {getLog().debug("Reaper thread: ", t);}}}4,總結(jié),OSSClient實(shí)際是基于httpclient進(jìn)行接口調(diào)用,并使用PoolingHttpClientConnectionManager進(jìn)行連接管理,單獨(dú)起線程進(jìn)行連接的定時(shí)回收。
總結(jié)
以上是生活随笔為你收集整理的阿里云OSS线程增长问题分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 视频数据丢失怎么办 怎样找回丢失的视频数
- 下一篇: Akka Actors入门案例解析