为什么多线程的文件服务器的效率好于单进程文件服务器

为什么多线程的文件服务器的效率好于单进程文件服务器,第1张

Windows XP可以通过文件共享为局域网中其他计算机提供文件服务,因此小型网络中经常在充当文件服务器的计算机上安装Windows XP系统而没有部署专门的Windows Server。当网络规模较小时一般也不会有什么差别,但当网络中的计算机数量很大时,有时会出现文件服务器上System进程CPU占用率很高的现象,甚至导致系统完全没有响应。

这种现象是由于Windows XP系统本身不是作为服务器系统设计的,如果网络规模比较大,最好还是选择使用专用的服务器系统(Windows 20003 Server或Windows 2000 Server)。

该问题在百度上的搜索结果给出了以下解释:

当安装了Windows XP的计算机做服务器的时候,收到端口 445 上的连接请求时,它将分配内存和少量地调配CPU资源来为这些连接提供服务。当负荷过重的时候,CPU占用率可能过高,这是因为在工作项的数目和响应能力之间存在固有的权衡关系。你要确定合适的 MaxWorkItems 设置以提高系统响应能力。如果设置的值不正确,服务器的响应能力可能会受到影响,或者某个用户独占太多系统资源。

Microsoft在知识库“You cannot configure the maximum number of concurrent SMB requests that are sent to the Server service in Windows XP”中讲解了这个问题,并且在HotFix186383中提供了lanmanserver参数MaxMpxCt和MaxWorkItems的调整办法。HotFix186383已经包含在Windows XP Service Pack 3中。 如果你没有安装SP3,你必须手工安装HotFix186383才能调整这些参数。

HotFix186383允许用户将Windows XPSMB连接数最大调整为255,而Windows XP的默认值为10。如果是Windows 2003 Server,这个最大连接数可以是65535。因此,Windows XP作为文件服务器无论怎样调整参数都不能替代Windows Server。本文绘出的方法只作为临时性解决方案。

lanmanserver参数的调整方法:

警告:以下操作需要修改注册表,修改注册表有风险,你应该在修改注册表前先备份。有关注册表的备份和还原请参考Microsoft知识库“如何在 Windows XP 和 Windows Server 2003 中备份、编辑和还原注册表”

注册表位置:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Lanmanserver\Parameters

新建DWORD值MaxMpxCt,值可以介于10~255之间(十进制)。

新建DWORD值MaxWorkItems,值至少是MaxMpxCt的4倍。如果MaxMpxCt为255,则MaxWorkItems取1024。

如果网络性能还是不理想,可以将Size值改为3。

什么原因造成服务器负载过重呢?Microsoft在知识库“How to troubleshoot Event ID 2021 and Event ID 2022”中分析了可能的原因,大致有以下的可能:

1.反病毒软件

现在的反病毒软件一般都采用实时监控文件系统的方式,因此会造成网络访问时的资源消耗数倍增加,尤其是那些扫描速度慢、感觉比较“卡”的杀毒软件。

有些人怕病毒感染,往往在计算机上安装几个反病毒软件,以为这样可以提升防病毒能力。殊不知反病毒软件之间往往是不能兼容的,知名度较大的反病毒软件在安装时会检测是否有其他厂商的反病毒产品存在,如果有,会要求先卸载其他厂商的产品才能安装。而知名度较小的反病毒产品往往不能互相检测,因此用户可以同时安装几个反病毒产品,并存的反病毒产品会严重降低系统性能,甚至造成系统的不稳定。

2.不正确的网络存取

这一般是由于网络驱动不完善造成的,使用名门大厂的产品和及时升级驱动程序可以较好地避免这些问题。

3.过多的文件系统过滤驱动

各种反病毒软件、安全软件、磁盘工具软件、监控软件、网络防火墙都属于这类软件,文件系统的访问在这些过滤驱动中被层层筛选,安装过多的这类软件会造成系统负担过重。

3.病毒或木马

病毒或木马会占用网络资源搜寻新的可感染目标或传送窃取的数据,网络带宽会被大量占用。

4.不当的系统参数配置

5.文件系统故障

经常使用chkdsk检查文件系统,错误的文件系统可能导致系统负载过重甚至死机。在不正常关机时系统要求检查文件系统时不要按Escape跳过检查,文件系统的坏链可能会造成数据永久丢失。

NFS服务器的工作原理

NFS服务器的安装和故障排除

NFS(Network File System,网络文件系统)服务器的工作原理。

安装配置NFS服务器。

NFS的图形化配置。

NFS的客户端配置。

NFS服务器的故障排除。

程序分Server和Client

服务器端打开侦听的端口,一有客户端连接就创建两个新的线程来负责这个连接

一个负责客户端发送的信息(ClientMsgCollectThread 类),

另一个负责通过该Socket发送数据(ServerMsgSendThread )

Server.java代码如下:

/*

* 创建日期 2009-3-7

*

* TODO 要更改此生成的文件的模板,请转至

* 窗口 - 首选项 - Java - 代码样式 - 代码模板

*/

package faue.MutiUser

import java.io.BufferedReader

import java.io.IOException

import java.io.InputStreamReader

import java.io.PrintWriter

import java.net.ServerSocket

import java.net.Socket

/**

* 服务器端

*

* @author Faue

*/

public class Server extends ServerSocket {

private static final int SERVER_PORT = 10000

/**

* 构造方法,用于实现连接的监听

*

* @throws IOException

*/

public Server() throws IOException {

super(SERVER_PORT)

try {

while (true) {

Socket socket = super.accept()

new Thread(new ClientMsgCollectThread(socket), "getAndShow"

+ socket.getPort()).start()

new Thread(new ServerMsgSendThread(socket), "send"

+ socket.getPort()).start()

}

} catch (IOException e) {

e.printStackTrace()

}

}

public static void main(String[] args) throws IOException {

new Server()

}

/**

* 该类用于创建接收客户端发来的信息并显示的线程

*

* @author Faue

* @version 1.0.0

*/

class ClientMsgCollectThread implements Runnable {

private Socket client

private BufferedReader in

private StringBuffer inputStringBuffer = new StringBuffer("Hello")

/**

* 得到Socket的输入流

*

* @param s

* @throws IOException

*/

public ClientMsgCollectThread(Socket s) throws IOException {

client = s

in = new BufferedReader(new InputStreamReader(client

.getInputStream(), "GBK"))

}

public void run() {

try {

while (!client.isClosed()) {

inputStringBuffer.delete(0, inputStringBuffer.length())

inputStringBuffer.append(in.readLine())

System.out.println(getMsg(inputStringBuffer.toString()))

}

} catch (IOException e) {

//e.printStackTrace()

System.out.println(client.toString() + " is closed!")

}

}

/**

* 构造显示的字符串

*

* @param line

* @return

*/

private String getMsg(String line) {

return client.toString() + " says:" + line

}

}

/**

* 该类用于创建发送数据的线程

*

* @author Faue

* @version 1.0.0

*/

class ServerMsgSendThread implements Runnable {

private Socket client

private PrintWriter out

private BufferedReader keyboardInput

private StringBuffer outputStringBuffer = new StringBuffer("Hello")

/**

* 得到键盘的输入流

*

* @param s

* @throws IOException

*/

public ServerMsgSendThread(Socket s) throws IOException {

client = s

out = new PrintWriter(client.getOutputStream(), true)

keyboardInput = new BufferedReader(new InputStreamReader(System.in))

}

public void run() {

try {

while (!client.isClosed()) {

outputStringBuffer.delete(0, outputStringBuffer.length())

outputStringBuffer.append(keyboardInput.readLine())

out.println(outputStringBuffer.toString())

}

} catch (IOException e) {

//e.printStackTrace()

System.out.println(client.toString() + " is closed!")

}

}

}

}

客户端:

实现基于IP地址的连接,连接后也创建两个线程来实现信息的发送和接收

/*

* 创建日期 2009-3-7

*

*/

package faue.MutiUser

import java.io.BufferedReader

import java.io.IOException

import java.io.InputStreamReader

import java.io.PrintWriter

import java.net.Socket

/**

* 客户端

*

* @author Faue

*/

public class Client {

private Socket mySocket

/**

* 创建线程的构造方法

*

* @param IP

* @throws IOException

*/

public Client(String IP) throws IOException {

try {

mySocket = new Socket(IP, 10000)

new Thread(new ServerMsgCollectThread(mySocket), "getAndShow"

+ mySocket.getPort()).start()

new Thread(new ClientMsgSendThread(mySocket), "send"

+ mySocket.getPort()).start()

} catch (IOException e) {

//e.printStackTrace()

System.out.println("Server.IP:" + IP

+ " port:10000 can not be Connected")

}

}

public static void main(String[] args) throws IOException {

try {

new Client(args[0])

} catch (Exception e) {

System.out.println("输入的IP地址错误")

}

}

/**

* 该类用于创建接收服务端发来的信息并显示的线程

*

* @author Faue

* @version 1.0.0

*/

class ServerMsgCollectThread implements Runnable {

private Socket client

private BufferedReader in

private StringBuffer inputStringBuffer = new StringBuffer("Hello")

/**

* 得到Socket的输入流

*

* @param s

* @throws IOException

*/

public ServerMsgCollectThread(Socket s) throws IOException {

client = s

in = new BufferedReader(new InputStreamReader(client

.getInputStream(), "GBK"))

}

public void run() {

try {

while (!client.isClosed()) {

inputStringBuffer.delete(0, inputStringBuffer.length())

inputStringBuffer.append(in.readLine())

System.out.println(getMsg(inputStringBuffer.toString()))

}

} catch (IOException e) {

//e.printStackTrace()

System.out.println(client.toString() + " is closed!")

System.exit(0)

}

}

/**

* 构造输入字符串

*

* @param line

* @return

*/

private String getMsg(String line) {

return client.toString() + " says:" + line

}

}

/**

* 该类用于创建发送数据的线程

*

* @author Faue

* @version 1.0.0

*/

class ClientMsgSendThread implements Runnable {

private Socket client

private PrintWriter out

private BufferedReader keyboardInput

private StringBuffer outputStringBuffer = new StringBuffer("Hello")

/**

* 得到键盘的输入流

*

* @param s

* @throws IOException

*/

public ClientMsgSendThread(Socket s) throws IOException {

client = s

out = new PrintWriter(client.getOutputStream(), true)

keyboardInput = new BufferedReader(new InputStreamReader(System.in))

}

public void run() {

try {

while (!client.isClosed()) {

outputStringBuffer.delete(0, outputStringBuffer.length())

outputStringBuffer.append(keyboardInput.readLine())

out.println(outputStringBuffer.toString())

}

out.println("--- See you, bye! ---")

} catch (IOException e) {

//e.printStackTrace()

System.out.println(client.toString() + " is closed!")

System.exit(0)

}

}

}

}

如果对您有帮助,请记得采纳为满意答案,谢谢!祝您生活愉快!

vaela


欢迎分享,转载请注明来源:夏雨云

原文地址:https://www.xiayuyun.com/zonghe/379368.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-15
下一篇2023-05-15

发表评论

登录后才能评论

评论列表(0条)

    保存