diff --git a/.gitignore b/.gitignore index 2ca8682..f40fbd8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ -_site/ -.sass-cache/ -.jekyll-cache/ +_site +.sass-cache +.jekyll-cache .jekyll-metadata +vendor diff --git a/404.html b/404.html new file mode 100644 index 0000000..086a5c9 --- /dev/null +++ b/404.html @@ -0,0 +1,25 @@ +--- +permalink: /404.html +layout: default +--- + + + +
Page not found :(
+The requested page could not be found.
+GET
/config
¶Return all configuration info.
+{ + "admin": { + "bind": { + "ip": "0.0.0.0", + "port": 12345 + } + }, + "services": { + "example.service": { + "name": "example.service", + "config": { + "listener": { + "address": { + "ip": "0.0.0.0", + "port": 8000 + } + }, + "healthCheck": { + "interval": "10s", + "timeout": "3s", + "fallThreshold": 3, + "riseThreshold": 3, + "tcpChecker": {} + }, + "connectTimeout": "3s", + "idleTimeout": "600s", + "lbPolicy": "LEAST_CONNECTION", + "protocol": "TCP" + }, + "endpoints": [ + { + "address": { + "ip": "10.0.0.1", + "port": 8000 + } + }, + { + "address": { + "ip": "10.0.0.2", + "port": 8000 + } + } + ] + } + } +} +
GET
/ops/shutdown
¶Immediately shut down the Samaritan.
+{"msg": "OK"} +
GET
/stats
¶Return all statistics for local debugging.
+live: 1 +runtime.alloc_bytes: 2222568 +runtime.frees: 23281 +runtime.gc_pause_total_ms: 0 +runtime.gc_total: 0 +runtime.goroutines: 10 +runtime.heap_alloc_bytes: 2222568 +runtime.heap_idle_bytes: 62750720 +... +
GET
/stats/prometheus
¶Return /stats in Prometheus format.
+# TYPE samaritan_service_downstream_cx_active gauge +samaritan_service_downstream_cx_active{hostname="localhost",service_name="service_01"} 0 +# TYPE samaritan_service_upstream_cx_active gauge +samaritan_service_upstream_cx_active{hostname="localhost",service_name="service_01"} 0 +# TYPE samaritan_live gauge +samaritan_live{hostname="localhost"} 1 +... +
An HTTP service for viewing Samaritan's runtime information, include config, stats.
+ +Store service configuration, process services and configuration updates, and notify the Controller.
+Static
+Read and parse service configuration from bootstrap file. Work only when init config.
+Dynamic
+The gRPC delivers service and service configuration information.
+Control proc creation, destruction, and runtime behavior.
+The smallest processing unit used to proxy a real service, different protocols can have their own implementation.
+Responsible for smooth upgrades to Samaritan without downtime, use SO_REUSEPORT.
+The new Samaritan instance use UNIX socket to communicate with the old samaritan instance.
+sequenceDiagram + participant new as New Samaritan + participant old as Old Samaritan + new ->> old: Dail to UNIX socket + new ->> new: Start controller + new ->> old: Shutdown admin request + old ->> old: Shutdown admin + new ->> new: Start admin + new ->> new: Start listeners + new ->> old: Drain listeners request + old ->> old: Drain listeners + new ->> old: Terminate parent request + old ->> old: Terminate +
sequenceDiagram + participant cfg as Config + participant ctl as Controller + participant proc as Proc + cfg ->> ctl: New service event + ctl ->> +proc: Create new proc + cfg ->> ctl: Endpoints add event + ctl ->> proc: Call OnSvcHostAdd() + cfg ->> ctl: Endpoints remove event + ctl ->> proc: Call OnSvcHostRemove() + cfg ->> ctl: Config update event + ctl ->> proc: Call OnSvcConfigUpdate() + cfg ->> ctl: Del service event + ctl ->> -proc: Call Stop() +
Redis Processor in samaritan serves as a Redis Cluster Proxy just as corvus.
+It adapts the Redis Cluster Protocol to the Single Redis Protocol. In Redis Cluster Protocol, a client should be able to react to MOVED
and ASK
response while in a single redis protocol clients know nothing about sharding.
Single Redis Protocol client -> Redis Cluster Proxy -> Redis Cluster +
MGET
: split to multiple GET
.MSET
: split to multiple SET
.DEL
: split to multiple single key DEL
.EXISTS
: split to multiple single key EXISTS
.PING
: ignored and won't be forwarded.INFO
, TIME
: won't be forwarded to backend redis, information collected in proxy
+ will be returned.AUTH
: do authentication in proxy.CONFIG
: support get
, set
, and rewrite
sub-command to retrieve and manipulate corvus config.SELECT
: ignored if index is 0
, won't be forwarded.Warning
+The following commands require all argument keys to belong to the same redis node.
+EVAL
: At least one key should be given.SDIFF
, SDIFFSTORE
, SINTER
, SINTERSTORE
, SMOVE
, SUNION
, SUNIONSTORE
.ZINTERSTORE
, ZUNIONSTORE
.PFCOUNTE
, PFMERGE
.The following commands are not available, such as KEYS
, we can't search keys across
+all backend redis instances.
KEYS
, MIGRATE
, MOVE
, OBJECT
, RANDOMKEY
, RENAME
, RENAMENX
, SCAN
, WAIT
.BITOP
, MSETNX
BLPOP
, BRPOP
, BRPOPLPUSH
.PSUBSCRIBE
, PUBLISH
, PUBSUB
, PUNSUBSCRIBE
, SUBSCRIBE
, UNSUBSCRIBE
.EVALSHA
, SCRIPT
.DISCARD
, EXEC
, MULTI
, UNWATCH
, WATCH
.CLUSTER
.ECHO
, QUIT
.BGREWRITEAOF
, BGSAVE
, CLIENT
, COMMAND
, CONFIG
, DBSIZE
, DEBUG
, FLUSHALL
,
+ FLUSHDB
, LASTSAVE
, MONITOR
, ROLE
, SAVE
, SHUTDOWN
, SLAVEOF
, SYNC
.SLOWLOG
sequenceDiagram + participant client as Client + participant sess as Session + participant node as Node + participant backend as Backend + + client ->> sess: send request + sess ->> sess: handle request + sess -->> node: select node by key, wait request finish + node ->> node: filter chain + node ->> backend: send request to backend + backend ->> node: read response from backend + node ->> node: handle error + node -->> sess: finish request + sess ->> client: send response +
Samaritan only open a connection to redis and uses the pipeline to communicate.
+graph LR + Client-- N:N ---Samaritan + Samaritan-- 1:1 ---Redis +
Filter is used to extend the redis proc, which can modify or intercept requests.
+type Filter interface { + Do(req *simpleRequest) FilterStatus + Destroy() +} +
Filter chain is used to store filter.
+Filter.Do
will be called by filter chain, if FilterStatus
is Stop
,
+the filter chain will stop and the subsequent filters will be ignored.
Samaritan provide detailed metrics about connection and request which could help us understand the state of network and services, make decisions.
+++Types of statistics:
++
+- +
+Counters: Unsigned integers that only increase and never decrease.
+- +
+Gauges: Unsigned integers that both increase and decrease.
+- +
+Histograms: Unsigned integers that are part of a stream of values that are then aggregated by the collector to ultimately yield summarized percentile values.
+
Name | +Type | +Description | +
---|---|---|
live | +Gauge | +live status | +
Name | +Type | +Description | +
---|---|---|
runtime.gc_total | +Counter | +Count of GC | +
runtime.gc_pause_us | +Histogram | +GC pause duration | +
runtime.goroutines | +Gauge | +Num of goroutines | +
runtime.gc_pause_total_ms | +Gauge | +Total gc pause time | +
runtime.alloc_bytes | +Gauge | +Alloc is bytes of allocated heap objects | +
runtime.total_alloc_bytes | +Gauge | +Cumulative bytes allocated for heap objects | +
runtime.sys_bytes | +Gauge | +Total bytes of memory obtained from the OS | +
runtime.heap_alloc_bytes | +Gauge | +HeapAlloc is bytes of allocated heap objects | +
runtime.heap_sys_bytes | +Gauge | +Bytes of heap memory obtained from the OS | +
runtime.heap_idle_bytes | +Gauge | +Bytes in idle (unused) spans | +
runtime.heap_inuse_bytes | +Gauge | +Bytes in in-use spans | +
runtime.heap_released_bytes | +Gauge | +Bytes of physical memory returned to the OS | +
runtime.heap_objects | +Gauge | +The number of allocated heap objects | +
runtime.stack_inuse_bytes | +Gauge | +Bytes in stack spans | +
runtime.stack_sys_bytes | +Gauge | +Bytes of stack memory obtained from the OS | +
runtime.lookups | +Gauge | +The number of pointer lookups performed by the runtime | +
runtime.mallocs | +Gauge | +The cumulative count of heap objects allocated | +
runtime.frees | +Gauge | +The cumulative count of heap objects freed | +
prefix: service.{service_name}.
+Name | +Type | +Description | +
---|---|---|
downstream.cx_total | +Counter | +downstream total connections | +
downstream.cx_destroy_total | +Counter | +downstream destroyed connections | +
downstream.cx_active | +Gauge | +downstream active connections | +
downstream.cx_length_sec | +Histogram | +downstream connection length | +
downstream.cx_rx_bytes_total | +Counter | +downstream received connection bytes | +
downstream.cx_tx_bytes_total | +Counter | +downstream sent connection bytes | +
downstream.cx_restricted | +Counter | +downstream restricted connections | +
upstream.cx_total | +Counter | +upstream total connections | +
upstream.cx_destroy_total | +Counter | +upstream destroyed connections | +
upstream.cx_active | +Counter | +upstream active connections | +
upstream.cx_length_sec | +Histogram | +upstream connection length | +
upstream.cx_rx_bytes_total | +Counter | +upstream received connection bytes | +
upstream.cx_tx_bytes_total | +Counter | +upstream sent connection bytes | +
upstream.cx_connect_timeout | +Counter | +upstream total connection connect timeouts | +
upstream.cx_connect_fail | +Counter | +upstream connection failures | +
prefix: service.{service_name}.
+Name | +Type | +Description | +
---|---|---|
downstream.rq_total | +Counter | +downstream total request | +
downstream.rq_success_total | +Counter | +downstream success request | +
downstream.rq_failure_total | +Counter | +downstream failed request | +
downstream.rq_active | +Gauge | +downstream active request | +
downstream.rq_duration_ms | +Histogram | +downstream request duration | +
downstream.rq_rx_bytes_length | +Histogram | +downstream received request bytes length | +
downstream.rq_tx_bytes_length | +Histogram | +downstream sent request bytes length | +
upstream.rq_total | +Counter | +upstream total request | +
upstream.rq_success_total | +Counter | +upstream success request | +
upstream.rq_failure_total | +Counter | +upstream failed request | +
upstream.rq_active | +Gauge | +upstream active request | +
upstream.rq_duration_ms | +Histogram | +upstream request duration | +
upstream.rq_rx_bytes_length | +Histogram | +upstream received request bytes length | +
upstream.rq_tx_bytes_length | +Histogram | +upstream sent request bytes length | +
prefix: service.{service_name}.
+Name | +Type | +Description | +
---|---|---|
slots_refresh.total | +Counter | +slots refresh total count | +
slots_refresh.success_total | +Counter | +slots refresh success count | +
slots_refresh.failure_total | +Counter | +slots refresh failure count | +
redis.{COMMAND}.total | +Counter | +{COMMAND} total count | +
redis.{COMMAND}.success | +Counter | +{COMMAND} success count | +
redis.{COMMAND}.error | +Counter | +{COMMAND} error count | +
redis.{COMMAND}.latency_micros | +Histogram | +{COMMAND} latency micros | +
redis.moved | +Counter | +MOVED count | +
All notable changes to this project will be documented in this file.
+The format is based on Keep a Changelog, +and this project adheres to Semantic Versioning.
+Config
Samaritan (səˈmerətn) is a client side proxy that works on L4 or L7 layer written by golang, provide high availability and load balancing. +You can call it Sam (sam) for simplicity.
+At the beginning of our adapting to SOA, we used HAProxy as a client-side load balancer. +It does the job, painfully, as we have to do a file-based re-configuration whenever a change happens to the back-end nodes.
+The maintenance of the configuration file really hurts our OPs a lot, not to mention that a reload to HAProxy causes downtime. +This issue is so popular that people created things like Synapse and Bamboo to manage HAProxy instances, even hack deeply to minimize the downtime caused by HAProxy reload. +Those are great projects and actually get things done, however our approach to this is different, we want something more solid than templated configuration file with managed HAProxy processes.
+Boldly we decide to write our own load balancer with SOA in mind to replace HAProxy, and that is Samaritan. +We name this project Samaritan for saving our OPs from extreme misery:
+++A charitable or helpful person (with reference to Luke 10:33).
+"suddenly, miraculously, a Good Samaritan leaned over and handed the cashier a dollar bill on my behalf"
+
Sidecar
+Sam is a separated process which runs alongside the application. All the requests to basic components such as MySQL, Redis and MQ from application will be proxied +by the local instance. It shields the cluster discovery, switching, shrinking and other details in the distributed environment of the basic components, so that the application +can use as smooth as a single machine.
+Written by golang
+Go is an open source programming language that makes it easy to build simple, reliable, and efficient software. It has good performance and is widely used in the cloud environment.
+Hot re-configuration without downtime
+Sam supports obtaining the proxy configuration and service endpoints from the remote and updating at runtime which means doesn't need to restart at all. It greatly reduces +the cost of operation and maintenance, makes the large-scale deployment possible.
+First-class Redis cluster support
+Redis Cluster provides a way to run a Redis installation where data is automatically sharded across multiple Redis nodes. Sam supports L7 transparent proxy for redis requests, will forward +the request to the correct node automatically. In addition, also supports transparent compression for big key and real-time hot key collection.
+Good observability
+Provide detailed metrics about connection and request which could help us understand the state of network and services, make decisions. These exported statistics could be viewable via prometheus +or the local admin api.
+Sam pulls proxy strategy and service endpoints from the management server and do the load balancing at client side.
+Sash is a management server. It delivers the change of proxy strategy and service endpoints to the related sam instances. Also, provides the ops tools, such as + deploy, upgrade, etc.
+++Sash is a combination of Sam and Dashboard.
+
I believe that by reading the above chapters, you should have a basic impression and concept of Sam, then you can try to play with it.
+ + + + + + + + + +Field | +Type | +Label | +Description | +
---|---|---|---|
svc_names_subscribe | +string | +repeated | +All service names that need to subscribe. | +
svc_names_unsubscribe | +string | +repeated | +All service names that need to unsubscribe. | +
Field | +Type | +Label | +Description | +
---|---|---|---|
updated | +SvcConfigDiscoveryResponse.UpdatedEntry | +repeated | +Update of configuration. | +
Field | +Type | +Label | +Description | +
---|---|---|---|
key | +string | ++ | + |
value | +service.Config | ++ | + |
Field | +Type | +Label | +Description | +
---|---|---|---|
instance | +common.Instance | ++ | Meta information of the current instance. | +
Field | +Type | +Label | +Description | +
---|---|---|---|
added | +service.Service | +repeated | +Added service. | +
removed | +service.Service | +repeated | +Removed service. | +
Field | +Type | +Label | +Description | +
---|---|---|---|
svc_names_subscribe | +string | +repeated | +All service names that need to subscribe. | +
svc_names_unsubscribe | +string | +repeated | +All service names that need to unsubscribe. | +
Field | +Type | +Label | +Description | +
---|---|---|---|
svc_name | +string | ++ | Name of service which endpoints had updated. | +
added | +service.Endpoint | +repeated | +Added endpoints. | +
removed | +service.Endpoint | +repeated | +Removed endpoints. | +
DiscoveryService is a service which is used to discover service, service config +and service endpoints.
+Method Name | +Request Type | +Response Type | +Description | +
---|---|---|---|
StreamSvcs | +SvcDiscoveryRequest | +SvcDiscoveryResponse stream | ++ |
StreamSvcConfigs | +SvcConfigDiscoveryRequest stream | +SvcConfigDiscoveryResponse stream | ++ |
StreamSvcEndpoints | +SvcEndpointDiscoveryRequest stream | +SvcEndpointDiscoveryResponse stream | ++ |
The admin message is required to configure the administration server.
+Field | +Type | +Label | +Description | +
---|---|---|---|
bind | +common.Address | ++ | The TCP address that the administration server will listen on, not null. | +
This message is supplied via '-config' cli flag and act as the +root of configuration.
+Field | +Type | +Label | +Description | +
---|---|---|---|
instance | +common.Instance | ++ | The instance contains the meta information of the current instance. | +
log | +Log | ++ | Configuration for log. | +
stats | +Stats | ++ | Configuration for stats. | +
admin | +Admin | ++ | Configuration for the local administration HTTP server. | +
static_services | +StaticService | +repeated | +Statically specified services. | +
dynamic_source_config | +ConfigSource | ++ | Configuration for dynamic source config. | +
Configuration for dynamic source config.
+Field | +Type | +Label | +Description | +
---|---|---|---|
endpoint | +string | ++ | The gRPC endpoint of dynamic source config service, not null. | +
Log config.
+Field | +Type | +Label | +Description | +
---|---|---|---|
level | +Log.Level | ++ | Logging level | +
output | +Log.Output | ++ | Output target configuration, support send log to stdout or syslog, use stdout as default. | +
Field | +Type | +Label | +Description | +
---|---|---|---|
type | +Log.Output.Type | ++ | Type of output target. | +
target | +string | ++ | Address of server which is required when SYSLOG is selected. |
+
Sink is a sink for stats. Each Sink is responsible for writing stats +to a backing store.
+Field | +Type | +Label | +Description | +
---|---|---|---|
type | +Sink.Type | ++ | + |
endpoint | +string | ++ | Sink endpoint, not empty. | +
The wrapper of service config and endpoints.
+Field | +Type | +Label | +Description | +
---|---|---|---|
name | +string | ++ | The name of service. | +
config | +service.Config | ++ | The proxy strategy of service. | +
endpoints | +service.Endpoint | +repeated | +The endpoints of service. Need at least one endpoint. | +
Stats config.
+Field | +Type | +Label | +Description | +
---|---|---|---|
sinks | +Sink | +repeated | +Optional set of stats sinks. | +
Name | +Number | +Description | +
---|---|---|
INFO | +0 | +Print base messages during running. This is in addition to warnings and errors. | +
DEBUG | +-1 | +Print everything, including debugging information. | +
WARING | +1 | +Print all warnings and errors. | +
ERROR | +2 | +Print all errors. | +
QUIET | +3 | +Print nothing. | +
Name | +Number | +Description | +
---|---|---|
STDOUT | +0 | +stdout | +
SYSLOG | +1 | +syslog | +
Sink type
+Name | +Number | +Description | +
---|---|---|
UNKNOWN | +0 | ++ |
STATSD | +1 | +statsd | +
ATCP checker config.
+Field | +Type | +Label | +Description | +
---|---|---|---|
action | +ATCPChecker.Action | +repeated | +List of actions. All actions will execute during the health check, if one of the actions fails, this health check will be considered as failed. Need at least one action. | +
Action represents a set of requests from Samaritan to the server +and what the expected server returns.
+Field | +Type | +Label | +Description | +
---|---|---|---|
send | +bytes | ++ | This is used to send a data along with a connection opening. | +
expect | +bytes | ++ | Expecting content returned from the server. | +
Configuration of health check.
+Field | +Type | +Label | +Description | +
---|---|---|---|
interval | +google.protobuf.Duration | ++ | The interval between two consecutive health checks. Must be greater than 0s. | +
timeout | +google.protobuf.Duration | ++ | The timeout when doing a health check. Must be greater than 0s. | +
fall_threshold | +uint32 | ++ | A server will be considered as dead after # consecutive unsuccessful health checks. Must be greater than 0. | +
rise_threshold | +uint32 | ++ | A server will be considered as operational after # consecutive successful health checks. Must be greater than 0. | +
tcp_checker | +TCPChecker | ++ | + |
atcp_checker | +ATCPChecker | ++ | + |
mysql_checker | +MySQLChecker | ++ | + |
redis_checker | +RedisChecker | ++ | + |
MySQL checker config.
+Field | +Type | +Label | +Description | +
---|---|---|---|
username | +string | ++ | MySQL server username, not null. | +
Redis checker config.
+Field | +Type | +Label | +Description | +
---|---|---|---|
password | +string | ++ | Redis server password, if the password is not empty, the AUTH command will be sent before the PING command. | +
TCP checker config.
+ +MySQL protocol option.
+ +Redis protocol option.
+Field | +Type | +Label | +Description | +
---|---|---|---|
read_strategy | +RedisOption.ReadStrategy | ++ | Strategy of a read only command. | +
TCP protocol option.
+ +Protocol enum.
+Name | +Number | +Description | +
---|---|---|
UNKNOWN | +0 | ++ |
TCP | +1 | +TCP | +
MySQL | +2 | +MySQL | +
Redis | +3 | +Redis | +
Name | +Number | +Description | +
---|---|---|
MASTER | +0 | +Read from master nodes. | +
SLAVE | +1 | +Read from slave nodes. | +
BOTH | +2 | +Read from all nodes. | +
Field | +Type | +Label | +Description | +
---|---|---|---|
id | +string | ++ | The id of this instance, if id is not define, it will generate by ip and admin port. | +
version | +string | ++ | Version of this instance running now. This field is automatically populated by Samaritan does not require to specify by user. | +
belong | +string | ++ | The service name which this instance belongs to. It's required when you want to change the behavior of Sam at runtime, such as update proxy policy, update service endpoints, etc. If two instances belong to the same service, it will be treated in one group. | +
Field | +Type | +Label | +Description | +
---|---|---|---|
ip | +string | ++ | IP address, IPv4 or IPv6. | +
port | +uint32 | ++ | Port, [0, 65535]. | +
Field | +Type | +Label | +Description | +
---|---|---|---|
address | +common.Address | ++ | Address of endpoint, must be set. | +
state | +Endpoint.State | ++ | Healthy state of endpoint. When state is DOWN, this host will not be selected for load balancing. | +
type | +Endpoint.Type | ++ | Type of endpoints. When all hosts whose type is main are in the DOWN state, the host whose type is backup will be selected. | +
Name | +Number | +Description | +
---|---|---|
UP | +0 | +healthy | +
DOWN | +1 | +unhealthy | +
UNKNOWN | +2 | +unknown | +
Name | +Number | +Description | +
---|---|---|
MAIN | +0 | +main | +
BACKUP | +1 | +backup | +
Service represents a service.
+Field | +Type | +Label | +Description | +
---|---|---|---|
name | +string | ++ | Name of service. | +
Configuration of service, +contains configuration information required for the processor to run.
+Field | +Type | +Label | +Description | +
---|---|---|---|
listener | +Listener | ++ | Listener config, must be set. | +
health_check | +hc.HealthCheck | ++ | Health check will be disabled when not defined. | +
connect_timeout | +google.protobuf.Duration | ++ | The maximum time to wait for a connection attempt to a server to succeed, default is 3s. | +
idle_timeout | +google.protobuf.Duration | ++ | The maximum inactivity time on the client side, default is 10min. | +
lb_policy | +LoadBalancePolicy | ++ | + |
protocol | +protocol.Protocol | ++ | Protocol of service, can not be UNKNOWN. | +
tcp_option | +protocol.TCPOption | ++ | + |
redis_option | +protocol.RedisOption | ++ | + |
mysql_option | +protocol.MySQLOption | ++ | + |
Listener configuration.
+Field | +Type | +Label | +Description | +
---|---|---|---|
address | +common.Address | ++ | The address that the listener should listen on, must be set. | +
connection_limit | +uint32 | ++ | The limit of connections, new connections that exceed this value are immediately be closed. Default value is 0 that the limit will be disable. | +
Load balance policy.
+Name | +Number | +Description | +
---|---|---|
ROUND_ROBIN | +0 | +RoundRobin | +
LEAST_CONNECTION | +1 | +LeastConnection | +
RANDOM | +2 | +Random | +
CLUSTER_PROVIDED | +3 | +Provided by redis cluster | +
It's the fastest way, you can choose the appropriate binaries from release page.
+Assuming your os system is darwin and platform is amd64, you can use the following command to download and install.
+$ VERSION=1.0.0 OS=darwin ARCH=amd64 curl -fsSL \ + https://github.com/samaritan-proxy/samaritan/releases/download/v$VERSION/samaritan-$OS-$ARCH.tar.gz \ + -o /tmp/samaritan-$VERSION.tar.gz && \ + tar -zxvf /tmp/samaritan-$VERSION.tar.gz && \ + install /tmp/samaritan-$VERSION/samaritan /usr/local/bin +
Note
+You should replace the version, os system and arch information in download link as needed.
+If the pre-built binaries doesn't meet your needs or want to try the lastest features which are not released, you could build +it from the source code. This first needs Go installed(version 1.13+ is required).
+Warning
+The master branch is in continuous development and has not undergone the extensive testing and verification. There may be +some unknown problems, please do not use it directly for production.
+$ git clone https://github.com/samaritan-proxy/samaritan.git +$ cd samaritan && make +$ install ./bin/samaritan /usr/local/bin +
The following is an example of using Sam as a L4 layer TCP proxy to access example.com
+Terminal 1
+$ # resolve example.com, get ip +$ ip=$(dig +short example.com | head -1) +$ # generate config file +$ sudo bash -c 'cat > /etc/samaritan.yaml' <<EOF +admin: + bind: + ip: 127.0.0.1 + port: 12345 +log: + level: INFO +static_services: + - name: exmaple.com + config: + listener: + address: + ip: 0.0.0.0 + port: 8080 + protocol: TCP + endpoints: + - address: + ip: $ip + port: 80 +EOF +$ # start samaritan +$ samaritan +I 2019/10/18 15:10:38.067913 samaritan.go:60: stats config is empty +I 2019/10/18 15:10:38.068501 samaritan.go:184: Using CPUs: 4 +I 2019/10/18 15:10:38.068513 samaritan.go:185: Version: 1.0.0 +D 2019/10/18 15:10:38.068579 config.go:114: Disable dynamic config +I 2019/10/18 15:10:38.070397 server.go:39: Starting HTTP server at 0.0.0.0:12345 +I 2019/10/18 15:10:38.070534 samaritan.go:89: PID: 60289 +I 2019/10/18 15:10:38.072735 monitor.go:48: health check config is null, healthy check will disable +I 2019/10/18 15:10:38.074646 controller.go:110: Add processor exmaple +I 2019/10/18 15:10:38.093603 listener.go:105: [exmaple] start serving at 0.0.0.0:8080 +
Tip
+You could store the config file anywhere you like and can find.
+Terminal 2
+$ curl -v -I -H "Host: example.com" http://127.0.0.1:8080 +* Rebuilt URL to: http://127.0.0.1:8080/ +* Trying 127.0.0.1... +* TCP_NODELAY set +* Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0) +> HEAD / HTTP/1.1 +> Host: example.com +> User-Agent: curl/7.54.0 +> Accept: */* +> +< HTTP/1.1 200 OK +HTTP/1.1 200 OK +< Accept-Ranges: bytes +Accept-Ranges: bytes +< Cache-Control: max-age=604800 +Cache-Control: max-age=604800 +< Content-Type: text/html; charset=UTF-8 +Content-Type: text/html; charset=UTF-8 +< Date: Fri, 18 Oct 2019 07:26:11 GMT +Date: Fri, 18 Oct 2019 07:26:11 GMT +< Etag: "3147526947+gzip+ident" +Etag: "3147526947+gzip+ident" +< Expires: Fri, 25 Oct 2019 07:26:11 GMT +Expires: Fri, 25 Oct 2019 07:26:11 GMT +< Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT +Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT +< Server: ECS (sjc/4E74) +Server: ECS (sjc/4E74) +< X-Cache: HIT +X-Cache: HIT +< Content-Length: 1256 +Content-Length: 1256 + +< +* Connection #0 to host 127.0.0.1 left intact +
As you can see, we visited example.com via Sam.
+In the aboved section, we generate a simple configuration file and start Sam with it. But you may have no idea about +it, you may be overwhelmed. For better understanding, we will show you the specific parts of the configuration file.
+The instance message is used to specify the environment in which the instance is located, and will be reported to +the management server.
+instance: + id: ip_port + belong: sash +
Warning
+If you want to use the dynamic config feature, you must add this section to configuration file.
+The log message is used to specify the log level and output destination.
+log: + level: INFO + output: + type: SYSLOG + target: 127.0.0.1:514 +
If it is omitted, the log level will be INFO and the message will be printed to terminal.
+Why does the output not support files
+The stats message is used to specify the stats config include internal metrics config and sinks.
+stats: + sinks: + - type: STATSD + endpoint: statsd-server.elenet.me:8125 +
If it is omitted, the internal metrics wouldn't flush to any TSDB except Prometheus which could still be visited via /amin/stats/prometheus
.
+Prometheus is sufficient for most users which means you could omit the stats config directly.
The admin message is used to specify the configuration for local admin api.
+admin: + bind: + ip: 127.0.0.1 + port: 12345 +
It's required, otherwise the entire process cannot be started. More details about admin api, you can view doc
+The static service message is used to specify the static service including name, proxy strategy and endpoints.
+static_services: + - name: example.com + config: + listener: + address: + ip: 127.0.0.1 + port: 8080 + protocol: TCP + endpoints: + - address: + ip: 93.184.216.34 + port: 80 +
You can use it to configure the proxy's services in a local development environment, but it is not recommended. +Here are the reasons:
+The correct and recommended way is to use dynamic source, which will be described in detail below.
+The dynamic source message is used to specify the dynamic source configuration.
+dynamic_source_config: + endpoint: sash.elenet.me:80 +
Once the dynamic source is configured, Sam could know and apply the changes of instance's dependent services, service's proxy policy and service's endpoints in real time. +The communication way between them is grpc, and here is the specific interface definition.
+Tip
+As the management server, Sash will implement all the interface required by dynamic source. +It is still private now, but we will open source as soon as possible.
+