当サイトは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