一、Amoeba介绍
Amoeba:基于Java研发,配置文件xml文档。对事务支持功能很差,不支持分布式读,尤其不支持分布式事务。默认监听在8066端口上。2.2.x开始支持单库事务,没有缓存功能,所有请求直接向后转发。对内存占用少,而对CPU占用大。
二、架构简介
Amoeba服:192.168.1.253 监听端口8066改3306,作为后端mysql服务器代理,监控后端mysql服务器健康的端口9066。
主服:station20:192.168.1.20,前端代理往主服写操作会自动复制到从服。
从服:station21:192.168.1.21
如果是多从,在前端代理里设置一个负载均衡从服组(虚拟服务器),组内按调度算法调度,三种算法:轮询rr,加权轮询wrr,高可用ha.
地址:http://sourceforge.net/projects/amoeba/files/Amoeba%20for%20mysql/
三、操作步骤
主服新建远程用户,从服自动复制次条目 mysql>grant all on *.* to 'root'@'%' identified by 'amoebapass'; mysql>flush privileges; ------------------------------------------------------------------ 从服 mysql>show grants for root@'%'; | Grantsfor root@% | GRANTALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY PASSWORD'*84BB5DF4823DA319BBF86C99624479A198E6EEE9' |
Amoba服
1.安装Amoeba [root@station253~]# cp /mnt/hgfs/Share64/jdk/jdk-6u31-linux-x64-rpm.bin /tmp [root@station253tmp]# chmod +x jdk-6u31-linux-x64-rpm.bin [root@station253tmp]# ./jdk-6u31-linux-x64-rpm.bin [root@station253tmp]# vim /etc/profile.d/java.sh exportJAVA_HOME=/usr/java/latest exportPATH=$JAVA_HOME/bin:$PATH [root@station253tmp]# . /etc/profile.d/java.sh [root@station253tmp]# java -version javaversion "1.6.0_31" Java(TM)SE Runtime Environment (build 1.6.0_31-b04) JavaHotSpot(TM) 64-Bit Server VM (build 20.6-b01, mixed mode) 混合模式,支持编译 [root@station253tmp]# cp /mnt/hgfs/Share64/amoeba/amoeba-mysql-binary-2.2.0.tar.gz . ameoba不会自行创建目录,手工创建 [root@station253tmp]# mkdir -pv /usr/local/amoeba-2.2.0 #保留版本信息便于后期识别 [root@station253tmp]# tar -zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba-2.2.0 [root@station253tmp]# cd /usr/local/ [root@station253local]# ln -sv amoeba-2.2.0/ amoeba "amoeba"-> "amoeba-2.2.0/"
2.添加环境变量 [root@station253local]# vim /etc/profile.d/amoeba.sh exportAMOEBA_HOME=/usr/local/amoeba exportPATH=$AMOEBA_HOME/bin:$PATH [root@station253local]# . /etc/profile.d/amoeba.sh [root@station253conf]# amoeba amoeba start|stop
3.配置amoeba服务 [root@station253local]# cd amoeba [root@station253amoeba]# cp -r conf/ backup [root@station253amoeba]# ls backup benchmark bin changelogs.txt conf lib LICENSE.txt README.html [root@station253amoeba]# cd conf 定义数据库读写分离及节点管理信息 [root@station253conf]# vim amoeba.xml <?xml version="1.0"encoding="gbk"?> <!DOCTYPE amoeba:configuration SYSTEM"amoeba.dtd"> <amoeba:configurationxmlns:amoeba="http://amoeba.meidusa.com/"> <proxy> #定义代理 <!-- service class must implementscom.meidusa.amoeba.service.Service --> <service name="Amoeba for Mysql"class="com.meidusa.amoeba.net.ServerableConnectionManager"> #定义服务,由类实现 <!-- port --> #定义连接池 <!-- <propertyname="port">8066</property> --> 加外括号注释 <property name="port">3306</property> #定义监听端口,将默认改动为3306 <!-- bindipAddress --> #定义代理服务器对外连接的监听IP <!-- <propertyname="ipAddress">127.0.0.1</property> --> <propertyname="ipAddress">0.0.0.0</property> #定义监听IP地址,这里定义为监听所有IP <propertyname="manager">${clientConnectioneManager}</property> <propertyname="connectionFactory"> #连接池 <beanclass="com.meidusa.amoeba.mysql.net.MysqlClientConnectionFactory"> <propertyname="sendBufferSize">128</property> #定义发送缓冲大小(可根据主机内存可调整) <propertyname="receiveBufferSize">64</property> #定义接受缓冲的大小(可根据主机内存可调整) </bean> </property> <propertyname="authenticator"> #认证器 <beanclass="com.meidusa.amoeba.mysql.server.MysqlClientAuthenticator"> <propertyname="user">root</property> #客户端连接后端时的用户名 <property name="password">amoebapass</property> #客户端连接后端时的密码 <propertyname="filter"> <beanclass="com.meidusa.amoeba.server.IPAccessController"> <propertyname="ipFile">${amoeba.home}/conf/access_list.conf</property> #只允许哪些客户端访问,基于文件实现访问控制 </bean> </property> </bean> </property> </service> <!-- server class must implementscom.meidusa.amoeba.service.Service --> <servicename="Amoeba Monitor Server"class="com.meidusa.amoeba.monitor.MonitorServer"> #amoeba的监控服务器,监测每一个后端的工作状态 <!-- port --> <property name="port">3306</property> #监控服务器监听的端口,默认注释表示使用随机端口 <!-- bind ipAddress --> <propertyname="ipAddress">127.0.0.1</property> #定义监控服务器监听的地址 <propertyname="daemon">true</property> <propertyname="manager">${clientConnectioneManager}</property> <propertyname="connectionFactory"> <beanclass="com.meidusa.amoeba.monitor.net.MonitorClientConnectionFactory"></bean> </property> </service> <runtimeclass="com.meidusa.amoeba.mysql.context.MysqlRuntimeContext"> <!-- proxy server net IO Read thread size --> <propertyname="readThreadPoolSize">20</property> <!-- proxyserver client process thread size --> <property name="clientSideThreadPoolSize">30</property> <!-- mysqlserver data packet process thread size --> <propertyname="serverSideThreadPoolSize">30</property> <!-- perconnection cache prepared statement size --> <propertyname="statementCacheSize">500</property> <!-- querytimeout( default: 60 second , TimeUnit:second) --> <propertyname="queryTimeout">60</property> </runtime> </proxy> <!-- EachConnectionManager will start as thread managerresponsible for the Connection IO read , Death Detection --> <connectionManagerList> #定义连接池的列表 <connectionManagername="clientConnectioneManager"class="com.meidusa.amoeba.net.MultiConnectionManagerWrapper"> <propertyname="subManagerClassName">com.meidusa.amoeba.net.ConnectionManager</property> <!-- default value is avaliable Processors <propertyname="processors">5</property> --> </connectionManager> <connectionManager name="defaultManager"class="com.meidusa.amoeba.net.MultiConnectionManagerWrapper"> <propertyname="subManagerClassName">com.meidusa.amoeba.net.AuthingableConnectionManager</property> <!-- default valueis avaliable Processors <propertyname="processors">5</property> --> </connectionManager> </connectionManagerList> #连接池的列表 <!-- defaultusing file loader --> <dbServerLoaderclass="com.meidusa.amoeba.context.DBServerConfigFileLoader"> <propertyname="configFile">${amoeba.home}/conf/dbServers.xml</property> </dbServerLoader> <queryRouterclass="com.meidusa.amoeba.mysql.parser.MysqlQueryRouter"> #定义查询路由 <property name="ruleLoader"> <beanclass="com.meidusa.amoeba.route.TableRuleFileLoader"> <propertyname="ruleFile">${amoeba.home}/conf/rule.xml</property> <propertyname="functionFile">${amoeba.home}/conf/ruleFunctionMap.xml</property> </bean> </property> <propertyname="sqlFunctionFile">${amoeba.home}/conf/functionMap.xml</property> <propertyname="LRUMapSize">1500</property> <propertyname="defaultPool">station20</property> #定义读写服务器,这里默认定义到主服务器上 <propertyname="writePool">station20</property> #定义写服务器,若有多个用逗号隔开,这些服务器名来自于dbservers.xml <propertyname="readPool">station21</property> #定义读服务器 <propertyname="needParse">true</property> </queryRouter> </amoeba:configuration> ###############定义连接后端Mysql服务器信息############ [root@node conf]# vim dbServers.xml <?xml version="1.0"encoding="gbk"?> <!DOCTYPE amoeba:dbServers SYSTEM"dbserver.dtd"> <amoeba:dbServersxmlns:amoeba="http://amoeba.meidusa.com/"> <!-- Each dbServerneeds to be configured into a Pool, If you need to configure multiple dbServer with loadbalancing that can be simplified by the following configuration:add attributewith name virtual = "true" in dbServer, but the configuration doesnot allow the element with name factoryConfig such as'multiPool' dbServer --> <dbServername="abstractServer" abstractive="true"> #定义服务器,名字叫抽象服务器,支持抽象功能:公共属性的定义 <factoryConfigclass="com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory"> <propertyname="manager">${defaultManager}</property> <propertyname="sendBufferSize">64</property> #定义发送缓冲大小 <propertyname="receiveBufferSize">128</property> #接受缓冲的大小 <!-- mysql port --> <propertyname="port">3306</property> #监听的端口 <!-- mysqlschema --> <property name="schema">test</property> #默认连接的数据库服务器 <!-- mysql user --> <property name="user">root</property> #用户名 <!-- mysql password --> -->上移与<!- 配对,取消下行注释 <propertyname="password">amoebapass</property> #后端服务器的密码,授权用户密码 </factoryConfig> <poolConfigclass="com.meidusa.amoeba.net.poolable.PoolableObjectPool"> <propertyname="maxActive">500</property> #定义最大活动连接数 <propertyname="maxIdle">500</property> #空闲连接数 <propertyname="minIdle">10</property> #最少空闲连接数 <propertyname="minEvictableIdleTimeMillis">600000</property> <propertyname="timeBetweenEvictionRunsMillis">600000</property> <propertyname="testOnBorrow">true</property> <propertyname="testOnReturn">true</property> <propertyname="testWhileIdle">true</property> </poolConfig> </dbServer> <dbServername="station20" parent="abstractServer"> #定义服务器,其父服务器就是上面的"abstractServer"继承其属性,若不想请添加属性实现定义 <factoryConfig> <!-- mysql ip--> <propertyname="ipAddress">192.168.1.20</property> #server1的IP地址 </factoryConfig> </dbServer> <dbServer name="station21" parent="abstractServer"> #server1的IP地址 <factoryConfig> <!-- mysqlip --> <propertyname="ipAddress">192.168.18.21</property> </factoryConfig> </dbServer> <dbServer name="multiPool"virtual="true"> #定义虚拟服务器组 <poolConfigclass="com.meidusa.amoeba.server.MultipleServerPool"> <!-- Loadbalancing strategy: 1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA--> #算法:1表示轮询,2:基于权重做轮询,3:高可用效果 <propertyname="loadbalance">1</property> #还可以实现负载均衡,算法为1 <!--Separated by commas,such as: server1,server2,server1 --> <propertyname="poolNames">station20,station21</property> #此处一定是定义的dbname </poolConfig> </dbServer> </amoeba:dbServers>
4.启动Amoeba [root@station253conf]# amoeba start log4j:WARNlog4j config load completed from file:/usr/local/amoeba/conf/log4j.xml 2014-05-2505:05:40,143 INFO context.MysqlRuntimeContext - Amoeba for Mysql currentversoin=5.1.45-mysql-amoeba-proxy-2.2.0 #检测后端mysql服务器兼容版本 log4j:WARNip access config load completed fromfile:/usr/local/amoeba/conf/access_list.conf 2014-05-2505:05:40,415 INFO net.ServerableConnectionManager- Amoeba for Mysql listening on /0.0.0.0:3306. #监听地址及端口 2014-05-2505:05:40,427 INFO net.ServerableConnectionManager - Amoeba Monitor Server listening on/127.0.0.1:23679. #管理地址及端口(随机) ##########停止amoeba########### Ctrl+C #########使用后端启动########## [root@station253conf]# amoeba start & #########后端启动服务时停止#### [root@station253conf]# amoeba stop amoebaserver shutting down with port=11422 ###########查看监听端口######## [root@station253conf]# ss -natlp | grep 3306 LISTEN 0 128 :::3306 :::* users:(("java",2467,50))
5.测试连接
[root@station253conf]# mysql -uroot -pamoebapass -h192.168.1.253 YourMySQL connection id is 432598870 前端连接的是代理服务器amoeba Serverversion: 5.1.45-mysql-amoeba-proxy-2.2.0 MySQLCommunity Server (GPL) mysql>select version(); 显示后端数据库版本 +------------+ |version() | +------------+ |5.6.13-log | +------------+ 测试读写分离是否到各自服务器 前端 读库 mysql>select user,host from mysql.user; 在读写分离后,select必须用库名+表名,因为默认路由是到test库 +------+-----------------------+ | user |host | +------+-----------------------+ | root |% | | root |127.0.0.1 | | root |::1 | | | localhost | | root |localhost | | | station21.example.com | | root |station21.example.com | +------+-----------------------+ 后端2服务器提前启用tcpdump抓包 [root@station21~]# tcpdump -i eth0 -A -nn -s0 tcp dst port 3306 and ip dst host 192.168.1.21 tcpdump:verbose output suppressed, use -v or -vv for full protocol decode listeningon eth0, link-type EN10MB (Ethernet), capture size 65535 bytes 07:20:03.771162IP 192.168.1.253.39815 > 192.168.1.21.3306: Flags [P.], select user,host from mysql.user 前端 写库 mysql>create database school; [root@station20~]# tcpdump -i eth0 -A -nn -s0 tcp dst port 3306 and ip dst host 192.168.1.20 tcpdump:verbose output suppressed, use -v or -vv for full protocol decode listeningon eth0, link-type EN10MB (Ethernet), capture size 65535 bytes 07:21:30.426165IP 192.168.1.253.33837 > 192.168.1.20.3306: Flags [P.], create database school mysql>drop database school; drop会先drop写库后select读库确认删除 07:33:40.080159IP 192.168.1.253.33849 > 192.168.1.20.3306: Flags [P.], drop database school 07:33:40.410321IP 192.168.1.253.39825 > 192.168.1.21.3306: Flags [P.], SELECT DATABASE()