`
Hooopo
  • 浏览: 335289 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

一个简单的delay server

    博客分类:
  • Ruby
阅读更多
web game里经常出现这样的需求:
1.建造一个房子,等待n秒后建好
2.种植一个植物,等待n秒后完成
3.生产一个汽车,等待n秒后完成
4.升级一个基地,等待n秒后完成
..................
无论是汽车还是房子,建造或升级这个动作很简单,只需要更新一下数据库里的某个字段。
关键是如何处理等待n秒这个操作。

cron + rake
最简单的做法就是后台定时rake,每隔一段时间扫描一下整个表,根据结束时间去改变状态字段。
但是这样作的缺陷很明显,即使扫描的时间间隔再短也达不到准确,还有就是rake每次执行都要加载一次rails环境,然后再释放,这样效率很低。

Delay Job:
看了各种delay job插件,这些插件主要解决的问题是异步的问题,同样达不到精确的计划。

异步线程or进程+sleep n
这种方案看起来不错,但是无论线程还是进程,一直sleep都会占很多资源.

EventMachine
引用
EventMachine是一个基于Reactor设计模式的、用于网络编程和并发编程的框架。Reactor模式描述了一种服务处理器,它接受事件并将其分发给已注册的事件处理。这种模式的好处就是清晰的分离了时间分发和处理事件的应用程序逻辑,而不需引入多线程来把代码复杂化。

好了,神器在手,,看代码:
Delay Server:

#!/usr/bin/env ruby

require 'rubygems'
require 'optparse'
require 'eventmachine'

require 'evma_httpserver'
require 'rack'

options = {
  :Port        => 3000,
  :Host        => "0.0.0.0",
  :environment => (ENV['RAILS_ENV'] || "development").dup
}

ARGV.clone.options do |opts|
  opts.on("-p", "--port=port", Integer,
          "Runs Delay Server on the specified port.", "Default: 3000") { |v| options[:Port] = v }
  opts.on("-b", "--binding=ip", String,
          "Binds Delay Server to the specified ip.", "Default: 0.0.0.0") { |v| options[:Host] = v }

  opts.on("-e", "--environment=name", String,
          "Specifies the environment to run this server under (test/development/production).",
          "Default: development") { |v| options[:environment] = v }

  opts.separator ""

  opts.on("-h", "--help", "Show this help message.") { puts opts; exit }

  opts.parse!
end

puts "=> Delay Server  starting on http://#{options[:Host]}:#{options[:Port]}"


ENV["RAILS_ENV"] = options[:environment]


require(File.join(File.dirname(__FILE__), 'config', 'boot'))
require(File.join(File.dirname(__FILE__), 'config', 'environment'))


class DelayServer < EM::Connection
  include EM::HttpServer

  def post_init
    super
  end

  def process_http_request

    params = Rack::Utils.parse_query(@http_query_string)
    
    response = EM::DelegatedHttpResponse.new(self)
    response.status = 200
    response.content_type 'text/html'

    current_time = Time.now
    response.content = "request time -> #{current_time.to_s(:db)} / delay time -> #{params['delay']}s\n"

    EM::add_timer(params["delay"]) do
      p params["operate"]
      puts Time.now.to_s(:db)
    end

    response.send_response
  end
end


trap(:INT) { exit }

puts "=> Ctrl-C to shutdown server"

EM.run{
  EM.start_server options[:Host], options[:Port], DelayServer
}





Rails Server:
class XxxController < ApplicationController
  def build
   #.................
   system('%Q{curl  "http://0.0.0.0:3000?delay=10&operate=build"  > ./log/delay_server.log 2>&1 &})
   #.................
  end
end



其实rails server与delay server之间通讯可以有多种选择,比如drb
本着简单高效的原则,选择了http协议..
虽然eventmachine是非阻塞io,但是单个进程的吞吐量有限,利用http协议很容易在前面加个nginx,变成一个小集群....




分享到:
评论
18 楼 paranoid945 2010-09-16  
不存在数据库中可以吗
17 楼 Hooopo 2010-09-12  
xds2000 写道
可以在数据库上做一个trigger,不扫表更方便.在做一个UDF发送你的请求.

如果系统使用了二级缓存,像cache_money..在数据库上做trigger,就会出现数据库数据与缓存不同步的现象。。
16 楼 dualface 2010-09-12  
我靠,高射炮打蚊子啊。。。。

假设建造一个房屋需要100秒,玩家点击确认后开始计时。

不需要搞什么后台任务,只需要把这个任务写入数据库。当客户端有请求时,才取出数据进行计算。如果时间未到,服务端直接忽略就行了。

所有其他工作都由客户端进行,比如“还剩下xx秒”都在客户端进行,说白了就是一个模拟计算的过程。
15 楼 xds2000 2010-09-12  
可以在数据库上做一个trigger,不扫表更方便.在做一个UDF发送你的请求.
14 楼 全冠清 2010-09-09  
很显然是第一种
13 楼 Saito 2010-09-09  
hooooopo这个需求让我想到了各种邪恶的网盘. .

由于各种门的存在.网盘的需求量很高.但是网盘不能让你无限制的下载.

然后每次下载都要有delay时间. 类似freakshare这个网盘会记录你的下载记录. 第一次一般等待60秒. 第二次就会变成10分钟.

这个其实也是一个delay server. 有些类似的功能. 不过他不需要保证 建造中断问题.如果离线他会重读60秒.

60秒/10分钟结束会发起一次请求.获得一个下载地址.跟update数据库其实是一样的.

或许可以参考.也是两次请求.


况且现在EM模式并没有解决delay的问题.大家实际上还是在排队..

还有空间啊.
12 楼 ray_linn 2010-09-09  
Hooopo 写道
ray_linn 写道
Hooopo 写道
ray_linn 写道
记录下duration和start time在数据库里
duration,start_time
5,  12:30:52

客户端的javascript access服务器端(比如login,或者客户端计时器到期)的时候,一条select,一条update.

是用户在线时利用前端的timer,不在线时在登录时候同步吗?
这样有一个问题:
比如建造一个房子
如果玩家A在未建造完成之前下线,
虽然玩家A再次上线的时候会得到建造完成的房子,
但是在其他玩家在查看玩家A的建筑的时候是看不到玩家A的房子的...


在其他玩家view你的地理坐标也可以同时触发这个事件吧。。。事实上

currenttime > start_time+duration 可以作为判断标记,来决定显示不显示这个房子。

说得更具体的:假设有个城 (破三国),城里有各种设施,比如厕所、停尸房之类的^_^,城和设施是个一对多的关系:

----- 设施----------------------------------------------
id, city_id, name,type,setup_duration,start_time,level,X-cordinator,Y-Cordinator
--------------------------------------------------------

每次有人(包括自己或者别人)来看这个城的时候,先根据current_time >start_time + duration 来update一下table, 简单的说就是把level+1,start_time清空,再一句select * from 设施 where start_time is empty 就搞定了。

这里用start_time+duration,是因为好像还可以盖某些设施来缩短duration,是个可变量,你也可以用expected_completet_time来代替之。



其实由于前端timer的不可靠性,后台再加上你说的这个同步机制是可以解决问题的。
但是,这样就会检查更新逻辑(可能不止一种这样的场景)混到了其他逻辑(你这个例子里的查看坐标)。。。
这样最终会使很多action里面充斥着各种同步状态的逻辑...很难维护。


我们只是把数据库更新延迟再延迟到有人来查看、改变城的状态(比如敌我查看城市、攻打城市等等),而这个操作可以完全写成一个SP,独立于所有的action,这样就解决了这个问题。。
11 楼 Hooopo 2010-09-09  
ray_linn 写道
Hooopo 写道
ray_linn 写道
记录下duration和start time在数据库里
duration,start_time
5,  12:30:52

客户端的javascript access服务器端(比如login,或者客户端计时器到期)的时候,一条select,一条update.

是用户在线时利用前端的timer,不在线时在登录时候同步吗?
这样有一个问题:
比如建造一个房子
如果玩家A在未建造完成之前下线,
虽然玩家A再次上线的时候会得到建造完成的房子,
但是在其他玩家在查看玩家A的建筑的时候是看不到玩家A的房子的...


在其他玩家view你的地理坐标也可以同时触发这个事件吧。。。事实上

currenttime > start_time+duration 可以作为判断标记,来决定显示不显示这个房子。

说得更具体的:假设有个城 (破三国),城里有各种设施,比如厕所、停尸房之类的^_^,城和设施是个一对多的关系:

----- 设施----------------------------------------------
id, city_id, name,type,setup_duration,start_time,level,X-cordinator,Y-Cordinator
--------------------------------------------------------

每次有人(包括自己或者别人)来看这个城的时候,先根据current_time >start_time + duration 来update一下table, 简单的说就是把level+1,start_time清空,再一句select * from 设施 where start_time is empty 就搞定了。

这里用start_time+duration,是因为好像还可以盖某些设施来缩短duration,是个可变量,你也可以用expected_completet_time来代替之。



其实由于前端timer的不可靠性,后台再加上你说的这个同步机制是可以解决问题的。
但是,这样就会检查更新逻辑(可能不止一种这样的场景)混到了其他逻辑(你这个例子里的查看坐标)。。。
这样最终会使很多action里面充斥着各种同步状态的逻辑...很难维护。
10 楼 ray_linn 2010-09-08  
Hooopo 写道
ray_linn 写道
记录下duration和start time在数据库里
duration,start_time
5,  12:30:52

客户端的javascript access服务器端(比如login,或者客户端计时器到期)的时候,一条select,一条update.

是用户在线时利用前端的timer,不在线时在登录时候同步吗?
这样有一个问题:
比如建造一个房子
如果玩家A在未建造完成之前下线,
虽然玩家A再次上线的时候会得到建造完成的房子,
但是在其他玩家在查看玩家A的建筑的时候是看不到玩家A的房子的...


在其他玩家view你的地理坐标也可以同时触发这个事件吧。。。事实上

currenttime > start_time+duration 可以作为判断标记,来决定显示不显示这个房子。

说得更具体的:假设有个城 (破三国),城里有各种设施,比如厕所、停尸房之类的^_^,城和设施是个一对多的关系:

----- 设施----------------------------------------------
id, city_id, name,type,setup_duration,start_time,level,X-cordinator,Y-Cordinator
--------------------------------------------------------

每次有人(包括自己或者别人)来看这个城的时候,先根据current_time >start_time + duration 来update一下table, 简单的说就是把level+1,start_time清空,再一句select * from 设施 where start_time is empty 就搞定了。

这里用start_time+duration,是因为好像还可以盖某些设施来缩短duration,是个可变量,你也可以用expected_completet_time来代替之。


9 楼 Hooopo 2010-09-08  
ray_linn 写道
记录下duration和start time在数据库里
duration,start_time
5,  12:30:52

客户端的javascript access服务器端(比如login,或者客户端计时器到期)的时候,一条select,一条update.

是用户在线时利用前端的timer,不在线时在登录时候同步吗?
这样有一个问题:
比如建造一个房子
如果玩家A在未建造完成之前下线,
虽然玩家A再次上线的时候会得到建造完成的房子,
但是在其他玩家在查看玩家A的建筑的时候是看不到玩家A的房子的...
8 楼 Hooopo 2010-09-08  
g.zhen.ning 写道
离题问个问题,这个eventmachine做的功能能被node.js取代么?

可以,node里有setTimeout
http://nodejs.org/api.html#timers-84
7 楼 Hooopo 2010-09-08  
刚才简单测试了一下,add_timer方式在并发情况不会出现覆盖现象,在同一时间如果出现处理不了的操作,前一个操作会阻塞后一个,但是每个操作最终还会执行,也就是quakewang说的卡机.
简单测试代码:
#!/usr/bin/env ruby

require 'rubygems'
require 'optparse'
require 'eventmachine'
require 'evma_httpserver'
require 'rack'

options = {
  :Port        => 3000,
  :Host        => "0.0.0.0",
  :environment => (ENV['RAILS_ENV'] || "development").dup
}

ARGV.clone.options do |opts|
  opts.on("-p", "--port=port", Integer,
          "Runs Delay Server on the specified port.", "Default: 3000") { |v| options[:Port] = v }
  opts.on("-b", "--binding=ip", String,
          "Binds Delay Server to the specified ip.", "Default: 0.0.0.0") { |v| options[:Host] = v }

  opts.on("-e", "--environment=name", String,
          "Specifies the environment to run this server under (test/development/production).",
          "Default: development") { |v| options[:environment] = v }

  opts.separator ""

  opts.on("-h", "--help", "Show this help message.") { puts opts; exit }

  opts.parse!
end

puts "=> Delay Server  starting on http://#{options[:Host]}:#{options[:Port]}"



ENV["RAILS_ENV"] = options[:environment]



require(File.join(File.dirname(__FILE__), 'config', 'boot'))
require(File.join(File.dirname(__FILE__), 'config', 'environment'))




class DelayServer < EM::Connection
  include EM::HttpServer

  def post_init
    super
  end

  def process_http_request

    #params = Rack::Utils.parse_query(@http_query_string)
    
    response = EM::DelegatedHttpResponse.new(self)
    response.status = 200
    response.content_type 'text/html'

    response.content = "ok"


    EM::add_timer(10) do
      sleep 0.5
      $count += 1
      p Time.now.to_s(:db) + "--->#{$count}"
    end

    response.send_response
  end
end



trap(:INT) { exit }

puts "=> Ctrl-C to shutdown server"



EM.run{
  $count = 0
  EM.start_server options[:Host], options[:Port], DelayServer
}

ab -c50 -n100 http://0.0.0.0:3000/


控制台输出:
引用

=> Ctrl-C to shutdown server
"2010-09-09 14:51:11--->1"
"2010-09-09 14:51:11--->2"
"2010-09-09 14:51:12--->3"
"2010-09-09 14:51:12--->4"
"2010-09-09 14:51:13--->5"
"2010-09-09 14:51:13--->6"
"2010-09-09 14:51:14--->7"
"2010-09-09 14:51:14--->8"
"2010-09-09 14:51:15--->9"
"2010-09-09 14:51:15--->10"
"2010-09-09 14:51:16--->11"
"2010-09-09 14:51:16--->12"
"2010-09-09 14:51:17--->13"
"2010-09-09 14:51:17--->14"
"2010-09-09 14:51:18--->15"
"2010-09-09 14:51:18--->16"
"2010-09-09 14:51:19--->17"
"2010-09-09 14:51:19--->18"
"2010-09-09 14:51:20--->19"
"2010-09-09 14:51:20--->20"
"2010-09-09 14:51:21--->21"
"2010-09-09 14:51:21--->22"
"2010-09-09 14:51:22--->23"
"2010-09-09 14:51:22--->24"
"2010-09-09 14:51:23--->25"
"2010-09-09 14:51:23--->26"
"2010-09-09 14:51:24--->27"
"2010-09-09 14:51:24--->28"
"2010-09-09 14:51:25--->29"
"2010-09-09 14:51:25--->30"
"2010-09-09 14:51:26--->31"
"2010-09-09 14:51:26--->32"
"2010-09-09 14:51:27--->33"
"2010-09-09 14:51:27--->34"
"2010-09-09 14:51:28--->35"
"2010-09-09 14:51:28--->36"
"2010-09-09 14:51:29--->37"
"2010-09-09 14:51:29--->38"
"2010-09-09 14:51:30--->39"
"2010-09-09 14:51:30--->40"
"2010-09-09 14:51:31--->41"
"2010-09-09 14:51:31--->42"
"2010-09-09 14:51:32--->43"
"2010-09-09 14:51:32--->44"
"2010-09-09 14:51:33--->45"
"2010-09-09 14:51:33--->46"
"2010-09-09 14:51:34--->47"
"2010-09-09 14:51:34--->48"
"2010-09-09 14:51:35--->49"
"2010-09-09 14:51:35--->50"
"2010-09-09 14:51:36--->51"
"2010-09-09 14:51:36--->52"
"2010-09-09 14:51:37--->53"
"2010-09-09 14:51:37--->54"
"2010-09-09 14:51:38--->55"
"2010-09-09 14:51:38--->56"
"2010-09-09 14:51:39--->57"
"2010-09-09 14:51:39--->58"
"2010-09-09 14:51:40--->59"
"2010-09-09 14:51:40--->60"
"2010-09-09 14:51:41--->61"
"2010-09-09 14:51:41--->62"
"2010-09-09 14:51:42--->63"
"2010-09-09 14:51:42--->64"
"2010-09-09 14:51:43--->65"
"2010-09-09 14:51:43--->66"
"2010-09-09 14:51:44--->67"
"2010-09-09 14:51:44--->68"
"2010-09-09 14:51:45--->69"
"2010-09-09 14:51:45--->70"
"2010-09-09 14:51:46--->71"
"2010-09-09 14:51:46--->72"
"2010-09-09 14:51:47--->73"
"2010-09-09 14:51:47--->74"
"2010-09-09 14:51:48--->75"
"2010-09-09 14:51:48--->76"
"2010-09-09 14:51:49--->77"
"2010-09-09 14:51:49--->78"
"2010-09-09 14:51:50--->79"
"2010-09-09 14:51:50--->80"
"2010-09-09 14:51:51--->81"
"2010-09-09 14:51:51--->82"
"2010-09-09 14:51:52--->83"
"2010-09-09 14:51:52--->84"
"2010-09-09 14:51:53--->85"
"2010-09-09 14:51:53--->86"
"2010-09-09 14:51:54--->87"
"2010-09-09 14:51:54--->88"
"2010-09-09 14:51:55--->89"
"2010-09-09 14:51:55--->90"
"2010-09-09 14:51:56--->91"
"2010-09-09 14:51:56--->92"
"2010-09-09 14:51:57--->93"
"2010-09-09 14:51:57--->94"
"2010-09-09 14:51:58--->95"
"2010-09-09 14:51:58--->96"
"2010-09-09 14:51:59--->97"
"2010-09-09 14:51:59--->98"
"2010-09-09 14:52:00--->99"
"2010-09-09 14:52:00--->100"


6 楼 ray_linn 2010-09-08  
记录下duration和start time在数据库里
duration,start_time
5,  12:30:52

客户端的javascript access服务器端(比如login,或者客户端计时器到期)的时候,一条select,一条update.
5 楼 g.zhen.ning 2010-09-08  
离题问个问题,这个eventmachine做的功能能被node.js取代么?
4 楼 QuakeWang 2010-09-08  
Hooopo 写道
QuakeWang 写道
eventmachine的add_timer不合适用来作这个需求,而且他在高并发下如果有相同的delay time会出现后者覆盖前者的情况。

webgame的delay job通常都是在数据库里面直接插入一条什么时间需要作什么事情的记录,后台一个job server每1秒都进行查询看是否有小于当前时间还未完成的job,然后处理掉,如果每秒要处理的事情太多,就会出现所谓的"卡机"。数据库1秒查询一次的代价其实是很小的。


如果出现你说的覆盖的情况,那么每秒处理一个也是必然会卡机的。而且会越卡越多。。
add_timer方式也可以通过增加进程数量方式避免这个问题。而添加多个job server势必又增加了数据库查询。
add_timer方式如果出现你说的情况,还可以加一个定时任务,每隔一段时间把覆盖调的处理掉。



不是每秒处理一个,而是每一秒查询一次,有几个早于当前时间需要完成的任务,就处理几个。玩家说的“卡机”是指原定于12:00:00会完成的任务,由于11:59:59的任务太多,导致处理任务的时间过长,可能到12:00:10才会执行查询,进行处理。

eventmachine用处很多,但是用他的add_timer不合适用在web game这种定时完成任务,你可以拿真实的项目数据做对比压力测试看看,你会发现这个架构和数据库查询相比是没有硬件成本和开发成本优势的,你说的加进程或者定时任务更会让这个架构复杂和不稳定。
3 楼 beneo 2010-09-08  
event actor真是越来越多啊

如果这种delay job的场景更清除一些就好了。。

web game种花种草的,长时间的,我觉得job server来做比较合适

如果是射击,法术即时的,你这个思路也许不错哦
2 楼 Hooopo 2010-09-07  
QuakeWang 写道
eventmachine的add_timer不合适用来作这个需求,而且他在高并发下如果有相同的delay time会出现后者覆盖前者的情况。

webgame的delay job通常都是在数据库里面直接插入一条什么时间需要作什么事情的记录,后台一个job server每1秒都进行查询看是否有小于当前时间还未完成的job,然后处理掉,如果每秒要处理的事情太多,就会出现所谓的"卡机"。数据库1秒查询一次的代价其实是很小的。


如果出现你说的覆盖的情况,那么每秒处理一个也是必然会卡机的。而且会越卡越多。。
add_timer方式也可以通过增加进程数量方式避免这个问题。而添加多个job server势必又增加了数据库查询。
add_timer方式如果出现你说的情况,还可以加一个定时任务,每隔一段时间把覆盖调的处理掉。


1 楼 QuakeWang 2010-09-07  
eventmachine的add_timer不合适用来作这个需求,而且他在高并发下如果有相同的delay time会出现后者覆盖前者的情况。

webgame的delay job通常都是在数据库里面直接插入一条什么时间需要作什么事情的记录,后台一个job server每1秒都进行查询看是否有小于当前时间还未完成的job,然后处理掉,如果每秒要处理的事情太多,就会出现所谓的"卡机"。数据库1秒查询一次的代价其实是很小的。

相关推荐

    SQL_SERVER命令大全.pdf

    SQL Server是一个流行的关系型数据库管理系统(RDBMS),由Microsoft开发。它广泛用于企业级应用,具有完善的数据管理、事务处理和存储过程等功能。SQL Server使用结构化查询语言(SQL)来管理数据,执行各种数据库...

    ESP8266的 TCP通信(server)

    这个例子展示了如何创建一个简单的TCP服务器,它将接收到的数据转发回客户端。 通过理解这些基本概念和实践,你可以利用ESP8266构建自己的TCP服务器,实现远程控制、数据传输等功能。在实际应用中,还可以结合MQTT...

    devserver:简单的开发服务器

    `devserver`就是这样一个轻量级的开发服务器,它提供了基本的功能,如延迟支持、静态文件服务以及对JSONP的支持,虽然在描述中提到JSONP和镜像JS脚本功能尚未实现。 ### 延迟支持 延迟支持(Delay Support)是一项...

    snap7-express-server:一个简单的node.js表达REST服务器以写入siemens徽标

    Snap7 Express服务器一个简单的node.js表示REST服务器即可写入siemens徽标。用法一个端点打开大门。 $ curl --location --request GET ' ...

    SQL Server 2008中SQL之WaitFor使用介绍

    在SQL Server 2008中,`WAITFOR`是一个非常有用的T-SQL语句,它允许你控制SQL Server执行的流程,使程序在执行特定操作之前暂停一段时间或等待特定事件发生。`WAITFOR`语句主要包含三个部分:`DELAY`、`TIME`和`( ...

    《SQL Server数据库技术及应用》期末考试试卷D.doc

    9. **延迟执行**:第十题要求SQL Server等待15秒后再执行,使用WAITFOR DELAY语句实现,正确选项是B,但书写格式有误,正确的写法是`WAITFOR DELAY '00:00:15'`。 通过以上解析,我们可以看出试卷主要测试了SQL ...

    c# tcp开源代码,包含server和client

    以下是一个简单的示例,展示如何在C#中实现TCP客户端的自动重连: ```csharp using System; using System.Net; using System.Net.Sockets; using System.Threading.Tasks; class TcpAutoReconnectClient { ...

    ASP常用函数:Delay()

    `Delay()`函数作为ASP开发中的一个小工具,虽然简单却十分实用。它可以帮助开发者更好地控制脚本的执行流程,提高程序的灵活性和可用性。然而,在实际应用中还需注意其对服务器性能的影响,并采取相应的优化措施。

    Vue使用json-server进行后端数据模拟功能

    为了解决这个问题,可以使用json-server这个轻量级的工具来快速搭建一个RESTful API接口,用以模拟后端数据。 json-server是一个零配置、轻量级的REST API服务器,它可以让开发者用JSON文件来模拟数据库,并提供...

    ESP8266 Web Server #Control LED

    在本主题中,我们将探讨如何使用ESP8266创建一个简单的Web服务器,以控制LED灯。这个项目可以帮助初学者理解Web服务器的基本工作原理,并学习如何通过HTTP请求与硬件交互。 **Web请求过程** 当我们在浏览器中输入一...

    sqlserver 日志恢复方法(搞定drop和truncate)

    尤其是在SQL Server这样的关系型数据库管理系统中,如何有效地进行数据恢复成为了一个不可忽视的问题。本文将通过一次实际的数据恢复案例来详细介绍SQL Server的日志恢复方法,特别是针对`DROP`和`TRUNCATE`操作后的...

    2.LVS(Linux Virtual Server)集群项目实践.pdf

    以一个简单的例子来说,假设我们有如下配置: - **VIP**:10.0.0.1 - **DIP**:192.168.0.200 - **RIP**:192.168.0.201 - **DGW**:192.168.0.200 在这种情况下,客户端发送的请求会首先到达DIP,即192.168.0.200...

    Nomster-Server:Nomster 是一种简化“午餐时间吃什么?”的简单方法。 过程

    它提供了一个 REST 接口来处理存储的数据。 什么是诺姆斯特? Nomster 是一种简化“午餐时间吃什么?”的简单方法。 过程。 它提供了同事现有建议的列表。 重要信息 此版本使用 H2 内存数据库。 要使其与您的 ...

    单片机计算器简易程序

    【单片机计算器简易程序】是一个基于C51语言编写的计算器应用,它实现了基本的四则运算(加、减、乘、除)。这个程序利用单片机的资源,通过键盘输入数字和运算符,然后在LCD显示屏上显示计算结果。 在程序中,可以...

    Python如何实现定时器功能

    下面是一个简单的例子,展示了如何使用 `Timer` 类来每隔一秒打印一条消息: ```python from threading import Timer import time def delay_run(): print('running') t = Timer(1, delay_run) # 创建一个新的 ...

    运维解决方案LVS+Keepalived实现服务器高可用群集

    2. **配置灵活**:LVS支持多种负载调度算法和转发模式,可以根据不同的场景选择最适合的策略,同时Keepalived的配置也相对简单,只需要一个配置文件即可完成复杂的高可用设置。 3. **高可用性**:Keepalived通过实时...

    嵌入式与物联网开发的简单例子

    该项目的目标是创建一个简易但功能完整的温度监测系统,该系统能够自动读取环境温度并通过Wi-Fi网络将数据上传至远程服务器或云平台。 #### 二、项目准备 ##### 1. 硬件需求 - **Arduino Uno**:作为主控单元,...

    详解Spring Cloud Zuul重试机制探秘

    1. 注册中心(Eureka Server):创建一个 Eureka Server,只需要在主函数上添加 @EnableEurekaServer 注解,并在 properties 文件进行简单配置即可。 2. Zuul: Zuul 需要注册到 Eureka Server 上,并添加 @...

Global site tag (gtag.js) - Google Analytics