PAAS的架構設計與應用實踐(二)

四、PaaS應用實踐

1.    應用部署條件

  • APP的應用開發原則

    應用必須遵從無狀態規則,只有遵從無狀態規則才能避免容器故障帶來的單點問題。 

  • APP的應用部署yaml規範

Web應用:

  

 

Work應用:

  

 

Yaml規範:

 

  

 

  • 容器內置環境變量(後續有例子)

      $WEB_PORT、$APPID、$LOG_FILE, $INSTANCEID, $USER_DIR

 

2.如何部署應用

 

第一步:選擇應用類型、環境、實例配置等信息。

 

  

 

 

第二步:創建成功,默認生成一個應用。

  

 

 

 

第三步:利用web方式上傳應用zip包,應用描述yaml文件非常重要。

  

 

第四步:應用日誌相關配置。

日誌輸出位置要嚴格要求的,不能隨便自定義路徑,只能輸出到 /opt/logs目錄下,而且自定義的日誌文件是不會被採集和保存的,如果想要被PAAS平臺收集並保存必須寫到它們預定義的環境變量 ${LOG_FILE}中,提供一個log4j的配置片段,如下:

 

log4j.rootCategory=INFO,FILE

 

log4j.appender.A1=org.apache.log4j.ConsoleAppender

log4j.appender.A1.layout=org.apache.log4j.PatternLayout

log4j.appender.A1.layout.ConversionPattern=[%d{yyyy-MM-dd HH\:mm\:ss}]%-5p %c(line\:%L) %x-%m%n

 

log4j.appender.FILE=org.apache.log4j.DailyRollingFileAppender

log4j.appender.FILE.Threshold = INFO

log4j.appender.FILE.File=${LOG_FILE}

log4j.appender.FILE.layout=org.apache.log4j.PatternLayout

log4j.appender.FILE.layout.ConversionPattern=[%d{yyyy-MM-dd HH\:mm\:ss}]%-5p %c(line\:%L) %x-%m%n

 

第五步:除了提供日誌搜索,監控視圖和安全策略外,還提供SSH功能。

  

 

 

提供了爲每個實例單獨的開啓SSH管理功能,需要上傳了公鑰,然後開發者可以直接登陸,但僅有app權限,限定其存儲空間和可操作的命令。

根據提供的ssh命令,可以登錄到容器進行查看了。

 

  

 

3.如何使用服務

 

PAAS平臺還應提供的服務,mysql,memcache,redis,storage等基本服務都支持,滿足了應用的需求,僅以使用redis爲例介紹一下如何使用redis的緩存服務功能。

第一步:需要到服務中去申請一個redis服務,可以自定義服務名稱。

  

 

第二步:PAAS針對申請Redis服務提供一個URL可用的服務列表,然後也提供了獲取服務列表認證所需要的uid和password。

  

第三步:應用程序使用申請Redis服務時,建議使用提供的uid和password來動態獲取配置信息,這樣支持動態配置生效。

//獲取redis服務列表

static List<RedisInstanceNode> getNodes(String uid, String password) throws ServiceException {

              Map<String, String> params = ParamUtils.getDefaultParams();

              params.put("uid", uid);

              params.put("password", password);

              String endpoint = "http://internal.cloudscape.com";

              String action = "/redis/service_instance/nodes";

              String url = endpoint + action;

              int timeout = HttpUtils.getRestTimeout();

              if (httpService == null) {

                     httpService = new HttpServiceImpl();

              }

              HttpService.HttpResult result = httpService.httpGet(url, params, timeout);            

 

              String info = result.getResult();

              Map<String, JsonNode> res = JsonUtils.readValueAsJson(info);

              JsonNode nodesJson = res.get(ApiKeys._nodes);

              if (nodesJson == null || nodesJson.isNull()) {

                     log.info("open api return error message, appinfos is empty , code: " + result.getCode() + ", message: "

                                   + res.get(ApiKeys._message));

                     return Collections.emptyList();

              }

 

              List<RedisInstanceNode> list = (List<RedisInstanceNode>) JsonUtils.readValueAsList(

                            JsonUtils.writeValueAsString(nodesJson), ArrayList.class, RedisInstanceNode.class);

              return list;

//根據返回的實例nodes列表構建redis 連接池。

private static ShardedJedisPool pool;

for (RedisInstanceNode redis : nodes) {

             String ip = redis.getIp();

             int port = redis.getPort();

             int master = redis.getIsMaster();

             JedisShardInfo jsi;

             if (master == 1) {

                 jsi = new JedisShardInfo(ip, port, "master");

                 jsi.setPassword(key);

                 jsi.setTimeout(3600000);

                 shards.add(jsi);

             } else {

                 continue;

             }

        }

        JedisPoolConfig jpc = new JedisPoolConfig();

         jpc.setMaxActive(500);// 最大活動實例數目

         jpc.setMaxIdle(200);// 最大停止實例數目

         jpc.setMaxWait(5000);// 最大等待時間

        jpc.setTestOnBorrow(false);

 

        pool = new ShardedJedisPool(jpc, shards); 

//使用連接池,進行數據setget

 

                     try {

                                jedis = pool.getResource();

                                jedis.setex("test-key", defaultTimeout, "test-value");

                     } catch (Exception ex) {

                                log.error(ex.getMessage(), ex);

                                if (jedis != null) {

                                          pool.returnBrokenResource(jedis);

                                }

                     } finally {

                                if (jedis != null) {

                                          pool.returnResource(jedis);

                                }

                     }

 

其他幾個服務類似,最關鍵針對不同的服務要具有分佈式的特性,就是針對不同開源服務組件進行二次開發,以服務插件方式集成到平臺上,提供不同應用使用。同時,要考慮組件監控與報警機制,爲應用開發者提供一站式平臺。

 

五、PaaS其他功能

 

1.實例配置

 

   應用可以根據業務評估所需資源,支持最小最大動態實例配置 ,支持根據規則引擎動態自動縮擴容。

 

2.綁定域名

 

   應用不僅僅提供默認域名,還可以綁定業務自有域名。

 

3.綁定服務

 

   應用可以申請依賴中間件服務,並設置配額和權限。

 

4.粘性會話

 

    應用可以開啓粘性會話,儘可能保持用戶訪問狀態,但若存在實例調度,會影響部分用戶狀態有效性。完美方案,建議採用分佈式緩存來保持有效性。

 

5.應用監控

 

   圍繞Node、Container和App三個維度的指標分析爲應用提供可視化展示。

 

6.應用日誌

 

    基於ES搭建了一套搜索應用日誌的功能。

 

7.應用安全

 

  對於應用層提供UA阻斷、IP名單、流量限制;

  對於網絡層,  爲應用採用ovs+floodlight控制容器與服務的隔離。

 

    

    

8.應用授權

 

   提供了應用授權給非管理員之外角色也擁有管理APP能力。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章