1,平臺的服務器總體架構redis
2,項目結構算法
3,業務結構數據庫
4,技術實現json
5,業務舉例緩存
登陸頁:服務器
登陸:cookie
其它的服務只是業務不一樣,這裏省略...架構
6,應用的啓動過程資源準備併發
7,json的封裝app
public static void CrossDomain2(HttpServletResponse response, HttpServletRequest request, Object msg) throws IOException {
response.setContentType("application/json");
final String call = request.getParameter("callBack");
final ObjectMapper mapper = new ObjectMapper();
String resp = mapper.writeValueAsString(msg);
if (!Strings.isNullOrEmpty(call)) {resp = call + "(" + resp + ")";}
PrintWriter out = response.getWriter();
out.write(resp);
out.flush();
out.close(); }
8,cookie域的算法
//構造cookie
final long time = System.currentTimeMillis();
String userId = String.valueOf(uid);
String USERINFO = userId + "," + userName + "," + time;
String u = Base64.encode(USERINFO + "," +
buildUserInfoSign(String.valueOf(userId), userName, String.valueOf(time)));
u = URLEncoder.encode(u, "utf-8");
String key = URLEncoder.encode(Base64.encode("USERINFO"), "UTF-8");
Cookie cookie = new Cookie(key, u);
//構造cookie加密部分
public static String buildUserInfoSign(String id, String name, String time) {
String userInfoSrc = id + name + time;
String key = ConfigurationUtils.get("login.cookieKey");
String userInfo = userInfoSrc + key;
String md5UserInfo = MD5Utils.digestAsHex(userInfo);
return md5UserInfo;
}
//解析cookie
public static int getUserId(HttpServletRequest request) {
int userId = 0;
String value = getCookieValueByKey(request);
if (!Strings.isNullOrEmpty(value)) {
String val[] = value.split(",");
userId = Integer.parseInt(val[0]);
}
return userId;
}
public static String getCookieValueByKey(HttpServletRequest request) {
String value = "";
Cookie[] cookies = request.getCookies();
String name = "USERINFO";
try {
name = Base64.encode(name);
name = URLEncoder.encode(name, "utf-8");
} catch (Exception e) {
log.error("USERINFO解碼出錯!{}", e.getMessage());
}
if (cookies != null && cookies.length > 0) {
for (Cookie cookie : cookies) {
String nameStr = cookie.getName();
if (nameStr.equals(name)) {
value = cookie.getValue();
break;
}
}
}
if (!Strings.isNullOrEmpty(value)) {
try {
value = URLDecoder.decode(value, "UTF-8");
value = Base64.decode2Str(value);
} catch (Exception e) {
log.error("URL解碼出錯!{}", e.getMessage());
}
String val[] = value.split(",");
String sign = buildUserInfoSign(val[0], val[1], val[2]);
if (!Strings.isNullOrEmpty(sign) && !Strings.isNullOrEmpty(val[3]) && sign.equals(val[3])) {
return value;
} else {
return "";}
}
return "";
}
9,http的理解和封裝
public class HeadlessServlet extends HttpServlet implements InjectionProxy
裏面加了一個對自定以的註解的過濾;
protected boolean filters(final HeadlessServletRequest request, final HeadlessServletResponse response) throws ServletException, IOException {
final Parameter parameter = this.getClass().getAnnotation(Parameter.class);
if (null == parameter)
return true;// filter methods
if (!Strings.isNullOrEmpty(parameter.method()) && !request.getMethod().equalsIgnoreCase(parameter.method())) {
notFound(response);
return false;
}
// filter parameters
boolean flag = true, emptyCheck = false;
try {
final Map<String, String[]> parameterMap = request.getParameterMap();
for (String name : parameter.value()) {
if (name.endsWith(":")) {
name = name.substring(0, name.length() - 1);
emptyCheck = true;
}
flag = parameterMap.containsKey(name);
if (emptyCheck) {
// must has parameter.
flag = flag && parameterMap.get(name) != null;
flag = flag && parameterMap.get(name).length > 0;
flag = flag && !Strings.isNullOrEmpty(parameterMap.get(name)[0]);
}
if (!flag)
break;
emptyCheck = false;
}
return flag;
} finally {
if (!flag) {
response.sendInvalidParameters();
}
}
}
10,db設計
11,老平臺小結
老平臺採用的架構很簡單,一個Guice+Servlet,簡單的把一個url映射到一個特定的Servlet, 這裏借用Guice-servlet,省去了原生的servlet配置文件複雜的嫌疑,簡單的使用Guice容器, 把所需資源按照分類和層級一一放到容器中初始化,簡化了實例化的過程,提升了效率;業 務也不復雜,很容易從其它的遊戲平臺移植過來,業務的技術難點有兩個,一個是跟其它服 務器的交互和通訊,另一個是緩存的使用;對於跟其它服務器的交互,主要是基於http 請求,若是對這一部分比較熟悉,只要文檔給的比較規範,開發和調試起來仍是徹底沒有問 題的;而後是緩存的問題,這裏主要使用的Redis,一個key-value數據庫,經過把常常用的 數據從db中查詢出來,放到redis裏面,須要的時候從redis裏面取得,這大大提高了性能, 若是redis不穩定,能夠直接從db裏取得,保證了程序的健壯性;暫未進行過併發性測試, 目前能支撐2000w用戶的使用已經算是一個還不錯的架構。 |