tarscloud / tarsgo Goto Github PK
View Code? Open in Web Editor NEWA high performance microservice framework in golang. A linux foundation project.
License: BSD 3-Clause "New" or "Revised" License
A high performance microservice framework in golang. A linux foundation project.
License: BSD 3-Clause "New" or "Revised" License
Is your feature request related to a problem? Please describe.
Adding tcp or udp servant is different from http, it should be by same interface
Describe the solution you'd like
Abstract AddServant
method.
Describe alternatives you've considered
NONE
Additional context
NONE
We've encounter a problem when deploy services with set division.
The code below expect enableset=Y
to take effect
https://github.com/TarsCloud/TarsGo/blob/dev/tars/application.go#L82
but the config file generated by NodeServer contains the following line:
enableset=y
This mismatch disables set division deployment.
The function reportnotifyinfo in notifyf.go cannot be used outside. The example tar.reportnotifyinfo in the help document is also wrong and needs to be adjusted
I think it's necessary to implement a generic goroutine pool, which helps reuse codes.
背景:
目前在做tarsgo的HTTP server框架。希望能够在框架层记录所有接收到的HTTP请求、以及发送到其他tars服务的tars请求。
目标:
对业务无侵入
设置log等级,即可以打开全局日志
作为Tars client,filter内部如何把RequestPacket、ResponsePacket解析成utf-8的string?可否给出代码示例呢?
或者说有什么全局日志的推荐方式吗?
package filter
import (
"context"
"a.com/x/y/global"
"github.com/TarsCloud/TarsGo/tars"
"github.com/TarsCloud/TarsGo/tars/protocol/res/requestf"
"time"
)
func sBufferToBytes(int8Slice []int8)([]byte){
bytes := make([]byte, 0, len(int8Slice))
for _, reqByte := range int8Slice {
bytes = append(bytes, byte(reqByte))
}
return bytes
//todo 此函数需要判断log等级,保证线上性能
//todo 此处为tars格式的二进制,需要反射+解包,
//bytes := codec.FromInt8(int8Slice)
//reader := codec.NewReader(bytes)
//return bytes
}
func TafClientLogFilter() tars.ClientFilter {
return func(ctx context.Context, msg *tars.Message, invoke tars.Invoke, timeout time.Duration) (err error) {
global.Log.Debugf("ctx=%+v, msg=%+v, invoke=%+v, timeout=%+v", ctx, msg, invoke, timeout)
if msg.Req != nil{
global.Log.Debug("TafClientLogFilter msg.Req.SBuffer=", string(sBufferToBytes(msg.Req.SBuffer)))
}
err = invoke(ctx, msg, timeout)
if err != nil {
global.Log.Errorf("error=%+v", err);
}
if msg.Resp != nil{
global.Log.Debug("TafClientLogFilter msg.Resp.SBuffer=", string(sBufferToBytes(msg.Resp.SBuffer)))
}
return err
}
}
特性监控和服务监控数据不显示
代码已经修改,示例能不能更新一下呢?
Tars/go/tars/servant.go:52:3: cannot use buf (type []byte) as type []int8 in field value
This is a problem with the go compiler or a tars file error?
env:
tarsgo 1.0
go 1.11.2
tars2go 1.0
当一个jce引用其他jce文件时,在jce的所在目录执行tars2go才能转换,否则会报错。请问一下这是怎么解决的
请问关于性能测试可以提供详细的测试脚本吗?我测试的结果和你们提供的数据有很大出入,关于grpc请问你们性能测试的时候使用了什么生成插件,gogofast or 原生的插件?
When you login successfully
, where should i go login ?thanks a lot
Server should respect logLevel
configuration.
看了源码之后,发现EndpointF返回的权重似乎没有用到,完全使用了round-robin的方法进行负载均衡
如题
tars2go -outdir TestApp\HelloGo\tars -I TestApp/HelloGo/tars TestApp\HelloGo\tars\SayHello.tars
期望生成的是所有的 *_IF.go 放在TestApp/HelloGo/tars下,结果变成了TestApp/HelloGo/tars/TestApp
默认直接放到了TestApp/HelloGo下,那我要是有100个tars文件那你岂不是要在我的项目的根目录的父目录创建100个go文件,简直无法忍受。
还有HelloWorld这种路径命名简直就是不能忍受,我是在写go,不是写Java,谢谢。
我项目根目录上层为何要默认再加一层,如果说当作子项目还能接受。tars需要用Xxx.Xxx作为标识,但没必要逼着golang按照java的规范写。
Go
Linux
gcc version 4.4.6 20110731 (Red Hat 4.4.6-4) (GCC)
Make sure you include information that can help us debug (full error message, exception listing, stack trace, logs).
flag.Parse() must not be called during init. Instead, register flags during init, and call flag.Parse() in main().
Otherwise, if your own program or a 3rd-party lib(say, glog) you use registers flags during init and expects flags to be parsed during execution, you program will panic with "flag provided but not defined".
Line 54 in 846b163
Below is the output of the command "tars2go -h" :
Usage: tars2go [flags] *.tars tars2go -I tars/protocol/res/endpoint [-I ...] QueryF.tars -E 生成未fmt前的代码便于排错 -I value 指定具体的import路径 -add-servant 生成AddServant函数 (default true) -outdir string 生成的代码放到哪个目录 -tarsPath string specify the tars source path. (default "github.com/TarsCloud/TarsGo/tars")
请问,按照ars_go_quickstart_en.md文档t操作,启动client时,报错:dial tcp 192.168.1.93:10015: getsockopt: connection refused,可以ping通192.168.1.93,如何解决?谢谢~!
Not a bug, For code optimization
go func() {
tm := time.NewTimer(time.Second)
//remove these 2 unuseful lines below
if err := recover(); err != nil { // avoid timer panic
}
......
}()
//there's a way to avoid chan panic and recover for AdapterProxy
defer func() {
// TODO readCh has a certain probability to be closed after the load, and we need to recover
// Maybe there is a better way
if err := recover(); err != nil {
TLOG.Error("recv pkg painc:", err)
}
}()
省点心吧,让小白还得一个个对
go版本应该是没有获取服务地址列表,还有路由策略的接口,望完善一下,谢谢
Considering that a large number of Companies in container cluster management have started to use k8s
Is there any plan for k8s integration? Or is it supported right now? I read the document, and I need to select the machine for deployment
多个服务是否可以共享同一套协议文件?
TarsGo中RequestF.tars 中struct RequestPacket的成员为:7 require vector<unsigned byte> sBuffer; 而TarsNode中RequestF.tars 中struct RequestPacket的成员为:7 require vector<byte> sBuffer; 导致互相请求时,出现“code=-1, message=type mismatch, tag:7,type:9” 的错误。
Why don't workers go directly to grab jobs from the pool? Based on what considerations? You can use fewer channels, which should reduce the performance loss.
For example:
func (w *Worker) Start() {
go func() {
for {
select {
case job = <-pool.JobQueue:
job()
case <-w.Stop:
w.Stop <- struct{}{}
return
}
}
}()
}
I found that tarsgo does not support TUP yet when we plan to use go to implement gateway for TUP.
So when will tarsgo support the protocol of TUP?
It will be great if TUP for go comes soon.Thx a lot.
tars.AddHttpServant() 的第一个参数是 TarsHttpMux struct
所以好像不能使用像 Alice - https://github.com/justinas/alice
或者 gorilla - https://github.com/gorilla/mux
这种middleware?
能改成interface吗?这样用户可以定制自己的TarsHttpMux来使用 自己想要的middleware?
Ask two questions:
1grpc has a timeout setting: CTX, cancel: = context. Withtimeout (context. Background(), time. Minute)
How can tarsgo set the timeout.
2 now I have deployed a service on 172.18.12.226, but I also want to deploy this service on 172.18.12.229, but it fails after uploading. There is no reason for failure. I don't know how to debug..
Look at the print function. In debug mode, you can print out the file name and line, but not the function name. Because some file names may be the same in the project, it is not a good for trouble -shooting problem. Please add function name to be printed.
The following code is where you can see the name and line number of the printed file
#/tars/util/logger/logger.go
if logLevel == DEBUG {
_, file, line, ok := runtime.Caller(2)
If! OK {
File =???
Line = 0
} else {
file = filepath.Base(file)
}
fmt.Fprintf(buf, "%s:%d|", file, line)
}
It is suggested to amend it to
227 if logLevel == DEBUG {
228 pc, file, line, ok := runtime.Caller(2)
229 if !ok {
230 file = "???"
231 line = 0
232 } else {
233 file = filepath.Base(file)
234 }
235 fmt.Fprintf(buf, "%s|%s:%d|", runtime.FuncForPC(pc).Name(), file, line)
236 }
RT
When will SSL communication be supported?
Is your feature request related to a problem? Please describe.
Optimize the description of tars2go tools compilation and installation.
Describe the solution you'd like
NONE
Describe alternatives you've considered
NONE
Additional context
NONE
I have some grpc service, can we use it ?
tars文件:
module TestApp{
interface SayHello{
int echoHello(string name, out string greeting);
};
};
php代码:
// 指定主控ip
$config = new \Tars\client\CommunicatorConfig();
$config->setLocator('tars.tarsregistry.QueryObj@tcp -h 10.0.2.15 -p 17890');
$config->setModuleName('App.Server');
$config->setCharsetName('UTF-8');
$servant = new \TestApp\HelloGo\SayHelloObj\SayHelloServant($config);
echo "Locator specified with default socketmode 1\n";
$name = 'ted';
$intVal = $servant->echoHello($name, $greetings);
var_dump($greetings);
Is your feature request related to a problem? Please describe.
Adding tcp or udp servant is different from http, it should be by same interface.
Describe the solution you'd like
Abstract AddServant method to unify tcp/udp and http servant adding.
Describe alternatives you've considered
NONE.
Additional context
NONE.
The problem is introduced by the pr #113 , it removes the flag.Parse()
call from initConfig()
and expects users to call it from main()
.
It may break all existing applications that don't call flag.Parse()
, and the application exits silently.(Consider replace the two os.Exit(1)
calls in initConfig()
with panic
to make troubleshooting easily)
notifyServer [Goapp.Goweb] 'Goapp.setloglevel ERROR' succ:Goapp.setloglevel ERROR not support now!
currently, more and more people are using Python, so when can you support Python?
//Mobile number repeated query return
struct SC_PhoneQuery {
0 require int ret; / / result 1 does not exist 2 exists
1 require string phone; / / Account
}
interface DB{
Int phonequery (CS? Phonequery MSG, out SC? Phonequery RET); / / query the phone number
}
//Login results
enum LOGIN_RESULT {
Login? Result? Success, / / login succeeded
...
}
Like the above definition file, the single line comments written by yourself can be generated into the target code, if there are single line comments written!
Is there any way to run make tars under windows
// 登录结果
enum LOGIN_RESULT {
LOGIN_RESULT_SUCCESS, // 登录成功
LOGIN_RESULT_REPEAT_LOGIN, // 重复登录
LOGIN_RESULT_DB_ERR, // 数据库操作返回错误
LOGIN_RESULT_ACCOUNT_PASSWORD_ERR, // 该账号密码错误
LOGIN_RESULT_NO_DEFAULT_LOBBY , // 没有找到默认大厅
LOGIN_RESULT_SMS_CLOSED , // 没有开启短信验证
LOGIN_RESULT_SMS_REPEATED, // 短信验证重复发送消息
LOGIN_RESULT_RESET_ACCOUNT_FAILED , // 完善账号数据库操作失败
LOGIN_RESULT_SMS_FAILED , // 短信验证失败
LOGIN_RESULT_ALIYUN_FAILED , // 阿里云失败
LOGIN_RESULT_SET_PASSWORD_FAILED , // 修改密码失败
LOGIN_RESULT_SET_NICKNAME_FAILED, // 设置昵称数据库操作失败
LOGIN_RESULT_SET_PASSWORD_GUEST, // 游客不能修改密码
LOGIN_RESULT_SAME_PASSWORD , // 相同密码
LOGIN_RESULT_LOGIN_VALIDATEBOX_FAIL, // 登陆验证框失败
LOGIN_RESULT_ACCOUNT_DISABLED, // 账号被封
LOGIN_RESULT_RESET_ACCOUNT_DUP_ACC, // 完善账号失败:已经绑定了该手机
LOGIN_RESULT_RESET_ACCOUNT_DUP_NICKNAME, // 完善账号失败:已经设置了改昵称
LOGIN_RESULT_SET_NICKNAME_DUP_NICKNAME, // 设置昵称失败:已经设置了改昵称
LOGIN_RESULT_SET_ACCOUNT_OR_PASSWORD_EMPTY, // 账号或者密码为空
LOGIN_RESULT_PASSWORD_SIZE_LIMIT, // 密码长度限制为9-18位
LOGIN_RESULT_PASSWORD_CHAR_LIMIT, // 密码只能为数字,字母,下划线
LOGIN_RESULT_ACCOUNT_SIZE_LIMIT, // 账号只能为7-18位
LOGIN_RESULT_ACCOUNT_CHAR_LIMIT, // 账号只能为数字
LOGIN_RESULT_SMS_ERR, // 验证码只能输入数字,限制6位
LOGIN_RESULT_NICKNAME_EMPTY, // 昵称不能为空
LOGIN_RESULT_NICKNAME_LIMIT, // 昵称输入框只能输入字母数字汉字,限制2-7个汉字的长度。
LOGIN_RESULT_ACCOUNT_EMPTY, // 账号为空
LOGIN_RESULT_TEL_LEN_ERR, // 手机号长度不正确
LOGIN_RESULT_TEL_ERR , // 手机号不正确
LOGIN_RESULT_TEL_USED, // 手机号已被使用
LOGIN_RESULT_REDIS_ERROR, //redis异常
LOGIN_RESULT_MAINTAIN, //系统进入维护中
LOGIN_RESULT_FREQUENTLY_LOGIN, // 频繁登录,dbserver收到多个
LOGIN_RESULT_UNCOMPLETED_LOGIN, // 未完成登录,login又收到一个
LOGIN_RESULT_LOGIN_QUQUE // 已经在登录排队中,gate又收到一个
};
生成的结果如下 没法用
//Package QPAPP comment
// This file war generated by tars2go 1.1
// Generated from DB.tars
package QPAPP
type LOGIN_RESULT int32
const (
//LOGIN_RESULT_LOGIN_RESULT_SUCCESS enumLOGIN_RESULT_LOGIN_RESULT_SUCCESS = 0
//LOGIN_RESULT_LOGIN_RESULT_REPEAT_LOGIN enumLOGIN_RESULT_LOGIN_RESULT_REPEAT_LOGIN = 1
//LOGIN_RESULT_LOGIN_RESULT_DB_ERR enumLOGIN_RESULT_LOGIN_RESULT_DB_ERR = 2
//LOGIN_RESULT_LOGIN_RESULT_ACCOUNT_PASSWORD_ERR enumLOGIN_RESULT_LOGIN_RESULT_ACCOUNT_PASSWORD_ERR = 3
//LOGIN_RESULT_LOGIN_RESULT_NO_DEFAULT_LOBBY enumLOGIN_RESULT_LOGIN_RESULT_NO_DEFAULT_LOBBY = 4
//LOGIN_RESULT_LOGIN_RESULT_SMS_CLOSED enumLOGIN_RESULT_LOGIN_RESULT_SMS_CLOSED = 5
//LOGIN_RESULT_LOGIN_RESULT_SMS_REPEATED enumLOGIN_RESULT_LOGIN_RESULT_SMS_REPEATED = 6
//LOGIN_RESULT_LOGIN_RESULT_RESET_ACCOUNT_FAILED enumLOGIN_RESULT_LOGIN_RESULT_RESET_ACCOUNT_FAILED = 7
//LOGIN_RESULT_LOGIN_RESULT_SMS_FAILED enumLOGIN_RESULT_LOGIN_RESULT_SMS_FAILED = 8
//LOGIN_RESULT_LOGIN_RESULT_ALIYUN_FAILED enumLOGIN_RESULT_LOGIN_RESULT_ALIYUN_FAILED = 9
//LOGIN_RESULT_LOGIN_RESULT_SET_PASSWORD_FAILED enumLOGIN_RESULT_LOGIN_RESULT_SET_PASSWORD_FAILED = 10
//LOGIN_RESULT_LOGIN_RESULT_SET_NICKNAME_FAILED enumLOGIN_RESULT_LOGIN_RESULT_SET_NICKNAME_FAILED = 11
//LOGIN_RESULT_LOGIN_RESULT_SET_PASSWORD_GUEST enumLOGIN_RESULT_LOGIN_RESULT_SET_PASSWORD_GUEST = 12
//LOGIN_RESULT_LOGIN_RESULT_SAME_PASSWORD enumLOGIN_RESULT_LOGIN_RESULT_SAME_PASSWORD = 13
//LOGIN_RESULT_LOGIN_RESULT_LOGIN_VALIDATEBOX_FAIL enumLOGIN_RESULT_LOGIN_RESULT_LOGIN_VALIDATEBOX_FAIL = 14
//LOGIN_RESULT_LOGIN_RESULT_ACCOUNT_DISABLED enumLOGIN_RESULT_LOGIN_RESULT_ACCOUNT_DISABLED = 15
//LOGIN_RESULT_LOGIN_RESULT_RESET_ACCOUNT_DUP_ACC enumLOGIN_RESULT_LOGIN_RESULT_RESET_ACCOUNT_DUP_ACC = 16
//LOGIN_RESULT_LOGIN_RESULT_RESET_ACCOUNT_DUP_NICKNAME enumLOGIN_RESULT_LOGIN_RESULT_RESET_ACCOUNT_DUP_NICKNAME = 17
//LOGIN_RESULT_LOGIN_RESULT_SET_NICKNAME_DUP_NICKNAME enumLOGIN_RESULT_LOGIN_RESULT_SET_NICKNAME_DUP_NICKNAME = 18
//LOGIN_RESULT_LOGIN_RESULT_SET_ACCOUNT_OR_PASSWORD_EMPTY enumLOGIN_RESULT_LOGIN_RESULT_SET_ACCOUNT_OR_PASSWORD_EMPTY = 19
//LOGIN_RESULT_LOGIN_RESULT_PASSWORD_SIZE_LIMIT enumLOGIN_RESULT_LOGIN_RESULT_PASSWORD_SIZE_LIMIT = 20
//LOGIN_RESULT_LOGIN_RESULT_PASSWORD_CHAR_LIMIT enumLOGIN_RESULT_LOGIN_RESULT_PASSWORD_CHAR_LIMIT = 21
//LOGIN_RESULT_LOGIN_RESULT_ACCOUNT_SIZE_LIMIT enumLOGIN_RESULT_LOGIN_RESULT_ACCOUNT_SIZE_LIMIT = 22
//LOGIN_RESULT_LOGIN_RESULT_ACCOUNT_CHAR_LIMIT enumLOGIN_RESULT_LOGIN_RESULT_ACCOUNT_CHAR_LIMIT = 23
//LOGIN_RESULT_LOGIN_RESULT_SMS_ERR enumLOGIN_RESULT_LOGIN_RESULT_SMS_ERR = 24
//LOGIN_RESULT_LOGIN_RESULT_NICKNAME_EMPTY enumLOGIN_RESULT_LOGIN_RESULT_NICKNAME_EMPTY = 25
//LOGIN_RESULT_LOGIN_RESULT_NICKNAME_LIMIT enumLOGIN_RESULT_LOGIN_RESULT_NICKNAME_LIMIT = 26
//LOGIN_RESULT_LOGIN_RESULT_ACCOUNT_EMPTY enumLOGIN_RESULT_LOGIN_RESULT_ACCOUNT_EMPTY = 27
//LOGIN_RESULT_LOGIN_RESULT_TEL_LEN_ERR enumLOGIN_RESULT_LOGIN_RESULT_TEL_LEN_ERR = 28
//LOGIN_RESULT_LOGIN_RESULT_TEL_ERR enumLOGIN_RESULT_LOGIN_RESULT_TEL_ERR = 29
//LOGIN_RESULT_LOGIN_RESULT_TEL_USED enumLOGIN_RESULT_LOGIN_RESULT_TEL_USED = 30
//LOGIN_RESULT_LOGIN_RESULT_REDIS_ERROR enumLOGIN_RESULT_LOGIN_RESULT_REDIS_ERROR = 31
//LOGIN_RESULT_LOGIN_RESULT_MAINTAIN enumLOGIN_RESULT_LOGIN_RESULT_MAINTAIN = 32
//LOGIN_RESULT_LOGIN_RESULT_FREQUENTLY_LOGIN enumLOGIN_RESULT_LOGIN_RESULT_FREQUENTLY_LOGIN = 33
//LOGIN_RESULT_LOGIN_RESULT_UNCOMPLETED_LOGIN enumLOGIN_RESULT_LOGIN_RESULT_UNCOMPLETED_LOGIN = 34
//LOGIN_RESULT_LOGIN_RESULT_LOGIN_QUQUE enumLOGIN_RESULT_LOGIN_RESULT_LOGIN_QUQUE = 35
)
package main
import (
"fmt"
"github.com/TarsCloud/TarsGo/tars"
"StressTest"
"sync"
"sync/atomic"
"time"
)
func main() {
comm := tars.NewCommunicator()
obj := fmt.Sprintf("StressTest.EchoClientServer.EchoClientObj@tcp -h 127.0.0.1 -p 10015 -t 60000")
app := new(StressTest.EchoClient)
comm.StringToProxy(obj, app)
var num int64
start := time.Now().UnixNano() / 1e6
var wg sync.WaitGroup
f := func() {
var out, i int32
for i = 0; i < 2000; i++ {
atomic.AddInt64(&num, 1)
ret, err := app.Add(i, i*2, &out)
if err != nil {
fmt.Println(ret, out)
return
}
}
wg.Done()
}
for i := 0; i < 200; i++ {
go f()
wg.Add(1)
}
wg.Wait()
end := time.Now().UnixNano() / 1e6
cost := end - start
fmt.Printf("num:%d time:%d qps:%d\n", num, cost/1000, num*int64(1000)/(end-start))
}
如题,希望接口调用提供IP白名单,以及访问频率限制(防止DDOS攻击)
udp rpc调用 context的servant无法获取客户端ip和端口,tcp的rpc调用是可以的,建议udp也加上。
Can you put up a demo?
使用该docker镜像搭建了tars的管理平台,并根据tar_go_quickstart.md搭建了服务端,并打包上传到服务平台,服务日志一直报服务为僵尸进程
后查看服务的配置运行的配置文件发现servant均少了Obj
字样
<tars>
<application>
enableset=n
setdivision=NULL
<server>
node=tars.tarsnode.ServerObj@tcp -h 172.17.0.3 -p 19386 -t 60000
app=TestApp
server=HelloGo
localip=172.17.0.3
local=tcp -h 127.0.0.1 -p 10006 -t 3000
basepath=/usr/local/app/tars/tarsnode/data/TestApp.HelloGo/bin/
datapath=/usr/local/app/tars/tarsnode/data/TestApp.HelloGo/data/
logpath=/usr/local/app/tars/app_log/
logsize=10M
config=tars.tarsconfig.ConfigObj
notify=tars.tarsnotify.NotifyObj
log=tars.tarslog.LogObj
deactivating-timeout=3000
logLevel=DEBUG
# 实际因该为 <TestApp.HelloGo.SayHelloObjAdapter>
<TestApp.HelloGo.SayHelloAdapter>
allow
endpoint=tcp -h 172.17.0.3 -p 10006 -t 60000
# 实际应该为 handlegroup=TestApp.HelloGo.SayHelloObjAdapter
handlegroup=TestApp.HelloGo.SayHelloAdapter
maxconns=200000
protocol=tars
queuecap=10000
queuetimeout=60000
# 实际应该为 servant=TestApp.HelloGo.SayHelloObj
servant=TestApp.HelloGo.SayHello
threads=5
# 实际因该为 </TestApp.HelloGo.SayHelloObjAdapter>
</TestApp.HelloGo.SayHelloAdapter>
</server>
<client>
locator=tars.tarsregistry.QueryObj@tcp -h 172.17.0.3 -p 17890
sync-invoke-timeout=3000
async-invoke-timeout=5000
refresh-endpoint-interval=60000
stat=tars.tarsstat.StatObj
property=tars.tarsproperty.PropertyObj
report-interval=60000
sample-rate=100000
max-sample-count=50
asyncthread=3
modulename=TestApp.HelloGo
</client>
</application>
</tars>
然后将tar_go_quickstart.md中服务端源码app.AddServant(imp, cfg.App+"."+cfg.Server+".SayHelloObj") //Register Servant
修改为app.AddServant(imp, cfg.App+"."+cfg.Server+".SayHello") //Register Servant
(客户端同理)重新编译打包后发布,运行日志正常,客户端也能正常请求响应。
请问这个是文档编写错误,还是发布平台的模板问题?我查看了模板管理中的tars.default的模板,发现是无法对Adapter和Servant的名字进行配置的。
Tars中每个Servant似乎都是独立的IP和端口。如果想把服务接口分割成多个Servant,每个Servant负责少量的服务接口。这样的话似乎并不是太友好。
多个Servant可以共享同一套IP端口吗?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.