文档章节

Thrift连接池实现

引鸩怼孑
 引鸩怼孑
发布于 2016/01/03 12:40
字数 1786
阅读 162
收藏 7
点赞 0
评论 2
简介


Thrift是Facebook的核心框架之一,使不同的开发语言开发的系统可以通过该框架实现彼此的通信,类似于webservice,但是Thrift提供了近乎变态的效率和开发的方便性,是webservice所不能比拟的。给分布式开发带来了极大的方便。但是这柄利器也有一些不完美。


 


问题


首先文档相当的少,只有一个wiki网站提供相应的帮助。这对于Thrift的推广极为不利。


其次框架本身实现有一些缺陷,就Thrift的java部分来说,没有提供连接池的支持,对RPC的调用效率有所影响。


对于文档稀少的问题,只能是通过一些Thrift的开发者和使用者多供献一些自己的心得来解决。这得需要一个过程。而连接池的问题的解决则可以快速一些。


         提到池一般做过Java开发的肯定会想到ObjectPool,Apache Commons项目确实给我们的开发得来了很大的便利性,其中的pool项目正是我们实现thrift连接池的基础,当然也少不了神器spring framework。


 


实现


一,定义thrift连接池接口


复制代码
ConnectionProvider 


Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->/*
 * @(#)ConnectionProvider.java    0.1 05/11/17
 *
 * Copyright 2010 QISI, Inc. All rights reserved.
 * QISI PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package com.qidea.thrift.pool;
import org.apache.thrift.transport.TSocket;
/**
 * 
 * @author sunwei
 * @version 2010-8-6
 * @since JDK1.5
 */
public interface ConnectionProvider
{
    /**
     * 取链接池中的一个链接
     * 
     * @return
     */
    public TSocket getConnection();
    /**
     * 返回链接
     * 
     * @param socket
     */
    public void returnCon(TSocket socket);
}
复制代码
二,实现连接池


复制代码
GenericConnectionProvider 


Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->/*
 * @(#)DefaultConnectionProviderImpl.java    0.1 05/11/17
 *
 * Copyright 2010 QISI, Inc. All rights reserved.
 * QISI PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package com.qidea.thrift.pool;
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.apache.thrift.transport.TSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
/**
 * 
 * @author sunwei
 * @version 2010-8-10
 * @since JDK1.5
 */
public class GenericConnectionProvider implements ConnectionProvider,
        InitializingBean, DisposableBean
{
    public static final Logger logger = LoggerFactory
            .getLogger(GenericConnectionProvider.class);
    /** 服务的IP地址 */
    private String serviceIP;
    /** 服务的端口 */
    private int servicePort;
    /** 连接超时配置 */
    private int conTimeOut;
    /** 可以从缓存池中分配对象的最大数量 */
    private int maxActive = GenericObjectPool.DEFAULT_MAX_ACTIVE;
    /** 缓存池中最大空闲对象数量 */
    private int maxIdle = GenericObjectPool.DEFAULT_MAX_IDLE;
    /** 缓存池中最小空闲对象数量 */
    private int minIdle = GenericObjectPool.DEFAULT_MIN_IDLE;
    /** 阻塞的最大数量 */
    private long maxWait = GenericObjectPool.DEFAULT_MAX_WAIT;
    /** 从缓存池中分配对象,是否执行PoolableObjectFactory.validateObject方法 */
    private boolean testOnBorrow = GenericObjectPool.DEFAULT_TEST_ON_BORROW;
    private boolean testOnReturn = GenericObjectPool.DEFAULT_TEST_ON_RETURN;
    private boolean testWhileIdle = GenericObjectPool.DEFAULT_TEST_WHILE_IDLE;
    /** 对象缓存池 */
    private ObjectPool objectPool = null;
    /**
     * 
     */
    @Override
    public void afterPropertiesSet() throws Exception
    {
        // 对象池
        objectPool = new GenericObjectPool();
        //
        ((GenericObjectPool) objectPool).setMaxActive(maxActive);
        ((GenericObjectPool) objectPool).setMaxIdle(maxIdle);
        ((GenericObjectPool) objectPool).setMinIdle(minIdle);
        ((GenericObjectPool) objectPool).setMaxWait(maxWait);
        ((GenericObjectPool) objectPool).setTestOnBorrow(testOnBorrow);
        ((GenericObjectPool) objectPool).setTestOnReturn(testOnReturn);
        ((GenericObjectPool) objectPool).setTestWhileIdle(testWhileIdle);
        ((GenericObjectPool) objectPool)
                .setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK);
        // 设置factory
        ThriftPoolableObjectFactory thriftPoolableObjectFactory = new ThriftPoolableObjectFactory(
                serviceIP, servicePort, conTimeOut);
        objectPool.setFactory(thriftPoolableObjectFactory);
    }
    @Override
    public void destroy()
    {
        try
        {
            objectPool.close();
        }
        catch (Exception e)
        {
            throw new RuntimeException("erorr destroy()", e);
        }
    }
    @Override
    public TSocket getConnection()
    {
        try
        {
            TSocket socket = (TSocket) objectPool.borrowObject();
            return socket;
        }
        catch (Exception e)
        {
            throw new RuntimeException("error getConnection()", e);
        }
    }
    @Override
    public void returnCon(TSocket socket)
    {
        try
        {
            objectPool.returnObject(socket);
        }
        catch (Exception e)
        {
            throw new RuntimeException("error returnCon()", e);
        }
    }
    public String getServiceIP()
    {
        return serviceIP;
    }
    public void setServiceIP(String serviceIP)
    {
        this.serviceIP = serviceIP;
    }
    public int getServicePort()
    {
        return servicePort;
    }
    public void setServicePort(int servicePort)
    {
        this.servicePort = servicePort;
    }
    public int getConTimeOut()
    {
        return conTimeOut;
    }
    public void setConTimeOut(int conTimeOut)
    {
        this.conTimeOut = conTimeOut;
    }
    public int getMaxActive()
    {
        return maxActive;
    }
    public void setMaxActive(int maxActive)
    {
        this.maxActive = maxActive;
    }
    public int getMaxIdle()
    {
        return maxIdle;
    }
    public void setMaxIdle(int maxIdle)
    {
        this.maxIdle = maxIdle;
    }
    public int getMinIdle()
    {
        return minIdle;
    }
    public void setMinIdle(int minIdle)
    {
        this.minIdle = minIdle;
    }
    public long getMaxWait()
    {
        return maxWait;
    }
    public void setMaxWait(long maxWait)
    {
        this.maxWait = maxWait;
    }
    public boolean isTestOnBorrow()
    {
        return testOnBorrow;
    }
    public void setTestOnBorrow(boolean testOnBorrow)
    {
        this.testOnBorrow = testOnBorrow;
    }
    public boolean isTestOnReturn()
    {
        return testOnReturn;
    }
    public void setTestOnReturn(boolean testOnReturn)
    {
        this.testOnReturn = testOnReturn;
    }
    public boolean isTestWhileIdle()
    {
        return testWhileIdle;
    }
    public void setTestWhileIdle(boolean testWhileIdle)
    {
        this.testWhileIdle = testWhileIdle;
    }
    public ObjectPool getObjectPool()
    {
        return objectPool;
    }
    public void setObjectPool(ObjectPool objectPool)
    {
        this.objectPool = objectPool;
    }
}
复制代码
复制代码
ThriftPoolableObjectFactory 


Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->/*
 * @(#)ThriftPoolableObjectFactory.java    0.1 05/11/17
 *
 * Copyright 2010 QISI, Inc. All rights reserved.
 * QISI PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package com.qidea.thrift.pool;
import org.apache.commons.pool.PoolableObjectFactory;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * 
 * @author sunwei
 * @version 2010-8-10
 * @since JDK1.5
 */
public class ThriftPoolableObjectFactory implements PoolableObjectFactory
{
    /** 日志记录器 */
    public static final Logger logger = LoggerFactory
            .getLogger(ThriftPoolableObjectFactory.class);
    /** 服务的IP */
    private String serviceIP;
    /** 服务的端口 */
    private int servicePort;
    /** 超时设置 */
    private int timeOut;
    /**
     * 
     * @param serviceIP
     * @param servicePort
     * @param timeOut
     */
    public ThriftPoolableObjectFactory(String serviceIP, int servicePort,
            int timeOut)
    {
        this.serviceIP = serviceIP;
        this.servicePort = servicePort;
        this.timeOut = timeOut;
    }
    @Override
    public void destroyObject(Object arg0) throws Exception
    {
        if (arg0 instanceof TSocket)
        {
            TSocket socket = (TSocket) arg0;
            if (socket.isOpen())
            {
                socket.close();
            }
        }
    }
    /**
     * 
     */
    @Override
    public Object makeObject() throws Exception
    {
        try
        {
            TTransport transport = new TSocket(this.serviceIP,
                    this.servicePort, this.timeOut);
            transport.open();
            return transport;
        }
        catch (Exception e)
        {
            logger.error("error ThriftPoolableObjectFactory()", e);
            throw new RuntimeException(e);
        }
    }
    @Override
    public boolean validateObject(Object arg0)
    {
        try
        {
            if (arg0 instanceof TSocket)
            {
                TSocket thriftSocket = (TSocket) arg0;
                if (thriftSocket.isOpen())
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }
        catch (Exception e)
        {
            return false;
        }
    }
    @Override
    public void passivateObject(Object arg0) throws Exception
    {
        // DO NOTHING
    }
    @Override
    public void activateObject(Object arg0) throws Exception
    {
        // DO NOTHING
    }
    public String getServiceIP()
    {
        return serviceIP;
    }
    public void setServiceIP(String serviceIP)
    {
        this.serviceIP = serviceIP;
    }
    public int getServicePort()
    {
        return servicePort;
    }
    public void setServicePort(int servicePort)
    {
        this.servicePort = servicePort;
    }
    public int getTimeOut()
    {
        return timeOut;
    }
    public void setTimeOut(int timeOut)
    {
        this.timeOut = timeOut;
    }
}
复制代码
  三,定义连接的管理类 


复制代码
ConnectionManager 


Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->/*
 * @(#)ConnectionManager.java    0.1 05/11/17
 *
 * Copyright 2010 QISI, Inc. All rights reserved.
 * QISI PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package com.qidea.thrift.pool;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.thrift.transport.TSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * 
 * @author sunwei
 * @version 2010-8-10
 * @since JDK1.5
 */
public class ConnectionManager implements MethodInterceptor
{
    /** 日志记录器 */
    public Logger logger = LoggerFactory.getLogger(ConnectionManager.class);
    /** 保存local对象 */
    ThreadLocal<TSocket> socketThreadSafe = new ThreadLocal<TSocket>();
    /** 连接提供池 */
    public ConnectionProvider connectionProvider;
    @Override
    public Object invoke(MethodInvocation arg0) throws Throwable
    {
        TSocket socket = null;
        try
        {
            socket = connectionProvider.getConnection();
            socketThreadSafe.set(socket);
            Object ret = arg0.proceed();
            return ret;
        }
        catch (Exception e)
        {
            logger.error("error ConnectionManager.invoke()", e);
            throw new Exception(e);
        }
        finally
        {
            connectionProvider.returnCon(socket);
            socketThreadSafe.remove();
        }
    }
    /**
     * 取socket
     * 
     * @return
     */
    public TSocket getSocket()
    {
        return socketThreadSafe.get();
    }
    public ConnectionProvider getConnectionProvider()
    {
        return connectionProvider;
    }
    public void setConnectionProvider(ConnectionProvider connectionProvider)
    {
        this.connectionProvider = connectionProvider;
    }
}
复制代码
四,定义spring配置,对受管的bean提供thrift连接


复制代码
Thrift连接池spring配置 


Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--><?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:flex="http://www.springframework.org/schema/flex" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
    http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
      http://www.springframework.org/schema/flex http://www.springframework.org/schema/flex/spring-flex-1.0.xsd">


    <!-- thrift连接池配置 -->
    <bean id="connectionProvider" class="com.qidea.thrift.pool.GenericConnectionProvider">
        <property name="serviceIP" value="localhost" />
        <property name="servicePort" value="9090" />
        <property name="maxActive" value="10" />
        <property name="maxIdle" value="10" />
        <property name="testOnBorrow" value="true" />
        <property name="testOnReturn" value="true" />
        <property name="testWhileIdle" value="true" />
        <property name="conTimeOut" value="2000" />
    </bean>
    <!-- thrift连接管理配置  -->
    <bean id="connectionManager" class="com.qidea.thrift.pool.ConnectionManager">
        <property name="connectionProvider" ref="connectionProvider" />
    </bean>
    <!-- 客户端接口配置  -->
    <bean class="com.qidea.pushserver.rpc.client.PushServiceClient">
        <property name="connectionManager" ref="connectionManager" />
    </bean>
    <!-- thrift连接AOP配置  -->
    <aop:config proxy-target-class="true">
        <aop:pointcut id="clientMethods"
            expression="execution(* com.qidea.pushserver.rpc.client.*.*(..))" />
        <aop:advisor advice-ref="connectionManager" pointcut-ref="clientMethods" />
    </aop:config>
</beans>
复制代码
五,使用连接池


复制代码
PushRPCClient 


Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->/*
 * @(#)PushRPCClient.java    0.1 05/11/17
 *
 * Copyright 2010 QISI, Inc. All rights reserved.
 * QISI PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package com.qidea.pushserver.rpc;
import java.util.ArrayList;
import java.util.List;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.qidea.pushserver.ServiceException;
import com.qidea.thrift.pool.ConnectionManager;
/**
 * 
 * @author sunwei
 * @version 2010-8-11
 * @since JDK1.5
 */
public class PushRPCClient
{
    public static Logger logger = LoggerFactory.getLogger(PushRPCClient.class);
    private ConnectionManager connectionManager;
    /**
     * 取在线玩家列表
     * 
     * @param roleIdList
     * @return
     * @throws ServiceException
     */
    public List<Long> getOnLineRoleIdList(List<Long> roleIdList)
    {
        TProtocol protocol = new TBinaryProtocol(connectionManager.getSocket());
        PushRPCService.Client client = new PushRPCService.Client(protocol);
        try
        {
            List<Long> onLineIdList = client.getOnLineRoleIdList(roleIdList);
            return onLineIdList;
        }
        catch (TException e)
        {
            logger.error("error getOnLineRoleIdList()", e);
        }
        return new ArrayList<Long>();
    }
    /**
     * 解散联盟
     * 
     * @param allianceId
     */
    public void dismissAlliance(long allianceId)
    {
        TProtocol protocol = new TBinaryProtocol(connectionManager.getSocket());
        PushRPCService.Client client = new PushRPCService.Client(protocol);
        try
        {
            client.dismissAlliance(allianceId);
        }
        catch (TException e)
        {
            logger.error("error dismissAlliance()", e);
        }
    }
    /**
     * 加入联盟
     * 
     * @param roleId
     * @param allianceId
     */
    public void joinAlliance(long roleId, long allianceId)
    {
        TProtocol protocol = new TBinaryProtocol(connectionManager.getSocket());
        PushRPCService.Client client = new PushRPCService.Client(protocol);
        try
        {
            client.joinAlliance(roleId, allianceId);
        }
        catch (TException e)
        {
            logger.error("error joinAlliance()", e);
        }
    }
    /**
     * 解散联盟
     * 
     * @param roleId
     * @param allianceId
     */
    public void getOutAlliance(long roleId, long allianceId)
    {
        TProtocol protocol = new TBinaryProtocol(connectionManager.getSocket());
        PushRPCService.Client client = new PushRPCService.Client(protocol);
        try
        {
            client.getOutAlliance(roleId, allianceId);
        }
        catch (Exception e)
        {
            logger.error("error getOutAlliance()", e);
        }
    }
    public ConnectionManager getConnectionManager()
    {
        return connectionManager;
    }
    public void setConnectionManager(ConnectionManager connectionManager)
    {
        this.connectionManager = connectionManager;
    }
}
复制代码
 

© 著作权归作者所有

共有 人打赏支持
引鸩怼孑
粉丝 37
博文 202
码字总数 16947
作品 0
南京
项目经理
加载中

评论(2)

引鸩怼孑
引鸩怼孑

引用来自“强子哥哥”的评论

我们也做了连接池,也是基于CommonsPools, 大问题没有,validateObject方法仅仅这样写是有问题的,无法在生产环境中使用
嗯 谢谢!
强子哥哥
强子哥哥
我们也做了连接池,也是基于CommonsPools, 大问题没有,validateObject方法仅仅这样写是有问题的,无法在生产环境中使用
带你进入数据库连接池

概述 连接池的作用就是为了提高性能,将已经创建好的连接保存在池中,当有请求来时,直接使用已经创建好的连接对Server端进行访问。这样省略了创建连接和销毁连接的过程(TCP连接建立时的三次...

VincentZ ⋅ 2017/11/28 ⋅ 0

Thrift源码剖析

由于工作的关系,需要定位一个 bug 是否和 Thrift 有关, 所以用了一下午的时间研读了 Thrift-0.9.0 代码,虽然发现这个 bug 和 thrift 无关。 但是读源码还是有所收获,所以整理成这篇文章,...

Mr_Tea ⋅ 2016/07/12 ⋅ 0

郑大侠/forest-thrift

#forest-thrift thrift服务的简单的封装 ##thrift-client 池化的高可用thrift客户端 future 支持连接池 支持thrift描述文件的ping校验 支持负载均衡策略 支持容灾策略 支持自动熔断策略 支持...

郑大侠 ⋅ 2016/12/29 ⋅ 0

五个最佳案例带你解读Node.js的前后之道

Node.js 是什么? Node.js采用C++语言编写而成,浏览器内核V8做为执行引擎;Node不是JS应用、而是一个Javascript的运行环境。Node保留了前端浏览器js的接口,没有改写语言本身的任何特性,依...

问题达人 ⋅ 2016/04/01 ⋅ 0

五个最佳案例带你解读Node.js的前后之道

Node.js 是什么? Node.js采用C++语言编写而成,浏览器内核V8做为执行引擎;Node不是JS应用、而是一个Javascript的运行环境。Node保留了前端浏览器js的接口,没有改写语言本身的任何特性,依...

illy安智 ⋅ 2016/03/28 ⋅ 0

Thrift源码分析1-server

前言 Thrift是由FB开发的rpc框架,后贡献到apache成为开源项目,thrift可以支持多种语言,如 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk 等,本系列文章主...

Small-Liu ⋅ 2016/02/02 ⋅ 0

commons-pool2对象池使用

概念 对象池(ObjectPool): 掌管对象的生命周期,获取,激活,验证,钝化,销毁等 池对象(PooledObject): 被创建在池中的对象,自己可以有一些附加信息 池对象工厂(PooledObjectFactory): 池中...

Small-Liu ⋅ 2016/01/21 ⋅ 0

MyThrift V0.3 增加注册中心实现服务注册和发现

本次更新主要是基于0.2的基础上增加了服务注册中心,基于ZooKeeper. 具体细节: 1) Server端 继承thrift的TThreadedSelectorServer类,覆盖setServing方法,使得thrift服务器端口处于监听状态...

强子哥哥 ⋅ 2016/10/30 ⋅ 10

MyThrift 0.0.1 发布,轻量级 RPC 服务框架

1)什么是MyThrift? 基于以下组件打造的一款轻量级RPC服务框架:thrift(facebook出品)、commons-pool(socket连接池)、自研服务治理框架(zookeeper). 2)为什么要写MyThrift? 2.1)提出问题: ...

强子哥哥 ⋅ 2016/05/05 ⋅ 14

轻量级RPC服务框架--MyThrift

http://git.oschina.net/qiangzigege/MyThrift 基于以下组件打造的一款轻量级RPC服务框架:thrift(facebook出品)、commons-pool(socket连接池)、自研服务治理框架(zookeeper). 提出问题: 各种...

强子哥哥 ⋅ 2016/05/04 ⋅ 2

没有更多内容

加载失败,请刷新页面

加载更多

下一页

uWSGI + Django @ Ubuntu

创建 Django App Project 创建后, 可以看到路径下有一个wsgi.py的问题 uWSGI运行 直接命令行运行 利用如下命令, 可直接访问 uwsgi --http :8080 --wsgi-file dj/wsgi.py 配置文件 & 运行 [u...

袁祾 ⋅ 29分钟前 ⋅ 0

JVM堆的理解

在JVM中,我们经常提到的就是堆了,堆确实很重要,其实,除了堆之外,还有几个重要的模块,看下图: 大 多数情况下,我们并不需要关心JVM的底层,但是如果了解它的话,对于我们系统调优是非常...

不羁之后 ⋅ 昨天 ⋅ 0

推荐:并发情况下:Java HashMap 形成死循环的原因

在淘宝内网里看到同事发了贴说了一个CPU被100%的线上故障,并且这个事发生了很多次,原因是在Java语言在并发情况下使用HashMap造成Race Condition,从而导致死循环。这个事情我4、5年前也经历...

码代码的小司机 ⋅ 昨天 ⋅ 1

聊聊spring cloud gateway的RetryGatewayFilter

序 本文主要研究一下spring cloud gateway的RetryGatewayFilter GatewayAutoConfiguration spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/config/G......

go4it ⋅ 昨天 ⋅ 0

创建新用户和授予MySQL中的权限教程

导读 MySQL是一个开源数据库管理软件,可帮助用户存储,组织和以后检索数据。 它有多种选项来授予特定用户在表和数据库中的细微的权限 - 本教程将简要介绍一些选项。 如何创建新用户 在MySQL...

问题终结者 ⋅ 昨天 ⋅ 0

android -------- 颜色的半透明效果配置

最近有朋友问我 Android 背景颜色的半透明效果配置,我网上看资料,总结了一下, 开发中也是常常遇到的,所以来写篇博客 常用的颜色值格式有: RGB ARGB RRGGBB AARRGGBB 这4种 透明度 透明度...

切切歆语 ⋅ 昨天 ⋅ 0

CentOS开机启动subversion

建立自启动脚本: vim /etc/init.d/subversion 输入如下内容: #!/bin/bash## subversion startup script for the server## chkconfig: 2345 90 10# description: start the subve......

随风而飘 ⋅ 昨天 ⋅ 0

版本控制工具

CSV , SVN , GIT ,VSS

颖伙虫 ⋅ 昨天 ⋅ 0

【2018.06.19学习笔记】【linux高级知识 13.1-13.3】

13.1 设置更改root密码 13.2 连接mysql 13.3 mysql常用命令

lgsxp ⋅ 昨天 ⋅ 0

LVM

LVM: 硬盘划分分区成物理卷->物理卷组成卷组->卷组划分逻辑分区。 1.磁盘分区: fdisk /dev/sdb 划分几个主分区 输入t更改每个分区类型为8e(LVM) 使用partprobe生成分区的文件:如/dev/sd...

ZHENG-JY ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部