Initial code import
[msb/apigateway.git] / apiroute / apiroute-service / src / main / java / org / openo / msb / ApiRouteApp.java
1 /**\r
2 * Copyright (C) 2016 ZTE, Inc. and others. All rights reserved. (ZTE)\r
3 *\r
4 * Licensed under the Apache License, Version 2.0 (the "License");\r
5 * you may not use this file except in compliance with the License.\r
6 * You may obtain a copy of the License at\r
7 *\r
8 * http://www.apache.org/licenses/LICENSE-2.0\r
9 *\r
10 * Unless required by applicable law or agreed to in writing, software\r
11 * distributed under the License is distributed on an "AS IS" BASIS,\r
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13 * See the License for the specific language governing permissions and\r
14 * limitations under the License.\r
15 */\r
16 \r
17 package org.openo.msb;\r
18 \r
19 import io.dropwizard.Application;\r
20 import io.dropwizard.assets.AssetsBundle;\r
21 import io.dropwizard.jetty.HttpConnectorFactory;\r
22 import io.dropwizard.server.SimpleServerFactory;\r
23 import io.dropwizard.setup.Bootstrap;\r
24 import io.dropwizard.setup.Environment;\r
25 import io.swagger.jaxrs.config.BeanConfig;\r
26 import io.swagger.jaxrs.listing.ApiListingResource;\r
27 \r
28 import java.io.BufferedWriter;\r
29 import java.io.File;\r
30 import java.io.FileNotFoundException;\r
31 import java.io.FileWriter;\r
32 import java.io.IOException;\r
33 import java.net.URL;\r
34 import java.util.List;\r
35 \r
36 import net.sf.json.JSONObject;\r
37 \r
38 import org.apache.commons.lang3.StringUtils;\r
39 import org.openo.msb.api.ApiRouteInfo;\r
40 import org.openo.msb.api.ConsulInfo;\r
41 import org.openo.msb.api.CustomRouteInfo;\r
42 import org.openo.msb.api.DiscoverInfo;\r
43 import org.openo.msb.api.IuiRouteInfo;\r
44 import org.openo.msb.api.RouteServer;\r
45 import org.openo.msb.api.exception.ExtendedNotFoundException;\r
46 import org.openo.msb.health.ApiRouteHealthCheck;\r
47 import org.openo.msb.resources.ApiRouteResource;\r
48 import org.openo.msb.resources.CustomRouteResource;\r
49 import org.openo.msb.resources.IuiRouteResource;\r
50 import org.openo.msb.resources.MetricsResource;\r
51 import org.openo.msb.resources.MicroServiceResource;\r
52 import org.openo.msb.resources.ServiceAccessResource;\r
53 import org.openo.msb.wrapper.ApiRouteServiceWrapper;\r
54 import org.openo.msb.wrapper.CustomRouteServiceWrapper;\r
55 import org.openo.msb.wrapper.IuiRouteServiceWrapper;\r
56 import org.openo.msb.wrapper.serviceListener.MicroServiceChangeListener;\r
57 import org.openo.msb.wrapper.util.FileUtil;\r
58 import org.openo.msb.wrapper.util.JacksonJsonUtil;\r
59 import org.openo.msb.wrapper.util.JedisUtil;\r
60 import org.openo.msb.wrapper.util.MetricsUtil;\r
61 import org.openo.msb.wrapper.util.MicroServiceDB;\r
62 import org.openo.msb.wrapper.util.RegExpTestUtil;\r
63 import org.openo.msb.wrapper.util.RouteUtil;\r
64 import org.slf4j.Logger;\r
65 import org.slf4j.LoggerFactory;\r
66 \r
67 import com.fasterxml.jackson.annotation.JsonInclude;\r
68 \r
69 public class ApiRouteApp extends Application<ApiRouteAppConfig> {\r
70 \r
71     private static final Logger LOGGER = LoggerFactory.getLogger(ApiRouteApp.class);\r
72 \r
73     public static void main(String[] args) throws Exception {\r
74         new ApiRouteApp().run(args);\r
75 \r
76     }\r
77 \r
78     private ApiRouteAppConfig config;\r
79 \r
80     @Override\r
81     public String getName() {\r
82         return " MicroService Bus ";\r
83     }\r
84 \r
85     @Override\r
86     public void initialize(Bootstrap<ApiRouteAppConfig> bootstrap) {\r
87         \r
88         \r
89     }\r
90 \r
91     @Override\r
92     public void run(ApiRouteAppConfig configuration, Environment environment) {\r
93         \r
94         initRootPath();\r
95         \r
96       \r
97         new AssetsBundle("/iui-metrics", "/"+RouteUtil.IUI_ROOT_PATH+"/microservices/metrics",\r
98             "index.html", "iui-metrics").run(environment); \r
99         \r
100         new AssetsBundle("/iui-route",  "/"+RouteUtil.IUI_ROOT_PATH+"/microservices", "index.html",\r
101                 "iui-microservices").run(environment); \r
102         \r
103         new AssetsBundle("/api-doc",  "/"+RouteUtil.IUI_ROOT_PATH+"/microservices/api-doc",\r
104             "index.html", "api-doc").run(environment);\r
105         \r
106         new AssetsBundle("/ext",  "/"+RouteUtil.IUI_ROOT_PATH+"/microservices/ext",\r
107             "index.html", "ext").run(environment);\r
108         \r
109         \r
110         \r
111 \r
112         final ApiRouteHealthCheck healthCheck =\r
113                 new ApiRouteHealthCheck(configuration.getDefaultWorkspace());\r
114         environment.healthChecks().register("template", healthCheck);\r
115         environment.jersey().register(new ApiRouteResource());\r
116         environment.jersey().register(new IuiRouteResource());\r
117         environment.jersey().register(new MetricsResource());\r
118         environment.jersey().register(new CustomRouteResource());\r
119         environment.jersey().register(new ServiceAccessResource());\r
120         environment.jersey().register(new MicroServiceResource());\r
121 \r
122         config = configuration;\r
123 \r
124         initSwaggerConfig(environment, configuration);\r
125         initRedisConfig(configuration);\r
126         checkRedisConnect();\r
127         initMetricsConfig(configuration);\r
128         initVisualRangeMatches();\r
129 \r
130         registerServiceChangeListener();\r
131 \r
132 \r
133     }\r
134 \r
135     private void initMetricsConfig(ApiRouteAppConfig configuration) {\r
136 \r
137         SimpleServerFactory simpleServerFactory =\r
138                 (SimpleServerFactory) configuration.getServerFactory();\r
139         HttpConnectorFactory httpConnectorFactory =\r
140                 (HttpConnectorFactory) simpleServerFactory.getConnector();\r
141         MetricsUtil.adminContextPath =\r
142                 "http://127.0.0.1:" + httpConnectorFactory.getPort()\r
143                         + simpleServerFactory.getAdminContextPath() + "/metrics";\r
144     }\r
145 \r
146     private void initSwaggerConfig(Environment environment, ApiRouteAppConfig configuration) {\r
147 \r
148         environment.jersey().register(new ApiListingResource());\r
149         environment.getObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);\r
150 \r
151         BeanConfig config = new BeanConfig();\r
152         config.setTitle("MicroService Bus rest API");\r
153         config.setVersion("1.0.0");\r
154         config.setResourcePackage("org.openo.msb.resources");\r
155         SimpleServerFactory simpleServerFactory =\r
156                 (SimpleServerFactory) configuration.getServerFactory();\r
157         String basePath = simpleServerFactory.getApplicationContextPath();\r
158         String rootPath = simpleServerFactory.getJerseyRootPath();\r
159 \r
160         rootPath = rootPath.substring(0, rootPath.indexOf("/*"));\r
161 \r
162         basePath =\r
163                 basePath.equals("/") ? rootPath : (new StringBuilder()).append(basePath)\r
164                         .append(rootPath).toString();\r
165 \r
166         LOGGER.info("getApplicationContextPath: " + basePath);\r
167         config.setBasePath(basePath);\r
168         config.setScan(true);\r
169     }\r
170     \r
171     \r
172     private void initRootPath(){\r
173         try {\r
174             \r
175             URL urlRootPath = ApiRouteApp.class.getResource("/ext/initUrlRootPath/initUrlRootPath.json");\r
176             if (urlRootPath != null) {\r
177                 String path = urlRootPath.getPath();\r
178     \r
179                 LOGGER.info("read initUrlRootPath:" + path);\r
180               \r
181                 String fileContent = FileUtil.readFile(path);\r
182                 JSONObject jsonObj = JSONObject.fromObject(fileContent);\r
183                 RouteUtil.IUI_ROOT_PATH=jsonObj.get("iuiRootPath").toString();\r
184                 RouteUtil.API_ROOT_PATH=jsonObj.get("apiRootPath").toString();\r
185                 }\r
186         } catch (Exception e) {\r
187             // TODO Auto-generated catch block\r
188             LOGGER.error("read  initUrlRootPath Files throw exception", e);\r
189         }\r
190         \r
191     }\r
192     private void initRedisConfig(ApiRouteAppConfig configuration) {\r
193 \r
194         String path = this.getClass().getProtectionDomain().getCodeSource().getLocation().getPath();\r
195         String jarPath = path.substring(0, path.lastIndexOf("/"));\r
196 \r
197         LOGGER.info("jarpath: " + jarPath);\r
198         LOGGER.info("getDefaultWorkspace " + configuration.getDefaultWorkspace());\r
199 \r
200         String confDir =\r
201                 jarPath + "/" + configuration.getDefaultWorkspace() + "/"\r
202                         + configuration.getPropertiesDir();\r
203         String propertiesPath = confDir + "/" + configuration.getPropertiesName();\r
204 \r
205         JedisUtil.propertiesPath = propertiesPath;\r
206 \r
207         LOGGER.info("propertiesPath: " + propertiesPath);\r
208         LOGGER.info("confDir: " + confDir);\r
209 \r
210         try {\r
211             File dirFile = new File(confDir);\r
212 \r
213             if (!dirFile.exists()) {\r
214                 dirFile.mkdirs();\r
215             }\r
216         } catch (Exception e) {\r
217             // TODO Auto-generated catch block\r
218             LOGGER.info("create RedisConfig confDir error: " + confDir + e.getMessage());\r
219         }\r
220 \r
221 \r
222         try {\r
223             File propertiesFile = new File(propertiesPath);\r
224             if (!propertiesFile.exists()) {\r
225 \r
226 \r
227                 propertiesFile.createNewFile();\r
228 \r
229                 BufferedWriter output = new BufferedWriter(new FileWriter(propertiesFile));\r
230                 StringBuilder contentBuilder = new StringBuilder();\r
231                 contentBuilder.append("redis.host=127.0.0.1\n").append("redis.port=6379\n")\r
232                         .append("#connectionTimeout\n").append("redis.connectionTimeout=2000\n")\r
233                         .append("#redis dbIndex,defaule:0\n")\r
234                         .append("redis.db_index=0\n\n")\r
235                         .append("#--------------redis pool config--------------\n")\r
236                         .append("#maxTotal\n").append("redis.pool.maxTotal=100\n")\r
237                         .append("#maxIdle\n").append("redis.pool.maxIdle=20\n")\r
238                         .append("#maxWaitMillis:ms\n")\r
239                         .append("redis.pool.maxWaitMillis=1000\n")\r
240                         .append("#testOnBorrow\n")\r
241                         .append("redis.pool.testOnBorrow=false\n")\r
242                         .append("#testOnReturn\n")\r
243                         .append("redis.pool.testOnReturn=true\n")\r
244                         .append("#nginx Port\n").append("server.port=10080\n");\r
245 \r
246                 output.write(contentBuilder.toString());\r
247                 output.close();\r
248 \r
249             }\r
250         } catch (IOException e) {\r
251             // TODO Auto-generated catch block\r
252             LOGGER.info("create RedisConfig File error: " + propertiesPath + e.getMessage());\r
253         }\r
254     }\r
255 \r
256 \r
257     private void checkRedisConnect() {\r
258 \r
259         new Thread(new Runnable() {\r
260             public void run() {\r
261                 int n = 0;\r
262                 while (true) {\r
263                     if (ApiRouteServiceWrapper.checkRedisConnect() == false) {\r
264                         n++;\r
265                         System.out.println(n\r
266                                 + "/10 : Initial Route Configuration——redis connection fail...");\r
267 \r
268                         try {\r
269                             Thread.sleep(10000);\r
270                         } catch (InterruptedException e) {\r
271                             LOGGER.error("Thread.sleep throw except:"+e.getMessage());\r
272                         }\r
273 \r
274 \r
275                         if (n >= 10) {\r
276                             System.out.println("Initial Route Configuration fail,timeout exit");\r
277                             LOGGER.error("Initial Route Configuration——redis connection fail,timeout exit...");\r
278                             break;\r
279                         }\r
280                     } else {\r
281                         System.out.println("starting to initial Route Configuration");\r
282                         // initRouteInfoFromConfig();\r
283                         initRouteInfoFromJson();\r
284                         System.out.println("starting to initial consul Configuration");\r
285                         runConsulClientApp();\r
286 \r
287                         break;\r
288                     }\r
289                 }\r
290 \r
291             }\r
292         }).start();\r
293     }\r
294 \r
295 \r
296     \r
297 \r
298     /**\r
299      * @Title: initVisualRangeMatches\r
300      * @Description: TODO(According to the environment variable or a JSON file configuration initialization VisualRange filter conditions)\r
301      * @return: void\r
302      */\r
303     private void initVisualRangeMatches(){\r
304         try {\r
305             if(System.getenv("APIGATEWAY_VISUAL_RANGE")==null)\r
306             {\r
307             \r
308             URL visualRangePath = ApiRouteApp.class.getResource("/ext/initVisualRange/initVisualRangeMatches.json");\r
309             if (visualRangePath != null) {\r
310                 String path = visualRangePath.getPath();\r
311     \r
312                 LOGGER.info("read initVisualRangeMatches:" + path);\r
313               \r
314                 String fileContent = FileUtil.readFile(path);\r
315                 JSONObject jsonObj = JSONObject.fromObject(fileContent);\r
316                 String visualRangeArray=jsonObj.get("visualRange").toString();\r
317                 \r
318             \r
319                 RouteUtil.visualRangeMatches=StringUtils.split(visualRangeArray, ",");  \r
320              \r
321                 \r
322                \r
323                 }\r
324             }\r
325             else{\r
326                 RouteUtil.visualRangeMatches=StringUtils.split(System.getenv("APIGATEWAY_VISUAL_RANGE"), ",");\r
327             }\r
328         } catch (Exception e) {\r
329             // TODO Auto-generated catch block\r
330             LOGGER.error("read  initVisualRangeMatches Files or env(APIGATEWAY_VISUAL_RANGE) throw exception", e);\r
331         }\r
332     }\r
333 \r
334     /**\r
335      * @Title: initRouteInfoFromJson\r
336      * @Description: TODO(按照JSON文件配置初始化route数据)\r
337      * @return: void\r
338      */\r
339     private void initRouteInfoFromJson() {\r
340 \r
341         URL apiDocsPath = ApiRouteApp.class.getResource("/ext/initServices");\r
342         if (apiDocsPath != null) {\r
343             String path = apiDocsPath.getPath();\r
344 \r
345             LOGGER.info("read JsonFilefolder:" + path);\r
346 \r
347             try {\r
348                 File[] files = FileUtil.readFileFolder(path);\r
349                 for (int i = 0; i < files.length; i++) {\r
350                     File file = files[i];\r
351                     if (file.isFile() && file.getName().endsWith(".json")) {\r
352                         LOGGER.info("read JsonFile:" + file.getPath());\r
353                         String fileContent = FileUtil.readFile(file.getPath());\r
354                         saveInitService2redis(fileContent);\r
355                     } else {\r
356                         LOGGER.warn(file.getName() + " is not a right file");\r
357                     }\r
358                 }\r
359 \r
360 \r
361 \r
362             } catch (FileNotFoundException e) {\r
363                 // TODO Auto-generated catch block\r
364                 LOGGER.error("read  initServices Files throw FileNotFoundException", e);\r
365             } catch (IOException e) {\r
366                 // TODO Auto-generated catch block\r
367                 LOGGER.error("read  initServices Files throw IOexception", e);\r
368             }\r
369 \r
370         }\r
371 \r
372 \r
373 \r
374     }\r
375 \r
376 \r
377 \r
378     private void saveInitService2redis(String fileContent) {\r
379         try {\r
380             List<ApiRouteInfo> routeList =\r
381                     (List<ApiRouteInfo>) JacksonJsonUtil.jsonToListBean(fileContent);\r
382             for (ApiRouteInfo route : routeList) {\r
383                 String url = route.getUrl();\r
384 \r
385                 if (RegExpTestUtil.urlRegExpTest(route.getServiceName())) {\r
386                     \r
387                     try{\r
388                     CustomRouteInfo dbCustomRoute =\r
389                             CustomRouteServiceWrapper.getInstance().getCustomRouteInstance(\r
390                                     route.getServiceName());\r
391                     }\r
392                     catch(ExtendedNotFoundException e){\r
393 \r
394                         LOGGER.info("initCustomRoute: ServiceName--" + route.getServiceName());\r
395 \r
396                         CustomRouteInfo customRouteInfo = new CustomRouteInfo();\r
397                         customRouteInfo.setControl(route.getControl());\r
398                         customRouteInfo.setServers(route.getServers());\r
399                         customRouteInfo.setServiceName(route.getServiceName());\r
400                         customRouteInfo.setStatus(route.getStatus());\r
401                         customRouteInfo.setUrl(route.getUrl());\r
402 \r
403 \r
404                         CustomRouteServiceWrapper.getInstance().saveCustomRouteInstance(\r
405                                 customRouteInfo, "");\r
406 \r
407 \r
408                     }\r
409                 } else {\r
410 \r
411                     if (RegExpTestUtil.apiRouteUrlRegExpTest(url) || url.startsWith("/api/microservices/")) {\r
412 \r
413 \r
414                         try{\r
415                         ApiRouteInfo dbApiRoute =\r
416                                 ApiRouteServiceWrapper.getInstance().getApiRouteInstance(\r
417                                         route.getServiceName(), route.getVersion());\r
418                         }\r
419                         catch(ExtendedNotFoundException e){\r
420                             LOGGER.info("initapiRoute: ServiceName--" + route.getServiceName());\r
421                             ApiRouteServiceWrapper.getInstance().saveApiRouteInstance(route, "");\r
422                         }\r
423 \r
424                        \r
425                     } else if (RegExpTestUtil.iuiRouteUrlRegExpTest(url)  || url.equals("/iui/microservices")) {\r
426                         \r
427                         try{\r
428                         IuiRouteInfo dbIuiRoute =\r
429                                 IuiRouteServiceWrapper.getInstance().getIuiRouteInstance(\r
430                                         route.getServiceName());\r
431                         }\r
432                         catch(ExtendedNotFoundException e){\r
433                     \r
434                             LOGGER.info(" initiuiRoute: ServiceName--" + route.getServiceName());\r
435                             IuiRouteInfo iuiRouteInfo = new IuiRouteInfo();\r
436                             iuiRouteInfo.setControl(route.getControl());\r
437                             iuiRouteInfo.setServers(route.getServers());\r
438                             iuiRouteInfo.setServiceName(route.getServiceName());\r
439                             iuiRouteInfo.setStatus(route.getStatus());\r
440                             \r
441                             if(url.equals("/iui/microservices")){\r
442                                 iuiRouteInfo.setUrl("/"+RouteUtil.IUI_ROOT_PATH+"/microservices");\r
443                             }\r
444                             else{\r
445                             iuiRouteInfo.setUrl(route.getUrl());\r
446                             }\r
447 \r
448                             IuiRouteServiceWrapper.getInstance().saveIuiRouteInstance(iuiRouteInfo);\r
449 \r
450                         }\r
451 \r
452                     } else {\r
453                         LOGGER.error("init Service throw exception——serviceName: " + route.getServiceName()+",url:"+url);\r
454                     }\r
455                 }\r
456 \r
457 \r
458 \r
459             }\r
460 \r
461         } catch (Exception e) {\r
462             // TODO Auto-generated catch block\r
463             LOGGER.error("read  initServices Files throw exception", e);\r
464         }\r
465 \r
466     }\r
467 \r
468 \r
469 \r
470     /**\r
471      * The listener registration service changes\r
472      */\r
473     private void registerServiceChangeListener() {\r
474         MicroServiceDB.getInstance().addServiceChangeListener(new MicroServiceChangeListener());\r
475     }\r
476 \r
477     // Open the consul to monitor subscription service\r
478     private void runConsulClientApp() {\r
479         DiscoverInfo config_discoverInfo = config.getDiscoverInfo();\r
480         \r
481         ConsulInfo config_consulInfo=config.getConsulInfo();\r
482         \r
483         RouteUtil.discoverInfo.setEnabled(config_discoverInfo.isEnabled());        \r
484         \r
485         if (config_discoverInfo.isEnabled()) {\r
486             try{\r
487             if(System.getenv("SDCLIENT_SVC_PORT")==null)\r
488             {\r
489                 //yml          \r
490                 RouteUtil.discoverInfo.setIp(config_discoverInfo.getIp()); \r
491                 RouteUtil.discoverInfo.setPort(config_discoverInfo.getPort());\r
492                 \r
493             }\r
494             else{\r
495                \r
496                  String  discoverAddress=System.getenv("SDCLIENT_SVC_PORT").split("//")[1];\r
497                  String sdIP=discoverAddress.split(":")[0];\r
498                  int sdPort=Integer\r
499                          .parseInt(discoverAddress.split(":")[1]);\r
500                  \r
501                  RouteUtil.discoverInfo.setIp(sdIP);\r
502                  RouteUtil.discoverInfo.setPort(sdPort);\r
503                  \r
504                  config_consulInfo.setIp(sdIP);\r
505                  config_consulInfo.setPort(sdPort);\r
506              \r
507                 \r
508             }\r
509             \r
510            \r
511                \r
512                 //Registration service discovery routing\r
513                 //api\r
514                 ApiRouteInfo discoverApiService=new ApiRouteInfo();\r
515                 discoverApiService.setServiceName("msdiscover");\r
516                 discoverApiService.setUrl("/api/microservices/v1");\r
517                 discoverApiService.setVersion("v1");\r
518                 discoverApiService.setMetricsUrl("/admin/metrics");\r
519                 discoverApiService.setApiJson("/api/microservices/v1/swagger.json");\r
520                 \r
521                 RouteServer[] servers=new RouteServer[1];\r
522                 servers[0]=new RouteServer(RouteUtil.discoverInfo.getIp(),String.valueOf(RouteUtil.discoverInfo.getPort()));\r
523                 discoverApiService.setServers(servers);\r
524              \r
525                 ApiRouteServiceWrapper.getInstance().saveApiRouteInstance(discoverApiService, "");\r
526                \r
527                 //iui\r
528                 IuiRouteInfo discoverIUIService=new IuiRouteInfo();\r
529                 discoverIUIService.setServiceName("msdiscover");\r
530                 discoverIUIService.setUrl("/iui/microservices");\r
531                 discoverIUIService.setServers(servers);\r
532                 IuiRouteServiceWrapper.getInstance().saveIuiRouteInstance(discoverIUIService);\r
533                 \r
534                \r
535 \r
536             ConsulClientApp consulClientApp = new ConsulClientApp(config_consulInfo.getIp(), config_consulInfo.getPort());\r
537             // Monitor service change\r
538             consulClientApp.startServiceListen();\r
539             LOGGER.info("start monitor consul service--" +config_consulInfo.getIp() + ":"\r
540                     + config_consulInfo.getPort());\r
541             }\r
542             catch(Exception e){\r
543                 LOGGER.error("start monitor consul service fail:"+e.getMessage()); \r
544             }\r
545         }\r
546         \r
547        \r
548     }\r
549 \r
550 }\r