不急不徐,持之以恒。

          http://blog.gopersist.com/

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            24 隨筆 :: 0 文章 :: 52 評論 :: 0 Trackbacks

          #

          并發(fā)編程時,必須考慮安全性問題,即線程安全,所謂線程安全就是可以同時被多個線程調(diào)用,調(diào)用者無須額外的操作,程序也不會出現(xiàn)錯誤的結(jié)果。
          要使程序是線程安全的,必須考慮以下2點:
          1. 是否存在競態(tài)條件,常見的是那些先檢查后執(zhí)行的操作行為,它的正確結(jié)果取決于運氣。避免錯誤結(jié)果的方法是保證操作的原子性,通常使用加鎖,也有一些原子變量類可以達到目的。
          2. 對象狀態(tài)在內(nèi)存中是否可見,即當一個線程修改了對象的狀態(tài)后,其他線程不一定看到修改后的狀態(tài)。保證其他線程總是能看到最新狀態(tài)的方法有2種:一種是加鎖,另一種是使用volatile變量。
          于是得出幾個結(jié)論:
          1. 加鎖機制可保證可見性和原子性,所以能保證線程安全;
          2. 原子變量可保證原子性,但不能保證可見性,所以不能保證線程安全;
          3. volatile變量能保證可見性,但不能保證原子性,所以不能保證線程安全;
          4. volatile的原子變量能保證線程安全。
          除此之外,還有一些對象一定是線程安全的:
          1. 無狀態(tài)對象;
          2. 不可變對象。
          但是加鎖機制會產(chǎn)生活躍性問題,活躍性問題關(guān)注正確的行為是否一定會發(fā)生,主要有死鎖問題。
          死鎖簡單來講是這樣的:線程A持有鎖L并想獲得鎖M,同時線程B持有鎖M并想獲得鎖L,這時線程A和B都永久阻塞。
          避免死鎖的關(guān)鍵是要保證每個線程獲取鎖的順序必須相同,如上面線程A和B獲取鎖的順序如果都是先獲取鎖L再獲取鎖M,就不會發(fā)生死鎖問題。
          當持有鎖時調(diào)用外部方法,會很難分析獲取鎖的順序,要盡量避免。
          編碼參考:
          1. 將所有可變狀態(tài)都封裝在對象內(nèi)部,并通過對象的內(nèi)置鎖對所有訪問可變狀態(tài)的代碼進行同步;
          2. 擴展線程安全的容器類時,在新類中委托容器類的其他方法,使用新鎖,不要關(guān)心原來的容器類是否線程安全。
          參考資料:
          《JAVA并發(fā)編程實戰(zhàn)》
          posted @ 2014-10-10 13:41 老林 閱讀(1301) | 評論 (0)編輯 收藏

          試用Keepalived來做雙機熱備,服務器信息如下:
          服務器 操作系統(tǒng) IP 虛擬IP
          Server 1 Centos 192.168.18.20 192.168.18.22
          Server 2 Centos 192.168.18.21 192.168.18.22

          1. 安裝Keepalived

          2臺Server都使用下面的命令安裝Keepalived:
          yum install keepalived -y

          2. Server1 Keepalived 配置

          $ vi /etc/keepalived/keepalived.conf

          vrrp_instance VI_1 {
              state MASTER
              interface eth0
              virtual_router_id 51
              priority 100                   # 優(yōu)先級
              advert_int 1                 # 心跳間隔(秒)
              authentication {
                  auth_type PASS
                  auth_pass 1111
              }
              virtual_ipaddress {
                  192.168.18.22         # 虛擬IP
              }
          }

          3. Server2 Keepalived 配置

          $ vi /etc/keepalived/keepalived.conf

          vrrp_instance VI_1 {
              state BACKUP              # 備份機
              interface eth0
              virtual_router_id 51
              priority 99                   # 優(yōu)先級,比主服務器底
              advert_int 1                 # 心跳間隔(秒)
              authentication {
                  auth_type PASS
                  auth_pass 1111
              }
              virtual_ipaddress {
                  192.168.18.22         # 虛擬IP
              }
          }

          4. 啟動Keepalived

          $ service keepalived start
          啟動keepalived后,可看到2臺Server都綁定了虛擬IP:
          $ ip a

          # Server 1:
          2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
              link/ether 00:24:8c:8c:67:43 brd ff:ff:ff:ff:ff:ff
              inet 192.168.18.20/24 brd 192.168.18.255 scope global eth0
              inet 192.168.18.22/32 scope global eth0
              inet6 fe80::224:8cff:fe8c:6743/64 scope link 
                 valid_lft forever preferred_lft forever

          # Server 2:
          2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
              link/ether 00:23:54:bf:ab:17 brd ff:ff:ff:ff:ff:ff
              inet 192.168.18.21/24 brd 192.168.18.255 scope global eth0
              inet 192.168.18.22/32 scope global eth0
              inet6 fe80::223:54ff:febf:ab17/64 scope link 
                 valid_lft forever preferred_lft forever

          5. 測試

          瀏覽器訪問http://192.168.18.22,出現(xiàn) This is Server 1.
          將192.168.18.20關(guān)閉,再訪問http://192.168.18.22,出現(xiàn)This is Server 2.

          微信訂閱號:
          源文地址:http://blog.gopersist.com/2014/09/24/keepalived/
          posted @ 2014-09-24 11:34 老林 閱讀(2052) | 評論 (2)編輯 收藏

          試用IPVS的直接路由方式來做負載均衡。服務器信息如下:


           

          IP配置信息如下:

          服務器

          操作系統(tǒng)

          IP

          IP別名

          網(wǎng)關(guān)

          調(diào)度服務器

          Centos

          192.168.2.90

          192.168.2.99

          192.168.2.1

          實際服務器

          Centos

          192.168.2.71

          192.168.2.99

          192.168.2.1

          Centos

          192.168.2.72

          192.168.2.99

          192.168.2.1

           

          直接路由方式工作在數(shù)據(jù)鏈路層,通過修改數(shù)據(jù)包的MAC地址,將數(shù)據(jù)包轉(zhuǎn)發(fā)到實際服務器上。實際服務器響應時直接發(fā)送給用戶端,而不經(jīng)過調(diào)度器。

           

          因為調(diào)度服務器并沒有修改數(shù)據(jù)包的IP地址,所以我們需要為實際服務器設置與調(diào)度服務器相同的IP別名,以使實際服務器接受數(shù)據(jù)包。

           

          為調(diào)度服務器設置IP別名:

          ifconfig eth1:0 192.168.2.99

          IP別名與原來的IP地址在使用上并沒有什么不同,這里可以ping9099兩個IP。

           

          為實際服務器設置IP別名:

          ifconfig lo:0 192.168.2.99 broadcast 192.168.2.99 netmask 255.255.255.255 up

          為實際服務器添加路由規(guī)則,使它不去尋找其他擁有這個IP的服務器:

          route add -host 192.168.2.99 dev lo:0

          防止實際服務器響應針對IP別名的ARP廣播:

          echo 1>/proc/sys/net/ipv4/conf/lo/arp_ignore

          echo 2>/proc/sys/net/ipv4/conf/lo/arp_announce

          echo 1>/proc/sys/net/ipv4/conf/all/arp_ignore

          echo 2>/proc/sys/net/ipv4/conf/all/arp_announce

           

          使用ipvsadm配置調(diào)度服務器:

          ipvsadm -A -t 192.168.2.99:8888 -s rr

          ipvsadm -a -t 192.168.2.99:8888 -r 192.168.2.71:8888 -g

          ipvsadm -a -t 192.168.2.99:8888 -r 192.168.2.72:8888 -g

           

          使用下面的命令將連接有效時間改為1秒來測試,:

          ipvsadm --set 1 120 300

           

          瀏覽器訪問http://192.168.2.99:8888,每隔1秒多點擊刷新,就會交替出現(xiàn)192.168.2.71192.168.2.72。

           

          posted @ 2014-04-28 11:15 老林 閱讀(889) | 評論 (0)編輯 收藏

          試用IPVS來做負載均衡,使用了1臺雙網(wǎng)卡服務器和2臺單網(wǎng)卡服務器,2個網(wǎng)段。服務器信息如下:



          IP配置信息如下:

          服務器

          操作系統(tǒng)

          網(wǎng)卡

          IP

          調(diào)度服務器

          Centos

          eth0

          192.168.18.58

          eth1

          192.168.2.90

          實際服務器

          Centos

          eth0

          192.168.2.71

          Centos

          eth0

          192.168.2.72

           

          1.         首先配置調(diào)度服務器:

           

          a)         IPVS模塊已經(jīng)內(nèi)置到linux2.6.x內(nèi)核中,可以通過下面的命令查看是否已安裝:

          modprobe -l | grep ipvs

          看到類似下面的輸出,表示已經(jīng)安裝了

          kernel/net/netfilter/ipvs/ip_vs.ko

          kernel/net/netfilter/ipvs/ip_vs_rr.ko

          kernel/net/netfilter/ipvs/ip_vs_wrr.ko

          kernel/net/netfilter/ipvs/ip_vs_lc.ko

          kernel/net/netfilter/ipvs/ip_vs_wlc.ko

          kernel/net/netfilter/ipvs/ip_vs_lblc.ko

          kernel/net/netfilter/ipvs/ip_vs_lblcr.ko

          kernel/net/netfilter/ipvs/ip_vs_dh.ko

          kernel/net/netfilter/ipvs/ip_vs_sh.ko

          kernel/net/netfilter/ipvs/ip_vs_sed.ko

          kernel/net/netfilter/ipvs/ip_vs_nq.ko

          kernel/net/netfilter/ipvs/ip_vs_ftp.ko

          kernel/net/netfilter/ipvs/ip_vs_pe_sip.ko

           

          b)         安裝IPVS的管理工具ipvsadm

          yum install -y ipvsadm

           

          c)         清除表中所有記錄:

          ipvsadm -C

          使用下面的命令增加虛擬服務器,采用輪詢調(diào)度策略:

          ipvsadm -A -t 192.168.18.58:8888 -s rr

           

          使用下面的命令添加實際服務器,并采用NAT方式轉(zhuǎn)發(fā)數(shù)據(jù)包:

          ipvsadm -a -t 192.168.18.58:8888 -r 192.168.2.71:9999 -m

          ipvsadm -a -t 192.168.18.58:8888 -r 192.168.2.72:9999 -m

           

          d)         打開數(shù)據(jù)包轉(zhuǎn)發(fā):

          echo 1 > /proc/sys/net/ipv4/ip_forward

           

          2.         接下來配置2臺實際服務器,分別做以下工作:

           

          a)         9999端口上啟動一個web服務:

          配置好web服務后,當訪問http://192.168.2.71:9999時,頁面返回:This is 192.168.2.71.;當訪問http://192.168.2.72:9999時,頁面返回:This is 192.168.2.72.

           

          b)         設置默認網(wǎng)關(guān)指向調(diào)度服務器

          route del default

          route add default gw 192.168.2.90

           

          3.         測試

           

          訪問192.168.18.58:8888,會顯示This is 192.168.2.71This is 192.168.2.72,多次刷新應該要交替出現(xiàn)7172,但實際上并沒有這樣,瀏覽器只顯示與第一次相同的內(nèi)容,也就是ipvsadm每次都選擇了同一臺服務器。這是因為當一個TCP連接的初始SYN報文到達時,IPVS就選擇了一臺服務器,后繼報文會被轉(zhuǎn)發(fā)到相同的服務器。這個TCP連接在ipvsadm中默認有效時間為15分鐘,可以通過下面的命令查看:

          ipvsadm -L --timeout

          Timeout (tcp tcpfin udp): 900 120 300

          現(xiàn)在將有效時間改為1秒來測試,使用下面的命令:

          ipvsadm --set 1 120 300

           

          再到瀏覽器中每隔1秒多點擊刷新,就會交替出現(xiàn)7172,說明輪詢調(diào)度正在正常工作。

           

           

          posted @ 2014-04-25 14:32 老林 閱讀(1374) | 評論 (0)編輯 收藏

          為了搞清楚iptables NAT的過程,做了這個實驗。使用了1臺雙網(wǎng)卡服務器和1臺單網(wǎng)卡服務器,2個網(wǎng)段。服務器信息如下:


          IP配置信息如下:

          服務器

          操作系統(tǒng)

          網(wǎng)卡

          IP

          調(diào)度服務器

          Centos

          eth0

          192.168.18.58

          eth1

          192.168.2.90

          實際服務器

          Centos

          eth0

          192.168.2.73

           

          1.       為了看到調(diào)度服務器上的數(shù)據(jù)轉(zhuǎn)發(fā)過程,首先在調(diào)度服務器上分出內(nèi)核的debug日志:

          /etc/rsyslog.conf最后增加:kern.debug /var/log/iptables.log

          重啟日志服務:/etc/init.d/rsyslog restart

           

          2.       啟動調(diào)度服務器的iptables并清空規(guī)則

          service iptables start

          iptables -F

           

          3.       增加調(diào)度服務器的iptables特定日志輸出

          假設要將對調(diào)度服務器8888端口的訪問轉(zhuǎn)發(fā)給實際服務器的9999端口處理,在iptables中增加與這2個端口相關(guān)的日志輸出:

          iptables -t mangle -A PREROUTING -p tcp --dport 8888 -j LOG --log-level debug --log-prefix "<<<<< PER IN:"

          iptables -t mangle -A PREROUTING -p tcp --sport 9999 -j LOG --log-level debug --log-prefix "<<<<< PER IN:"

          iptables -t mangle -A POSTROUTING -p tcp --sport 8888 -j LOG --log-level debug --log-prefix ">>>>> POST OUT:"

          iptables -t mangle -A POSTROUTING -p tcp --dport 9999 -j LOG --log-level debug --log-prefix ">>>>> POST OUT:"

          iptables -t mangle -A POSTROUTING -p tcp --sport 9999 -j LOG --log-level debug --log-prefix ">>>>> POST OUT:"

           

          這時,通過瀏覽器訪問http://192.168.18.58:8888可以看到iptables.log中打印出下面的日志:

          Apr 24 16:24:35 route-server1 kernel: <<<<< PER IN:IN=eth0 OUT= MAC=00:1f:c6:cb:eb:e0:00:1f:33:de:29:ad:08:00 SRC=192.168.18.25 DST=192.168.18.58 LEN=60 TOS=0x00 PREC=0x00 TTL=63 ID=28721 DF PROTO=TCP SPT=50270 DPT=8888 WINDOW=14600 RES=0x00 SYN URGP=0

          Apr 24 16:24:35 route-server1 kernel: <<<<< POST OUT:IN= OUT=eth0 SRC=192.168.18.58 DST=192.168.18.25 LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=8888 DPT=50270 WINDOW=0 RES=0x00 ACK RST URGP=0

           

          雖然這個端口上即沒有應用,也沒有將請求轉(zhuǎn)發(fā)出去,但日志打印出了內(nèi)核獲取到的對這個端口的請求。

           

          4.       配置iptables將對8888的請求轉(zhuǎn)發(fā)到192.168.2.73:9999

          iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8888 -j DNAT --to-destination 192.168.2.73:9999

           

          訪問http://192.168.18.58:8888,日志中打印如下信息:

          Apr 24 16:39:21 route-server1 kernel: <<<<< PER IN:IN=eth0 OUT= MAC=00:1f:c6:cb:eb:e0:00:1f:33:de:29:ad:08:00 SRC=192.168.18.25 DST=192.168.18.58 LEN=60 TOS=0x00 PREC=0x00 TTL=63 ID=56888 DF PROTO=TCP SPT=50274 DPT=8888 WINDOW=14600 RES=0x00 SYN URGP=0

           

          日志中只打印了從eth0收到的對8888端口的請求,這是因為當數(shù)據(jù)要被轉(zhuǎn)發(fā)到192.168.2.73:9999時,默認情況下被禁止了。

           

          5.       打開數(shù)據(jù)包轉(zhuǎn)發(fā)功能

          echo 1 > /proc/sys/net/ipv4/ip_forward

           

          訪問http://192.168.18.58:8888,日志中打印如下信息:

          Apr 24 16:39:21 route-server1 kernel: <<<<< PER IN:IN=eth0 OUT= MAC=00:1f:c6:cb:eb:e0:00:1f:33:de:29:ad:08:00 SRC=192.168.18.25 DST=192.168.18.58 LEN=60 TOS=0x00 PREC=0x00 TTL=63 ID=56888 DF PROTO=TCP SPT=50274 DPT=8888 WINDOW=14600 RES=0x00 SYN URGP=0

          Apr 24 16:39:21 route-server1 kernel: <<<<< POST OUT:IN= OUT=eth1 SRC=192.168.18.25 DST=192.168.2.73 LEN=60 TOS=0x00 PREC=0x00 TTL=62 ID=56888 DF PROTO=TCP SPT=50274 DPT=9999 WINDOW=14600 RES=0x00 SYN URGP=0

           

          第一條日志顯示從eth0收到了對8888端口的請求,第二條日志顯示iptables已經(jīng)更改了數(shù)據(jù)包的目的地為192.168.2.73:9999,并通過eth1發(fā)出去。

           

          但這時請求雖然已經(jīng)被轉(zhuǎn)發(fā)到實際處理的服務器,但調(diào)度服務器收不到響應,瀏覽器仍在不停重試,日志也在不斷打印。這是因為實際服務器收到的數(shù)據(jù)包的來源IP是另一個網(wǎng)段的,實際服務器回復時,發(fā)現(xiàn)不是本網(wǎng)段的就把數(shù)據(jù)包發(fā)給網(wǎng)關(guān),網(wǎng)關(guān)設置的是192.168.2.1,這時數(shù)據(jù)就丟了。

           

          6.       將實際服務器的默認網(wǎng)關(guān)設置為192.168.2.90

          在實際服務器上執(zhí)行以下命令:

          route del default

          route add default gw 192.168.2.90

           

          再次訪問http://192.168.18.58:8888,日志打印如下信息:

          Apr 24 16:47:27 route-server1 kernel: <<<<< PER IN:IN=eth0 OUT= MAC=00:1f:c6:cb:eb:e0:00:1f:33:de:29:ad:08:00 SRC=192.168.18.25 DST=192.168.18.58 LEN=60 TOS=0x00 PREC=0x00 TTL=63 ID=37000 DF PROTO=TCP SPT=50279 DPT=8888 WINDOW=14600 RES=0x00 SYN URGP=0

          Apr 24 16:47:27 route-server1 kernel: <<<<< POST OUT:IN= OUT=eth1 SRC=192.168.18.25 DST=192.168.2.73 LEN=60 TOS=0x00 PREC=0x00 TTL=62 ID=37000 DF PROTO=TCP SPT=50279 DPT=9999 WINDOW=14600 RES=0x00 SYN URGP=0

          Apr 24 16:47:27 route-server1 kernel: <<<<< PER IN:IN=eth1 OUT= MAC=00:22:b0:de:f7:49:00:24:8c:b4:a1:8c:08:00 SRC=192.168.2.73 DST=192.168.18.25 LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=9999 DPT=50279 WINDOW=0 RES=0x00 ACK RST URGP=0

          Apr 24 16:47:27 route-server1 kernel: <<<<< POST OUT:IN= OUT=eth0 SRC=192.168.2.73 DST=192.168.18.25 LEN=40 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=TCP SPT=9999 DPT=50279 WINDOW=0 RES=0x00 ACK RST URGP=0

           

          上面第一條第二條日志和之前一樣,iptables將目地址更改后,通過eth1網(wǎng)卡發(fā)送出去。第三條日志通過eth1網(wǎng)卡接收到了實際服務器發(fā)送過來的數(shù)據(jù),并在第四條日志中通過eth0發(fā)回請求方。

           

          posted @ 2014-04-24 17:15 老林 閱讀(3982) | 評論 (0)編輯 收藏

          一、準備
          1. 安裝apache,http://httpd.apache.org/
          2. 安裝perl, http://www.perl.org/
          3. 安裝awstat, http://awstats.sourceforge.net/
          awstat安裝會自動進行一些配置,可能不需要下面的設置。
          二、apache配置
          在apache安裝目錄conf\httpd.conf中增加以下配置:
          Alias /awstatsclasses "C:/Program Files/AWStats/wwwroot/classes/"
          Alias /awstatscss "C:/Program Files/AWStats/wwwroot/wwwroot/css/"
          Alias /awstatsicons "C:/Program Files/AWStats/wwwroot/icon/"
          ScriptAlias /awstats/ "C:/Program Files/AWStats/wwwroot/cgi-bin/"

          <Directory "C:/Program Files/AWStats/wwwroot/cgi-bin/">
              AllowOverride None
              Options ExecCGI
              Order allow,deny
              Allow from all
          </Directory>

          將common注釋掉,放開combined的注釋
          #CustomLog "logs/access.log" common
          CustomLog "logs/access.log" combined
          三、awstat配置
          1. 修改{awstats_home}/wwwroot/cgi-bin/下的awredir.pl、awstats.pl文件的第一行從#!/usr/bin/perl改成#!C:\strawberry\perl\bin\perl.exe。
          3. 
          修改{awstats_home}/wwwroot/cgi-bin/下的awstats.demo.conf
          LogFile="C:\Program Files\Apache Software Foundation\Apache2.2\logs\access.log"
          LogType=W
          LogFormat=1
          SiteDomain="demo"
          四、更新報表
          命令行進行{awstats_home}\wwwroot\cgi-bin
          perl awstats.pl -config=demo –update
          五、訪問統(tǒng)計報表
          http://localhost/awstats/awstats.pl?config=demo
          注意:httpd.conf更改后要重啟apache服務
          posted @ 2010-11-11 23:36 老林 閱讀(627) | 評論 (0)編輯 收藏

               摘要: Play Framework Eclipse 開發(fā)入門  閱讀全文
          posted @ 2010-10-30 13:18 老林 閱讀(5773) | 評論 (4)編輯 收藏

               摘要: 一個軟件實體,應當對擴展開放,對修改關(guān)閉。
          要求一個軟件系統(tǒng)可以在不修改原有代碼的情況下,通過擴展達到增強其功能的目的。  閱讀全文
          posted @ 2010-03-30 08:44 老林 閱讀(2040) | 評論 (1)編輯 收藏

               摘要: Struts2與JasperReport無縫整合,使用iReport設計報表,取JavaBean數(shù)據(jù)源、類導航取值、排序、分組、參數(shù)傳遞、分頁...  閱讀全文
          posted @ 2010-03-12 23:54 老林 閱讀(6350) | 評論 (8)編輯 收藏

               摘要: 之前整合的框架中struts部分有問題,現(xiàn)將其升級到strtus2.1.8.1,可以解決兩個問題:
          1. 程序工作正常但后臺報錯,Unable to set parameter [location] in result of type [com.googlecode.jsonplugin.JSONResult]。
          2. 無法提交double為0值的問題。 ...  閱讀全文
          posted @ 2010-01-29 23:34 老林 閱讀(1033) | 評論 (0)編輯 收藏

          僅列出標題
          共3頁: 上一頁 1 2 3 下一頁 
          主站蜘蛛池模板: 白城市| 平果县| 九台市| 防城港市| 岐山县| 康定县| 孟津县| 抚松县| 宜兰县| 新乡市| 新乐市| 建德市| 汝南县| 贡嘎县| 邯郸县| 邢台市| 霍州市| 赞皇县| 柘城县| 鄂伦春自治旗| 北海市| 永兴县| 庐江县| 绍兴县| 青浦区| 麻江县| 都江堰市| 宿迁市| 多伦县| 兴宁市| 棋牌| 化州市| 和平区| 平塘县| 尼勒克县| 新密市| 绥阳县| 敖汉旗| 鹤峰县| 四川省| 三穗县|