当サイトはhttpサーバとして、
nginxで運用しているのだが、
nginxをipv4とipv6のハイブリット運用に変更したので、
メモを残す。
nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
multi_accept on;
use epoll;
}
http {
server_tokens off;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 10;
client_header_timeout 10;
client_body_timeout 10;
reset_timedout_connection on;
send_timeout 10;
include /etc/nginx/mime.types;
default_type application/octet-stream;
charset UTF-8;
server {
listen 80;
listen [::]:80 ipv6only=on;
}
include /etc/nginx/conf.d/*.conf;
}
そして、一部sslサイトがあるので、
ssl側は以下のようにする。
※httpでアクセスしてきたときのリダイレクトも入れている
server {
server_name example.com;
return 301 https://$host$request_uri;
}
server {
listen 443;
listen [::]:443 ipv6only=on ssl;
ssl on;
ssl_certificate /etc/pki/tls/certs/server.crt;
ssl_certificate_key /etc/pki/tls/certs/server.key;
server_name example.com;
:
:
}
netstatの結果、
nginxがipv4の80と443、ipv6の80と443で待ち受けていることがわかる。
# netstat -tnlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 27124/nginx: master
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 27124/nginx: master
tcp6 0 0 :::443 :::* LISTEN 27124/nginx: master
tcp6 0 0 :::80 :::* LISTEN 27124/nginx: master
ちなみに、centos7で、nginxのバージョンは1.6.3です。
投稿日時:2015年12月07日 14:22
カテゴリー:
nginx
昨日書いた記事を検証してみた。
以下3つの例を検証。
1.単純ケース
@WebServlet(name = "test01", urlPatterns = {"/test01"})
public class Test01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
try (PrintWriter writer = resp.getWriter();) {
resp.setStatus(200);
resp.setContentType("text/plain");
writer.write("name is " + name);
writer.flush();
writer.close();
}
}
}
2.絶対ダメなケース
@WebServlet(name = "test02", urlPatterns = {"/test02"})
public class Test02 extends HttpServlet {
private String name;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
name = req.getParameter("name");
try (PrintWriter writer = resp.getWriter();) {
resp.setStatus(200);
resp.setContentType("text/plain");
writer.write("name is " + name);
writer.flush();
writer.close();
}
}
}
3.今回検証したかったケース
@WebServlet(name = "test03", urlPatterns = {"/test03"})
public class Test03 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
new MyClass(req, resp).execute();
}
class MyClass {
private HttpServletRequest req;
private HttpServletResponse resp;
private String name;
public MyClass(HttpServletRequest req, HttpServletResponse resp) {
this.req = req;
this.resp = resp;
name = req.getParameter("name");
}
public void execute() throws IOException {
try (PrintWriter writer = resp.getWriter();) {
resp.setStatus(200);
resp.setContentType("text/plain");
writer.write("name is " + name);
writer.flush();
writer.close();
}
}
}
}
結論としては、3は大丈夫であった。
jmeterで同時接続100を10回やって、一度も不整合は起きず。
投稿日時:2015年11月27日 14:52
カテゴリー:
java
servletはエントリーポイントのインスタンスは1つしか作成しない。
そして、それが複数スレッドで共有される。
そのため、インスタンスフィールドはスレッドセーフにならない。
・スレッドセーフではない例
public class TestServlet extends HttpServlet {
private String name;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
name = req.getParameter("name");
PrintWriter writer = res.getWriter();
writer.print(name);
}
}
で、ここからがわからんところなのだが、
ローカル変数はスレッドセーフになるのだから、
doGetの処理の中で、以下のようなことをしたら、問題ないのか?
public class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
new MyClass(req, res).execute();
}
}
public class MyClass {
private HttpServletRequest req;
private HttpServletResponse res;
public MyClass(HttpServletRequest req, HttpServletResponse res) {
this.req = req;
this.res = res;
}
public void execute() {
String name = req.getParameter("name");
PrintWriter writer = res.getWriter();
writer.print(name);
}
}
もし、上記でスレッドセーフになるっていうなら、
それでよくね?って思っちゃう。
それとも、MyClassのインスタンスフィールドは実はスレッドセーフではないのか?
メモリ使用量としては、生成するインスタンス分大きいのはわかるが、
もし上記で解決するなら、煩わしいスレッド問題とはオサラバできると思うのだが、
問題あるのだろうか?
servletはフレームワークの世界だから、厳密にわかる人は少ないのだろうけど、
ここは教えて欲しい。。。
・・・後日
上の例は大丈夫だった。
新しく記事を書きました。
投稿日時:2015年11月26日 19:58
カテゴリー:
java
RDBで大量のselectをしたら、
DBサーバの負荷は重いのだろうか?
例えば、1億レコードが入っているテーブルに対して、
select * from [table]
したら、DBサーバの負荷は重いのだろうか?
個人的に思うところとして、
サーバ側は、クライアント側に一定のバッファで
結果を返すことにのみ注力しているのであれば、
少々ネットワークは忙しくなるかもしれないが、
サーバのシステム負荷(CPU使用率、メモリ使用率)は低いんじゃないか?
って考えてます。
誰か教えて欲しいわ。。
ソースコード見るしかないかね。。
この仮定が成立するとすれば、
インデックスがない環境で複雑なクエリーを発行するより、
一気に大量レコードを引いて、
アプリケーションプログラムで分散並列で処理しちゃえば、いいんじゃないの?って思う。
Hadoopは詳しくないけど、似たようなものなのかな?
ちょっと勉強してみようかな。。
投稿日時:2015年11月26日 13:07
カテゴリー:
rdb
AWSのRDSにmariadbが追加されましたね。
xtradbのサポートはあるようだけど、
mariadbのクラスター関連のエンジンはサポートしていない感じがする。
AWSの場合、Auroraがあるから、mariadb流行らないかも。。
クラスター関連をサポートしてくれないかな。。
投稿日時:2015年11月17日 13:19
カテゴリー:
aws,
mariadb
windows10にvirtualbox5を入れて、
ゲストOSをローカルネットワーク内に参加させる方法が、
windows8とvirtualbox4のときと異なったので、
メモしておく。
以前は、wifiとホストオンリーアダプタでブリッジを作っていたが、
今回はブリッジのみでいけるが、Oracleのドライバーが必要らしい。
(前提)
- ホストOSのアドレスは192.168.1.10
- ゲストOSのアドレスは192.168.1.15
- 他ホストのアドレスを192.168.1.11
とする。
手順1. Oracleのドライバーを入れる
ホストオンリーアダプタのプロパティから、以下の画面を開き、
「VirtualBox NDIS6〜」なるものをインストールする。

立ち上がった画面で、「サービス」を選択して追加する。

「「VirtualBox NDIS6〜」なるものを選択して「OK」を押す。

これで、ok。
手順2. ゲストOSのネットワークにブリッジアダプターを選択する
ゲストOSの設定で、ブリッジアダプターを選択する。

手順3. ゲストOSのネットワークを固定IPに設定する
今回は192.168.1.15とする。
これで、ゲスト側のネットワークを起動すれば、
192.168.1.11のような同一ネットワーク内の他ホストから接続可能となる。
もちろん、firewall等もあるから、そこは適宜設定。
以上
投稿日時:2015年11月06日 13:49
カテゴリー:
virtualbox,
windows
java8でラムダ式を始めてみて、
こりゃscalaも勉強しとかなきゃあかんな、
と思い、scalaをダウンロードしにいったら、
TypesafeActivatorもあったから、こっちでやることにした。
1.まずsbtをいれる
# port install sbt
2.次にeclipseのscalaプラグインを入れる
マーケットプレイスにもある。
3.そしてsbtをダウンロードして、パスを通す
# cd /opt
# curl -O "http://downloads.typesafe.com/typesafe-activator/1.3.6/typesafe-activator-1.3.6.zip"
# unzip typesafe-activator-1.3.6.zip
# ln -s /opt/typesafe-activator-1.3.6 /opt/typesafe-activator
# echo "export PATH=$PATH:/opt/activator-dist" >> /etc/profile
# source /etc/profile
これで、activatorコマンドが実行できるようになった。
4.eclipseプロジェクトへの変換
activator new
とかで新規プロジェクトの雛形をつくってくれるので、
そのプロジェクトに移動後、
$ sbt eclipse
ってやれば、eclipseへのインポートが可能になる。
なんか、
activator eclipse
とか、plugin.sbtに追加しろとかあるけど、
どれも不要だった。。
投稿日時:2015年10月29日 16:28
カテゴリー:
scala
ラムダ式が導入されて(java8)結構たちましたが、
あまりやる気がしなかったが、
重い腰を上げて、おれおれフレームワークに少しづつ適用中。
いろいろ例はあるが、やはりコレクションには適用しやすい。
二元ループをするケースで結構はまったので、
メモを残しておく。
(例)URLのBodyパラメータを手作業で分解する場合
Bodyパラメータはこんな感じを想定
hoge=1&fuga=2&piyo[]=1&piyo[]=2
ここではInputStreamから抜かないで、一度分解したのち、文字列に戻すということをやる。
これを従来の処理でやると以下になる。
Map<String, List<String>> paramsBody = new LinkedHashMap<String, List<String>>();
StringBuffer buffer = new StringBuffer();
// サーブレットリクエストからパラメータの情報をとる
Map<String, String[]> params = servletRequest.getParameterMap();
// 回しながら、List型に変換して、さらに文字列を構築する
String sep = "";
for (Iterator<Entry<String, String[]>> iterator = params.entrySet().iterator(); iterator.hasNext();) {
Map.Entry<String, String[]> entry = (Map.Entry<String, String[]>) iterator.next();
String name = entry.getKey();
String[] values = entry.getValue();
if (!paramsBody.containsKey(name)) {
paramsBody.put(name, new ArrayList<String>(Arrays.asList(values)));
}
for (String value : values) {
buffer.append(sep).append(name).append("=").append(WsUrl.decode(value, encoding));
sep = "&";
}
body = buffer.toString();
}
おなじことをラムダ式をつかうと、
Map<String, List<String>> paramsBody = new LinkedHashMap<String, List<String>>();
StringBuffer buffer = new StringBuffer();
// サーブレットリクエストからパラメータの情報をとる
Map<String, String[]> params = servletRequest.getParameterMap();
// 回しながら、List型に変換して、さらに文字列を構築する
String paramString = params.entrySet()
.stream()
.map(entry -> {
String name = entry.getKey();
return Arrays.stream(entry.getValue())
.map(value -> String.format("%s=%s", name, WsUrl.decode(value, encoding)))
.collect(Collectors.joining("&"));
})
.collect(Collectors.joining("&"));
buffer.append(paramString);
body = buffer.toString();
ここまでくるのに結構大変だった。。
投稿日時:2015年10月29日 16:28
カテゴリー:
java
td-agentはプラグインが豊富だけど、
結構品質(というか、どこまで想定して作られているか)がよくないものが多いように感じる。
OSS時代の申し子的な存在だけど、
意外にプラグインの品質が悪くて、修正してしまうケースもある。
本体はとても優れたプロダクトですが、
プラグインの品質は優劣が激しいので、
気をつけましょう。
・・・それに毎回設定で苦労してるから、
td-agentに代わるものを、akkaで作りたいな。。
投稿日時:2015年10月26日 17:09
カテゴリー:
server
MySQLでは、
・truncate
・load in file
・create
などの一部はトランザクションが効かないのね。。
また、load in fileは、
replaceキーワードを使えば、主キーが存在していれば、
updateを行ってくれるのね。。
基本的なことだろうけど、知らなかったわ。。
load in fileの例(RDSにて)
LOAD DATA LOCAL INFILE '${file_path}' REPLACE INTO TABLE ${table_name} FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n'
投稿日時:2015年10月08日 19:17
カテゴリー:
mysql