Skip to main content

Getting real client IP in Docker Swarm

· 2 min read

在 Docker Swarm 中通过 Stack Deploy 部署 Service 的时候,在 Service 中默认无法获取到客户端的 IP 地址, Github 中有一个 issue 在 track 这个问题:Unable to retrieve user's IP address in docker swarm mode

目前的解决方法或 Workaround 是把 port 改成 host 模式, 以 kong 为例.

默认的 port 发布模式:

version: "3.7"
services:
kong-proxy:
image: kong:1.0.3-alpine
deploy:
mode: global
labels:
- "tier=frontend"
restart_policy:
condition: any
ports:
<span style="color: #ff0000;"> - "80:8000"
- "443:8443"</span>
depends_on:
- database-postgresql
environment:
KONG_ADMIN_LISTEN: 0.0.0.0:8001, 0.0.0.0:8444 ssl
KONG_DATABASE: postgres
KONG_PG_DATABASE: kong
KONG_PG_USER: kong
KONG_PG_PASSWORD: PaSsW0rd
KONG_PG_HOST: database-postgresql
KONG_PG_PORT: "5432"

volumes:
- type: "bind"
source: "/var/log/kong/"
target: "/usr/local/kong/logs/"
# read_only: true
networks:
- backend
- frontend
networks:
frontend:
backend:

修改 port 为 host 模式:

version: "3.7"
services:
kong-proxy:
image: kong:1.0.3-alpine
deploy:
mode: global
labels:
- "tier=frontend"
restart_policy:
condition: any
ports:
<span style="color: #ff0000;"> - target: 8000</span>
<span style="color: #ff0000;"> published: 80</span>
<span style="color: #ff0000;"> mode: host</span>
<span style="color: #ff0000;"> - target: 8443</span>
<span style="color: #ff0000;"> published: 43</span>
<span style="color: #ff0000;"> mode: host
</span> depends_on:
- database-postgresql
environment:
KONG_ADMIN_LISTEN: 0.0.0.0:8001, 0.0.0.0:8444 ssl
KONG_DATABASE: postgres
KONG_PG_DATABASE: kong
KONG_PG_USER: kong
KONG_PG_PASSWORD: PaSsW0rd
KONG_PG_HOST: database-postgresql
KONG_PG_PORT: "5432"

volumes:
- type: "bind"
source: "/var/log/kong/"
target: "/usr/local/kong/logs/"
# read_only: true
networks:
- backend
- frontend
networks:
frontend:
backend:

Aggregate in Mongodb in C#

· One min read

Filter record from collection "OperationSession", sort by "WorldId" descending, then group by "WorldId", then pick first record from each group, then sort result:

Way #1:

db.getCollection('OperationSession').aggregate(
[
{ "$match": {"ActivityId":74,"GameId":2109} },
{ "$sort":{ "CreateTime" : -1} },
{ "$group":
{
_id:"$WorldId",
SessionId:{"$first": "$_id" },
GameId:{"$first": "$GameId" },
WorldId:{"$first": "$WorldId" },
ActivityId:{"$first": "$ActivityId" },
Type:{"$first": "$Type" },
Status:{"$first": "$Status" },
ActivityStatus:{"$first": "$ActivityStatus" }
}
},
{ "$sort":{ "WorldId" : 1} },
{ "$skip": 20},
{ "$limit": 10}
]
)

Way #2:

db.OperationSession.aggregate()
.match({"ActivityId":74,"GameId":2109})
.sort({"CreateTime":-1})
.group({
"_id":"$WorldId",
"SessionId":{"$first": "$_id" },
"GameId":{"$first": "$GameId" },
"WorldId":{"$first": "$WorldId" },
"ActivityId":{"$first": "$ActivityId" },
"Type":{"$first": "$Type" },
"Status":{"$first": "$Status" },
"ActivityStatus":{"$first": "$ActivityStatus" }
})
.sort({"WorldId":1})
.skip(20)
.limit(10)

In C#:

collection.Aggregate<DataEntity.OperationSession>()
.Match(s => s.ActivityId == 74 && s.GameId == 2109)
.SortByDescending(s => s.CreateTime)
.Group(
s => s.WorldId,
s => new Interface.OperationSession
{
SessionId = s.Select(x => x.Id).First(),
GameId = s.Select(x => x.GameId).First(),
WorldId = s.Select(x => x.WorldId).First(),
ActivityId = s.Select(x => x.ActivityId).First(),
Type = s.Select(x => x.Type).First(),
Status = s.Select(x => x.Status).First(),
ActivityStatus = s.Select(x => x.ActivityStatus).First()
})
.SortBy(s => s.WorldId)
.Skip(20)
.Limit(10).ToList();
ClustrMaps