搜索词>>modbus tcp 耗时0.0130
  • modbus tcp 通讯modbus-master-tcp Java使用说明

    modbus tcp通讯在之前的博客已经有一种方案。通过modbus4j来实现。本文章主要讲解另外一种方案。通过modbus-master-tcp实现。<h2>引言</h2>     modbus tcp通讯Java的方案之前已经讲解过一种,<a rel="" target="_blank"href="http://www.leftso.com/blog/83.html" rel="" target="_blank">modbus4j实现Java语言的modbus tcp协议通讯</a>。从上一个方案中我们不难发现modbus4j的通讯实现方式是同步的。实际应用中可能会读取大量的数据。同步处理对于应用的响应还是不太友好的。本博客主要讲解另外一种Java语言的modbux tcp通讯方案。那就是modbus-master-tcp。 <h2>一.创建一个demo项目</h2> 创建一个简单的maven项目,项目结构图如下:<br /> <img alt="modbus tcp通讯例子项目结构图" class="img-thumbnail" src="/resources/assist/images/blog/cd159cddb83c4b9191a1b2d126cdd9fc.png" /> <h2>二.pom.xml maven依赖</h2> <pre> <code class="language-xml"><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.leftso.demo.modbus</groupId> <artifactId>demo-modbus-master-slave</artifactId> <version>1.0</version> <dependencies> <dependency> <groupId>com.digitalpetri.modbus</groupId> <artifactId>modbus-master-tcp</artifactId> <version>1.1.0</version> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project></code></pre> <br /> <strong>pom.xml注意,需要将java的编译版本指定到1.8.因为只有1.8以后才支持lambda表达式。</strong><br /> <br /> 配置完成后,我们观察引入的依赖包:<br /> <img alt="modbus maven依赖" class="img-thumbnail" src="/resources/assist/images/blog/f00bb8ebc3c54c80a3ee512f9849a4c7.png" /><br /> 观察可以发现,modbus-master-tcp项目的底层是基于netty框架开发。天然的支持异步处理。在性能方面有很好的提升。 <h2>三.编写modbus tcp读取案例</h2> <pre> <code class="language-java">package com.leftso.demo.modbus; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import com.digitalpetri.modbus.codec.Modbus; import com.digitalpetri.modbus.master.ModbusTcpMaster; import com.digitalpetri.modbus.master.ModbusTcpMasterConfig; import com.digitalpetri.modbus.requests.ReadCoilsRequest; import com.digitalpetri.modbus.requests.ReadDiscreteInputsRequest; import com.digitalpetri.modbus.requests.ReadHoldingRegistersRequest; import com.digitalpetri.modbus.requests.ReadInputRegistersRequest; import com.digitalpetri.modbus.responses.ReadCoilsResponse; import com.digitalpetri.modbus.responses.ReadDiscreteInputsResponse; import com.digitalpetri.modbus.responses.ReadHoldingRegistersResponse; import com.digitalpetri.modbus.responses.ReadInputRegistersResponse; import io.netty.buffer.ByteBuf; import io.netty.util.ReferenceCountUtil; /*** * modbus TCP协议Java通讯读取例子 * * @author xqlee * */ public class SimpleMasterExample { static ModbusTcpMaster master; /** * 获取TCP协议的Master * * @return */ public static void initModbusTcpMaster() { if (master == null) { // 创建配置 ModbusTcpMasterConfig config = new ModbusTcpMasterConfig.Builder("localhost").setPort(502).build(); master = new ModbusTcpMaster(config); } } /*** * 释放资源 */ public static void release() { if (master != null) { master.disconnect(); } Modbus.releaseSharedResources(); } /** * 读取HoldingRegister数据 * * @param address * 寄存器地址 * @param quantity * 寄存器数量 * @param unitId * id * @return 读取结果 * @throws InterruptedException * 异常 * @throws ExecutionException * 异常 */ public static Number readHoldingRegisters(int address, int quantity, int unitId) throws InterruptedException, ExecutionException { Number result = null; CompletableFuture<ReadHoldingRegistersResponse> future = master .sendRequest(new ReadHoldingRegistersRequest(address, quantity), unitId); ReadHoldingRegistersResponse readHoldingRegistersResponse = future.get();// 工具类做的同步返回.实际使用推荐结合业务进行异步处理 if (readHoldingRegistersResponse != null) { ByteBuf buf = readHoldingRegistersResponse.getRegisters(); result = buf.readFloat(); ReferenceCountUtil.release(readHoldingRegistersResponse); } return result; } /** * 读取InputRegisters模拟量数据 * * @param address * 寄存器开始地址 * @param quantity * 数量 * @param unitId * ID * @return 读取值 * @throws InterruptedException * 异常 * @throws ExecutionException * 异常 */ public static Number readInputRegisters(int address, int quantity, int unitId) throws InterruptedException, ExecutionException { Number result = null; CompletableFuture<ReadInputRegistersResponse> future = master .sendRequest(new ReadInputRegistersRequest(address, quantity), unitId); ReadInputRegistersResponse readInputRegistersResponse = future.get();// 工具类做的同步返回.实际使用推荐结合业务进行异步处理 if (readInputRegistersResponse != null) { ByteBuf buf = readInputRegistersResponse.getRegisters(); result = buf.readFloat(); ReferenceCountUtil.release(readInputRegistersResponse); } return result; } /** * 读取Coils开关量 * * @param address * 寄存器开始地址 * @param quantity * 数量 * @param unitId * ID * @return 读取值 * @throws InterruptedException * 异常 * @throws ExecutionException * 异常 */ public static Boolean readCoils(int address, int quantity, int unitId) throws InterruptedException, ExecutionException { Boolean result = null; CompletableFuture<ReadCoilsResponse> future = master.sendRequest(new ReadCoilsRequest(address, quantity), unitId); ReadCoilsResponse readCoilsResponse = future.get();// 工具类做的同步返回.实际使用推荐结合业务进行异步处理 if (readCoilsResponse != null) { ByteBuf buf = readCoilsResponse.getCoilStatus(); result = buf.readBoolean(); ReferenceCountUtil.release(readCoilsResponse); } return result; } /** * 读取readDiscreteInputs开关量 * * @param address * 寄存器开始地址 * @param quantity * 数量 * @param unitId * ID * @return 读取值 * @throws InterruptedException * 异常 * @throws ExecutionException * 异常 */ public static Boolean readDiscreteInputs(int address, int quantity, int unitId) throws InterruptedException, ExecutionException { Boolean result = null; CompletableFuture<ReadDiscreteInputsResponse> future = master .sendRequest(new ReadDiscreteInputsRequest(address, quantity), unitId); ReadDiscreteInputsResponse discreteInputsResponse = future.get();// 工具类做的同步返回.实际使用推荐结合业务进行异步处理 if (discreteInputsResponse != null) { ByteBuf buf = discreteInputsResponse.getInputStatus(); result = buf.readBoolean(); ReferenceCountUtil.release(discreteInputsResponse); } return result; } public static void main(String[] args) { try { // 初始化资源 initModbusTcpMaster(); // 执行操作 // 读取模拟量 System.out.println(readHoldingRegisters(0, 4, 1)); System.out.println(readInputRegisters(0, 4, 1)); // 读取开关量 System.out.println(readCoils(0, 1, 1)); System.out.println(readDiscreteInputs(0, 1, 1)); System.out.println(readDiscreteInputs(2, 1, 1)); // 释放资源 release(); } catch (Exception e) { e.printStackTrace(); } } } </code></pre> 上面的代码中模拟量的读取需要注意,根据实际类型来读取相应的类型,例子中读取的double类型数据 <h2>四.运行上面的案例演示modbus tcp数据读取</h2> 首先打开软件Modbus Slave(没有的可以百度下载)。启动连接:<br /> <img alt="连接到slave" class="img-thumbnail" src="/resources/assist/images/blog/6f9cb23d6ab04284bc2d1c08b328c37e.png" /><br /> 连接完成后,创建四个文档如下图所示:<br /> <img alt="modbus 数据文档" class="img-thumbnail" src="/resources/assist/images/blog/104a6b808dc2451bbd2bfe042d2005d4.png" /><br /> <br /> 好了,现在运行我们刚才编写的Java demo程序,SimpleMasterExample:<br /> <br /> <img alt="执行结果" class="img-thumbnail" src="/resources/assist/images/blog/31a4549943574c5aa3d5d1d3a20b955a.png" /><br /> 通过执行结果可以看到与Modbus Slave软件中的文档数据一致。<br />   <h2> </h2>
  • modbus tcp通讯modbus4j使用说明-java编程

    modbus tcp 通讯协议在Java编程中的使用。本文主要讲解Java编程中通过modbus4j工具类来实现modbus tcp通讯协议的通讯。包括通过modbus协议读取数据,写入数据的实现。<h2>一.什么是modbus</h2>   Modbus是由Modicon(现为施耐德电气公司的一个品牌)在1979年发明的,是全球第一个真正用于工业现场的总线协议。<br /> ModBus网络是一个工业通信系统,由带智能终端的可编程序控制器和计算机通过公用线路或局部专用线路连接而成。其系统结构既包括硬件、亦包括软件。它可应用于各种数据采集和过程监控。<br />   ModBus网络只有一个主机,所有通信都由他发出。网络可支持247个之多的远程从属控制器,但实际所支持的从机数要由所用通信设备决定。采用这个系统,各PC可以和中心主机交换信息而不影响各PC执行本身的控制任务。 <h2>二.Java实现modbus协议通讯</h2> Java编程中,使用modbus4j实现Java中的modbus协议通讯<br /> <br /> modbus4j实现了Java与modbus协议的以下几种通讯方式:<br /> modbus TCP/IP通讯<br /> modubs UDP/IP通讯<br /> modbus RTU/IP通讯<br /> <br /> 核心依赖:<br /> <strong>modbus4j.jar<br /> commons-lang3-3.0.jar<br /> //下载地址代码里有</strong><br /> Java读取工具类 <pre> <code class="language-java">package com.leftso.project.demo.modbus4j; import com.serotonin.modbus4j.BatchRead; import com.serotonin.modbus4j.BatchResults; import com.serotonin.modbus4j.ModbusFactory; import com.serotonin.modbus4j.ModbusMaster; import com.serotonin.modbus4j.code.DataType; import com.serotonin.modbus4j.exception.ErrorResponseException; import com.serotonin.modbus4j.exception.ModbusInitException; import com.serotonin.modbus4j.exception.ModbusTransportException; import com.serotonin.modbus4j.ip.IpParameters; import com.serotonin.modbus4j.locator.BaseLocator; /** * modbus通讯工具类,采用modbus4j实现 * * @author lxq * @dependencies modbus4j-3.0.3.jar * @website https://github.com/infiniteautomation/modbus4j */ public class Modbus4jUtils { /** * 工厂。 */ static ModbusFactory modbusFactory; static { if (modbusFactory == null) { modbusFactory = new ModbusFactory(); } } /** * 获取master * * @return * @throws ModbusInitException */ public static ModbusMaster getMaster() throws ModbusInitException { IpParameters params = new IpParameters(); params.setHost("localhost"); params.setPort(502); // // modbusFactory.createRtuMaster(wapper); //RTU 协议 // modbusFactory.createUdpMaster(params);//UDP 协议 // modbusFactory.createAsciiMaster(wrapper);//ASCII 协议 ModbusMaster master = modbusFactory.createTcpMaster(params, false);// TCP 协议 master.init(); return master; } /** * 读取[01 Coil Status 0x]类型 开关数据 * * @param slaveId * slaveId * @param offset * 位置 * @return 读取值 * @throws ModbusTransportException * 异常 * @throws ErrorResponseException * 异常 * @throws ModbusInitException * 异常 */ public static Boolean readCoilStatus(int slaveId, int offset) throws ModbusTransportException, ErrorResponseException, ModbusInitException { // 01 Coil Status BaseLocator<Boolean> loc = BaseLocator.coilStatus(slaveId, offset); Boolean value = getMaster().getValue(loc); return value; } /** * 读取[02 Input Status 1x]类型 开关数据 * * @param slaveId * @param offset * @return * @throws ModbusTransportException * @throws ErrorResponseException * @throws ModbusInitException */ public static Boolean readInputStatus(int slaveId, int offset) throws ModbusTransportException, ErrorResponseException, ModbusInitException { // 02 Input Status BaseLocator<Boolean> loc = BaseLocator.inputStatus(slaveId, offset); Boolean value = getMaster().getValue(loc); return value; } /** * 读取[03 Holding Register类型 2x]模拟量数据 * * @param slaveId * slave Id * @param offset * 位置 * @param dataType * 数据类型,来自com.serotonin.modbus4j.code.DataType * @return * @throws ModbusTransportException * 异常 * @throws ErrorResponseException * 异常 * @throws ModbusInitException * 异常 */ public static Number readHoldingRegister(int slaveId, int offset, int dataType) throws ModbusTransportException, ErrorResponseException, ModbusInitException { // 03 Holding Register类型数据读取 BaseLocator<Number> loc = BaseLocator.holdingRegister(slaveId, offset, dataType); Number value = getMaster().getValue(loc); return value; } /** * 读取[04 Input Registers 3x]类型 模拟量数据 * * @param slaveId * slaveId * @param offset * 位置 * @param dataType * 数据类型,来自com.serotonin.modbus4j.code.DataType * @return 返回结果 * @throws ModbusTransportException * 异常 * @throws ErrorResponseException * 异常 * @throws ModbusInitException * 异常 */ public static Number readInputRegisters(int slaveId, int offset, int dataType) throws ModbusTransportException, ErrorResponseException, ModbusInitException { // 04 Input Registers类型数据读取 BaseLocator<Number> loc = BaseLocator.inputRegister(slaveId, offset, dataType); Number value = getMaster().getValue(loc); return value; } /** * 批量读取使用方法 * * @throws ModbusTransportException * @throws ErrorResponseException * @throws ModbusInitException */ public static void batchRead() throws ModbusTransportException, ErrorResponseException, ModbusInitException { BatchRead<Integer> batch = new BatchRead<Integer>(); batch.addLocator(0, BaseLocator.holdingRegister(1, 1, DataType.FOUR_BYTE_FLOAT)); batch.addLocator(1, BaseLocator.inputStatus(1, 0)); ModbusMaster master = getMaster(); batch.setContiguousRequests(false); BatchResults<Integer> results = master.send(batch); System.out.println(results.getValue(0)); System.out.println(results.getValue(1)); } /** * 测试 * * @param args */ public static void main(String[] args) { try { // 01测试 Boolean v011 = readCoilStatus(1, 0); Boolean v012 = readCoilStatus(1, 1); Boolean v013 = readCoilStatus(1, 6); System.out.println("v011:" + v011); System.out.println("v012:" + v012); System.out.println("v013:" + v013); // 02测试 Boolean v021 = readInputStatus(1, 0); Boolean v022 = readInputStatus(1, 1); Boolean v023 = readInputStatus(1, 2); System.out.println("v021:" + v021); System.out.println("v022:" + v022); System.out.println("v023:" + v023); // 03测试 Number v031 = readHoldingRegister(1, 1, DataType.FOUR_BYTE_FLOAT);// 注意,float Number v032 = readHoldingRegister(1, 3, DataType.FOUR_BYTE_FLOAT);// 同上 System.out.println("v031:" + v031); System.out.println("v032:" + v032); // 04测试 Number v041 = readInputRegisters(1, 1, DataType.FOUR_BYTE_FLOAT);// Number v042 = readInputRegisters(1, 3, DataType.FOUR_BYTE_FLOAT);// System.out.println("v041:" + v041); System.out.println("v042:" + v042); // 批量读取 batchRead(); } catch (Exception e) { e.printStackTrace(); } } }</code></pre> <h2>三、测试</h2> 使用ModbusSlave模拟modbus协议<br /> slave中模拟数据如下<br /> <img alt="modbus slave模拟数据" class="img-thumbnail" src="/resources/assist/images/blog/afe4a730-8fb5-4aa2-9f6b-ff09f4368459.png" style="height:856px; width:825px" /><br /> 运行工具类的main方法: <pre> <code>11:14:54.547 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 01 00 00 00 01 11:14:54.550 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502 11:14:54.598 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 04 01 01 01 01 11:14:54.600 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 01 00 01 00 01 11:14:54.600 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502 11:14:54.650 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 04 01 01 01 00 11:14:54.652 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 01 00 06 00 01 11:14:54.652 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502 11:14:54.703 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 04 01 01 01 01 v011:true v012:false v013:true 11:14:54.704 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 02 00 00 00 01 11:14:54.704 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502 11:14:54.755 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 04 01 02 01 01 11:14:54.757 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 02 00 01 00 01 11:14:54.757 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502 11:14:54.807 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 04 01 02 01 00 11:14:54.810 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 02 00 02 00 01 11:14:54.810 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502 11:14:54.860 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 04 01 02 01 01 v021:true v022:false v023:true 11:14:54.866 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 03 00 01 00 02 11:14:54.866 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502 11:14:54.915 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 07 01 03 04 40 20 00 00 11:14:54.917 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 03 00 03 00 02 11:14:54.917 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502 11:14:54.967 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 07 01 03 04 41 28 00 00 v031:2.5 v032:10.5 11:14:54.971 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 04 00 01 00 02 11:14:54.971 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502 11:14:55.020 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 07 01 04 04 3F C0 00 00 11:14:55.021 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 04 00 03 00 02 11:14:55.021 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502 11:14:55.072 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 07 01 04 04 40 40 00 00 v041:1.5 v042:3.0 11:14:55.074 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 02 00 00 00 01 11:14:55.074 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502 11:14:55.123 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 04 01 02 01 01 11:14:55.125 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 01 00 00 00 06 01 03 00 01 00 02 11:14:55.125 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502 11:14:55.179 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 01 00 00 00 07 01 03 04 40 20 00 00 2.5 true </code></pre> <br /> 观察输出结果与 slave上的模拟数据一致 <h2>四、Java通过modbus4j对数据的写入</h2> <strong>Modbus4jWriteUtils.java</strong> <pre> <code class="language-java">package com.leftso.project.demo.modbus4j; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.serotonin.modbus4j.ModbusFactory; import com.serotonin.modbus4j.ModbusMaster; import com.serotonin.modbus4j.code.DataType; import com.serotonin.modbus4j.exception.ErrorResponseException; import com.serotonin.modbus4j.exception.ModbusInitException; import com.serotonin.modbus4j.exception.ModbusTransportException; import com.serotonin.modbus4j.ip.IpParameters; import com.serotonin.modbus4j.locator.BaseLocator; import com.serotonin.modbus4j.msg.ModbusResponse; import com.serotonin.modbus4j.msg.WriteCoilRequest; import com.serotonin.modbus4j.msg.WriteCoilResponse; import com.serotonin.modbus4j.msg.WriteCoilsRequest; import com.serotonin.modbus4j.msg.WriteCoilsResponse; import com.serotonin.modbus4j.msg.WriteRegisterRequest; import com.serotonin.modbus4j.msg.WriteRegisterResponse; import com.serotonin.modbus4j.msg.WriteRegistersRequest; /** * modbus4j写入数据 * * @author xq * */ public class Modbus4jWriteUtils { static Log log = LogFactory.getLog(Modbus4jWriteUtils.class); /** * 工厂。 */ static ModbusFactory modbusFactory; static { if (modbusFactory == null) { modbusFactory = new ModbusFactory(); } } /** * 获取tcpMaster * * @return * @throws ModbusInitException */ public static ModbusMaster getMaster() throws ModbusInitException { IpParameters params = new IpParameters(); params.setHost("localhost"); params.setPort(502); ModbusMaster tcpMaster = modbusFactory.createTcpMaster(params, false); tcpMaster.init(); return tcpMaster; } /** * 写 [01 Coil Status(0x)]写一个 function ID = 5 * * @param slaveId * slave的ID * @param writeOffset * 位置 * @param writeValue * 值 * @return 是否写入成功 * @throws ModbusTransportException * @throws ModbusInitException */ public static boolean writeCoil(int slaveId, int writeOffset, boolean writeValue) throws ModbusTransportException, ModbusInitException { // 获取master ModbusMaster tcpMaster = getMaster(); // 创建请求 WriteCoilRequest request = new WriteCoilRequest(slaveId, writeOffset, writeValue); // 发送请求并获取响应对象 WriteCoilResponse response = (WriteCoilResponse) tcpMaster.send(request); if (response.isException()) { return false; } else { return true; } } /** * 写[01 Coil Status(0x)] 写多个 function ID = 15 * * @param slaveId * slaveId * @param startOffset * 开始位置 * @param bdata * 写入的数据 * @return 是否写入成功 * @throws ModbusTransportException * @throws ModbusInitException */ public static boolean writeCoils(int slaveId, int startOffset, boolean[] bdata) throws ModbusTransportException, ModbusInitException { // 获取master ModbusMaster tcpMaster = getMaster(); // 创建请求 WriteCoilsRequest request = new WriteCoilsRequest(slaveId, startOffset, bdata); // 发送请求并获取响应对象 WriteCoilsResponse response = (WriteCoilsResponse) tcpMaster.send(request); if (response.isException()) { return false; } else { return true; } } /*** * 写[03 Holding Register(4x)] 写一个 function ID = 6 * * @param slaveId * @param writeOffset * @param writeValue * @return * @throws ModbusTransportException * @throws ModbusInitException */ public static boolean writeRegister(int slaveId, int writeOffset, short writeValue) throws ModbusTransportException, ModbusInitException { // 获取master ModbusMaster tcpMaster = getMaster(); // 创建请求对象 WriteRegisterRequest request = new WriteRegisterRequest(slaveId, writeOffset, writeValue); WriteRegisterResponse response = (WriteRegisterResponse) tcpMaster.send(request); if (response.isException()) { log.error(response.getExceptionMessage()); return false; } else { return true; } } /** * * 写入[03 Holding Register(4x)]写多个 function ID=16 * * @param slaveId * modbus的slaveID * @param startOffset * 起始位置偏移量值 * @param sdata * 写入的数据 * @return 返回是否写入成功 * @throws ModbusTransportException * @throws ModbusInitException */ public static boolean writeRegisters(int slaveId, int startOffset, short[] sdata) throws ModbusTransportException, ModbusInitException { // 获取master ModbusMaster tcpMaster = getMaster(); // 创建请求对象 WriteRegistersRequest request = new WriteRegistersRequest(slaveId, startOffset, sdata); // 发送请求并获取响应对象 ModbusResponse response = tcpMaster.send(request); if (response.isException()) { log.error(response.getExceptionMessage()); return false; } else { return true; } } /** * 写入数字类型的模拟量(如:写入Float类型的模拟量、Double类型模拟量、整数类型Short、Integer、Long) * * @param slaveId * @param offset * @param value * 写入值,Number的子类,例如写入Float浮点类型,Double双精度类型,以及整型short,int,long * @param registerCount * ,com.serotonin.modbus4j.code.DataType * @throws ModbusTransportException * @throws ErrorResponseException * @throws ModbusInitException */ public static void writeHoldingRegister(int slaveId, int offset, Number value, int dataType) throws ModbusTransportException, ErrorResponseException, ModbusInitException { // 获取master ModbusMaster tcpMaster = getMaster(); // 类型 BaseLocator<Number> locator = BaseLocator.holdingRegister(slaveId, offset, dataType); tcpMaster.setValue(locator, value); } public static void main(String[] args) { try { //@formatter:off // 测试01 // boolean t01 = writeCoil(1, 0, true); // System.out.println("T01:" + t01); // 测试02 // boolean t02 = writeCoils(1, 0, new boolean[] { true, false, true }); // System.out.println("T02:" + t02); // 测试03 // short v = -3; // boolean t03 = writeRegister(1, 0, v); // System.out.println("T03:" + t03); // 测试04 // boolean t04 = writeRegisters(1, 0, new short[] { -3, 3, 9 }); // System.out.println("t04:" + t04); //写模拟量 writeHoldingRegister(1,0, 10.1f, DataType.FOUR_BYTE_FLOAT); //@formatter:on } catch (Exception e) { e.printStackTrace(); } } } </code></pre> <br /> <img alt="浮点类型数据写入" class="img-thumbnail" src="/resources/assist/images/blog/0cee0505f42e44bda68381524f669ba1.png" /><br /> <br /> modbus协议中常见功能代码说明:<br /> <img alt="function ID/code说明" class="img-thumbnail" src="/resources/assist/images/blog/6333daae54c94281b86fba2676238c48.png" /><br />  
  • linux系统iptables防火墙基本使用规则

    linux系统iptables防火墙基本使用规则<p>一、规则分类<br /> 1.进入本机,即访问本机规则<br /> 2.出本机,即本机访问外面规则<br /> 3.转发,即本地转发规则,如端口7001转发到80<br /> <img alt="一、规则分类" class="img-thumbnail" src="/resources/assist/images/blog/594adbe6-21cd-43cb-b0f9-19a5730a6de0.jpg" style="height:241px; width:453px" /><br />  </p> <p>二、使用<br /> 1.允许来自IP 10.1.1.101的访问<br /> 命令:<br />  </p> <pre> <code>iptables -A INPUT -s 10.1.1.101 -j ACCEPT</code></pre> 查看<br /> <img alt="2" class="img-thumbnail" src="/resources/assist/images/blog/a1bf589d-135e-44a2-a681-6bcdad99f702.jpg" style="height:258px; width:429px" /><br /> 2.允许来自IP 10.1.1.102的TCP协议的访问<br /> 命令: <pre> <code>iptables -A INPUT -s 10.1.1.102 -p tcp -j ACCEPT</code></pre> 3.禁止来自IP 10.1.1.103的访问,即屏蔽来自该IP的访问<br /> 命令: <pre> <code>iptables -A INPUT -s 10.1.1.103 -j DROP</code></pre> 4.开放本机端口7001<br /> 命令: <pre> <code>iptables -A INPUT -p tcp --dport 7001 -j ACCEPT</code></pre> 5.对外屏蔽端口3306<br /> 命令: <pre> <code>iptables -A INPUT -p tcp --dport 3306 -j DROP</code></pre> 5.删除规则<br /> <br /> 1.通过规则详情删除<br /> 删除操作1中的规则 <pre> <code>iptables -D INPUT -s 10.1.1.101 -j ACCEPT</code></pre> 删除操作2中的规则 <pre> <code>iptables -D INPUT -s 10.1.1.102 -p tcp -j ACCEPT</code></pre> 删除操作3中的规则 <pre> <code>iptables -D INPUT -s 10.1.1.103 -j DROP</code></pre> 删除操作4中的规则 <pre> <code>iptables -D INPUT -p tcp --dport 7001 -j ACCEPT</code></pre> 2.通过规则序号删除<br /> 显示规则序号,命令: <pre> <code>iptables -L -n --line-number</code></pre> 通过规则序号删除,命令: <pre> <code>iptables -D INPUT 序号</code></pre>  
  • centos 7 firewall(防火墙)开放端口/删除端口/查看端口

    centos 7 firewall(防火墙)开放端口/删除端口/查看端口centos 7 firewall(防火墙)开放端口/删除端口/查看端口<br /> <br /> 1.firewall的基本启动/停止/重启命令 <pre> <code class="language-bash">#centos7启动防火墙 systemctl start firewalld.service #centos7停止防火墙/关闭防火墙 systemctl stop firewalld.service #centos7重启防火墙 systemctl restart firewalld.service #设置开机启用防火墙 systemctl enable firewalld.service #设置开机不启动防火墙 systemctl disable firewalld.service</code></pre> 2.新增开放一个端口号 <pre> <code class="language-bash">firewall-cmd --zone=public --add-port=80/tcp --permanent #说明: #–zone #作用域 #–add-port=80/tcp #添加端口,格式为:端口/通讯协议 #–permanent 永久生效,没有此参数重启后失效 #多个端口: firewall-cmd --zone=public --add-port=80-90/tcp --permanent</code></pre> <img alt="开放端口" class="img-thumbnail" src="/resources/assist/images/blog/f1300696a53946ef9756fe2c5464a363.jpg" /><br /> <span style="color:#e74c3c"><strong>注意:新增/删除操作需要重启防火墙服务.<br /> 其他PC telnet开放的端口必须保证本地 telnet 127.0.0.1 端口号 能通。本地不通不一定是防火墙的问题。<br /> <br /> 查看本机已经启用的监听端口:</strong></span> <pre> <code class="language-bash">#centos7以下使用netstat -ant,7使用ss ss -ant </code></pre> <img alt="端口查看 ss -ant" class="img-thumbnail" src="/resources/assist/images/blog/4c73b219ce4c4e6ca51d15f2521489be.jpg" /><br /> 3.查看 <pre> <code class="language-bash">#centos7查看防火墙所有信息 firewall-cmd --list-all #centos7查看防火墙开放的端口信息 firewall-cmd --list-ports</code></pre> <img alt="查看端口" class="img-thumbnail" src="/resources/assist/images/blog/260c39801ff7429898029b298306bda1.jpg" /><br /> 4.删除 <pre> <code class="language-bash">#删除 firewall-cmd --zone=public --remove-port=80/tcp --permanent</code></pre> <img alt="删除端口" class="img-thumbnail" src="/resources/assist/images/blog/d5e499e6d4a045b0a595a365ef5842c9.jpg" /><br /> <br /> <span style="color:#e74c3c"><strong>注意:新增/删除操作需要重启防火墙服务.</strong></span>
  • HTTP协议2.0_HTTP2.0新特性

    HTTP协议2.0,HTTP 2.0如何升级_HTTP2.0新特性_HTTP2.0详解。<h2>引用</h2>   本文主要讲述HTTP协议2.0版本,以及<a rel="external nofollow" target="_blank" id="http2.0" name="http2.0">HTTP协议2.0</a>的新特性说明 <h2>一.开篇HTTP发展的心路历程</h2> <br /> <img alt="开篇HTTP发展的心路历程,1" class="img-thumbnail" src="/resources/assist/images/blog/76f5c3db6d6843809b1f42d62f0f8a6d.png" /><br /> 上图:连接无法复用<br /> <img alt="HTTP 协议 订单流程" class="img-thumbnail" src="/resources/assist/images/blog/e77a5ee7ca904be584f248722782ccfb.png" /><br /> 上图:设置Connection:Keep-Alive,保持连接在一段时间内不断开。<br /> <img alt="HTTP协议多个订单" class="img-thumbnail" src="/resources/assist/images/blog/f260aa472f694465ba83da7498272ade.png" /><br /> 上图:HTTPpipelining:建立多个连接<br /> <img alt="HTTP多路复用" class="img-thumbnail" src="/resources/assist/images/blog/af6c10458a3146fdb9bc4b8b0254deed.png" /><br /> 上图:多路复用 <h2>二.先对HTTP协议进行简单介绍</h2> <p>   1. HTTP协议 :Hyper Text Transfer Protocol(超文本传输协议),是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。是互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准。</p> <p>    2. HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。</p> <p>   3. HTTP是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展。</p> <p>   4. HTTP协议工作于客户端-服务端架构为上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。Web服务器根据接收到的请求后,向客户端发送响应信息。<br /> <img alt="Http协议客户端和服务端" class="img-thumbnail" src="/resources/assist/images/blog/bd2f47f787154d74a164ca4cdc3cb381.png" /></p> <h2>三.HTTP 协议的版本</h2> <ul> <li>HTTP 0.9作为HTTP协议的第一个版本。是非常弱的。请求(Request)只有一行,比如: GET www.leautolink.com</li> <li>HTTP1.0最早在网页中使用是在1996年,那个时候只是使用一些较为简单的网页上和网络请求上。</li> <li>HTTP1.1则在1999年才开始广泛应用于现在的各大浏览器网络请求中,同时HTTP1.1也是当前使用最为广泛的HTTP协议。</li> </ul> <img alt="HTTP协议版本" class="img-thumbnail" src="/resources/assist/images/blog/be03a1e810d5455483dd40e6c644428e.png" /><br />   <p><strong>HTTP 1.1 做了哪些升级:</strong></p> <p> </p> <ul> <li> <p><strong>缓存处理</strong>,在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。</p> </li> <li> <p><strong>带宽优化及网络连接的使用</strong>,HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。</p> </li> <li> <p><strong>错误通知的管理</strong>,在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。</p> </li> <li> <p><strong>Host头处理</strong>,在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。</p> </li> <li> <p><strong>长连接</strong>,HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。</p> </li> </ul> <p><strong>如何建立连接(三次握手)</strong></p> <p>    HTTP 是基于 TCP 协议的,浏览器最快也要在第三次握手时才能捎带 HTTP 请求报文,达到真正的建立连接,但是这些连接无法复用会导致每次请求都经历三次握手和慢启动。三次握手在高延迟的场景下影响较明显,慢启动则对文件类大请求影响较大。</p> <ul> <li> <p><strong>第一次</strong><strong>握手:</strong>建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。</p> </li> <li> <p><strong>第二次握手:</strong>服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;</p> </li> <li> <p><strong>第三次握手:</strong>客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。</p> </li> </ul> <p><strong>完成三次握手,客户端与服务器开始传送数据。</strong></p> <img alt="HTTP协议三次握手流程图" class="img-thumbnail" src="/resources/assist/images/blog/5891e7762d3843e8aaf04edf552f6930.png" /> <p><strong>如何关闭连接(四次挥手):</strong></p> <p> </p> <p>    由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这个原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。</p> <p> </p> <p>     TCP的连接的拆除需要发送四个包,因此称为<strong>四次挥手(four-way handshake)</strong>。客户端或服务器均可主动发起挥手动作,在socket编程中,任何一方执行close()操作即可产生挥手操作。</p> <p> </p> <ol> <li> <p>客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送。 </p> </li> <li> <p>服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。 </p> </li> <li> <p>服务器B关闭与客户端A的连接,发送一个FIN给客户端A。 </p> </li> <li> <p>客户端A发回ACK报文确认,并将确认序号设置为收到序号加1。 <br /> <img alt="HTTP 第三次和第四次握手" class="img-thumbnail" src="/resources/assist/images/blog/7314195885b54567bac1275375c419fe.png" /><br />  </p> </li> </ol> <p><strong>浏览器阻塞(HOL blocking):</strong></p> <p>   浏览器对于同一个域名,一般PC端浏览器会针对单个域名的server同时建立6~8个连接,手机端的连接数则一般控制在4~6个(这个根据浏览器内核不同可能会有所差异),超过浏览器最大连接数限制,后续请求就会被阻塞。</p> <h2>三.在讲HTTP/2之前我们先来说说SPDY</h2> <p>  SPDY协议是Google提出的基于传输控制协议(TCP)的应用层协议,通过压缩、多路复用和优先级来缩短加载时间。该协议是一种更加快速的内容传输协议,于2009 年年中发布。</p> <p>  GoogleChrome、MozillaFirefox以及Opera已默认开启SPDY。Google曾经称它的测试显示,页面载入提高了一倍。该协议是一种更加快速的内容传输协议。</p> <p><strong>SPDY协议设定的目标</strong></p> <p>    1. 页面加载时间(PLT,Page • Load Time)降低 50%;</p> <p>    2. 无需网站作者修改任何内容;</p> <p>    3. 最小化配置复杂度,无需变更网络基础设施;</p> <p>注:为了达到降低50% 页面加载时间的目标,SPDY 引入了一个新的二进制分帧数据层,以实现多向请求和响应、优先次序、最小化及消除不必要的网络延迟,目的是更有效地利用底层TCP 连接;</p> <h2>四.HTTP/2:SPDY的升级版</h2> <ul> <li> <p>HTTP-WG(HTTP Working Group)在2012 年初把HTTP 2.0提到了议事日程,吸取SPDY 的经验教训,并在此基础上制定官方标准。</p> </li> <li> <p>HTTP/2 的主要目标是改进传输性能,更有效地利用网络资源,实现低延迟和高吞吐量。从另一方面看,HTTP 的高层协议语义并不会因为这次版本升级而受影响。所有HTTP 首部、值,以及它们的使用场景都不会变。</p> </li> <li> <p>HTTP/2 致力于突破上一代标准众所周知的性能限制,但它也是对之前1.x 标准的扩展,而非替代。之所以要递增一个大版本到2.0,主要是因为它改变了客户端与服务器之间交换数据的方式</p> </li> </ul> <p><strong>HTTP/2 是如何提高效率呢?</strong></p> <p><strong>  二进制分帧:HTTP 2.0 的所有帧都采用二进制编码</strong></p> <ul> <li> <p><strong>帧</strong>:客户端与服务器通过交换帧来通信,帧是基于这个新协议通信的最小单位。</p> </li> <li> <p><strong>消息</strong>:是指逻辑上的 HTTP 消息,比如请求、响应等,由一或多个帧组成。</p> </li> <li> <p><strong>流</strong>:流是连接中的一个虚拟信道,可以承载双向的消息;每个流都有一个唯一的整数标识符(1、2…N);</p> </li> </ul> <img alt="HTTP 2.0连接" class="img-thumbnail" src="/resources/assist/images/blog/f3e1405c2a1f43c3a8ef78325d360f3b.png" /> <p><strong>多路复用 (Multiplexing)</strong></p> <p>    多路复用允许同时通过单一的 HTTP/2 连接发起多重的请求-响应消息。有了新的分帧机制后,HTTP/2 不再依赖多个TCP 连接去实现多流并行了。每个数据流都拆分成很多互不依赖的帧,而这些帧可以交错(乱序发送),还可以分优先级。最后再在另一端把它们重新组合起来。HTTP 2.0 连接都是持久化的,而且客户端与服务器之间也只需要一个连接(<strong>每个域名一个连接</strong>)即可。 </p> <p> </p> <p><strong>请求优先级</strong></p> <ul> <li> <p>把HTTP 消息分解为很多独立的帧之后,就可以通过优化这些帧的交错和传输顺序,每个流都可以带有一个31 比特的优先值:0 表示最高优先级;2的31次方-1 表示最低优先级。</p> </li> <li> <p>服务器可以根据流的优先级,控制资源分配(CPU、内存、带宽),而在响应数据准备好之后,优先将最高优先级的帧发送给客户端。</p> </li> <li> <p>HTTP 2.0 一举解决了所有这些低效的问题:浏览器可以在发现资源时立即分派请求,指定每个流的优先级,让服务器决定最优的响应次序。这样请求就不必排队了,既节省了时间,也最大限度地利用了每个连接。</p> </li> </ul> <p> </p> <p><strong>header压缩</strong></p> <p>    HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP/2使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。</p> <p> </p> <p><strong>服务端推送</strong></p> <ul> <li> <p>服务器可以对一个客户端请求发送多个响应。服务器向客户端推送资源无需客户端明确地请求。</p> </li> <li> <p>HTTP 2.0 连接后,客户端与服务器交换SETTINGS 帧,借此可以限定双向并发的流的最大数量。</p> </li> <li> <p>所有推送的资源都遵守同源策略。换句话说,服务器不能随便将第三方资源推送给客户端,而必须是经过双方确认才行。</p> </li> <li> <p>服务器必须遵循请求- 响应的循环,只能借着对请求的响应推送资源</p> </li> </ul> <p> </p> <p><strong>服务器推送到底是什么?</strong></p> <p>    服务端推送能把客户端所需要的资源伴随着index.html一起发送到客户端,省去了客户端重复请求的步骤。正因为没有发起请求,建立连接等操作,所以静态资源通过服务端推送的方式可以极大地提升速度。</p> <p> </p> <p>普通的客户端请求过程:<br /> <img alt="普通客户端请求HTTP协议过程" class="img-thumbnail" src="/resources/assist/images/blog/98d6549c4dfe4180a51242a61353286a.png" /><br />  </p> 服务端推送的过程:<br /> <img alt="服务端推送的过程" class="img-thumbnail" src="/resources/assist/images/blog/b1ca4e63108a42b8a7f49454b948416f.png" /> <p><strong>HTTP/2的多路复用和HTTP1.1中的长连接复用有什么区别?</strong></p> <ul> <li> <p>HTTP/1.0 一次请求-响应,建立一个连接,用完关闭;每一个请求都要建立一个连接;</p> </li> <li> <p>HTTP/1.1 Pipeling解决方式为,若干个请求排队串行化单线程处理,后面的请求等待前面请求的返回才能获得执行机会,一旦有某请求超时等,后续请求只能被阻塞,毫无办法,也就是人们常说的线头阻塞;</p> </li> <li> <p>HTTP/2多个请求可同时在一个连接上并行执行。某个请求任务耗时严重,不会影响到其它连接的正常执行;<br /> <img alt="HTTP" class="img-thumbnail" src="/resources/assist/images/blog/ab81f47df21b4aa7941fec0556dcb814.png" /><br />  </p> </li> </ul> <h2>五.如何应用到自己的项目里</h2> <p>  现有的任何网站和应用,无需做任何修改都可以在HTTP 2.0 上跑起来。不用为了利用HTTP 2.0 的好处而修改标记。HTTP 服务器必须运行HTTP 2.0 协议,但大部分用户都不会因此而受到影响。</p> <p>  如果你使用NGINX,只要在配置文件中启动相应的协议就可以了,可以参考NGINX白皮书,NGINX配置HTTP2.0官方指南。</p> <p>  使用了HTTP2.0那么,原本的HTTP1.x怎么办,这个问题其实不用担心,HTTP2.0完全兼容HTTP1.x的语义,对于不支持HTTP2.0的浏览器,NGINX会自动向下兼容的。</p>
  • spring boot整合activemq实现MQ的使用-java编程中

    spring boot整合activemq。本博客将通过一个简单的例子讲解在spring boot中activemq如何作为消费者(Consumer )和如何在spring boot中消息提供者(Provider )的实现。<h2>一.去activemq官网下载mq软件</h2> 去Apache官网下载activemq软件,并安装。 <h2>二.编写Java代码</h2> java编程中spring boot整合activemq实现MQ的使用<br /> 1.在spring boot项目中添加activemq的依赖 <pre> <code class="language-xml"><!-- activemq support --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-activemq</artifactId> </dependency> <!-- /activemq support --></code></pre> 2.application.properties配置文件中添加mq的相关配置 <pre> <code>#==================activemq Config Start================== spring.activemq.broker-url=tcp://127.0.0.1:61616 spring.activemq.in-memory=true spring.activemq.password=admin spring.activemq.user=admin spring.activemq.packages.trust-all=false spring.activemq.packages.trusted= spring.activemq.pool.configuration.*= spring.activemq.pool.enabled=false spring.activemq.pool.expiry-timeout=0 spring.activemq.pool.idle-timeout=30000 spring.activemq.pool.max-connections=1 #==================activemq Config End ==================</code></pre> <br /> 3.消息提供者 <pre> <code class="language-java">package com.htwl.collection.cqyth.amq; import java.text.SimpleDateFormat; import java.util.Date; import javax.jms.Destination; import org.apache.activemq.command.ActiveMQQueue; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jms.core.JmsMessagingTemplate; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; /** * MQ消息提供者 * * @author leftso * */ @Component @EnableScheduling // 测试用启用任务调度 public class Provider { /** MQ jms实例 **/ @Autowired private JmsMessagingTemplate jmsMessagingTemplate; private static int count = 0; @Scheduled(fixedDelay = 5000) // 每5s执行1次-测试使用 public void send() { Destination destination = new ActiveMQQueue("TEST_QUEUE_LOG");// 这里定义了Queue的key String message = "Send AMQ Test ..." + count; System.out.println("[" + new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()) + "]" + message); count++; this.jmsMessagingTemplate.convertAndSend(destination, message); } } </code></pre> 4.消费 <pre> <code class="language-java">package com.htwl.collection.cqyth.amq; import java.text.SimpleDateFormat; import java.util.Date; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.jms.annotation.JmsListener; import org.springframework.stereotype.Component; @Component public class Consumer { Logger LOGGER = LoggerFactory.getLogger(this.getClass()); /** * 使用@JmsListener注解来监听指定的某个队列内的消息 **/ @JmsListener(destination = "TEST_QUEUE_LOG") public void removeMessage(String msg) { System.out.println("["+new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date())+"]Receive:"+msg); } } </code></pre>  
  • keepalived安装及配置使用keepalived监听端口

    keepalived安装及配置使用keepalived监听端口<h2><img alt="keepalived" class="img-thumbnail" src="/resources/assist/images/blog/8eb5bf8739af46eca1ffa100e0b1bb8a.png" /></h2> <p>(keepalived双机网络图)<br />  </p> <h2>1.通过yum安装keepalived软件<br />  </h2> <pre> <code>yum install keepalived -y </code></pre> <h2><br /> 2.keepalived默认配置文件存放位置</h2> <pre> <code>/etc/keepalived/keepalived.conf</code></pre> <h2>3.keepalived配置文件详解</h2> <h3><strong>模式1</strong>:通过keepalived检查脚本,脚本检查应用的方式使用。</h3> 通过shell脚本检查应用的进程是否存在,如果不存在则停止keepalived服务,达到让本机失去抢占VIP的机会。剩下的其他机器根据优先级占用VIP;<br /> 注意:每个机器的优先级必须不同;每个机器状态默认均为BACKUP(BACKUP不会在高优先级启动的时候瞬间抢占VIP,主要用于数据库方面的数据同步,如果瞬间抢回中间未同步完全的数据将会出现问题); <pre> <code class="language-html">! Configuration File for keepalived global_defs { router_id 10086 #用户标识本节点的名称,通常为hostname } vrrp_script check_redis {#创建一个vrrp_script脚本,检查配置 script "/etc/keepalived/check_redis.sh" #在脚本中杀死keepalived的进程 interval 2 #检查脚本的频率,单位(秒) } vrrp_instance VI_1 { state BACKUP #配置为BACKUP节点,一般有三个配置可选MASTER(主机)、BACKUP(备机) nopreempt #不抢占模式,必须配合BACKUP。在配置了该模式后优先级则失去作用。谁先启动谁就是MASTER,失败后必须杀死当前keepalived进程,再次重启不会立即抢占资源。实际场合中推荐使用该方式而不是使用优先级的抢占模式。抢占模式会出现一些数据同步的问题。 interface eth0 #虚拟IP使用的网卡名称 virtual_router_id 51 #VRRP组名,多个节点的设置值必须一样,以指明各个节点属于同一个VRRP组 priority 90 #节点的优先级(1-254之间的值) advert_int 1 #组播信息发送间隔,多个节点设置必须一样 authentication {#设置验证信息,同一个组的多个节点设置必须一致 auth_type PASS auth_pass 1111 } virtual_ipaddress {#指定虚拟IP(即VIP)同一个组的多个节点必须设置一致 192.168.1.100 } track_script { check_redis #执行指定vrrp_script脚本 } }</code></pre> <p><strong>check_redis.sh脚本:</strong></p> <pre> <code class="language-bash">#!/bin/sh CHECK_PROCESS=`ps -C redis-server --no-heading| wc -l` if [ $CHECK_PROCESS -eq 0 ];then echo "Redis is stop" sleep 2 CHECK_PROCESS=`ps -C redis-server --no-heading| wc -l` if [ $CHECK_PROCESS -eq 0 ];then /etc/init.d/keepalived stop fi fi </code></pre> <h3><strong>check_port.sh脚本</strong><br />  </h3> <pre> <code class="language-bash">#!/bin/bash #keepalived 监控端口脚本 #使用方法: #在keepalived的配置文件中 #vrrp_script check_port {#创建一个vrrp_script脚本,检查配置 # script "/etc/keepalived/check_port.sh 6379" #配置监听的端口 # interval 2 #检查脚本的频率,单位(秒) #} CHK_PORT=$1 echo $CHK_PORT if [ "$CHK_PORT" != "" ];then PORT_PROCESS=`lsof -i:$CHK_PORT|wc -l` if [ $PORT_PROCESS -eq 0 ];then echo "Port $CHK_PORT Is Not Used,End." sleep 2 PORT_PROCESS=`lsof -i:$CHK_PORT|wc -l` if [ $PORT_PROCESS -eq 0 ];then /etc/init.d/keepalived stop fi fi else echo "Check Port Cant Be Empty!" fi</code></pre> <h3><br /> <strong>模式二:</strong>通过keepalived直接监听应用端口方式使用</h3> 配置文件:/etc/keepalived.conf <pre> <code class="language-bash">! Configuration File for keepalived global_defs { router_id 10086 } vrrp_script check_redis { script "</dev/tcp/127.0.0.1/6379" #修改最后的redis端口6379为自己需要监听的端口,理论上可以监听远程端口 interval 2 #检查脚本的频率,单位(秒) weight -30 #端口检查失败,优先级减少30,默认减少2[注意:两台主机配置的weight相同时候必须保证weight的值大于priority差值] } vrrp_instance VI_1 { state MASTER#BACKUP interface eth0 virtual_router_id 51 priority 95 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.100 192.168.2.110 } track_script { check_redis } }</code></pre> 每个主机配置的内容仅仅优先级不能相同,其他保持一致。这里默认使用的MASTER,所以在优先级高的节点恢复之后会立即抢占VIP。如果不希望立即抢回VIP则配置BACKUP,BACKUP则是当前VIP机器的keepalived服务挂掉再去寻找高优先级的主机。<br /> <br /> 整个过程可以通过一下命令查看日志: <pre> <code>tail -f /var/log/message</code></pre> <h2> </h2> <p><span style="color:#8e44ad"><strong>推荐使用脚本+非抢占模式使用</strong></span></p> <h2><br /> 4.开放防火墙端口</h2> <strong>注意:keepalived默认使用端口122进行通讯,必须开放112端口,或者停用防火墙.保证各个主机之间112端口的连通性</strong><br /> CentOS6中iptables配置开放112端口 <pre> <code class="language-html">#iptables -I INPUT -p 112 -j ACCEPT</code></pre> 保存规则并重启防火墙 <pre> <code>service iptables save service iptables restart</code></pre> <p>查看iptables端口开放情况</p> <pre> <code class="language-bash">[root@template keepalived]# iptables -L -n --line-numbers Chain INPUT (policy ACCEPT) num target prot opt source destination 1 ACCEPT 112 -- 0.0.0.0/0 0.0.0.0/0 2 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED 3 ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 4 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 5 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22 6 REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited Chain FORWARD (policy ACCEPT) num target prot opt source destination 1 REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited Chain OUTPUT (policy ACCEPT) num target prot opt source destination [root@template keepalived]# </code></pre> <h2><br /> 5.启动keepalived</h2> 启动命令: <pre> <code>service keepalived start</code></pre> 查看启用状态 <pre> <code>service keepalived status</code></pre> 设置开机启动 <pre> <code>chkconfig keepalived on</code></pre> <br /> <br /> keepalived其他详细配置说明 <p><strong>全局定义块</strong></p> <p>1、email通知(notification_email、smtp_server、smtp_connect_timeout):用于服务有故障时发送邮件报警,可选项,不建议用。需要系统开启sendmail服务,建议用第三独立监控服务,如用<a href="http://baike.baidu.com/link?url=eiaO-UZufjBG-j-e-nMS2RZrjxE_Xd2PpecyOrAq3sv0umvlhfpMlkR7pO-wEnpV4Vb2e7DWnZ9kKDfeh9YiDa" rel="external nofollow" target="_blank">nagios</a>全面监控代替。 <br /> 2、lvs_id:lvs负载均衡器标识,在一个网络内,它的值应该是唯一的。 <br /> 3、router_id:用户标识本节点的名称,通常为hostname <br /> 4、花括号{}:用来分隔定义块,必须成对出现。如果写漏了,keepalived运行时不会得到预期的结果。由于定义块存在嵌套关系,因此很容易遗漏结尾处的花括号,这点需要特别注意。</p> <p><strong>VRRP</strong><strong>实例定义块</strong></p> <ol start="1"> <li>vrrp_sync_group:同步vrrp级,用于确定失败切换(FailOver)包含的路由实例个数。即在有2个负载均衡器的场景,一旦某个负载均衡器失效,需要自动切换到另外一个负载均衡器的实例是哪</li> <li>group:至少要包含一个vrrp实例,vrrp实例名称必须和vrrp_instance定义的一致</li> <li>vrrp_instance:vrrp实例名 <br /> <strong>1> state</strong>:实例状态,只有MASTER 和 BACKUP两种状态,并且需要全部大写。抢占模式下,其中MASTER为工作状态,BACKUP为备用状态。当MASTER所在的服务器失效时,BACKUP所在的服务会自动把它的状态由BACKUP切换到MASTER状态。当失效的MASTER所在的服务恢复时,BACKUP从MASTER恢复到BACKUP状态。 <br /> <strong>2> interface</strong>:对外提供服务的网卡接口,即VIP绑定的网卡接口。如:eth0,eth1。当前主流的服务器都有2个或2个以上的接口(分别对应外网和内网),在选择网卡接口时,一定要核实清楚。 <br /> <strong>3>mcast_src_ip</strong>:本机IP地址 <br /> <strong>4>virtual_router_id</strong>:虚拟路由的ID号,每个节点设置必须一样,可选择IP最后一段使用,相同的 VRID 为一个组,他将决定多播的 MAC 地址。 <br /> <strong>5> priority</strong>:节点优先级,取值范围0~254,MASTER要比BACKUP高 <br /> <strong>6>advert_int</strong>:MASTER与BACKUP节点间同步检查的时间间隔,单位为秒 <br /> <strong>7>lvs_sync_daemon_inteface</strong>:负载均衡器之间的监控接口,类似于 HA HeartBeat的心跳线。但它的机制优于 Heartbeat,因为它没有“裂脑”这个问题,它是以优先级这个机制来规避这个麻烦的。在 DR 模式中,lvs_sync_daemon_inteface与服务接口interface使用同一个网络接口 <br /> <strong>8> authentication</strong>:验证类型和验证密码。类型主要有 PASS、AH 两种,通常使用PASS类型,据说AH使用时有问题。验证密码为明文,同一vrrp实例MASTER与BACKUP使用相同的密码才能正常通信。 <br /> <strong>9>smtp_alert</strong>:有故障时是否激活邮件通知 <br /> <strong>10>nopreempt</strong>:禁止抢占服务。默认情况,当MASTER服务挂掉之后,BACKUP自动升级为MASTER并接替它的任务,当MASTER服务恢复后,升级为MASTER的BACKUP服务又自动降为BACKUP,把工作权交给原MASTER。当配置了nopreempt,MASTER从挂掉到恢复,不再将服务抢占过来。 <br /> <strong>11>virtual_ipaddress</strong>:虚拟IP地址池,可以有多个IP,每个IP占一行,不需要指定子网掩码。注意:这个IP必须与我们的设定的vip保持一致。</li> </ol> <p>keepalived.conf配置文件中加入以下内容</p> <p>1.notify_master“想要执行的脚本路径” #表示当切换到master状态时,要执行的脚本</p> <p>2.notify_backup “想要执行的脚本路径”#表示当切换到backup状态时,要执行的脚本</p> <p>3.notify_fault“想要执行的脚本路径”#表示切换出现故障时要执行的脚本</p> <br />  
  • spring框架之bean的Scopes(作用域)

    Spring框架中,可以在6个内置的Scope中创建bean,也可以定义自定义范围。 在这六个范围中,只有在使用Web感知的ApplicationContext时才有四个范围可用。singleton 和prototype (单例和多例)作用域 在任何的spring框架IOC容器都可用。<h2>引言</h2>     在Java编程中spring框架已经使用的非常广泛,如今由spring框架派生的spring周边项目也逐渐流行起来,如spring boot,在现在的微服务里面用的甚多。但是用了这么多spring框架的模块和项目,有些时候还是需要对spring框架的基本知识进行深入了解,这里我讲记录下spring框架中bean的作用域。  <br />     在Spring框架中,可以在6个内置的范围中创建bean,也可以定义自定义范围。 在这六个范围中,只有在使用Web感知的ApplicationContext时才有四个范围可用。<code>singleton</code> 和<code>prototype</code> (单例和多例)作用域 在任何的spring框架IOC容器都可用。 <h2>一.spring框架中Bean的作用域类型讲解</h2> 下面是六个spring框架中默认可用的作用域 <table class="table table-bordered table-hover"> <tbody> <tr> <th>作用域类型</th> <th>简介</th> </tr> <tr> <td><code>singleton</code>(默认单例)</td> <td>spring框架的 IoC 容器中只有单个实例。</td> </tr> <tr> <td><code>prototype</code></td> <td>与单例相反, 多例会在每次使用他的时候创建一个新的实例.</td> </tr> <tr> <td><code>request</code></td> <td>在HTTP request的完整生命周期中,将创建并提供一个实例。 <p>只在web感知的Spring ApplicationContext中有效。</p> </td> </tr> <tr> <td><code>session</code></td> <td>在HTTP session的整个生命周期中,将创建一个单一的实例并使其可用。 <p>只在web感知的Spring ApplicationContext中有效。</p> </td> </tr> <tr> <td><code>application</code></td> <td>在ServletContext的完整生命周期中,将创建并提供一个实例。 <p>只在web感知的Spring ApplicationContext中有效。</p> </td> </tr> <tr> <td><code>websocket</code></td> <td>WebSocket的完整生命周期中将创建并提供一个实例。 <p>Only valid in web-aware Spring <code>ApplicationContext</code>.</p> </td> </tr> </tbody> </table> <h3>1.1 spring框架singleton(单例) scope(作用域)</h3>     <code>singleton</code> 是spring容器中的默认bean作用域。 它告诉容器创建和管理每个容器只有一个bean类的实例。 这个单实例存储在这样的单例bean的缓存中,并且该命名bean的所有后续请求和引用都会返回缓存的实例。<br /> <br /> 下面是一个单例作用域,使用的Java代码配置方式: <pre> <code class="language-java">@Component @Scope("singleton")//这个语句其实是多余的 - 单例是默认范围 public class BeanClass { }</code></pre> 同样,下面是一个基于xml配置的方式: <pre> <code class="language-xml"><!-- 指定单例作用域是多余的 --> <bean id="beanId" class="com.leftso.BeanClass" scope="singleton" /> //或者 <bean id="beanId" class="com.leftso.BeanClass" /></code></pre> <h3>1.2 spring框架prototype(多例)scope(作用域)</h3>     <code>prototype</code> (多例)作用域,每一次请求使用到该bean都会被应用创建一个新的实例。<br /> <br />     你应该知道销毁bean的生命周期方法并不会调用<code>prototype</code> 作用域的beans,只有在初始化回调方法的时候调用。因此作为开发人员,应该负责清理<code>prototype</code> 作用域的beans实例和他们挂着的其他资源。<br /> <br /> Java代码配置的方式的prototype(多例)作用域例子: <pre> <code class="language-java">@Component @Scope("prototype") public class BeanClass { }</code></pre> 下面是xml的方式: <pre> <code class="language-xml"><bean id="beanId" class="com.leftso.BeanClass" scope="singleton" /></code></pre> <br /> <span style="color:#1abc9c"><strong>提示:</strong></span><span style="color:#ff0000"><strong>通常应该使用prototype(多例)在有状态的bean ,singleton(单例)处理无状态的bean</strong></span><br /> <br /> <strong><span style="color:#9b59b6">注意:在request, session, application 和 websocket 作用域中使用beans,必须注册RequestContextListener或者RequestContextFilter</span></strong><br />   <h3>1.3 spring框架request scope(作用域)</h3>     在<code>request</code> 范围中,容器为每个HTTP请求创建一个新的实例。因此,如果服务器正在处理50个请求,然而容器最多可以创建50个单独bean的实例。 任何状态更改为一个实例,其他实例将不可见。 这些实例一旦请求完成就被销毁。<br /> <br /> Java代码配置方式例子: <pre> <code class="language-java">@Component @Scope("request") public class BeanClass { } //或者 @Component @RequestScope public class BeanClass { }</code></pre> xml配置例子: <pre> <code class="language-xml"><bean id="beanId" class="com.leftso.BeanClass" scope="request" /></code></pre> <h3>1.4 spring框架session scope(作用域)</h3>     在<code>session</code> 作用域,容器为每个HTTP会话创建一个新的实例。因此,如果服务器有20个活动会话,并且容器最多可以有20个单独的bean类实例。在单个会话生命周期内的所有HTTP请求将有权访问该会话作用域中相同的单个bean实例。<br />     任何状态更改为一个实例,其他实例将不可见。 一旦会话被销毁/终止在服务器上,这些实例就被销毁了。<br /> <br /> Java代码配置例子: <pre> <code class="language-java">@Component @Scope("session") public class BeanClass { } //or @Component @SessionScope public class BeanClass { }</code></pre> xml配置例子: <pre> <code class="language-xml"><bean id="beanId" class="com.leftso.BeanClass" scope="session" /></code></pre> <h3>1.5 spring框架application scope(作用域)</h3>    在<code>application</code> 作用域中,容器每个Web应用程序运行时创建一个实例 它几乎类似于单一的范围,只有两个不同之处,即: <ol> <li><code>application</code> 范围的bean是每个<code>ServletContext</code> 单例,而<code>singleton</code> 范围的bean是每个ApplicationContext单例。 请注意,单个应用程序可以有多个应用程序上下文。</li> <li><code>application</code> 范围的bean作为一个<code>ServletContext</code> 属性是可见的。</li> </ol> java代码配置例子: <pre> <code class="language-java">@Component @Scope("application") public class BeanClass { } //or @Component @ApplicationScope public class BeanClass { }</code></pre> xml配置例子: <pre> <code class="language-xml"><bean id="beanId" class="com.leftos.BeanClass" scope="application" /></code></pre> <h3>1.6 spring框架websocket  scope(作用域)</h3>     WebSocket协议启用客户端和选择与客户端通信的远程主机之间的双向通信。 WebSocket协议为两个方向上的流量提供单个TCP连接。 这对于同时编辑和多用户游戏的多用户应用程序特别有用。<br /> <br />     在这种类型的Web应用程序中,HTTP仅用于初始握手。 服务器可以响应HTTP状态101(切换协议),如果它同意 - 握手请求。 如果握手成功,则TCP套接字保持打开状态,客户端和服务器都可以使用它来相互发送消息。<br /> <br /> java代码配置例子: <pre> <code class="language-java">@Component @Scope("websocket") public class BeanClass { }</code></pre> xml配置例子: <pre> <code class="language-xml"><bean id="beanId" class="com.howtodoinjava.BeanClass" scope="websocket" /></code></pre> <strong><span style="color:#f39c12">请注意,websocket范围的bean通常是单身,比任何单独的WebSocket会话寿命更长。</span></strong><br />   <h3>1.7当前线程作用域</h3>   Spring框架还提供了一个使用SimpleThreadScope类的非默认<code>thread</code> 作用域。 要使用此范围,您必须使用<code>CustomScopeConfigurer</code> 类将其注册到容器。 <pre> <code class="language-xml"><bean class="org.springframework.beans.factory.config.CustomScopeConfigurer"> <property name="scopes"> <map> <entry key="thread"> <bean class="org.springframework.context.support.SimpleThreadScope"/> </entry> </map> </property> </bean></code></pre> 每个bean的请求都会在同一个线程中返回相同的实例。<br /> <br /> Java配置例子: <pre> <code class="language-java">@Component @Scope("thread") public class BeanClass { }</code></pre> xml配置例子: <pre> <code class="language-xml"><bean id="beanId" class="com.howtodoinjava.BeanClass" scope="thread" /></code></pre> <h2>二.总结</h2>     Spring框架提供了六个bean作用域,每个作用域内的实例有不同的生命周期跨度。 作为开发人员,我们必须明智地选择任何容器管理bean的范围。 另外,当不同范围的豆子互相引用时,我们必须做出明智的选择。
  • FastDFS配置文件详细说明

    FastDFS配置文件详细说明<h2>一、tracker.conf</h2> <pre> <code># 这个配置文件是否无效,false表示有效 # is this config file disabled # false for enabled # true for disabled disabled=false # 是否绑定IP # bind_addr= 后面为绑定的IP地址 (常用于服务器有多个IP但只希望一个IP提供服务)。如果不填则表示所有的(一般不填就OK) # bind an address of this host # empty for bind all addresses of this host bind_addr= # 提供服务的端口 # the tracker server port port=22122 # 连接超时时间,针对socket套接字函数connect # connect timeout in seconds # default value is 30s connect_timeout=30 # tracker server的网络超时,单位为秒。发送或接收数据时,如果在超时时间后还不能发送或接收数据,则本次网络通信失败 # network timeout in seconds # default value is 30s network_timeout=60 # the base path to store data and log files base_path=/home/yuqing/fastdfs # base_path 目录地址(根目录必须存在,子目录会自动创建) # 附目录说明: # tracker server目录及文件结构: # ${base_path} # |__data # | |__storage_groups.dat:存储分组信息 # | |__storage_servers.dat:存储服务器列表 # |__logs # |__trackerd.log:tracker server日志文件 #数据文件storage_groups.dat和storage_servers.dat中的记录之间以换行符(\n)分隔,字段之间以西文逗号(,)分隔。 #storage_groups.dat中的字段依次为: # 1. group_name:组名 # 2. storage_port:storage server端口号 #storage_servers.dat中记录storage server相关信息,字段依次为: # 1. group_name:所属组名 # 2. ip_addr:ip地址 # 3. status:状态 # 4. sync_src_ip_addr:向该storage server同步已有数据文件的源服务器 # 5. sync_until_timestamp:同步已有数据文件的截至时间(UNIX时间戳) # 6. stat.total_upload_count:上传文件次数 # 7. stat.success_upload_count:成功上传文件次数 # 8. stat.total_set_meta_count:更改meta data次数 # 9. stat.success_set_meta_count:成功更改meta data次数 # 10. stat.total_delete_count:删除文件次数 # 11. stat.success_delete_count:成功删除文件次数 # 12. stat.total_download_count:下载文件次数 # 13. stat.success_download_count:成功下载文件次数 # 14. stat.total_get_meta_count:获取meta data次数 # 15. stat.success_get_meta_count:成功获取meta data次数 # 16. stat.last_source_update:最近一次源头更新时间(更新操作来自客户端) # 17. stat.last_sync_update:最近一次同步更新时间(更新操作来自其他storage server的同步) # 系统提供服务时的最大连接数。对于V1.x,因一个连接由一个线程服务,也就是工作线程数。 # 对于V2.x,最大连接数和工作线程数没有任何关系 # max concurrent connections this server supported max_connections=256 # work thread count, should <= max_connections # default value is 4 # since V2.00 # V2.0引入的这个参数,工作线程数,通常设置为CPU数 work_threads=4 # 上传组(卷) 的方式 0:轮询方式 1: 指定组 2: 平衡负载(选择最大剩余空间的组(卷)上传) # 这里如果在应用层指定了上传到一个固定组,那么这个参数被绕过 # the method of selecting group to upload files # 0: round robin # 1: specify group # 2: load balance, select the max free space group to upload file store_lookup=2 # 当上一个参数设定为1 时 (store_lookup=1,即指定组名时),必须设置本参数为系统中存在的一个组名。如果选择其他的上传方式,这个参数就没有效了 # which group to upload file # when store_lookup set to 1, must set store_group to the group name store_group=group2 # 选择哪个storage server 进行上传操作(一个文件被上传后,这个storage server就相当于这个文件的storage server源,会对同组的storage server推送这个文件达到同步效果) # 0: 轮询方式 # 1: 根据ip 地址进行排序选择第一个服务器(IP地址最小者) # 2: 根据优先级进行排序(上传优先级由storage server来设置,参数名为upload_priority) # which storage server to upload file # 0: round robin (default) # 1: the first server order by ip address # 2: the first server order by priority (the minimal) store_server=0 # 选择storage server 中的哪个目录进行上传。storage server可以有多个存放文件的base path(可以理解为多个磁盘)。 # 0: 轮流方式,多个目录依次存放文件 # 2: 选择剩余空间最大的目录存放文件(注意:剩余磁盘空间是动态的,因此存储到的目录或磁盘可能也是变化的) # which path(means disk or mount point) of the storage server to upload file # 0: round robin # 2: load balance, select the max free space path to upload file store_path=0 # 选择哪个 storage server 作为下载服务器 # 0: 轮询方式,可以下载当前文件的任一storage server # 1: 哪个为源storage server 就用哪一个 (前面说过了这个storage server源 是怎样产生的) 就是之前上传到哪个storage server服务器就是哪个了 # which storage server to download file # 0: round robin (default) # 1: the source storage server which the current file uploaded to download_server=0 # storage server 上保留的空间,保证系统或其他应用需求空间。可以用绝对值或者百分比(V4开始支持百分比方式)。 #(指出 如果同组的服务器的硬盘大小一样,以最小的为准,也就是只要同组中有一台服务器达到这个标准了,这个标准就生效,原因就是因为他们进行备份) # reserved storage space for system or other applications. # if the free(available) space of any stoarge server in # a group <= reserved_storage_space, # no file can be uploaded to this group. # bytes unit can be one of follows: ### G or g for gigabyte(GB) ### M or m for megabyte(MB) ### K or k for kilobyte(KB) ### no unit for byte(B) ### XX.XX% as ratio such as reserved_storage_space = 10% reserved_storage_space = 10% # 选择日志级别 #standard log level as syslog, case insensitive, value list: ### emerg for emergency ### alert ### crit for critical ### error ### warn for warning ### notice ### info ### debug log_level=info # 操作系统运行FastDFS的用户组 (不填 就是当前用户组,哪个启动进程就是哪个) #unix group name to run this program, #not set (empty) means run by the group of current user run_by_group= # 操作系统运行FastDFS的用户 (不填 就是当前用户,哪个启动进程就是哪个) #unix username to run this program, #not set (empty) means run by current user run_by_user= # 可以连接到此 tracker server 的ip范围(对所有类型的连接都有影响,包括客户端,storage server) # allow_hosts can ocur more than once, host can be hostname or ip address, # "*" means match all ip addresses, can use range like this: 10.0.1.[1-15,20] or # host[01-08,20-25].domain.com, for example: # allow_hosts=10.0.1.[1-15,20] # allow_hosts=host[01-08,20-25].domain.com allow_hosts=* # 同步或刷新日志信息到硬盘的时间间隔,单位为秒 # 注意:tracker server 的日志不是时时写硬盘的,而是先写内存 # sync log buff to disk every interval seconds # default value is 10 seconds sync_log_buff_interval = 10 # 检测 storage server 存活的时间隔,单位为秒。 # storage server定期向tracker server 发心跳,如果tracker server在一个check_active_interval内还没有收到storage server的一次心跳,那边将认为该storage server已经下线。所以本参数值必须大于storage server配置的心跳时间间隔。通常配置为storage server心跳时间间隔的2倍或3倍 # check storage server alive interval seconds check_active_interval = 120 # 线程栈的大小。FastDFS server端采用了线程方式。tracker server线程栈不应小于64KB # 线程栈越大,一个线程占用的系统资源就越多。如果要启动更多的线程(V1.x对应的参数为max_connections, V2.0为work_threads),可以适当降低本参数值 # thread stack size, should >= 64KB # default value is 64KB thread_stack_size = 64KB # 这个参数控制当storage server IP地址改变时,集群是否自动调整。注:只有在storage server进程重启时才完成自动调整 # auto adjust when the ip address of the storage server changed # default value is true storage_ip_changed_auto_adjust = true # V2.0引入的参数。存储服务器之间同步文件的最大延迟时间,缺省为1天。根据实际情况进行调整 # 注:本参数并不影响文件同步过程。本参数仅在下载文件时,判断文件是否已经被同步完成的一个阀值(经验值) # storage sync file max delay seconds # default value is 86400 seconds (one day) # since V2.00 storage_sync_file_max_delay = 86400 # V2.0引入的参数。存储服务器同步一个文件需要消耗的最大时间,缺省为300s,即5分钟。 # 注:本参数并不影响文件同步过程。本参数仅在下载文件时,作为判断当前文件是否被同步完成的一个阀值(经验值) # the max time of storage sync a file # default value is 300 seconds # since V2.00 storage_sync_file_max_time = 300 # V3.0引入的参数。是否使用小文件合并存储特性,缺省是关闭的 # if use a trunk file to store several small files # default value is false # since V3.00 use_trunk_file = false # V3.0引入的参数。 # trunk file分配的最小字节数。比如文件只有16个字节,系统也会分配slot_min_size个字节 # the min slot size, should <= 4KB # default value is 256 bytes # since V3.00 slot_min_size = 256 # V3.0引入的参数。 # 只有文件大小<=这个参数值的文件,才会合并存储。如果一个文件的大小大于这个参数值,将直接保存到一个文件中(即不采用合并存储方式)。 # the max slot size, should > slot_min_size # store the upload file to trunk file when it's size <= this value # default value is 16MB # since V3.00 slot_max_size = 16MB # V3.0引入的参数。 # 合并存储的trunk file大小,至少4MB,缺省值是64MB。不建议设置得过大 # the trunk file size, should >= 4MB # default value is 64MB # since V3.00 trunk_file_size = 64MB # 是否提前创建trunk file。只有当这个参数为true,下面3个以trunk_create_file_打头的参数才有效 # if create trunk file advancely # default value is false # since V3.06 trunk_create_file_advance = false # 提前创建trunk file的起始时间点(基准时间),02:00表示第一次创建的时间点是凌晨2点 # the time base to create trunk file # the time format: HH:MM # default value is 02:00 # since V3.06 trunk_create_file_time_base = 02:00 # 创建trunk file的时间间隔,单位为秒。如果每天只提前创建一次,则设置为86400 # the interval of create trunk file, unit: second # default value is 38400 (one day) # since V3.06 trunk_create_file_interval = 86400 # 提前创建trunk file时,需要达到的空闲trunk大小 # 比如本参数为20G,而当前空闲trunk为4GB,那么只需要创建16GB的trunk file即可 # the threshold to create trunk file # when the free trunk file size less than the threshold, will create # the trunk files # default value is 0 # since V3.06 trunk_create_file_space_threshold = 20G # trunk初始化时,是否检查可用空间是否被占用 # if check trunk space occupying when loading trunk free spaces # the occupied spaces will be ignored # default value is false # since V3.09 # NOTICE: set this parameter to true will slow the loading of trunk spaces # when startup. you should set this parameter to true when neccessary. trunk_init_check_occupying = false # 是否无条件从trunk binlog中加载trunk可用空间信息 # FastDFS缺省是从快照文件storage_trunk.dat中加载trunk可用空间, # 该文件的第一行记录的是trunk binlog的offset,然后从binlog的offset开始加载 # if ignore storage_trunk.dat, reload from trunk binlog # default value is false # since V3.10 # set to true once for version upgrade when your version less than V3.10 trunk_init_reload_from_binlog = false # 是否使用server ID作为storage server标识 # if use storage ID instead of IP address # default value is false # since V4.00 use_storage_id = false # use_storage_id 设置为true,才需要设置本参数 # 在文件中设置组名、server ID和对应的IP地址,参见源码目录下的配置示例:conf/storage_ids.conf # specify storage ids filename, can use relative or absolute path # since V4.00 storage_ids_filename = storage_ids.conf #文件名中的id类型,有ip和id两种,只有当use_storage_id设置为true时该参数才有效 # id type of the storage server in the filename, values are: ## ip: the ip address of the storage server ## id: the server id of the storage server # this paramter is valid only when use_storage_id set to true # default value is ip # since V4.03 id_type_in_filename = ip # 存储从文件是否采用symbol link(符号链接)方式 # 如果设置为true,一个从文件将占用两个文件:原始文件及指向它的符号链接 # if store slave file use symbol link # default value is false # since V4.01 store_slave_file_use_link = false # 是否定期轮转error log,目前仅支持一天轮转一次 # if rotate the error log every day # default value is false # since V4.02 rotate_error_log = false # error log定期轮转的时间点,只有当rotate_error_log设置为true时有效 # rotate error log time base, time format: Hour:Minute # Hour from 0 to 23, Minute from 0 to 59 # default value is 00:00 # since V4.02 error_log_rotate_time=00:00 # error log按大小轮转 # 设置为0表示不按文件大小轮转,否则当error log达到该大小,就会轮转到新文件中 # rotate error log when the log file exceeds this size # 0 means never rotates log file by log file size # default value is 0 # since V4.02 rotate_error_log_size = 0 # 是否使用连接池 # if use connection pool # default value is false # since V4.05 use_connection_pool = false # 如果一个连接的空闲时间超过这个值将会被自动关闭 # connections whose the idle time exceeds this time will be closed # unit: second # default value is 3600 # since V4.05 connection_pool_max_idle_time = 3600 # 用于提供http服务的端口 # HTTP port on this tracker server http.server_port=8080 # 检查http server是否还在工作的时间间隔,如果该值小于0则永远不检查 # check storage HTTP server alive interval seconds # <= 0 for never check # default value is 30 http.check_alive_interval=30 # 检查http server是否存活的类型,有tcp和http两种 # tcp方式只有http端口被连接 # http方式检查必须返回状态值200 # check storage HTTP server alive type, values are: # tcp : connect to the storge server with HTTP port only, # do not request and get response # http: storage check alive url must return http status 200 # default value is tcp http.check_alive_type=tcp # check storage HTTP server alive uri/url # NOTE: storage embed HTTP server support uri: /status.html http.check_alive_uri=/status.html</code></pre> <h2>二、storage.conf</h2> <pre> <code># 这个配置文件是否无效,false表示有效 # is this config file disabled # false for enabled # true for disabled disabled=false # 指定 此 storage server 所在组(卷) # the name of the group this storage server belongs to group_name=group1 # 是否绑定IP # bind_addr= 后面为绑定的IP地址 (常用于服务器有多个IP但只希望一个IP提供服务)。如果不填则表示所有的(一般不填就OK) # bind an address of this host # empty for bind all addresses of this host bind_addr= # bind_addr通常是针对server的。当指定bind_addr时,本参数才有效。 # 本storage server作为client连接其他服务器(如tracker server、其他storage server),是否绑定bind_addr。 # if bind an address of this host when connect to other servers # (this storage server as a client) # true for binding the address configed by above parameter: "bind_addr" # false for binding any address of this host client_bind=true # storage server服务端口 # the storage server port port=23000 # 连接超时时间,针对socket套接字函数connect # connect timeout in seconds # default value is 30s connect_timeout=30 # storage server 网络超时时间,单位为秒。发送或接收数据时,如果在超时时间后还不能发送或接收数据,则本次网络通信失败。 # network timeout in seconds # default value is 30s network_timeout=60 # 心跳间隔时间,单位为秒 (这里是指主动向tracker server 发送心跳) # heart beat interval in seconds heart_beat_interval=30 # storage server向tracker server报告磁盘剩余空间的时间间隔,单位为秒 # disk usage report interval in seconds stat_report_interval=60 # base_path 目录地址,根目录必须存在 子目录会自动生成 (注 :这里不是上传的文件存放的地址,之前是的,在某个版本后更改了) # the base path to store data and log files base_path=/home/yuqing/fastdfs # 系统提供服务时的最大连接数 # max concurrent connections the server supported # default value is 256 # more max_connections means more memory will be used max_connections=256 # V2.0引入本参数。设置队列结点的buffer大小。工作队列消耗的内存大小 = buff_size * max_connections # 设置得大一些,系统整体性能会有所提升。 # 消耗的内存请不要超过系统物理内存大小。另外,对于32位系统,请注意使用到的内存不要超过3GB # the buff size to recv / send data # this parameter must more than 8KB # default value is 64KB # since V2.00 buff_size = 256KB # 工作线程的数量,工作线程用于处理网络IO,应当小于max_connections的值 # work thread count, should <= max_connections # work thread deal network io # default value is 4 # since V2.00 work_threads=4 # V2.0引入本参数。磁盘IO读写是否分离,缺省是分离的 # if disk read / write separated ## false for mixed read and write ## true for separated read and write # default value is true # since V2.00 disk_rw_separated = true # V2.0引入本参数。针对单个存储路径的读线程数,缺省值为1。 # 读写分离时,系统中的读线程数 = disk_reader_threads * store_path_count # 读写混合时,系统中的读写线程数 = (disk_reader_threads + disk_writer_threads) * store_path_count # disk reader thread count per store base path # for mixed read / write, this parameter can be 0 # default value is 1 # since V2.00 disk_reader_threads = 1 # V2.0引入本参数。针对单个存储路径的写线程数,缺省值为1。 # 读写分离时,系统中的写线程数 = disk_writer_threads * store_path_count # 读写混合时,系统中的读写线程数 = (disk_reader_threads + disk_writer_threads) * store_path_count # disk writer thread count per store base path # for mixed read / write, this parameter can be 0 # default value is 1 # since V2.00 disk_writer_threads = 1 # 同步文件时,如果从binlog中没有读到要同步的文件,休眠N毫秒后重新读取。0表示不休眠,立即再次尝试读取。 # 出于CPU消耗考虑,不建议设置为0。如何希望同步尽可能快一些,可以将本参数设置得小一些,比如设置为10ms # when no entry to sync, try read binlog again after X milliseconds # must > 0, default value is 200ms sync_wait_msec=50 # 同步上一个文件后,再同步下一个文件的时间间隔,单位为毫秒,0表示不休眠,直接同步下一个文件。 # after sync a file, usleep milliseconds # 0 for sync successively (never call usleep) sync_interval=0 # 下面二个一起解释。允许系统同步的时间段 (默认是全天) 。一般用于避免高峰同步产生一些问题而设定,相信sa都会明白 # storage sync start time of a day, time format: Hour:Minute # Hour from 0 to 23, Minute from 0 to 59 sync_start_time=00:00 # storage sync end time of a day, time format: Hour:Minute # Hour from 0 to 23, Minute from 0 to 59 sync_end_time=23:59 # 同步完N个文件后,把storage的mark文件同步到磁盘 # 注:如果mark文件内容没有变化,则不会同步 # write to the mark file after sync N files # default value is 500 write_mark_file_freq=500 # 存放文件时storage server支持多个路径(例如磁盘)。这里配置存放文件的基路径数目,通常只配一个目录。 # path(disk or mount point) count, default value is 1 store_path_count=1 # 逐一配置store_path个路径,索引号基于0。注意配置方法后面有0,1,2 ......,需要配置0到store_path - 1。 # 如果不配置base_path0,那边它就和base_path对应的路径一样。 # store_path#, based 0, if store_path0 not exists, it's value is base_path # the paths must be exist store_path0=/home/yuqing/fastdfs #store_path1=/home/yuqing/fastdfs2 # FastDFS存储文件时,采用了两级目录。这里配置存放文件的目录个数 (系统的存储机制,大家看看文件存储的目录就知道了) # 如果本参数只为N(如:256),那么storage server在初次运行时,会自动创建 N * N 个存放文件的子目录。 # subdir_count * subdir_count directories will be auto created under each # store_path (disk), value can be 1 to 256, default value is 256 subdir_count_per_path=256 # tracker_server 的列表 要写端口的哦 (再次提醒是主动连接tracker_server ) # 有多个tracker server时,每个tracker server写一行 # tracker_server can ocur more than once, and tracker_server format is # "host:port", host can be hostname or ip address tracker_server=192.168.209.121:22122 # 日志级别 #standard log level as syslog, case insensitive, value list: ### emerg for emergency ### alert ### crit for critical ### error ### warn for warning ### notice ### info ### debug log_level=info # 操作系统运行FastDFS的用户组 (不填 就是当前用户组,哪个启动进程就是哪个) #unix group name to run this program, #not set (empty) means run by the group of current user run_by_group= # 操作系统运行FastDFS的用户 (不填 就是当前用户,哪个启动进程就是哪个) #unix username to run this program, #not set (empty) means run by current user run_by_user= # 允许连接本storage server的IP地址列表 (不包括自带HTTP服务的所有连接) # 可以配置多行,每行都会起作用 # allow_hosts can ocur more than once, host can be hostname or ip address, # "*" means match all ip addresses, can use range like this: 10.0.1.[1-15,20] or # host[01-08,20-25].domain.com, for example: # allow_hosts=10.0.1.[1-15,20] # allow_hosts=host[01-08,20-25].domain.com allow_hosts=* # 文件在data目录下分散存储策略。 # 0: 轮流存放,在一个目录下存储设置的文件数后(参数file_distribute_rotate_count中设置文件数),使用下一个目录进行存储。 # 1: 随机存储,根据文件名对应的hash code来分散存储。 # the mode of the files distributed to the data path # 0: round robin(default) # 1: random, distributted by hash code file_distribute_path_mode=0 # 当上面的参数file_distribute_path_mode配置为0(轮流存放方式)时,本参数有效。 # 当一个目录下的文件存放的文件数达到本参数值时,后续上传的文件存储到下一个目录中。 # valid when file_distribute_to_path is set to 0 (round robin), # when the written file count reaches this number, then rotate to next path # default value is 100 file_distribute_rotate_count=100 # 当写入大文件时,每写入N个字节,调用一次系统函数fsync将内容强行同步到硬盘。0表示从不调用fsync # call fsync to disk when write big file # 0: never call fsync # other: call fsync when written bytes >= this bytes # default value is 0 (never call fsync) fsync_after_written_bytes=0 # 同步或刷新日志信息到硬盘的时间间隔,单位为秒 # 注意:storage server 的日志信息不是时时写硬盘的,而是先写内存。 # sync log buff to disk every interval seconds # must > 0, default value is 10 seconds sync_log_buff_interval=10 # 同步binglog(更新操作日志)到硬盘的时间间隔,单位为秒 # 本参数会影响新上传文件同步延迟时间 # sync binlog buff / cache to disk every interval seconds # default value is 60 seconds sync_binlog_buff_interval=10 # 把storage的stat文件同步到磁盘的时间间隔,单位为秒。 # 注:如果stat文件内容没有变化,不会进行同步 # sync storage stat info to disk every interval seconds # default value is 300 seconds sync_stat_file_interval=300 # 线程栈的大小。FastDFS server端采用了线程方式。 # 对于V1.x,storage server线程栈不应小于512KB;对于V2.0,线程栈大于等于128KB即可。 # 线程栈越大,一个线程占用的系统资源就越多。 # 对于V1.x,如果要启动更多的线程(max_connections),可以适当降低本参数值。 # thread stack size, should >= 512KB # default value is 512KB thread_stack_size=512KB # 本storage server作为源服务器,上传文件的优先级,可以为负数。值越小,优先级越高。这里就和 tracker.conf 中store_server= 2时的配置相对应了 # the priority as a source server for uploading file. # the lower this value, the higher its uploading priority. # default value is 10 upload_priority=10 # 网卡别名前缀,就像Linux中的eth,可以使用ifconfig -a命令来查看 # 多个别名之间使用逗号分隔,如果不设置这个值表示自动的被系统类型设置 # the NIC alias prefix, such as eth in Linux, you can see it by ifconfig -a # multi aliases split by comma. empty value means auto set by OS type # default values is empty if_alias_prefix= # 是否检测上传文件已经存在。如果已经存在,则不存在文件内容,建立一个符号链接以节省磁盘空间。 # 这个应用要配合FastDHT 使用,所以打开前要先安装FastDHT # 1或yes 是检测,0或no 是不检测 # if check file duplicate, when set to true, use FastDHT to store file indexes # 1 or yes: need check # 0 or no: do not check # default value is 0 check_file_duplicate=0 # 文件去重时,文件内容的签名方式: # hash: 4个hash code # md5:MD5 # file signature method for check file duplicate ## hash: four 32 bits hash code ## md5: MD5 signature # default value is hash # since V4.01 file_signature_method=hash # 当上个参数设定为1 或 yes时 (true/on也是可以的) , 在FastDHT中的命名空间 # namespace for storing file indexes (key-value pairs) # this item must be set when check_file_duplicate is true / on key_namespace=FastDFS # 与FastDHT servers 的连接方式 (是否为持久连接) ,默认是0(短连接方式)。可以考虑使用长连接,这要看FastDHT server的连接数是否够用。 # set keep_alive to 1 to enable persistent connection with FastDHT servers # default value is 0 (short connection) keep_alive=0 # 下面是关于FastDHT servers 的设定 需要对FastDHT servers 有所了解,这里只说字面意思了 # 可以通过 #include filename 方式来加载 FastDHT servers 的配置,装上FastDHT就知道该如何配置啦。 # 同样要求 check_file_duplicate=1 时才有用,不然系统会忽略 # fdht_servers.conf 记载的是 FastDHT servers 列表 # you can use "#include filename" (not include double quotes) directive to # load FastDHT server list, when the filename is a relative path such as # pure filename, the base path is the base path of current/this config file. # must set FastDHT server list when check_file_duplicate is true / on # please see INSTALL of FastDHT for detail ##include /home/yuqing/fastdht/conf/fdht_servers.conf # 是否将文件操作记录到access log # if log to access log # default value is false # since V4.00 use_access_log = false # 是否定期轮转access log,目前仅支持一天轮转一次 # if rotate the access log every day # default value is false # since V4.00 rotate_access_log = false # access log定期轮转的时间点,只有当rotate_access_log设置为true时有效 # rotate access log time base, time format: Hour:Minute # Hour from 0 to 23, Minute from 0 to 59 # default value is 00:00 # since V4.00 access_log_rotate_time=00:00 # 是否定期轮转error log,目前仅支持一天轮转一次 # if rotate the error log every day # default value is false # since V4.02 rotate_error_log = false # error log定期轮转的时间点,只有当rotate_error_log设置为true时有效 # rotate error log time base, time format: Hour:Minute # Hour from 0 to 23, Minute from 0 to 59 # default value is 00:00 # since V4.02 error_log_rotate_time=00:00 # access log按文件大小轮转 # 设置为0表示不按文件大小轮转,否则当access log达到该大小,就会轮转到新文件中 # rotate access log when the log file exceeds this size # 0 means never rotates log file by log file size # default value is 0 # since V4.02 rotate_access_log_size = 0 # error log按文件大小轮转 # 设置为0表示不按文件大小轮转,否则当error log达到该大小,就会轮转到新文件中 # rotate error log when the log file exceeds this size # 0 means never rotates log file by log file size # default value is 0 # since V4.02 rotate_error_log_size = 0 # 文件同步的时候,是否忽略无效的binlog记录 # if skip the invalid record when sync file # default value is false # since V4.02 file_sync_skip_invalid_record=false # 是否使用连接池 # if use connection pool # default value is false # since V4.05 use_connection_pool = false # 如果一个连接的空闲时间超过这个值将会被自动关闭 # connections whose the idle time exceeds this time will be closed # unit: second # default value is 3600 # since V4.05 connection_pool_max_idle_time = 3600 # storage server上web server域名,通常仅针对单独部署的web server。这样URL中就可以通过域名方式来访问storage server上的文件了, # 这个参数为空就是IP地址的方式。 # use the ip address of this storage server if domain_name is empty, # else this domain name will ocur in the url redirected by the tracker server http.domain_name= # web server的端口 # the port of the web server on this storage server http.server_port=8888</code></pre> <h2>三、client.conf</h2> <pre> <code># 连接超时时间,针对socket套接字函数connect # connect timeout in seconds # default value is 30s connect_timeout=30 # client的网络超时,单位为秒。发送或接收数据时,如果在超时时间后还不能发送或接收数据,则本次网络通信失败 # network timeout in seconds # default value is 30s network_timeout=60 # 存储日志的根目录 # the base path to store log files base_path=/home/yuqing/fastdfs # tracker_server 的列表 要写端口 # tracker_server can ocur more than once, and tracker_server format is # "host:port", host can be hostname or ip address tracker_server=192.168.0.197:22122 # 日志的级别 #standard log level as syslog, case insensitive, value list: ### emerg for emergency ### alert ### crit for critical ### error ### warn for warning ### notice ### info ### debug log_level=info # 是否使用连接池 # if use connection pool # default value is false # since V4.05 use_connection_pool = false # 如果一个连接的空闲时间超过这个值将会被自动关闭 # connections whose the idle time exceeds this time will be closed # unit: second # default value is 3600 # since V4.05 connection_pool_max_idle_time = 3600 # 是否从FastDFS的tracker server加载参数 # if load FastDFS parameters from tracker server # since V4.05 # default value is false load_fdfs_parameters_from_tracker=false 是否使用storage ID 代替IP,只有当load_fdfs_parameters_from_tracker为false时才有效 # if use storage ID instead of IP address # same as tracker.conf # valid only when load_fdfs_parameters_from_tracker is false # default value is false # since V4.05 use_storage_id = false # 指定storage_ids的路径,可以使用绝对路径和相对路径,只有当load_fdfs_parameters_from_tracker为false时才有效 # specify storage ids filename, can use relative or absolute path # same as tracker.conf # valid only when load_fdfs_parameters_from_tracker is false # since V4.05 storage_ids_filename = storage_ids.conf #tracker server的http端口 #HTTP settings http.tracker_server_port=8080 #use "#include" directive to include HTTP other settiongs ##include http.conf</code></pre>
  • centos6.8 yum安装和配置ftp server(vsftpd)客服端

    centos6.8 yum安装和配置ftp server(vsftpd)客服端以及ftp常见问题解决,vsftpd################################ FTP Server ##########################<br /> centos6.8 yum安装和配置ftp server(vsftpd)<br /> 安装前提<br /> <strong>1.root用户<br /> 2.主机联网</strong><br /> 安装命令: <pre> <code class="language-bash"> yum install vsftpd</code></pre> <br /> 安装过程:<br /> <br /> <img alt="安装过程" class="img-thumbnail" src="/resources/assist/images/blog/2a19add45c0746c59ced57324b655948.png" /><br /> <br /> 查看是否安装成功<br />   <pre> <code>[root@VM_xx_xx_centos ~]# rpm -qa | grep vsftpd vsftpd-2.2.2-21.el6.x86_64</code></pre> <br /> 如果查询出来有vsftpd-版本号说明已经安装成功。<br /> <br /> 查看yum安装的配置信息: <pre> <code>[root@VM_xx_xx_centos ~]# whereis vsftpd vsftpd: /usr/sbin/vsftpd /etc/vsftpd /usr/share/man/man8/vsftpd.8.gz</code></pre> <br /> 安装的配置目录基本这里就三个: <pre> <code>/usr/sbin/vsftpd /etc/vsftpd ​​​​​​​/usr/share/man/man8/vsftpd.8.gz</code></pre> <br /> 很明显,核显配置文件sftpd.conf在/etc/vsftpd中<br /> 切换目录,修改配置.<br /> <span style="color:#e74c3c">注意修改前最好先备份一个原有的,纯属个人习惯</span><br /> sftp.conf常用配置信息说明 <pre> <code> # 允许本地用户登录 local_enable=YES # 本地用户的写权限 write_enable=YES # 使用FTP的本地文件权限,默认为077 # 一般设置为022 local_umask=022 # 切换目录时 # 是否显示目录下.message的内容 dirmessage_enable=YES dirlist_enable = NO #验证方式 #pam_service_name=vsftpd # 启用FTP数据端口的数据连接 connect_from_port_20=YES # 以独立的FTP服务运行 listen=yes # 修改连接端口 #listen_port=2121 ######### 匿名登录设置 ########### # 允许匿名登录 anonymous_enable=NO # 如果允许匿名登录 # 是否开启匿名上传权限 #anon_upload_enable=YES # 如果允许匿名登录 # 是否允许匿名建立文件夹并在文件夹内上传文件 #anon_mkdir_write_enable=YES # 如果允许匿名登录 # 匿名帐号可以有删除的权限 #anon_other_write_enable=yes # 如果允许匿名登录 # 匿名的下载权限 # 匿名为Other,可设置目录/文件属性控制 #anon_world_readable_only=no # 如果允许匿名登录 # 限制匿名用户传输速率,单位bite #anon_max_rate=30000 ######### 用户限制设置 ########### #### 限制登录 # 用userlist来限制用户访问 #userlist_enable=yes # 名单中的人不允许访问 #userlist_deny=no # 限制名单文件放置的路径 #userlist_file=/etc/vsftpd/userlist_deny.chroot #### 限制目录 # 限制所有用户都在家目录 #chroot_local_user=yes # 调用限制在家目录的用户名单 chroot_list_enable=YES # 限制在家目录的用户名单所在路径 chroot_list_file=/etc/vsftpd/chroot_list ######### 日志设置 ########### # 日志文件路径设置 xferlog_file=/var/log/vsftpd.log # 激活上传/下载的日志 xferlog_enable=YES # 使用标准的日志格式 #xferlog_std_format=YES ######### 安全设置 ########### # 用户空闲超时,单位秒 #idle_session_timeout=600 # 数据连接空闲超时,单位秒 #data_connection_timeout=120 # 将客户端空闲1分钟后断开 #accept_timeout=60 # 中断1分钟后重新连接 #connect_timeout=60 # 本地用户传输速率,单位bite #local_max_rate=50000 # FTP的最大连接数 #max_clients=200 # 每IP的最大连接数 #max_per_ip=5 ######### 被动模式设置 ########### # 是否开户被动模式 pasv_enable=yes # 被动模式最小端口 pasv_min_port=5000 # 被动模式最大端口 pasv_max_port=6000 ######### 其他设置 ########### # 欢迎信息 ftpd_banner=Welcome to Ftp Server!</code></pre> <br /> 添加ftp防火墙规则,一般用于安全策略 <pre> <code> /sbin/iptables -I INPUT -p tcp --dport 21 -j ACCEPT /etc/rc.d/init.d/iptables save /etc/init.d/iptables restart</code></pre> <br /> 常用启动重启停止ftp命令: <pre> <code>#启动 service vsftpd start #停止 service vsftpd stop #重启 service vsftpd restart #查看运行状态 service vsftpd status</code></pre> <br /> ftp server 分两种模式<br /> 主动模式配置 <pre> <code>#主动模式 #开启主动模式 port_enable=YES #当主动模式开启的时候 是否启用默认的20端口监听 connect_from_port_20=YES #上一选项使用NO参数是 指定数据传输端口 ftp_date_port=%portnumber%</code></pre> 被动模式配置 <pre> <code>#开启被动模式 pasv_enable=YES #被动模式最低端口 pasv_min_port=5100 #被动模式最高端口 pasv_max_port=5200</code></pre> <br /> 推荐使用被动模式<br /> <br /> <span style="color:#ff0000"><strong>注意:配置文件配置内容后面不允许有空格,所以最好注释写上面配置内容后无任何东西,否则会莫名奇妙报错</strong></span><br /> <br /> ################################ FTP Client ##########################<br /> 安装命令 <pre> <code>yum install ftp</code></pre> <br /> 安装过程<br /> <img alt="client" class="img-thumbnail" src="/resources/assist/images/blog/f54420cbd14f477282a1ecb09260402a.jpg" /><br /> <br /> 安装完成后执行ftp就可以进入ftp客服端<br /> <img alt="client" class="img-thumbnail" src="/resources/assist/images/blog/22b4ae19a1af4f62aec556baa0d514e7.jpg" /><br /> <br /> ################################ 常见问题 QA ################################<br /> 227 Entering Passive Mode<br /> 200 PORT command successful. Consider using PASV.<br /> 解决:<br /> 服务端配置文件中添加或修改以下内容,核心内容是最后一个pasv_address该参数必须绑定<br /> #sv_enable=YES<br /> #被动模式最低端口<br /> pasv_min_port=3100<br /> #被动模式最高端口<br /> pasv_max_port=3200<br /> <strong><span style="color:#cc0000">pasv_address=123.206.71.187(必须项,你自己主机的IP地址)</span></strong><br />   <p>227 Entering Passive Mode<br /> 解决:</p> <pre> <code>ftp> passive Passive mode on.</code></pre> <br /> <p> </p>