创建系统服务:

vim /etc/systemd/system/chat.service
[Unit]
Description=Chat-Server

[Service]
ExecStart=/var/www/chat/server.js
Restart=always
User=nobody
Group=nogroup
Environment=PATH=/usr/bin:/usr/local/bin
Environment=NODE_ENV=production
WorkingDirectory=/var/www/chat

[Install]
WantedBy=multi-user.target

修改权限:

chmod 644 /etc/systemd/system/chat.service

重新加载服务信息:

systemctl daemon-reload

设定自动启动服务:

systemctl enable chat

运行:

service chat start

对于在服务器上运行的内存需求较大的程序,建议开启 Server GC 模式,有利于提升程序的性能。

挺简单,不管是 windows 还是 Linux ,只需要增加环境变量即可:

export DOTNET_gcServer=1
export DOTNET_GCHeapCount=c

也可以在配置文中进行配置
.NET Core 在文件 runtimeconfig.json

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    ...
    <runtime>
        <gcServer enabled="true"/>
        <GCHeapCount>0xc</GCHeapCount>
    </runtime>
</configuration>

.NET Framework 在 app.config 文件

{
  "runtimeOptions": {
   "configProperties": {
      "System.GC.Server": true,
      "System.GC.HeapCount": 12
   }
  }
}

本来最简单的做法,就是将语言选择放在cookie中,但出于对SEO的考虑,这样做无法让搜索引擎抓取多语种页面,最好的做法,还是不同语言有不同的路径,例如:

http://www.xxx.com/zh-ch/products
http://www.xxx.com/en-us/products
....

静态类 Langs.cs 中,定义可以用的语言:

    public readonly static string[] LangCodes = new string[] { "vi-vn", "en-us", "zh-cn" };

识别用的路由约束类,其中的 "auto" 是特殊定义的,主要用于用户第一次进入时对用户的 Accept-Languages 进行自动识别:

public class LanguageRouteConstraint : IRouteConstraint
{
    public bool Match(HttpContext? httpContext, IRouter? route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
    {
        if (!values.ContainsKey("culture"))
            return false;

        var culture = values["culture"]?.ToString();
        if (culture == null) return false;
        return culture == "auto" || Langs.LangCodes.Contains(culture);
    }
}

路由约束:

public class LanguageRouteConstraint : IRouteConstraint
{
    public bool Match(HttpContext? httpContext, IRouter? route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
    {
        if (!values.ContainsKey("culture"))
            return false;

        var culture = values["culture"]?.ToString();
        if (culture == null) return false;
        return culture == "auto" || Langs.LangCodes.Contains(culture);
    }
}

然后在 program.cs 中配置:

builder.Services.AddRazorPages().AddRazorPagesOptions(options =>
{
    options.Conventions.Add(new CulturePageRouteConvention());
}).AddRazorRuntimeCompilation();

builder.Services.Configure<RouteOptions>(options =>
{
    options.ConstraintMap.Add("culture", typeof(LanguageRouteConstraint));
});

builder.Services.Configure<RouteOptions>(options =>
{
    options.ConstraintMap.Add("culture", typeof(LanguageRouteConstraint));
});

路由:

app.MapControllerRoute(name: "default", pattern: "{culture:culture=auto}/{controller:slugify=Home}/{action:slugify=Index}/{id?}");