@fastcar/template-microservices 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +124 -0
  3. package/package.json +35 -0
  4. package/template/.prettierrc +9 -0
  5. package/template/.vscode/launch.json +183 -0
  6. package/template/README.md +1 -0
  7. package/template/package.json +47 -0
  8. package/template/resource/application-dev.yml +56 -0
  9. package/template/resource/application.yml +2 -0
  10. package/template/src/annotation/AuthServiceRole.ts +76 -0
  11. package/template/src/annotation/EnableHotConfig.ts +13 -0
  12. package/template/src/app-node.ts +94 -0
  13. package/template/src/app-pm2.ts +191 -0
  14. package/template/src/common/Code.ts +26 -0
  15. package/template/src/common/Constant.ts +28 -0
  16. package/template/src/common/Result.ts +40 -0
  17. package/template/src/common/TaskAsync.ts +17 -0
  18. package/template/src/hotconfig/ExampleConfigService.ts +29 -0
  19. package/template/src/hotconfig/HotConfigInterface.ts +43 -0
  20. package/template/src/middleware/checkForm.ts +20 -0
  21. package/template/src/middleware/checkLogin.ts +25 -0
  22. package/template/src/middleware/parseSession.ts +44 -0
  23. package/template/src/servers/base/BaseServer.ts +120 -0
  24. package/template/src/servers/base/common/BackSessionEntryController.ts +33 -0
  25. package/template/src/servers/base/common/RemoteController.ts +70 -0
  26. package/template/src/servers/base/service/BackSessionService.ts +97 -0
  27. package/template/src/servers/base/service/CenterClient.ts +457 -0
  28. package/template/src/servers/base/service/DataService.ts +85 -0
  29. package/template/src/servers/base/service/RouterService.ts +185 -0
  30. package/template/src/servers/center/app.ts +14 -0
  31. package/template/src/servers/center/controller/EntryController.ts +89 -0
  32. package/template/src/servers/center/controller/ServerController.ts +62 -0
  33. package/template/src/servers/center/service/ServerManager.ts +336 -0
  34. package/template/src/servers/chat/RoomHandler.ts +65 -0
  35. package/template/src/servers/chat/RoomService.ts +24 -0
  36. package/template/src/servers/chat/app.ts +11 -0
  37. package/template/src/servers/connector/app.ts +13 -0
  38. package/template/src/servers/connector/controller/AccountHandler.ts +80 -0
  39. package/template/src/servers/connector/controller/ChannelRemote.ts +63 -0
  40. package/template/src/servers/connector/middleware/forwardMsg.ts +54 -0
  41. package/template/src/servers/web/HelloController.ts +51 -0
  42. package/template/src/servers/web/SyncConfigService.ts +13 -0
  43. package/template/src/servers/web/app.ts +15 -0
  44. package/template/src/types/ClientSimpleSession.ts +3 -0
  45. package/template/src/types/ForwardRpcContext.ts +3 -0
  46. package/template/src/types/ReqSession.ts +8 -0
  47. package/template/src/types/ResultType.ts +5 -0
  48. package/template/src/types/ServerMeta.ts +48 -0
  49. package/template/src/types/SessionAttribute.ts +13 -0
  50. package/template/src/utils/ConnectorUtils.ts +25 -0
  51. package/template/src/utils/MicroservicesUtils.ts +101 -0
  52. package/template/src/utils/NetWork.ts +31 -0
  53. package/template/src/utils/SessionUtil.ts +46 -0
  54. package/template/test/connector-test.ts +64 -0
  55. package/template/test/hello.ts +71 -0
  56. package/template/tsconfig.json +39 -0
@@ -0,0 +1,65 @@
1
+ import { Autowired, Controller, Rule, ValidForm } from "@fastcar/core/annotation";
2
+ import { InteractiveMode } from "@fastcar/rpc";
3
+ import { RPC, RPCMethod } from "@fastcar/rpc/annotation";
4
+ import RoomService from "./RoomService";
5
+ import Result from "@/common/Result";
6
+ import { SessionAttribute } from "@/types/SessionAttribute";
7
+ import { ForwardRpcContext } from "@/types/ForwardRpcContext";
8
+ import AuthServiceRole from "@/annotation/AuthServiceRole";
9
+ import { ServerKind } from "@/common/Constant";
10
+ import RouterService from "@/servers/base/service/RouterService";
11
+
12
+ @Controller
13
+ @RPC("/room")
14
+ export default class RoomHandler {
15
+ @Autowired
16
+ private roomService!: RoomService;
17
+
18
+ @Autowired
19
+ private routerService!: RouterService;
20
+
21
+ //加入世界
22
+ @RPCMethod()
23
+ @AuthServiceRole(ServerKind.remote)
24
+ join({}, { session }: ForwardRpcContext) {
25
+ this.roomService.add(session.settings.get(SessionAttribute.uid), session);
26
+ return Result.ok();
27
+ }
28
+
29
+ //离开世界
30
+ @RPCMethod()
31
+ @AuthServiceRole(ServerKind.remote)
32
+ leave({}, { session }: ForwardRpcContext) {
33
+ this.roomService.del(session.settings.get(SessionAttribute.uid));
34
+ return Result.ok();
35
+ }
36
+
37
+ //向别人发送消息
38
+ @RPCMethod()
39
+ @ValidForm
40
+ @AuthServiceRole(ServerKind.front)
41
+ sendMsg(
42
+ @Rule({
43
+ msg: { maxSize: 1000, required: true },
44
+ toUid: { required: true, type: "number" },
45
+ })
46
+ { msg, toUid }: { toUid: number; msg: string }
47
+ ) {
48
+ let otherSession = this.roomService.getSid(toUid);
49
+ if (!otherSession) {
50
+ return Result.ok();
51
+ }
52
+
53
+ this.routerService.request({
54
+ url: "/channelRemote/broadcastBySessionId",
55
+ serverType: "connector",
56
+ data: {
57
+ data: { data: msg, url: "/room/notify", mode: InteractiveMode.notify },
58
+ sessionId: otherSession.sessionId,
59
+ },
60
+ session: otherSession,
61
+ });
62
+
63
+ return Result.ok();
64
+ }
65
+ }
@@ -0,0 +1,24 @@
1
+ import { Service } from "@fastcar/core/annotation";
2
+ import { DataMap } from "@fastcar/core";
3
+ import { ClientSession } from "@fastcar/rpc";
4
+
5
+ @Service
6
+ export default class RoomService {
7
+ private onlineMap: DataMap<number, ClientSession>;
8
+
9
+ constructor() {
10
+ this.onlineMap = new DataMap();
11
+ }
12
+
13
+ add(uid: number, session: ClientSession) {
14
+ this.onlineMap.set(uid, session);
15
+ }
16
+
17
+ getSid(uid: number) {
18
+ return this.onlineMap.get(uid);
19
+ }
20
+
21
+ del(uid: number) {
22
+ this.onlineMap.delete(uid);
23
+ }
24
+ }
@@ -0,0 +1,11 @@
1
+ import checkForm from "@/middleware/checkForm";
2
+ import parseSession from "@/middleware/parseSession";
3
+ import { Application } from "@fastcar/core/annotation";
4
+ import { RPCMiddleware } from "@fastcar/rpc/annotation";
5
+ import BaseServer from "../base/BaseServer";
6
+
7
+ @Application
8
+ @RPCMiddleware(checkForm, parseSession)
9
+ class APP extends BaseServer {}
10
+
11
+ export default new APP();
@@ -0,0 +1,13 @@
1
+ import checkForm from "@/middleware/checkForm";
2
+ import checkLogin from "@/middleware/checkLogin";
3
+ import parseSession from "@/middleware/parseSession";
4
+ import { Application } from "@fastcar/core/annotation";
5
+ import { RPCMiddleware } from "@fastcar/rpc/annotation";
6
+ import forwardMsg from "./middleware/forwardMsg";
7
+ import BaseServer from "../base/BaseServer";
8
+
9
+ @Application
10
+ @RPCMiddleware(checkForm, parseSession, checkLogin, forwardMsg)
11
+ class APP extends BaseServer {}
12
+
13
+ export default new APP();
@@ -0,0 +1,80 @@
1
+ import { Autowired, Controller, Rule, ValidForm } from "@fastcar/core/annotation";
2
+ import { ClientSession, RpcContext, RpcServer } from "@fastcar/rpc";
3
+ import { RPC, RPCMethod } from "@fastcar/rpc/annotation";
4
+ import Result from "@/common/Result";
5
+ import { SessionAttribute } from "@/types/SessionAttribute";
6
+ import RouterService from "@/servers/base/service/RouterService";
7
+ import { ChannelKind, ServerKind } from "@/common/Constant";
8
+ import Code from "@/common/Code";
9
+ import DataService from "@/servers/base/service/DataService";
10
+
11
+ type DisconnectType = {
12
+ session: ClientSession;
13
+ reason: string;
14
+ };
15
+
16
+ @Controller
17
+ export default class AccountHandler {
18
+ @Autowired
19
+ private rpcServer!: RpcServer;
20
+
21
+ @Autowired
22
+ private routerService!: RouterService;
23
+
24
+ @Autowired
25
+ private dataService!: DataService;
26
+
27
+ @RPCMethod("/account/login")
28
+ @ValidForm
29
+ async login(
30
+ @Rule({
31
+ uid: { required: true, type: "number" },
32
+ })
33
+ { uid }: { uid: number },
34
+ ctx: RpcContext
35
+ ) {
36
+ //这边做一个校验 如果当前不是front连进来的则拒绝
37
+ let socketMgr = this.rpcServer.getSocketManager();
38
+ let socketServer = socketMgr.getSocketServerBySessionId(ctx.sessionId);
39
+
40
+ if (!socketServer?.getConfig().extra?.front) {
41
+ this.rpcServer.kickSessionId(ctx.sessionId, Code.COMMON.SERVER_CONNECT_FORBID.toString());
42
+ return Result.errorCode(Code.COMMON.SERVER_CONNECT_FORBID);
43
+ }
44
+
45
+ //这边可以进行校验
46
+ //加入频道 绑定会话
47
+ socketMgr.bindCustomID(uid.toString(), ctx.sessionId);
48
+ socketMgr.joinChannelByCustomId(uid.toString(), ChannelKind.FRONT);
49
+ ctx.settings.set(SessionAttribute.logged, true);
50
+ ctx.settings.set(SessionAttribute.uid, uid);
51
+ ctx.settings.set(SessionAttribute.serverKind, ServerKind.front);
52
+ ctx.settings.set(SessionAttribute.serviceId, this.dataService.getCurrServiceId());
53
+ ctx.settings.set(SessionAttribute.loginTime, Date.now());
54
+
55
+ this.routerService.request({
56
+ url: "/room/join",
57
+ serverType: "chat",
58
+ session: ctx,
59
+ });
60
+
61
+ //便于客户端同步
62
+ return Result.ok();
63
+ }
64
+
65
+ @RPCMethod()
66
+ async disconnect({ session, reason }: DisconnectType, ctx: RpcContext) {
67
+ let uid: number = ctx.settings.get(SessionAttribute.uid);
68
+ if (!!uid) {
69
+ this.rpcServer.getSocketManager().removeCustomID(uid.toString());
70
+
71
+ this.routerService.request({
72
+ url: "/room/leave",
73
+ serverType: "chat",
74
+ session,
75
+ });
76
+ }
77
+
78
+ return Result.ok();
79
+ }
80
+ }
@@ -0,0 +1,63 @@
1
+ import { Autowired, Controller, Log } from "@fastcar/core/annotation";
2
+ import { RpcServer, RpcMessage, InteractiveMode } from "@fastcar/rpc";
3
+ import { RPC, RPCMethod } from "@fastcar/rpc/annotation";
4
+ import AuthServiceRole from "@/annotation/AuthServiceRole";
5
+ import { ServerKind } from "@/common/Constant";
6
+ import Result from "@/common/Result";
7
+ import { Logger } from "@fastcar/core";
8
+
9
+ @Controller
10
+ @RPC("/channelRemote")
11
+ @AuthServiceRole(ServerKind.remote)
12
+ export default class ChannelRemote {
13
+ @Autowired
14
+ private rpcServer!: RpcServer;
15
+
16
+ @Log()
17
+ private logger!: Logger;
18
+
19
+ @RPCMethod()
20
+ addChannelByUid(data: { channel: string; uid: number }) {
21
+ this.rpcServer.getSocketManager().joinChannelByCustomId(data.uid.toString(), data.channel);
22
+ return Result.ok();
23
+ }
24
+
25
+ @RPCMethod()
26
+ delChannelByUid(data: { channel: string; uid: string }) {
27
+ this.rpcServer.getSocketManager().leaveChannelByCustomId(data.uid.toString(), data.channel);
28
+ return Result.ok();
29
+ }
30
+
31
+ //根据渠道广播
32
+ @RPCMethod()
33
+ broadcastByChannel(data: { channel: string; msg: RpcMessage; excludeIds?: string[] }) {
34
+ this.rpcServer.getSocketManager().sendMsgToCustomIdByChannel(data.channel, Object.assign(data.msg, { firstPriority: true }), data.excludeIds);
35
+ return Result.ok();
36
+ }
37
+
38
+ //根据单用户广播消息
39
+ @RPCMethod()
40
+ broadcastByUid(data: { data: RpcMessage; uid: number }) {
41
+ this.rpcServer.getSocketManager().sendMsgByCustomId(data.uid.toString(), Object.assign(data.data, { firstPriority: true }));
42
+ return Result.ok();
43
+ }
44
+
45
+ //消息踢掉
46
+ @RPCMethod()
47
+ logoutKick({ sessionId }: { sessionId: string }) {
48
+ this.rpcServer.getSocketManager().sendMsg(sessionId, {
49
+ url: "/logout/kick",
50
+ mode: InteractiveMode.notify,
51
+ });
52
+ //这边不强制删除
53
+ return Result.ok();
54
+ }
55
+
56
+ //强制踢掉
57
+ @RPCMethod()
58
+ forceKick({ sessionId }: { sessionId: string }) {
59
+ this.rpcServer.kickSessionId(sessionId, "force kick");
60
+ //这边不强制删除
61
+ return Result.ok();
62
+ }
63
+ }
@@ -0,0 +1,54 @@
1
+ import Code from "@/common/Code";
2
+ import RouterService from "@/servers/base/service/RouterService";
3
+ import { SessionAttribute } from "@/types/SessionAttribute";
4
+ import { CommonConstant, FastCarApplication } from "@fastcar/core";
5
+ import { RpcContext } from "@fastcar/rpc";
6
+
7
+ //转发消息
8
+ export default async function forwardMsg(context: RpcContext, next?: Function) {
9
+ let serverType: string = context.data?.serverType;
10
+
11
+ if (!serverType) {
12
+ //如果namespace是以://开头的
13
+ let index = context.url.indexOf(":/");
14
+ if (index != -1) {
15
+ serverType = context.url.substring(0, index);
16
+ context.url = context.url.substring(index + 2);
17
+ }
18
+ }
19
+
20
+ if (!!serverType) {
21
+ //这边加个二次重定向
22
+ let customServiceId = "";
23
+ let app: FastCarApplication = Reflect.get(global, CommonConstant.FastcarApp);
24
+ let selfServerType = app.getSetting(SessionAttribute.serverType);
25
+ //本地网关请求
26
+ if (selfServerType != serverType) {
27
+ //计算请求
28
+ let routerService = app.getComponentByTarget<RouterService>(RouterService);
29
+ if (!routerService) {
30
+ return (context.body = {
31
+ code: Code.SYS.NOT_FOUND,
32
+ });
33
+ }
34
+
35
+ let res = await routerService.request<{ [key: string]: any }, any>({
36
+ url: context.url,
37
+ data: context.data,
38
+ session: {
39
+ sessionId: context.sessionId,
40
+ settings: context.settings,
41
+ connectedTime: context.connectedTime,
42
+ },
43
+ serverType,
44
+ forward: true,
45
+ customServiceId,
46
+ });
47
+ context.body = res;
48
+ }
49
+ }
50
+
51
+ if (next) {
52
+ await next();
53
+ }
54
+ }
@@ -0,0 +1,51 @@
1
+ import { Autowired, Controller } from "@fastcar/core/annotation";
2
+ import { GET } from "@fastcar/koa/annotation";
3
+ import CenterClient from "../base/service/CenterClient";
4
+ import Result from "../../common/Result";
5
+ import RouterService from "../base/service/RouterService";
6
+
7
+ @Controller
8
+ export default class HelloController {
9
+ @Autowired
10
+ private centerClient!: CenterClient;
11
+
12
+ @Autowired
13
+ private routerService!: RouterService;
14
+
15
+ @GET("/")
16
+ hello() {
17
+ return this.routerService.request({
18
+ url: "/room/join",
19
+ serverType: "chat",
20
+ });
21
+ }
22
+
23
+ @GET("/serverList")
24
+ getServerList() {
25
+ return Result.ok(this.centerClient.getServerMap().toValues());
26
+ }
27
+
28
+ @GET("/test/rebalance")
29
+ async rebalance() {
30
+ let res = await this.centerClient.sendBalance();
31
+ return res;
32
+ }
33
+
34
+ @GET("/test/syncconfig")
35
+ syncConfig() {
36
+ this.routerService
37
+ .request({
38
+ url: "/center/syncConfig",
39
+ serverType: "center",
40
+ data: {
41
+ key: "SyncConfigService",
42
+ data: "hello world",
43
+ },
44
+ })
45
+ .then((res) => {
46
+ console.log(res);
47
+ });
48
+
49
+ return Result.ok();
50
+ }
51
+ }
@@ -0,0 +1,13 @@
1
+ import { Logger } from "@fastcar/core";
2
+ import { BeanName, Log, Service } from "@fastcar/core/annotation";
3
+
4
+ @BeanName("SyncConfigService")
5
+ @Service
6
+ export default class SyncConfigService {
7
+ @Log()
8
+ private logger!: Logger;
9
+
10
+ load(m: Object) {
11
+ this.logger.debug(`同步配置更新`, m);
12
+ }
13
+ }
@@ -0,0 +1,15 @@
1
+ import { Application } from "@fastcar/core/annotation";
2
+ import { EnableKoa, KoaMiddleware } from "@fastcar/koa/annotation";
3
+ import { ExceptionGlobalHandler, KoaBodyParser } from "@fastcar/koa";
4
+ import BaseServer from "../base/BaseServer";
5
+
6
+ @Application
7
+ //开启koa
8
+ //开启异常捕捉 可自定义 通常是放在中间件第一个
9
+ @KoaMiddleware(ExceptionGlobalHandler)
10
+ //开启参数解析
11
+ // @KoaMiddleware(KoaBody)
12
+ @KoaMiddleware(KoaBodyParser)
13
+ class APP extends BaseServer {}
14
+
15
+ export default new APP();
@@ -0,0 +1,3 @@
1
+ import { ClientSession } from "@fastcar/rpc";
2
+
3
+ export type ClientSimpleSession = Omit<ClientSession, "serverId">;
@@ -0,0 +1,3 @@
1
+ import { RpcContext, ClientSession } from "@fastcar/rpc";
2
+
3
+ export type ForwardRpcContext = { session: ClientSession; forward: boolean } & RpcContext;
@@ -0,0 +1,8 @@
1
+ import { CustomId } from "@fastcar/rpc";
2
+
3
+ export type ReqSession = {
4
+ sessionId: string;
5
+ connectedTime: number; //连接的开始时间
6
+ cid?: CustomId; //自定义逻辑id 这边可以代指uid
7
+ settings: { [key: string | symbol]: any }; //自定义设置项
8
+ };
@@ -0,0 +1,5 @@
1
+ export type ResultType<T> = {
2
+ code: number;
3
+ msg?: string;
4
+ data?: T;
5
+ };
@@ -0,0 +1,48 @@
1
+ import { CodeProtocolEnum, DecodeMsg, EncodeMsg, RetryConfig, SecureClientOptions, SocketEnum } from "@fastcar/rpc";
2
+ import { ServerConfig } from "@fastcar/server";
3
+
4
+ export type ServerItemConfig = {
5
+ front: boolean;
6
+ domainName?: string; //对外访问域名
7
+ type: SocketEnum; //具体为哪一种型号的连接器
8
+ server: ServerConfig;
9
+ extra?: any; //第三方拓展配置 用于灵活的调用第三方
10
+ clientExtra?: any; //客户端拓展配置
11
+ encode?: EncodeMsg; //编码解码
12
+ decode?: DecodeMsg;
13
+ codeProtocol?: CodeProtocolEnum; //约定协议 json protobuf 默认json
14
+ secure?: SecureClientOptions;
15
+ maxConnections?: number; //最大连接数 默认1024
16
+ disconnectInterval?: number;
17
+ connectionLimit?: number; //连接数限制 默认1
18
+ retry?: RetryConfig;
19
+ };
20
+
21
+ export type ServerMeta = {
22
+ host: string;
23
+ debugPort?: number; //调试端口号
24
+ serviceId: string;
25
+ clusters?: number; //集群数量
26
+ list: ServerItemConfig[];
27
+ retry?: RetryConfig;
28
+ id: number; //服务唯一ID
29
+ units?: number; //单元数量 默认100
30
+ };
31
+
32
+ type ServiceType = string;
33
+
34
+ export type ServerGroupType = {
35
+ [key: ServiceType]: {
36
+ token: string; //当前服务的token 用于认证使用的
37
+ servers: ServerMeta[];
38
+ };
39
+ };
40
+
41
+ export type ServerStatus = {
42
+ serviceId: string;
43
+ status: boolean;
44
+ createTime: number;
45
+ updateTime: number;
46
+ serverType: string;
47
+ centerId: string;
48
+ };
@@ -0,0 +1,13 @@
1
+ //session的属性key值
2
+ export enum SessionAttribute {
3
+ logged = "logged", //是否登录
4
+ serviceId = "serviceId", //服务索引id
5
+ serverType = "serverType", //自定义服务器类型
6
+ uid = "uid",
7
+ serverKind = "serverKind", //服务器分类
8
+ tid = "tid", //桌子分类
9
+ gameServerType = "gameServerType", //桌子的gameKey
10
+ logLoginId = "loginId", //登录日志id
11
+ loginTime = "loginTime", //登录时间
12
+ center_serviceId = "center_serviceId", //注册中心服务id
13
+ }
@@ -0,0 +1,25 @@
1
+ import { ServerItemConfig } from "@/types/ServerMeta";
2
+ import { SocketEnum } from "@fastcar/rpc";
3
+
4
+ export default class ConnectorUtils {
5
+ static getConnectUrl(item: ServerItemConfig, host: string = "localhost") {
6
+ let sslFlag = !!item.server.ssl;
7
+ let defaultPort = sslFlag ? "443" : "80";
8
+
9
+ switch (item.type) {
10
+ case SocketEnum.SocketIO:
11
+ case SocketEnum.WS: {
12
+ return `${sslFlag ? "wss" : "ws"}://${host}:${item.server.port || defaultPort}`;
13
+ }
14
+ case SocketEnum.MQTT: {
15
+ return `mqtt://${host}:${item.server.port || defaultPort}`;
16
+ }
17
+ case SocketEnum.Grpc: {
18
+ return `${host}:${item.server.port || defaultPort}`;
19
+ }
20
+ default: {
21
+ return "";
22
+ }
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,101 @@
1
+ import { ServerMicroservices } from "@/common/Constant";
2
+ import { ServerGroupType, ServerItemConfig, ServerMeta } from "@/types/ServerMeta";
3
+ import { CommonConstant } from "@fastcar/core";
4
+ import { FileUtil, MixTool } from "@fastcar/core/utils";
5
+ import * as path from "path";
6
+
7
+ //格式化微服务配置
8
+ export default class MicroservicesUtils {
9
+ static getMicroservicesConfig(): ServerGroupType {
10
+ let resPath = path.join(__dirname, "../../", "resource");
11
+ let sysConfig = FileUtil.getApplicationConfig(resPath, CommonConstant.Application);
12
+ let env = sysConfig.application.env;
13
+ sysConfig = FileUtil.getApplicationConfig(resPath, `${CommonConstant.Application}-${env}`, sysConfig);
14
+
15
+ const microservices: ServerGroupType = sysConfig.settings.get(ServerMicroservices);
16
+ if (!microservices) {
17
+ throw new Error("not found microservices");
18
+ }
19
+
20
+ return microservices;
21
+ }
22
+
23
+ static format(microservices: ServerGroupType): ServerGroupType {
24
+ let newMicroservices = {};
25
+ Object.keys(microservices).forEach((serverType) => {
26
+ //判断是否为
27
+ let item = microservices[serverType];
28
+ let servers = item.servers;
29
+
30
+ let n: {
31
+ token: string; //当前服务的token 用于认证使用的
32
+ servers: ServerMeta[];
33
+ } = {
34
+ token: item.token,
35
+ servers: [],
36
+ };
37
+
38
+ servers.forEach((citem, index) => {
39
+ let clusters = citem.clusters || 1;
40
+ let units = citem.units || 100;
41
+ let [stype, proto] = citem?.serviceId?.split("-") || "";
42
+ let commonBody: ServerMeta = {
43
+ host: citem.host,
44
+ serviceId: `${stype || serverType}-${proto || "server"}-`,
45
+ list: citem.list,
46
+ retry: citem.retry,
47
+ id: 0,
48
+ };
49
+
50
+ if (citem.debugPort) {
51
+ commonBody.debugPort = commonBody.debugPort;
52
+ }
53
+
54
+ let addNum = citem.list.length;
55
+
56
+ for (let i = 0; i < clusters; i++) {
57
+ let newItem: ServerMeta = Object.create(commonBody); //copy原型链
58
+ MixTool.copyProperties(newItem, JSON.parse(JSON.stringify(commonBody))); //copy序列化的值
59
+
60
+ if (newItem.debugPort) {
61
+ newItem.debugPort = newItem.debugPort + i;
62
+ }
63
+ newItem.serviceId = newItem.serviceId + ((index + 1) * units + (i + 1));
64
+ newItem.id = i;
65
+
66
+ newItem.list = newItem.list.map((n) => {
67
+ let t: ServerItemConfig = Object.assign({}, n);
68
+ let skipNum = i * addNum;
69
+
70
+ if (!!t.server.port) {
71
+ t.server.port = t.server.port + skipNum;
72
+ } else {
73
+ t.server.port = t.server.ssl ? 443 + skipNum : 80 + skipNum;
74
+ }
75
+
76
+ return t;
77
+ });
78
+
79
+ n.servers.push(newItem);
80
+ }
81
+ });
82
+
83
+ Reflect.set(newMicroservices, serverType, Object.assign({}, item, n));
84
+ });
85
+
86
+ return newMicroservices;
87
+ }
88
+
89
+ //格式化命令行参数
90
+ static parseArgs(args: string[]) {
91
+ let proto: { [key: string]: string } = {};
92
+ args.forEach((item: string) => {
93
+ let list = item.split("=");
94
+ if (list.length == 2) {
95
+ Reflect.set(proto, list[0].trim(), list[1].trim());
96
+ }
97
+ });
98
+
99
+ return proto;
100
+ }
101
+ }
@@ -0,0 +1,31 @@
1
+ import { Context } from "koa";
2
+ import * as os from "os";
3
+
4
+ const localIps: string[] = ["127.0.0.1", "localhost", "0.0.0.0"];
5
+ (function () {
6
+ let ifaces = os.networkInterfaces();
7
+ for (let key in ifaces) {
8
+ let details = ifaces[key];
9
+ details?.forEach((item) => {
10
+ if (item.family === "IPv4" && !localIps.includes(item.address)) {
11
+ localIps.push(item.address);
12
+ }
13
+ });
14
+ }
15
+ })();
16
+
17
+ export default class NetWork {
18
+ //判断是否为本地ip
19
+ static isLocalIP(host: string): boolean {
20
+ return localIps.includes(host);
21
+ }
22
+ }
23
+
24
+ export function getIP(ctx: Context): string {
25
+ let req = ctx.request;
26
+ let ips = req.headers["x-forwarded-for"] || req.headers["x-real-ip"] || ctx.ip;
27
+ if (Array.isArray(ips)) {
28
+ return ips[0] || "";
29
+ }
30
+ return ips;
31
+ }