Recently we need use some features which provided by the new Nginx release. And the current package is provided by the company's system team and they don't provide a new version package. So we need build it by ourselves.
Because the orignal package is installed by yum and we want to deploy new package by different method, so putting the new package in different place maybe better. So we face such a problem:
We want to upgrade Nginx to a new version, and the new version binary and all its dependency is put in different place. In the same time, the server must provide serivce continous without downtime.
Nginx release 1.9.1 introduces a new feature that enables use of SO_REUSEPORT. With this we can complete the task.
Operation Steps
First we compile new Nginx release and set absolute path for --prefix etc. Deploy the output on the machine. Enables reuseport directive for new packages.
Start another Nginx master using <NEW_PACKAGE>/sbin/nginx. Because reuseport enabled, we can start two masters by hand. And then stop master launched by <OLD_PACKAGE>/sbin/nginx gracefully. After 'old' nginx master stopped, <NEW_PACKAGE>/run/nginx.pid maybe deleted, because we have two masters write its process id into same file. We just generate this file for the last master by hand.
Remove reuseport directive in configure file, and then reload Nginx.
The StartupPlugin allows users to interact with the OpenTSDB configuration as soon as it is completely parsed, just before OpenTSDB begins to use it. 服务初始化时,准备提供服务时,退出时,会调用plugin接口。代码中没有提供已实现的Startup Plugin。
// File: PipelineFactory.java // Line: 132 /** * Dynamically changes the {@link ChannelPipeline} based on the request. * If a request uses HTTP, then this changes the pipeline to process HTTP. * Otherwise, the pipeline is changed to processes an RPC. */ finalclassDetectHttpOrRpcextendsFrameDecoder{
@Override protected Object decode(final ChannelHandlerContext ctx, final Channel chan, final ChannelBuffer buffer)throws Exception { if (buffer.readableBytes() < 1) { // Yes sometimes we can be called returnnull; // with an empty buffer... }
finalint firstbyte = buffer.getUnsignedByte(buffer.readerIndex()); final ChannelPipeline pipeline = ctx.getPipeline(); // None of the commands in the RPC protocol start with a capital ASCII // letter for the time being, and all HTTP commands do (GET, POST, etc.) // so use this as a cheap way to differentiate the two. if ('A' <= firstbyte && firstbyte <= 'Z') { pipeline.addLast("decoder", new HttpRequestDecoder()); if (tsdb.getConfig().enable_chunked_requests()) { pipeline.addLast("aggregator", new HttpChunkAggregator( tsdb.getConfig().max_chunked_requests())); } // allow client to encode the payload (ie : with gziped json) pipeline.addLast("inflater", new HttpContentDecompressor()); pipeline.addLast("encoder", new HttpResponseEncoder()); pipeline.addLast("deflater", new HttpContentCompressor()); } else { pipeline.addLast("framer", new LineBasedFrameDecoder(1024)); pipeline.addLast("encoder", ENCODER); pipeline.addLast("decoder", DECODER); }
// File: UniqueId.java // Line: 517 /** * Create the reverse mapping. * We do this before the forward one so that if we die before creating * the forward mapping we don't run the risk of "publishing" a * partially assigned ID. The reverse mapping on its own is harmless * but the forward mapping without reverse mapping is bad as it would * point to an ID that cannot be resolved. */ private Deferred<Boolean> createReverseMapping(final Object arg){ if (!(arg instanceof Long)) { thrownew IllegalStateException("Expected a Long but got " + arg); } id = (Long) arg; if (id <= 0) { thrownew IllegalStateException("Got a negative ID from HBase: " + id); } LOG.info("Got ID=" + id + " for kind='" + kind() + "' name='" + name + "'"); row = Bytes.fromLong(id); // row.length should actually be 8. if (row.length < id_width) { thrownew IllegalStateException("OMG, row.length = " + row.length + " which is less than " + id_width + " for id=" + id + " row=" + Arrays.toString(row)); } // Verify that we're going to drop bytes that are 0. for (int i = 0; i < row.length - id_width; i++) { if (row[i] != 0) { final String message = "All Unique IDs for " + kind() + " on " + id_width + " bytes are already assigned!"; LOG.error("OMG " + message); thrownew IllegalStateException(message); } } // Shrink the ID on the requested number of bytes. row = Arrays.copyOfRange(row, row.length - id_width, row.length);
state = CREATE_FORWARD_MAPPING; // We are CAS'ing the KV into existence -- the second argument is how // we tell HBase we want to atomically create the KV, so that if there // is already a KV in this cell, we'll fail. Technically we could do // just a `put' here, as we have a freshly allocated UID, so there is // not reason why a KV should already exist for this UID, but just to // err on the safe side and catch really weird corruption cases, we do // a CAS instead to create the KV. return client.compareAndSet(reverseMapping(), HBaseClient.EMPTY_ARRAY); }