这篇博客主要就铺代码吧,Mina的一些基础知识可以参考:

http://www.cnblogs.com/huangfox/p/3458272.html

场景假设:

1.客户端发送用户信息,服务端根据用户名查询用户年龄。(模拟查询)

2.同步请求

3.协议:直接采用字段类型编码解码。


具体代码结构:

codec负责编码解码,TCPAcceptor服务端,TCPConnector客户端,User业务对象。


User

package com.fox.mina.base.c2;

/**
* @author huangfox
* @date 2013年12月3日 上午11:23:55
*
*/
public class User {
String name;
int age; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} @Override
public String toString() {
return "User [name=" + name + ", age=" + age + "]";
} }

  

编码、解码工厂

DefaultMinaCodecFactory

package com.fox.mina.base.c2.codec;

import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolEncoder; /**
* @author huangfox
* @date 2013年12月5日 下午7:48:47
*
*/
public class DefaultMinaCodecFactory implements ProtocolCodecFactory {
ProtocolEncoder encoder;
ProtocolDecoder decoder; public DefaultMinaCodecFactory() { } public DefaultMinaCodecFactory(ProtocolEncoder encoder,
ProtocolDecoder decoder) {
super();
this.encoder = encoder;
this.decoder = decoder;
} @Override
public ProtocolEncoder getEncoder(IoSession session) throws Exception {
// TODO Auto-generated method stub
return encoder;
} @Override
public ProtocolDecoder getDecoder(IoSession session) throws Exception {
// TODO Auto-generated method stub
return decoder;
} public ProtocolEncoder getEncoder() {
return encoder;
} public void setEncoder(ProtocolEncoder encoder) {
this.encoder = encoder;
} public ProtocolDecoder getDecoder() {
return decoder;
} public void setDecoder(ProtocolDecoder decoder) {
this.decoder = decoder;
} }

  

编码器

FEncode

package com.fox.mina.base.c2.codec;

import org.apache.commons.lang.ArrayUtils;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
import org.apache.mina.filter.codec.ProtocolEncoderOutput; import com.fox.mina.base.c2.User; /**
* @author huangfox
* @date 2013年12月5日 下午7:49:21
*
*/
public class FEncoder extends ProtocolEncoderAdapter {
public static final NumberCodec numberCodec = DefaultNumberCodecs
.getBigEndianNumberCodec(); @Override
public void encode(IoSession session, Object message,
ProtocolEncoderOutput out) throws Exception {
byte[] bytes = null;
if (message instanceof User) {
User user = (User) message;
byte[] name = user.getName().getBytes();
bytes = ArrayUtils.addAll(bytes,
numberCodec.int2Bytes(name.length, 4));
bytes = ArrayUtils.addAll(bytes, name);
bytes = ArrayUtils.addAll(bytes,
numberCodec.int2Bytes(user.getAge(), 4));
out.write(IoBuffer.wrap(bytes));
} else {
System.out.println("encoder error!");
} } }

编码的协议:

用户姓名的长度(int 4字节)

用户年龄(int 4字节)

用户姓名(byte[])

解码器

FDecode

package com.fox.mina.base.c2.codec;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput; import com.fox.mina.base.c2.User; /**
* @author huangfox
* @date 2013年12月3日 上午11:35:46
*
*/
public class FDecoder extends CumulativeProtocolDecoder {
public static final NumberCodec numberCodec = DefaultNumberCodecs
.getBigEndianNumberCodec(); @Override
protected boolean doDecode(IoSession session, IoBuffer in,
ProtocolDecoderOutput out) throws Exception {
int len = 0;
Object lenAttr = session.getAttribute("len");
if (lenAttr == null) {
if (in.remaining() < 4) {
return false;
}
byte[] buffer = new byte[4];
in.get(buffer);
len = numberCodec.bytes2Int(buffer, 4);
session.setAttribute("len", len);
} else {
len = (Integer) lenAttr;
}
//
String name = "";
Object nameAttr = session.getAttribute("name");
if (nameAttr == null) {
if (in.remaining() < len) {
return false;
}
byte[] buffer = new byte[len];
in.get(buffer);
name = new String(buffer);
session.setAttribute("name", name);
} else {
name = (String) nameAttr;
}
if (in.remaining() < 4) {
return false;
}
byte[] buffer = new byte[4];
in.get(buffer);
int age = numberCodec.bytes2Int(buffer, 4);
User u = new User();
u.setName(name);
u.setAge(age);
//
out.write(u);
//
session.removeAttribute("len");
session.removeAttribute("name"); return true;
} }

编码、解码使用的工具类:

package com.fox.mina.base.c2.codec;

public interface NumberCodec {
String convertCharset(String charset); byte[] short2Bytes(short value, int byteLength); byte[] int2Bytes(int value, int byteLength); byte[] long2Bytes(long value, int byteLength); byte[] float2Bytes(float value, int byteLength); byte[] double2Bytes(double value, int byteLength); short bytes2Short(byte[] bytes, int byteLength); int bytes2Int(byte[] bytes, int byteLength); long bytes2Long(byte[] bytes, int byteLength); float bytes2Float(byte[] bytes, int byteLength); double bytes2Double(byte[] bytes, int byteLength);
}

  

package com.fox.mina.base.c2.codec;

public class DefaultNumberCodecs {

	private static int b2ui(byte b) {
return (int) (b + 256) % 256;
} private static long b2ul(byte b) {
return (long) (b + 256) % 256;
} private static NumberCodec littleEndianCodec = new NumberCodec() { public int bytes2Int(byte[] bytes, int byteLength) {
int value = 0;
for (int i = 0; i < byteLength; i++) {
value |= b2ui(bytes[i]) << (i * 8);
}
return value;
} public long bytes2Long(byte[] bytes, int byteLength) {
long value = 0;
for (int i = 0; i < byteLength; i++) {
value |= b2ul(bytes[i]) << (i * 8);
} return value;
} public short bytes2Short(byte[] bytes, int byteLength) {
short value = 0;
for (int i = 0; i < byteLength; i++) {
value |= b2ui(bytes[i]) << (i * 8);
} return value;
} @Override
public float bytes2Float(byte[] bytes, int byteLength) {
int value = 0;
for (int i = 0; i < byteLength; i++) {
value |= b2ui(bytes[i]) << (i * 8);
}
return Float.intBitsToFloat(value);
} @Override
public double bytes2Double(byte[] bytes, int byteLength) {
long value = 0;
for (int i = 0; i < byteLength; i++) {
value |= b2ul(bytes[i]) << (i * 8);
}
return Double.longBitsToDouble(value);
} public byte[] int2Bytes(int value, int byteLength) {
byte[] bytes = new byte[byteLength]; for (int i = 0; i < byteLength; i++) {
int shiftCount = i * 8;
bytes[i] = (byte) ((value & (0x000000ff << shiftCount)) >> shiftCount);
}
return bytes;
} public byte[] long2Bytes(long value, int byteLength) {
byte[] bytes = new byte[byteLength]; for (int i = 0; i < byteLength; i++) {
int shiftCount = i * 8;
bytes[i] = (byte) ((value & (0x00000000000000ffL << shiftCount)) >> shiftCount);
}
return bytes;
} public byte[] short2Bytes(short value, int byteLength) {
byte[] bytes = new byte[byteLength]; for (int i = 0; i < byteLength; i++) {
int shiftCount = i * 8;
bytes[i] = (byte) ((value & (0x00ff << shiftCount)) >> shiftCount);
}
return bytes;
} @Override
public byte[] float2Bytes(float value, int byteLength) {
byte[] bytes = new byte[byteLength]; // parse the bits that represent the floating-point number
// floatToRawIntBits gives the raw float bits without normalization
// using floatToRawIntBits is over 5 times as fast as
// floatToIntBits.
int x = Float.floatToRawIntBits(value);
for (int i = 0; i < byteLength; i++) {
int shiftCount = i * 8;
bytes[i] = (byte) ((x & (0x000000ff << shiftCount)) >> shiftCount);
}
return bytes;
} @Override
public byte[] double2Bytes(double value, int byteLength) {
byte[] bytes = new byte[byteLength]; // parse the the bits that represent the floating-point number
long x = Double.doubleToRawLongBits(value);
for (int i = 0; i < byteLength; i++) {
int shiftCount = i * 8;
bytes[i] = (byte) ((x & (0x00000000000000ffL << shiftCount)) >> shiftCount);
}
return bytes;
} public String convertCharset(String charset) {
if (charset.equals("UTF-16")) {
return "UTF-16LE";
} else {
return charset;
}
} }; private static NumberCodec bigEndianCodec = new NumberCodec() { public int bytes2Int(byte[] bytes, int byteLength) {
int value = 0;
for (int i = 0; i < byteLength; i++) {
value |= b2ui(bytes[i]) << ((byteLength - 1 - i) * 8);
}
return value;
} public long bytes2Long(byte[] bytes, int byteLength) {
long value = 0;
for (int i = 0; i < byteLength; i++) {
value |= b2ul(bytes[i]) << ((byteLength - 1 - i) * 8);
} return value;
} public short bytes2Short(byte[] bytes, int byteLength) {
short value = 0;
for (int i = 0; i < byteLength; i++) {
value |= b2ui(bytes[i]) << ((byteLength - 1 - i) * 8);
} return value;
} @Override
public float bytes2Float(byte[] bytes, int byteLength) {
int value = 0;
for (int i = 0; i < byteLength; i++) {
value |= b2ui(bytes[i]) << ((byteLength - 1 - i) * 8);
}
return Float.intBitsToFloat(value);
} @Override
public double bytes2Double(byte[] bytes, int byteLength) {
long value = 0;
for (int i = 0; i < byteLength; i++) {
value |= b2ul(bytes[i]) << ((byteLength - 1 - i) * 8);
}
return Double.longBitsToDouble(value);
} public byte[] int2Bytes(int value, int byteLength) {
byte[] bytes = new byte[byteLength]; for (int i = 0; i < byteLength; i++) {
int shiftCount = ((byteLength - 1 - i) * 8);
bytes[i] = (byte) ((value & (0x000000ff << shiftCount)) >> shiftCount);
}
return bytes;
} public byte[] long2Bytes(long value, int byteLength) {
byte[] bytes = new byte[byteLength]; for (int i = 0; i < byteLength; i++) {
int shiftCount = ((byteLength - 1 - i) * 8);
bytes[i] = (byte) ((value & (0x00000000000000ffL << shiftCount)) >> shiftCount);
}
return bytes;
} public byte[] short2Bytes(short value, int byteLength) {
byte[] bytes = new byte[byteLength]; for (int i = 0; i < byteLength; i++) {
int shiftCount = ((byteLength - 1 - i) * 8);
bytes[i] = (byte) ((value & (0x00ff << shiftCount)) >> shiftCount);
}
return bytes;
} @Override
public byte[] float2Bytes(float value, int byteLength) {
byte[] bytes = new byte[byteLength]; // parse the bits that represent the floating-point number
// floatToRawIntBits gives the raw float bits without normalization
// using floatToRawIntBits is over 5 times as fast as
// floatToIntBits.
int x = Float.floatToRawIntBits(value);
for (int i = 0; i < byteLength; i++) {
int shiftCount = ((byteLength - 1 - i) * 8);
bytes[i] = (byte) ((x & (0x000000ffL << shiftCount)) >> shiftCount);
}
return bytes;
} @Override
public byte[] double2Bytes(double value, int byteLength) {
byte[] bytes = new byte[byteLength]; // parse the the bits that represent the floating-point number
long x = Double.doubleToRawLongBits(value);
for (int i = 0; i < byteLength; i++) {
int shiftCount = ((byteLength - 1 - i) * 8);
bytes[i] = (byte) ((x & (0x00000000000000ffL << shiftCount)) >> shiftCount);
}
return bytes;
} public String convertCharset(String charset) {
if (charset.equals("UTF-16")) {
return "UTF-16BE";
} else {
return charset;
}
} }; public static NumberCodec getBigEndianNumberCodec() {
return bigEndianCodec;
} public static NumberCodec getLittleEndianNumberCodec() {
return littleEndianCodec;
}
}

  

服务端

TCPAcceptor

package com.fox.mina.base.c2;

import java.io.IOException;
import java.net.InetSocketAddress; import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.core.session.IoSessionConfig;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor; import com.fox.mina.base.c2.codec.DefaultMinaCodecFactory;
import com.fox.mina.base.c2.codec.FDecoder;
import com.fox.mina.base.c2.codec.FEncoder; /**
* @author huangfox
* @date 2013年12月3日 上午11:15:53
*
*/
public class TCPAcceptor {
IoAcceptor acceptor = null;
String addr = "127.0.0.1";
int port = 9999; public TCPAcceptor() { } public void start() {
acceptor = new NioSocketAcceptor();
//
IoSessionConfig sessionConf = acceptor.getSessionConfig();
sessionConf.setReadBufferSize(2048);
// filter chain(codec)
acceptor.getFilterChain().addLast(
"codec",
new ProtocolCodecFilter(new DefaultMinaCodecFactory(
new FEncoder(), new FDecoder())));
// handler
acceptor.setHandler(new IOHandler());
//
try {// 可做重连
acceptor.bind(new InetSocketAddress(addr, port));
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("server stated ... ");
} private class IOHandler extends IoHandlerAdapter { @Override
public void messageReceived(IoSession session, Object message)
throws Exception {
User u = (User) message;
System.out.println("[server]" + u.toString());
//模拟业务处理
u.setAge(u.hashCode()%100);
// send msg to client
session.write(u);
} } public static void main(String[] args) {
TCPAcceptor server = new TCPAcceptor();
server.start();
} }

  

客户端

TCPConnector

package com.fox.mina.base.c2;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.util.Random; import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.future.ReadFuture;
import org.apache.mina.core.future.WriteFuture;
import org.apache.mina.core.service.IoConnector;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector; import com.fox.mina.base.c2.codec.DefaultMinaCodecFactory;
import com.fox.mina.base.c2.codec.FDecoder;
import com.fox.mina.base.c2.codec.FEncoder; /**
* @author huangfox
* @date 2013年12月3日 上午11:15:46
*
*/
public class TCPConnector {
IoConnector connector = null;
IoSession session = null;
String ip = "127.0.0.1";
int port = 9999; public TCPConnector() {
connector = new NioSocketConnector();
connector.getSessionConfig().setUseReadOperation(true);
connector.getFilterChain().addLast(
"codec",
new ProtocolCodecFilter(new DefaultMinaCodecFactory(
new FEncoder(), new FDecoder())));
connector.setHandler(new IOHander());
ConnectFuture connectF = connector.connect(new InetSocketAddress(ip,
port));
connectF.awaitUninterruptibly();
session = connectF.getSession();
} Random r = new Random(); public void sendMsg(User u) {
WriteFuture writeF = session.write(u);
writeF.awaitUninterruptibly();
if (writeF.getException() != null) {
System.out.println(writeF.getException().getMessage());
} else if (writeF.isWritten()) {
System.out.println("msg was sent!");
// 发送、接受
ReadFuture readF = session.read();
readF.awaitUninterruptibly(1000);
if (readF.getException() != null) {
System.out.println(readF.getException().getMessage());
} else {
System.out.println("[client]"+readF.getMessage().toString());
}
} else {
System.out.println("error!");
}
} public void close() {
this.connector.dispose();
} private class IOHander extends IoHandlerAdapter { } public static void main(String[] args) {
TCPConnector client = new TCPConnector();
while (true) {
BufferedReader r = new BufferedReader(new InputStreamReader(
System.in));
try {
System.out.println("输入:");
String msg = r.readLine();
User u = new User();
u.setName(msg);
client.sendMsg(u);
} catch (IOException e) {
e.printStackTrace();
} }
} }

注意:以上代码在多线程环境下是有问题的!!!  

(最大字体的提示了!)

在TcpConnector中,只有一个session,如果多线程同时对这个session进行读写操作将发生问题(B可能拿到A的响应结果)。

最简单的处理方式就是,加入一个连接池,在sendMsg方法中先获取一个连接,用完以后再归还到连接池。可以理解为“一个线程独占一个连接”。

代码如下:

package com.fox.mina.base.c2;

import java.net.InetSocketAddress;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit; import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.future.ReadFuture;
import org.apache.mina.core.future.WriteFuture;
import org.apache.mina.core.service.IoConnector;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector; import com.fox.mina.base.c2.codec.DefaultMinaCodecFactory;
import com.fox.mina.base.c2.codec.FDecoder;
import com.fox.mina.base.c2.codec.FEncoder; /**
* @author huangfox
* @date 2013年12月3日 上午11:15:46
*
*/
public class TCPConnector {
IoConnector connector = null;
// IoSession session = null;
String ip = "127.0.0.1";
int port = 9999;
int poolSize = 1;
LinkedBlockingQueue<IoSession> pool; public TCPConnector() {
connector = new NioSocketConnector(10);
connector.getSessionConfig().setUseReadOperation(true);
connector.getFilterChain().addLast(
"codec",
new ProtocolCodecFilter(new DefaultMinaCodecFactory(
new FEncoder(), new FDecoder())));
connector.setHandler(new IOHander());
// pool
pool = new LinkedBlockingQueue<IoSession>(poolSize);
for (int i = 0; i < poolSize; i++) {
ConnectFuture connectF = connector.connect(new InetSocketAddress(
ip, port));
connectF.awaitUninterruptibly();
IoSession session = connectF.getSession();
try {
pool.put(session);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} Random r = new Random(); public void sendMsg(User u) {
IoSession session = null;
try {
session = pool.take();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (session == null)
return;
try {
WriteFuture writeF = session.write(u);
writeF.awaitUninterruptibly();
if (writeF.getException() != null) {
System.out.println(writeF.getException().getMessage());
} else if (writeF.isWritten()) {
// System.out.println("msg was sent!");
// 发送、接受
ReadFuture readF = session.read();
readF.awaitUninterruptibly();
if (readF.getException() != null) {
System.out.println(readF.getException().getMessage());
} else {
Date d = new Date(System.currentTimeMillis());
// System.out.println(Thread.currentThread().getId() + "-"
// + d.getSeconds() + "-" + session.hashCode());
// System.out.println("[client]"
// + readF.getMessage().toString());
}
} else {
System.out.println("error!");
}
} finally {
try {
pool.put(session);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} public void close() {
this.connector.dispose();
} private class IOHander extends IoHandlerAdapter { } }

  


扩展:

1.加入连接池(见上文)

2.加入连接、读写超时

Mina - 模拟同步请求的更多相关文章

  1. axios 模拟同步请求

    axios本身没有同步请求,但是我们很多情况下必须得需要同步请求.那么应该怎么做? 上网查了一些资料有人说用es6的 async +  assert 我不知道有没有效果,因为我的功能中是没啥效果的. ...

  2. 网络处理2-异步POST请求和同步请求

    一.异步POST请求 假如请求路径是http://192.168.1.102:8080/MJServer/login,请求参数有2个: username :母鸡 pwd :123 1.POST请求细节 ...

  3. JSON(五)——同步请求中使用JSON格式字符串进行交互(不太常见的用法)

    在同步请求中使用JSON格式进行数据交互的场景并不多,同步请求是浏览器直接与服务器进行数据交互的大多是用jsp的标签jstl和el表达式对请求中的数据进行数据的渲染.我也是在一次开发中要从其它服务器提 ...

  4. C#模拟httpwebrequest请求_向服务器模拟cookie发送

    使用C#代码模拟web请求,是一种常用的方法,以前没专门整理过,这里暂时贴上自己整理的完整代码,以后再做梳理: public class MyRequest { #region 辅助方法 public ...

  5. 使用httpClient模拟http请求

    在很多场景下都需要用到java代码来发送http请求:如和短信后台接口的数据发送,发送数据到微信后台接口中: 这里以apache下的httpClient类来模拟http请求:以get和Post请求为例 ...

  6. js_html_input中autocomplete="off"在chrom中失效的解决办法 使用JS模拟锚点跳转 js如何获取url参数 C#模拟httpwebrequest请求_向服务器模拟cookie发送 实习期学到的技术(一) LinqPad的变量比较功能 ASP.NET EF 使用LinqPad 快速学习Linq

    js_html_input中autocomplete="off"在chrom中失效的解决办法 分享网上的2种办法: 1-可以在不需要默认填写的input框中设置 autocompl ...

  7. c# 模拟并发请求 ,只能并发2个连接。

    使用 HttpWebRequest 模拟并发请求的时候,发现不管怎么提高thread 的数量,都没用,服务器端用计数器看到的都是2个连接,见下图(关于计数器怎么开,百度) 然后搜了一下,发现需要在ap ...

  8. ASP模拟POST请求异步提交数据的方法

    这篇文章主要介绍了ASP模拟POST请求异步提交数据的方法,本文使用MSXML2.SERVERXMLHTTP.3.0实现POST请求,需要的朋友可以参考下 有时需要获取远程网站的某些信息,而服务器又限 ...

  9. java模拟post请求发送json

    java模拟post请求发送json,用两种方式实现,第一种是HttpURLConnection发送post请求,第二种是使用httpclient模拟post请求, 方法一: package main ...

随机推荐

  1. HDU - 5157 :Harry and magic string (回文树,求多少对不相交的回文串)

    Sample Input aca aaaa Sample Output 3 15 题意: 多组输入,每次给定字符串S(|S|<1e5),求多少对不相交的回文串. 思路:可以用回文树求出以每个位置 ...

  2. linux最常用的20个命令

    玩过Linux的人都会知道,Linux中的命令的确是非常多,但是玩过Linux的人也从来不会因为Linux的命令如此之多而烦恼,因为我们只需要掌握我们最常用的命令就可以了.当然你也可以在使用时去找一下 ...

  3. java sftp 报错 Permission denied (没有权限;拒绝访问)

    解决办法: 1.检查账号密码是否错误 2.检查freeSSHD是否是以管理员身份运行的 3.检查sftp路劲有没有配置错误,java通过sftp将图片文件传输到指定文件夹,如果这个文件夹在配置的当前目 ...

  4. 你不能阻止DOM

    浏览器数据库景观 对于外行来说,浏览器数据库的世界可能是一个令人困惑的世界.Lawnchair,PouchDB,LocalForage,Dexie,Lovefield,LokiJS,AlaSQL,Ma ...

  5. Blender简单动画:一个小球从一座山上滚下.

    简单动画:一个小球从一座山上滚下.注:[key]方括号内是快捷键; {大括号}内是模式,页签名称或选项等. ==== 1. 建模:    == 1.1 山[shift A] 建立平面plane,可以大 ...

  6. php基础-5

     php的面相对象 <?php class Hello { public function say_hello() { echo "hello"; } } $say = ne ...

  7. Linux配置浮动IP

    在高可用集群环境中,一般都需要使用浮动IP来实现web高可用(High Availability). 浮动IP的概念以及为什么需要浮动IP请参考:https://blog.csdn.net/readi ...

  8. centos7安装部署mysql5.7服务器

    因为自带源没有最新版的mysql,所以我们需要自己下载rpm包,先下载下面的rpm包源 https://repo.mysql.com//mysql57-community-release-el7-11 ...

  9. Nginx配置基于ip的虚拟主机

    我是在centos7虚拟机上进行实验的 该实验基于添加好ip的基础上,如何给网卡添加ip请查阅我的博客 先来看一下我的ip [root@localhost nginx]# ifconfig ens33 ...

  10. 数学 它的内容,方法和意义 第三卷 (A. D. 亚历山大洛夫 著)

    第十五章 实变数函数论 1. 绪论 2. 集合论 3. 实数 4. 点集 5. 集合的测度 6. 勒贝格积分 第十六章 线性代数 1. 线性代数的对象和它的工具 2. 线性空间 3. 线性方程组 4. ...