A股底部顶部特征

=================================>>> 底部特征

  • 破净股大量出现

    1
    2
    3
    2005.06.06	998点附近, 破净股176只,占A股总数13.42%
    2008.10.28 1664点附近, 破净股214只,占A股总数13.54%
    2013.06.25 1849点附近, 破净股161只,占A股总数6.53%
  • 1元股

    1
    2
    3
    2005.06.03	998点附近, 24只	占A股总数1.83%	A股总数1311
    2008.11.06 1664点附近, 63只 占A股总数3.99% A股总数1580
    2013.06.25 1849点附近, 16只 占A股总数0.65% A股总数2465
  • 抗跌版块补跌 优质龙头下跌

    1
    茅台 格力 伊利股份等白马股扑倒在地, 茅台可能腰斩
  • 券商过苦日子

    1
    券商是靠天吃饭的,关于券商裁员,减薪,减奖金的消息
  • 低估值(TTM)

    1
    2
    3
    4
    5
    2005年06月估值18, 2005.07.18似乎最低点是15(实际是14.58)
    2008年10月估值14
    2013年06月估值12, 2014年7月似乎PE最低达到了9.69,

    要来的底部2020-2021年,估值可能在10甚至更低, 操作策略应该是上证PE为12左右就慢慢开始介入券商为首的金融股
  • 金融股全面破净

    1
    银行PB压到0.7~0.8甚至更低
  • 政府救市

    1
    TODO
  • 成交量低迷

    1
    TODO
  • 股民大面积亏损

    1
    市场中不论是机构投资者还是散户,均处于高度亏损状态,市场亏损面达70%以上,且亏损幅度较大
  • 新股破发或停止发行

    1
    新股上市即跌破或接近发行价,不论质地好坏,新股均没能得到市场的认可,价格定位低于平时
  • 利好失效

    1
    TODO

=================================>>> 顶部特征

  • 新开户

    1
    2
    3
    4
    李大霄开门见山地说,“首先,我们的新开户数是166万户,已经接近2007年 5·30 (5月30日股票大跌)前后的178万户的峰值。
    第二,我们现在有1.7万亿元的杠杆(编者注:即借钱炒股的融资余额),杠杆率接近10%。
    第三,我们现在的成交量是1.55万亿,算下来平均两周能够换一次手,而成熟市场的换手率是一到两年换一次手。
    我们现在的上市公司的利润已经被换手率消化干净了,我们现在是炒空气,不是炒利润。”
  • 高估值

    1
    2
    3
    最后一个,我们高估值的股票太多了,现在股市在4000点附近,100倍以上估值的股票占44.63%,
    但是2008年股市最高点6124点的时候,100倍以上的股票占42%;
    我们看到创业板整体估值水平已经接近100倍,这是纳斯达克泡沫爆破前的水平,是人类股市的极限。任何一根针有可能把这个泡沫刺破,比如扩容、新三板转板等等。”
  • 巴菲特指数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    巴菲特有一个判断股市风险的最简单办法,就是看股票市值和GDP的比例。
    当比例超过100%,也就是总市值等于GDP,属于风险开始急剧,开始适当的建仓,保住本金。
    当比值超过125%,崩盘的风险非常大,最好跑掉。
    历史上很少有这个比例能超过135%的情况。

    当然,每个国家的股市都有自己的特点,不同的时期,支持每个股市的货币量也不同。

    2015-05-23沪深A股的总市值不到70万亿,还不到GDP的110%,属于有大风险,还没到崩盘线。
    而美国股票的市值,超过了135%,不也再涨吗?
    所以,啥时候跑只能大家自己把握。从投资纪律上讲,现在至少应该撤出资本金,先保本再看后市了。

Assign_arrow_keys_to_history_search_in_bash

1
2
3
4
"\e[A": history-search-backward
"\e[B":history-search-forward
set show-all-if-ambiguous on
set completion-ignore-case on

在 /etc/inputrc
或者 ~/.inputrc 里加上如上配置,重新登录shell就行了

http://hints.macworld.com/article.php?story=20031026174236860

With Panther, the default shell is now Bash. I had customized my tcsh shell using this hint In bash you can get similar results by adding this to your .bash_profile

1
2
bind '"M-[A":history-search-backward'
bind '"M-[B":history-search-forward'

where M-[A is the up key and M-[B is the down key.

authorized_keys不生效的解决方法

配置用户的公钥登陆时,配置完authorized_keys居然一直不生效,于是google之,发现原来是因为.ssh目录和下面文件的权限问题导致的,

因为目录的权限已经超过了sshd的要求权限。

如果希望ssh公钥生效需满足至少下面两个条件:

1
2
1) .ssh目录的权限必须是700
2) .ssh/authorized_keys文件权限必须是600

smart_deploy_war

  1. install jdk1.8.0_192 to /usr/local/
  2. set the classpath in /etc/profile
  3. ln -s /usr/local/jdk1.8.0_192/bin/java /bin/java
  4. scp apache-tomcat-8.5.35 to the target server (/usr/local/apache-tomcat-8.5.35)
  5. chmod -R 777 /usr/local/apache-tomcat-8.5.35
  6. stop firewalld
1
2
3
4
5
6
7
# 停止并禁用firewalld开机启动
sytemctl disable firewalld
chkconfig iptables off

# 查看防火状态
systemctl status firewalld
service iptables status
  1. /data/docker_volumes/jenkins/.ssh/192.1.114.170_jenkins_id_rsa.pub >>>>>>>>>>>>>>>> user@ip–>authorized_keys

    1
    FYI https://www.cnblogs.com/weifeng1463/p/7878366.html
  2. ~/.ssh/id_rsa.pub >>>>>>>>>>>>>>>> user@ip–>authorized_keys

  3. target-server /etc/ssh/ssh_config 中的 StrictHostKeyChecking ask 改成 StrictHostKeyChecking no

spring-cloud-gateway-paper

https://wsk1103.github.io/2018/12/16/Spring-Cloud学习笔记8-spring-cloud-gateway(第二代网关)/

Spring Cloud Gateway网关研究
Spring Cloud Gateway初体验
Spring Cloud Gateway 之Predict篇
Spring Cloud Gateway 之filter篇
Spring Cloud Gateway 之限流篇
spring cloud gateway之服务注册与发现

简介
网关作为流量的,在微服务系统中有着非常作用,网关常见的功能有路由转发、权限校验、限流控制等作用。Spring Cloud Gateway是Spring Cloud体系的第二代网关组件,基于Spring 5.0的新特性WebFlux进行开发,底层网络通信框架使用的是Netty,所以其吞吐量高、性能强劲,未来将会取代第一代的网关组件Zuul。本文将以成体系的的方式逐步介绍Spring Cloud Gateway。

创建工程
本案例的的源码下载于官方案例,工程使用的Spring Boot版本为2.0.5.RELEASE,Spring Cloud版本为Finchley.SR1。
新建一个工程,取名为sc-f-gateway-first-sight在工程的pom文件引用工程所需的依赖,包括spring boot和spring cloud,以及gateway的起步依赖spring-cloud-starter-gateway,代码如下:

org.springframework.boot
spring-boot-starter-parent
2.0.5.RELEASE

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Finchley.SR1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

org.springframework.cloud
spring-cloud-starter-gateway

注:详细的pom文件依赖,可以见源码。

创建一个简单的路由
在spring cloud gateway中使用RouteLocator的Bean进行路由转发,将请求进行处理,最后转发到目标的下游服务。在本案例中,会将请求转发到http://httpbin.org:80这个地址上。代码如下:
@SpringBootApplication
@RestController
public class Application {

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public RouteLocator myRoutes(RouteLocatorBuilder builder) {
return builder.routes()
.route(p -> p
.path(“/get”)
.filters(f -> f.addRequestHeader(“Hello”, “World”))
.uri(“http://httpbin.org:80“))
.build();
}
}
在上面的myRoutes方法中,使用了一个RouteLocatorBuilder的bean去创建路由,除了创建路由RouteLocatorBuilder可以让你添加各种predicates和filters,predicates断言的意思,顾名思义就是根据具体的请求的规则,由具体的route去处理,filters是各种过滤器,用来对请求做各种判断和修改。

上面创建的route可以让请求“/get”请求都转发到“http://httpbin.org/get”。在route配置上,我们添加了一个filter,该filter会将请求添加一个header,key为hello,value为world。

启动springboot项目,在浏览器上http://localhost:8080/get,浏览器显示如下:

{
“args”: {},
“headers”: {
“Accept”: “text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8”,
“Accept-Encoding”: “gzip, deflate, br”,
“Accept-Language”: “zh-CN,zh;q=0.9,en;q=0.8”,
“Cache-Control”: “max-age=0”,
“Connection”: “close”,
“Cookie”: “_ga=GA1.1.412536205.1526967566; JSESSIONID.667921df=node01oc1cdl4mcjdx1mku2ef1l440q1.node0; screenResolution=1920x1200”,
“Forwarded”: “proto=http;host=\”localhost:8080\”;for=\”0:0:0:0:0:0:0:1:60036\””,
“Hello”: “World”,
“Host”: “httpbin.org”,
“Upgrade-Insecure-Requests”: “1”,
“User-Agent”: “Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36”,
“X-Forwarded-Host”: “localhost:8080”
},
“origin”: “0:0:0:0:0:0:0:1, 210.22.21.66”,
“url”: “http://localhost:8080/get
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
可见当我们向gateway工程请求“/get”,gateway会将工程的请求转发到“http://httpbin.org/get”,并且在转发之前,加上一个filter,该filter会将请求添加一个header,key为hello,value为world。

注意HTTPBin展示了请求的header hello和值world。

使用Hystrix

在spring cloud gateway中可以使用Hystrix。Hystrix是 spring cloud中一个服务熔断降级的组件,在微服务系统有着十分重要的作用。
Hystrix是 spring cloud gateway中是以filter的形式使用的,代码如下:

@Bean
public RouteLocator myRoutes(RouteLocatorBuilder builder) {
String httpUri = “http://httpbin.org:80“;
return builder.routes()
.route(p -> p
.path(“/get”)
.filters(f -> f.addRequestHeader(“Hello”, “World”))
.uri(httpUri))
.route(p -> p
.host(“.hystrix.com”)
.filters(f -> f
.hystrix(config -> config
.setName(“mycmd”)
.setFallbackUri(“forward:/fallback”)))
.uri(httpUri))
.build();
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
在上面的代码中,我们使用了另外一个router,该router使用host去断言请求是否进入该路由,当请求的host有“
.hystrix.com”,都会进入该router,该router中有一个hystrix的filter,该filter可以配置名称、和指向性fallback的逻辑的地址,比如本案例中重定向到了“/fallback”。

现在写的一个“/fallback”的l逻辑:


@RequestMapping(“/fallback”)
public Mono fallback() {
return Mono.just(“fallback”);
}

1
2
3
4
5
6
Mono是一个Reactive stream,对外输出一个“fallback”字符串。

使用curl执行以下命令:

curl –dump-header - –header ‘Host: www.hystrix.com’ http://localhost:8080/delay/3

1
2
返回的响应为:

fallback
1
可见,带hostwww.hystrix.com的请求执行了hystrix的fallback的逻辑。

总结

本文通过官方的一个简单的案例,来讲解了spring cloud gateway的简单用法,在spring cloud gateway中有2个重要的概念predicates和filters,它们个将会在后续文章讲解。敬请期待。






Spring Cloud gateway工作流程

在之前的文章的Spring Cloud Gateway初体验中,大家已经对Spring Cloud Gateway的功能有一个初步的认识,网关作为一个系统的流量的入口,有着举足轻重的作用,通常的作用如下:

协议转换,路由转发
流量聚合,对流量进行监控,日志输出
作为整个系统的前端工程,对流量进行控制,有限流的作用
作为系统的前端边界,外部流量只能通过网关才能访问系统
可以在网关层做权限的判断
可以在网关层做缓存
Spring Cloud Gateway作为Spring Cloud框架的第二代网关,在功能上要比Zuul更加的强大,性能也更好。随着Spring Cloud的版本迭代,Spring Cloud官方有打算弃用Zuul的意思。在笔者调用了Spring Cloud Gateway的使用和功能上,Spring Cloud Gateway替换掉Zuul的成本上是非常低的,几乎可以无缝切换。Spring Cloud Gateway几乎包含了zuul的所有功能。



注:该图片来自官网

如上图所示,客户端向Spring Cloud Gateway发出请求。 如果Gateway Handler Mapping确定请求与路由匹配(这个时候就用到predicate),则将其发送到Gateway web handler处理。 Gateway web handler处理请求时会经过一系列的过滤器链。 过滤器链被虚线划分的原因是过滤器链可以在发送代理请求之前或之后执行过滤逻辑。 先执行所有“pre”过滤器逻辑,然后进行代理请求。 在发出代理请求之后,收到代理服务的响应之后执行“post”过滤器逻辑。这跟zuul的处理过程很类似。在执行所有“pre”过滤器逻辑时,往往进行了鉴权、限流、日志输出等功能,以及请求头的更改、协议的转换;转发之后收到响应之后,会执行所有“post”过滤器的逻辑,在这里可以响应数据进行了修改,比如响应头、协议的转换等。

在上面的处理过程中,有一个重要的点就是讲请求和路由进行匹配,这时候就需要用到predicate,它是决定了一个请求走哪一个路由。

predicate简介

Predicate来自于java8的接口。Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将Predicate组合成其他复杂的逻辑(比如:与,或,非)。可以用于接口请求参数校验、判断新老数据是否有变化需要进行更新操作。add–与、or–或、negate–非。
Spring Cloud Gateway内置了许多Predict,这些Predict的源码在org.springframework.cloud.gateway.handler.predicate包中,如果读者有兴趣可以阅读一下。现在列举各种Predicate如下图:



注:图片来自网络

在上图中,有很多类型的Predicate,比如说时间类型的Predicated(AfterRoutePredicateFactory BeforeRoutePredicateFactory BetweenRoutePredicateFactory),当只有满足特定时间要求的请求会进入到此predicate中,并交由router处理;cookie类型的CookieRoutePredicateFactory,指定的cookie满足正则匹配,才会进入此router;以及host、method、path、querparam、remoteaddr类型的predicate,每一种predicate都会对当前的客户端请求进行判断,是否满足当前的要求,如果满足则交给当前请求处理。如果有很多个Predicate,并且一个请求满足多个Predicate,则按照配置的顺序第一个生效。

predicate实战

现在以案例的形式来讲解predicate,本文中的案例基本来源于官方文档,官方文档地址:http://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.0.0.RELEASE/single/spring-cloud-gateway.html ;如果有任何问题欢迎和我联系,和我讨论。

创建一个工程,在工程的pom文件引入spring cloud gateway 的起步依赖spring-cloud-starter-gateway,spring cloud版本和spring boot版本,代码如下:



org.springframework.boot
spring-boot-starter-parent
2.0.5.RELEASE





org.springframework.cloud
spring-cloud-dependencies
Finchley.SR1
pom
import





org.springframework.cloud
spring-cloud-starter-gateway

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
After Route Predicate Factory

AfterRoutePredicateFactory,可配置一个时间,当请求的时间在配置时间之后,才交给 router去处理。否则则报错,不通过路由。

在工程的application.yml配置如下:

server:
port: 8081
spring:
profiles:
active: after_route


spring:
cloud:
gateway:
routes:

- id: after_route
  uri: http://httpbin.org:80/get
  predicates:
  - After=2017-01-20T17:42:47.789-07:00[America/Denver]

profiles: after_route

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
在上面的配置文件中,配置了服务的端口为8081,配置spring.profiles.active:after_route指定了程序的spring的启动文件为after_route文件。在application.yml再建一个配置文件,语法是三个横线,在此配置文件中通过spring.profiles来配置文件名,和spring.profiles.active一致,然后配置spring cloud gateway 相关的配置,id标签配置的是router的id,每个router都需要一个唯一的id,uri配置的是将请求路由到哪里,本案例全部路由到http://httpbin.org:80/get。

predicates:
After=2017-01-20T17:42:47.789-07:00[America/Denver] 会被解析成PredicateDefinition对象 (name =After ,args= 2017-01-20T17:42:47.789-07:00[America/Denver])。在这里需要注意的是predicates的After这个配置,遵循的契约大于配置的思想,它实际被AfterRoutePredicateFactory这个类所处理,这个After就是指定了它的Gateway web handler类为AfterRoutePredicateFactory,同理,其他类型的predicate也遵循这个规则。

当请求的时间在这个配置的时间之后,请求会被路由到http://httpbin.org:80/get。

启动工程,在浏览器上访问http://localhost:8081/,会显示http://httpbin.org:80/get返回的结果,此时gateway路由到了配置的uri。如果我们将配置的时间设置到当前时之后,浏览器会显示404,此时证明没有路由到配置的uri.

跟时间相关的predicates还有Before Route Predicate Factory、Between Route Predicate Factory,读者可以自行查阅官方文档,再次不再演示。

Header Route Predicate Factory

Header Route Predicate Factory需要2个参数,一个是header名,另外一个header值,该值可以是一个正则表达式。当此断言匹配了请求的header名和值时,断言通过,进入到router的规则中去。

在工程的配置文件加上以下的配置:

spring:
profiles:
active: header_route


spring:
cloud:
gateway:
routes:

- id: header_route
  uri: http://httpbin.org:80/get
  predicates:
  - Header=X-Request-Id, \d+

profiles: header_route

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
在上面的配置中,当请求的Header中有X-Request-Id的header名,且header值为数字时,请求会被路由到配置的 uri. 使用curl执行以下命令:

$ curl -H ‘X-Request-Id:1’ localhost:8081

1
2
执行命令后,会正确的返回请求结果,结果省略。如果在请求中没有带上X-Request-Id的header名,并且值不为数字时,请求就会报404,路由没有被正确转发。

Cookie Route Predicate Factory

Cookie Route Predicate Factory需要2个参数,一个时cookie名字,另一个时值,可以为正则表达式。它用于匹配请求中,带有该名称的cookie和cookie匹配正则表达式的请求。

在配置文件添加以下配置:

spring:
profiles:
active: cookie_route


spring:
cloud:
gateway:
routes:

- id: cookie_route
  uri: http://httpbin.org:80/get
  predicates:
  - Cookie=name, forezp

profiles: cookie_route

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
在上面的配置中,请求带有cookie名为
name, cookie值为forezp 的请求将都会转发到uri为 http://httpbin.org:80/get的地址上。
使用curl命令进行请求,在请求中带上 cookie,会返回正确的结果,否则,请求报404错误。

$ curl -H ‘Cookie:name=forezp’ localhost:8081

1
2
Host Route Predicate Factory

Host Route Predicate Factory需要一个参数即hostname,它可以使用. * 等去匹配host。这个参数会匹配请求头中的host的值,一致,则请求正确转发。

在工程的配置文件,加上以下配置:

spring:
profiles:

active: host_route

spring:
cloud:
gateway:
routes:

- id: host_route
  uri: http://httpbin.org:80/get
  predicates:
  - Host=**.fangzhipeng.com

profiles: host_route
1
2
3
4
5
6
7
8
9
10
11
12
13
14
在上面的配置中,请求头中含有Host为fangzhipeng.com的请求将会被路由转发转发到配置的uri。 启动工程,执行以下的curl命令,请求会返回正确的请求结果:

curl -H ‘Host:www.fangzhipeng.com’ localhost:8081

1
2
3
Method Route Predicate Factory

Method Route Predicate Factory 需要一个参数,即请求的类型。比如GET类型的请求都转发到此路由。在工程的配置文件加上以下的配置:

spring:
profiles:
active: method_route


spring:
cloud:
gateway:
routes:

- id: method_route
  uri: http://httpbin.org:80/get
  predicates:
  - Method=GET

profiles: method_route

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
在上面的配置中,所有的GET类型的请求都会路由转发到配置的uri。使用 curl命令模拟 get类型的请求,会得到正确的返回结果。

$ curl localhost:8081

1
2
3
使用 curl命令模拟 post请求,则返回404结果。

$ curl -XPOST localhost:8081

1
2
Path Route Predicate Factory

Path Route Predicate Factory 需要一个参数: 一个spel表达式,应用匹配路径。

在工程的配置文件application.yml文件中,做以下的配置:

spring:
profiles:

active: path_route

spring:
cloud:
gateway:
routes:

- id: path_route
  uri: http://httpbin.org:80/get
  predicates:
  - Path=/foo/{segment}

profiles: path_route

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
在上面的配置中,所有的请求路径满足/foo/{segment}的请求将会匹配并被路由,比如/foo/1 、/foo/bar的请求,将会命中匹配,并成功转发。

使用curl模拟一个请求localhost:8081/foo/dew,执行之后会返回正确的请求结果。

$ curl localhost:8081/foo/dew

1
2
Query Route Predicate Factory

Query Route Predicate Factory 需要2个参数:一个参数名和一个参数值的正则表达式。在工程的配置文件application.yml做以下的配置:

spring:
profiles:

active: query_route

spring:
cloud:
gateway:
routes:

- id: query_route
  uri: http://httpbin.org:80/get
  predicates:
  - Query=foo, ba.

profiles: query_route

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
在上面的配置文件中,配置了请求中含有参数foo,并且foo的值匹配ba.,则请求命中路由,比如一个请求中含有参数名为foo,值的为bar,能够被正确路由转发。

模拟请求的命令如下:

$ curl localhost:8081?foo=bar

1
2
3
Query Route Predicate Factory也可以只填一个参数,填一个参数时,则只匹配参数名,即请求的参数中含有配置的参数名,则命中路由。比如以下的配置中,配置了请求参数中含有参数名为foo 的参数将会被请求转发到uri为http://httpbin.org:80/get。

spring:
cloud:
gateway:
routes:

- id: query_route
  uri: http://httpbin.org:80/get
  predicates:
  - Query=foo

profiles: query_route

1
2
3
4
5
6
7
8
9
10
11
总结

在本篇文章中,首先介绍了Spring Cloud Gateway的工作流程和原理,然后介绍了gateway框架内置的predict及其分类,最后以案例的形式重点讲解了几个重要的Predict。Predict作为断言,它决定了请求会被路由到哪个router 中。在断言之后,请求会被进入到filter过滤器的逻辑,下篇文章将会为大家介绍Spring Cloud Gateway过滤器相关的内容。

在上一篇文章详细的介绍了Gateway的Predict,Predict决定了请求由哪一个路由处理,在路由处理之前,需要经过“pre”类型的过滤器处理,处理返回响应之后,可以由“post”类型的过滤器处理。

filter的作用和生命周期

由filter工作流程点,可以知道filter有着非常重要的作用,在“pre”类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,在“post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等。首先需要弄清一点为什么需要网关这一层,这就不得不说下filter的作用了。

作用

当我们有很多个服务时,比如下图中的user-service、goods-service、sales-service等服务,客户端请求各个服务的Api时,每个服务都需要做相同的事情,比如鉴权、限流、日志输出等。

对于这样重复的工作,有没有办法做的更好,答案是肯定的。在微服务的上一层加一个全局的权限控制、限流、日志输出的Api Gatewat服务,然后再将请求转发到具体的业务服务层。这个Api Gateway服务就是起到一个服务边界的作用,外接的请求访问系统,必须先通过网关层。

生命周期

Spring Cloud Gateway同zuul类似,有“pre”和“post”两种方式的filter。客户端的请求先经过“pre”类型的filter,然后将请求转发到具体的业务服务,比如上图中的user-service,收到业务服务的响应之后,再经过“post”类型的filter处理,最后返回响应到客户端。

与zuul不同的是,filter除了分为“pre”和“post”两种方式的filter外,在Spring Cloud Gateway中,filter从作用范围可分为另外两种,一种是针对于单个路由的gateway filter,它在配置文件中的写法同predict类似;另外一种是针对于所有路由的global gateway filer。现在从作用范围划分的维度来讲解这两种filter。

gateway filter

过滤器允许以某种方式修改传入的HTTP请求或传出的HTTP响应。过滤器可以限定作用在某些特定请求路径上。 Spring Cloud Gateway包含许多内置的GatewayFilter工厂。

GatewayFilter工厂同上一篇介绍的Predicate工厂类似,都是在配置文件application.yml中配置,遵循了约定大于配置的思想,只需要在配置文件配置GatewayFilter Factory的名称,而不需要写全部的类名,比如AddRequestHeaderGatewayFilterFactory只需要在配置文件中写AddRequestHeader,而不是全部类名。在配置文件中配置的GatewayFilter Factory最终都会相应的过滤器工厂类处理。

Spring Cloud Gateway 内置的过滤器工厂一览表如下:

现在挑几个常见的过滤器工厂来讲解,每一个过滤器工厂在官方文档都给出了详细的使用案例,如果不清楚的还可以在org.springframework.cloud.gateway.filter.factory看每一个过滤器工厂的源码。

AddRequestHeader GatewayFilter Factory

创建工程,引入相关的依赖,包括spring boot 版本2.0.5,spring Cloud版本Finchley,gateway依赖如下:


org.springframework.cloud
spring-cloud-starter-gateway

1
2
3
4
5
在工程的配置文件中,加入以下的配置:

server:
port: 8081
spring:
profiles:
active: add_request_header_route


spring:
cloud:
gateway:
routes:

- id: add_request_header_route
  uri: http://httpbin.org:80/get
  filters:
  - AddRequestHeader=X-Request-Foo, Bar
  predicates:
  - After=2017-01-20T17:42:47.789-07:00[America/Denver]

profiles: add_request_header_route

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
在上述的配置中,工程的启动端口为8081,配置文件为add_request_header_route,在add_request_header_route配置中,配置了roter的id为add_request_header_route,路由地址为http://httpbin.org:80/get,该router有AfterPredictFactory,有一个filter为AddRequestHeaderGatewayFilterFactory(约定写成AddRequestHeader),AddRequestHeader过滤器工厂会在请求头加上一对请求头,名称为X-Request-Foo,值为Bar。为了验证AddRequestHeaderGatewayFilterFactory是怎么样工作的,查看它的源码,AddRequestHeaderGatewayFilterFactory的源码如下:

public class AddRequestHeaderGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {

@Override
public GatewayFilter apply(NameValueConfig config) {
    return (exchange, chain) -> {
        ServerHttpRequest request = exchange.getRequest().mutate()
                .header(config.getName(), config.getValue())
                .build();

        return chain.filter(exchange.mutate().request(request).build());
    };
}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
由上面的代码可知,根据旧的ServerHttpRequest创建新的 ServerHttpRequest ,在新的ServerHttpRequest加了一个请求头,然后创建新的 ServerWebExchange ,提交过滤器链继续过滤。

启动工程,通过curl命令来模拟请求:

curl localhost:8081

1
2
3
最终显示了从 http://httpbin.org:80/get得到了请求,响应如下:

{
“args”: {},
“headers”: {
“Accept”: “/“,
“Connection”: “close”,
“Forwarded”: “proto=http;host=\”localhost:8081\”;for=\”0:0:0:0:0:0:0:1:56248\””,
“Host”: “httpbin.org”,
“User-Agent”: “curl/7.58.0”,
“X-Forwarded-Host”: “localhost:8081”,
“X-Request-Foo”: “Bar”
},
“origin”: “0:0:0:0:0:0:0:1, 210.22.21.66”,
“url”: “http://localhost:8081/get
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
可以上面的响应可知,确实在请求头中加入了X-Request-Foo这样的一个请求头,在配置文件中配置的AddRequestHeader过滤器工厂生效。

跟AddRequestHeader过滤器工厂类似的还有AddResponseHeader过滤器工厂,在此就不再重复。

RewritePath GatewayFilter Factory

在Nginx服务启中有一个非常强大的功能就是重写路径,Spring Cloud Gateway默认也提供了这样的功能,这个功能是Zuul没有的。在配置文件中加上以下的配置:

spring:
profiles:

active: rewritepath_route

spring:
cloud:
gateway:
routes:

- id: rewritepath_route
  uri: https://blog.csdn.net
  predicates:
  - Path=/foo/**
  filters:
  - RewritePath=/foo/(?<segment>.*), /$\{segment}

profiles: rewritepath_route

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
上面的配置中,所有的/foo/*开始的路径都会命中配置的router,并执行过滤器的逻辑,在本案例中配置了RewritePath过滤器工厂,此工厂将/foo/(?.)重写为{segment},然后转发到https://blog.csdn.net。比如在网页上请求localhost:8081/foo/forezp,此时会将请求转发到https://blog.csdn.net/forezp的页面,比如在网页上请求localhost:8081/foo/forezp/1,页面显示404,就是因为不存在https://blog.csdn.net/forezp/1这个页面。

自定义过滤器

Spring Cloud Gateway内置了19种强大的过滤器工厂,能够满足很多场景的需求,那么能不能自定义自己的过滤器呢,当然是可以的。在spring Cloud Gateway中,过滤器需要实现GatewayFilter和Ordered2个接口。写一个RequestTimeFilter,代码如下:

public class RequestTimeFilter implements GatewayFilter, Ordered {

private static final Log log = LogFactory.getLog(GatewayFilter.class);
private static final String REQUEST_TIME_BEGIN = "requestTimeBegin";

@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

    exchange.getAttributes().put(REQUEST_TIME_BEGIN, System.currentTimeMillis());
    return chain.filter(exchange).then(
            Mono.fromRunnable(() -> {
                Long startTime = exchange.getAttribute(REQUEST_TIME_BEGIN);
                if (startTime != null) {
                    log.info(exchange.getRequest().getURI().getRawPath() + ": " + (System.currentTimeMillis() - startTime) + "ms");
                }
            })
    );

}

@Override
public int getOrder() {
    return 0;
}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
在上面的代码中,Ordered中的int getOrder()方法是来给过滤器设定优先级别的,值越大则优先级越低。还有有一个filterI(exchange,chain)方法,在该方法中,先记录了请求的开始时间,并保存在ServerWebExchange中,此处是一个“pre”类型的过滤器,然后再chain.filter的内部类中的run()方法中相当于”post”过滤器,在此处打印了请求所消耗的时间。然后将该过滤器注册到router中,代码如下:

@Bean
public RouteLocator customerRouteLocator(RouteLocatorBuilder builder) {
    // @formatter:off
    return builder.routes()
            .route(r -> r.path("/customer/**")
                    .filters(f -> f.filter(new RequestTimeFilter())
                            .addResponseHeader("X-Response-Default-Foo", "Default-Bar"))
                    .uri("http://httpbin.org:80/get")
                    .order(0)
                    .id("customer_filter_router")
            )
            .build();
    // @formatter:on
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
重启程序,通过curl命令模拟请求:

curl localhost:8081/customer/123

1
2
在程序的控制台输出一下的请求信息的日志:

2018-11-16 15:02:20.177 INFO 20488 — [ctor-http-nio-3] o.s.cloud.gateway.filter.GatewayFilter : /customer/123: 152ms

1
2
3
自定义过滤器工厂

在上面的自定义过滤器中,有没有办法自定义过滤器工厂类呢?这样就可以在配置文件中配置过滤器了。现在需要实现一个过滤器工厂,在打印时间的时候,可以设置参数来决定是否打印请参数。查看GatewayFilterFactory的源码,可以发现GatewayFilterfactory的层级如下:

过滤器工厂的顶级接口是GatewayFilterFactory,我们可以直接继承它的两个抽象类来简化开发AbstractGatewayFilterFactory和AbstractNameValueGatewayFilterFactory,这两个抽象类的区别就是前者接收一个参数(像StripPrefix和我们创建的这种),后者接收两个参数(像AddResponseHeader)。

过滤器工厂的顶级接口是GatewayFilterFactory,有2个两个较接近具体实现的抽象类,分别为AbstractGatewayFilterFactory和AbstractNameValueGatewayFilterFactory,这2个类前者接收一个参数,比如它的实现类RedirectToGatewayFilterFactory;后者接收2个参数,比如它的实现类AddRequestHeaderGatewayFilterFactory类。现在需要将请求的日志打印出来,需要使用一个参数,这时可以参照RedirectToGatewayFilterFactory的写法。

public class RequestTimeGatewayFilterFactory extends AbstractGatewayFilterFactory {

private static final Log log = LogFactory.getLog(GatewayFilter.class);
private static final String REQUEST_TIME_BEGIN = "requestTimeBegin";
private static final String KEY = "withParams";

@Override
public List<String> shortcutFieldOrder() {
    return Arrays.asList(KEY);
}

public RequestTimeGatewayFilterFactory() {
    super(Config.class);
}

@Override
public GatewayFilter apply(Config config) {
    return (exchange, chain) -> {
        exchange.getAttributes().put(REQUEST_TIME_BEGIN, System.currentTimeMillis());
        return chain.filter(exchange).then(
                Mono.fromRunnable(() -> {
                    Long startTime = exchange.getAttribute(REQUEST_TIME_BEGIN);
                    if (startTime != null) {
                        StringBuilder sb = new StringBuilder(exchange.getRequest().getURI().getRawPath())
                                .append(": ")
                                .append(System.currentTimeMillis() - startTime)
                                .append("ms");
                        if (config.isWithParams()) {
                            sb.append(" params:").append(exchange.getRequest().getQueryParams());
                        }
                        log.info(sb.toString());
                    }
                })
        );
    };
}


public static class Config {

    private boolean withParams;

    public boolean isWithParams() {
        return withParams;
    }

    public void setWithParams(boolean withParams) {
        this.withParams = withParams;
    }

}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
在上面的代码中 apply(Config config)方法内创建了一个GatewayFilter的匿名类,具体的实现逻辑跟之前一样,只不过加了是否打印请求参数的逻辑,而这个逻辑的开关是config.isWithParams()。静态内部类类Config就是为了接收那个boolean类型的参数服务的,里边的变量名可以随意写,但是要重写List shortcutFieldOrder()这个方法。

需要注意的是,在类的构造器中一定要调用下父类的构造器把Config类型传过去,否则会报ClassCastException

最后,需要在工程的启动文件Application类中,向Srping Ioc容器注册RequestTimeGatewayFilterFactory类的Bean。

@Bean
public RequestTimeGatewayFilterFactory elapsedGatewayFilterFactory() {
    return new RequestTimeGatewayFilterFactory();
}

1
2
3
4
5
6
然后可以在配置文件中配置如下:

spring:
profiles:
active: elapse_route


spring:
cloud:
gateway:
routes:

- id: elapse_route
  uri: http://httpbin.org:80/get
  filters:
  - RequestTime=false
  predicates:
  - After=2017-01-20T17:42:47.789-07:00[America/Denver]

profiles: elapse_route

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
启动工程,在浏览器上访问localhost:8081?name=forezp,可以在控制台上看到,日志输出了请求消耗的时间和请求参数。

global filter

Spring Cloud Gateway根据作用范围划分为GatewayFilter和GlobalFilter,二者区别如下:

GatewayFilter : 需要通过spring.cloud.routes.filters 配置在具体路由下,只作用在当前路由上或通过spring.cloud.default-filters配置在全局,作用在所有路由上

GlobalFilter : 全局过滤器,不需要在配置文件中配置,作用在所有的路由上,最终通过GatewayFilterAdapter包装成GatewayFilterChain可识别的过滤器,它为请求业务以及路由的URI转换为真实业务服务的请求地址的核心过滤器,不需要配置,系统初始化时加载,并作用在每个路由上。

Spring Cloud Gateway框架内置的GlobalFilter如下:

上图中每一个GlobalFilter都作用在每一个router上,能够满足大多数的需求。但是如果遇到业务上的定制,可能需要编写满足自己需求的GlobalFilter。在下面的案例中将讲述如何编写自己GlobalFilter,该GlobalFilter会校验请求中是否包含了请求参数“token”,如何不包含请求参数“token”则不转发路由,否则执行正常的逻辑。代码如下:

public class TokenFilter implements GlobalFilter, Ordered {

Logger logger=LoggerFactory.getLogger( TokenFilter.class );
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    String token = exchange.getRequest().getQueryParams().getFirst("token");
    if (token == null || token.isEmpty()) {
        logger.info( "token is empty..." );
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        return exchange.getResponse().setComplete();
    }
    return chain.filter(exchange);
}

@Override
public int getOrder() {
    return -100;
}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
在上面的TokenFilter需要实现GlobalFilter和Ordered接口,这和实现GatewayFilter很类似。然后根据ServerWebExchange获取ServerHttpRequest,然后根据ServerHttpRequest中是否含有参数token,如果没有则完成请求,终止转发,否则执行正常的逻辑。

然后需要将TokenFilter在工程的启动类中注入到Spring Ioc容器中,代码如下:

@Bean
public TokenFilter tokenFilter(){
return new TokenFilter();
}

1
2
3
4
5
6
启动工程,使用curl命令请求:

curl localhost:8081/customer/123

1
2
可以看到请没有被转发,请求被终止,并在控制台打印了如下日志:

2018-11-16 15:30:13.543 INFO 19372 — [ctor-http-nio-2] gateway.TokenFilter : token is empty…
1
上面的日志显示了请求进入了没有传“token”的逻辑。

总结

本篇文章讲述了Spring Cloud Gateway中的过滤器,包括GatewayFilter和GlobalFilter。从官方文档的内置过滤器讲起,然后讲解自定义GatewayFilter、GatewayFilterFactory以及自定义的GlobalFilter。有很多内置的过滤器并没有讲述到,比如限流过滤器,这个我觉得是比较重要和大家关注的过滤器,将在之后的文章讲述。

在高并发的系统中,往往需要在系统中做限流,一方面是为了防止大量的请求使服务器过载,导致服务不可用,另一方面是为了防止网络攻击。

常见的限流方式,比如Hystrix适用线程池隔离,超过线程池的负载,走熔断的逻辑。在一般应用服务器中,比如tomcat容器也是通过限制它的线程数来控制并发的;也有通过时间窗口的平均速度来控制流量。常见的限流纬度有比如通过Ip来限流、通过uri来限流、通过用户访问频次来限流。

一般限流都是在网关这一层做,比如Nginx、Openresty、kong、zuul、Spring Cloud Gateway等;也可以在应用层通过Aop这种方式去做限流。

本文详细探讨在 Spring Cloud Gateway 中如何实现限流。

常见的限流算法

计数器算法

计数器算法采用计数器实现限流有点简单粗暴,一般我们会限制一秒钟的能够通过的请求数,比如限流qps为100,算法的实现思路就是从第一个请求进来开始计时,在接下去的1s内,每来一个请求,就把计数加1,如果累加的数字达到了100,那么后续的请求就会被全部拒绝。等到1s结束后,把计数恢复成0,重新开始计数。具体的实现可以是这样的:对于每次服务调用,可以通过AtomicLong#incrementAndGet()方法来给计数器加1并返回最新值,通过这个最新值和阈值进行比较。这种实现方式,相信大家都知道有一个弊端:如果我在单位时间1s内的前10ms,已经通过了100个请求,那后面的990ms,只能眼巴巴的把请求拒绝,我们把这种现象称为“突刺现象”

漏桶算法

漏桶算法为了消除”突刺现象”,可以采用漏桶算法实现限流,漏桶算法这个名字就很形象,算法内部有一个容器,类似生活用到的漏斗,当请求进来时,相当于水倒入漏斗,然后从下端小口慢慢匀速的流出。不管上面流量多大,下面流出的速度始终保持不变。不管服务调用方多么不稳定,通过漏桶算法进行限流,每10毫秒处理一次请求。因为处理的速度是固定的,请求进来的速度是未知的,可能突然进来很多请求,没来得及处理的请求就先放在桶里,既然是个桶,肯定是有容量上限,如果桶满了,那么新进来的请求就丢弃。

在算法实现方面,可以准备一个队列,用来保存请求,另外通过一个线程池(ScheduledExecutorService)来定期从队列中获取请求并执行,可以一次性获取多个并发执行。

这种算法,在使用过后也存在弊端:无法应对短时间的突发流量。

令牌桶算法

从某种意义上讲,令牌桶算法是对漏桶算法的一种改进,桶算法能够限制请求调用的速率,而令牌桶算法能够在限制调用的平均速率的同时还允许一定程度的突发调用。在令牌桶算法中,存在一个桶,用来存放固定数量的令牌。算法中存在一种机制,以一定的速率往桶中放令牌。每次请求调用需要先获取令牌,只有拿到令牌,才有机会继续执行,否则选择选择等待可用的令牌、或者直接拒绝。放令牌这个动作是持续不断的进行,如果桶中令牌数达到上限,就丢弃令牌,所以就存在这种情况,桶中一直有大量的可用令牌,这时进来的请求就可以直接拿到令牌执行,比如设置qps为100,那么限流器初始化完成一秒后,桶中就已经有100个令牌了,这时服务还没完全启动好,等启动完成对外提供服务时,该限流器可以抵挡瞬时的100个请求。所以,只有桶中没有令牌时,请求才会进行等待,最后相当于以一定的速率执行。

实现思路:可以准备一个队列,用来保存令牌,另外通过一个线程池定期生成令牌放到队列中,每来一个请求,就从队列中获取一个令牌,并继续执行。

Spring Cloud Gateway限流

在Spring Cloud Gateway中,有Filter过滤器,因此可以在“pre”类型的Filter中自行实现上述三种过滤器。但是限流作为网关最基本的功能,Spring Cloud Gateway官方就提供了RequestRateLimiterGatewayFilterFactory这个类,适用Redis和lua脚本实现了令牌桶的方式。具体实现逻辑在RequestRateLimiterGatewayFilterFactory类中,lua脚本在如下图所示的文件夹中:

具体源码不打算在这里讲述,读者可以自行查看,代码量较少,先以案例的形式来讲解如何在Spring Cloud Gateway中使用内置的限流过滤器工厂来实现限流。

首先在工程的pom文件中引入gateway的起步依赖和redis的reactive依赖,代码如下:


org.springframework.cloud
spring-cloud-starter-gateway

org.springframework.boot
spring-boot-starter-data-redis-reactive

1
2
3
4
5
6
7
8
9
10
11
在配置文件中做以下的配置:

server:
port: 8081
spring:
cloud:
gateway:
routes:

- id: limit_route
  uri: http://httpbin.org:80/get
  predicates:
  - After=2017-01-20T17:42:47.789-07:00[America/Denver]
  filters:
  - name: RequestRateLimiter
    args:
      key-resolver: '#{@hostAddrKeyResolver}'
      redis-rate-limiter.replenishRate: 1
      redis-rate-limiter.burstCapacity: 3

application:
name: gateway-limiter
redis:
host: localhost
port: 6379
database: 0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
在上面的配置文件,指定程序的端口为8081,配置了 redis的信息,并配置了RequestRateLimiter的限流过滤器,该过滤器需要配置三个参数:

burstCapacity,令牌桶总容量。
replenishRate,令牌桶每秒填充平均速率。
key-resolver,用于限流的键的解析器的 Bean 对象的名字。它使用 SpEL 表达式根据#{@beanName}从 Spring 容器中获取 Bean 对象。
KeyResolver需要实现resolve方法,比如根据Hostname进行限流,则需要用hostAddress去判断。实现完KeyResolver之后,需要将这个类的Bean注册到Ioc容器中。

public class HostAddrKeyResolver implements KeyResolver {

@Override
public Mono<String> resolve(ServerWebExchange exchange) {
    return Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
}

}

@Bean
public HostAddrKeyResolver hostAddrKeyResolver() {
return new HostAddrKeyResolver();
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
可以根据uri去限流,这时KeyResolver代码如下:

public class UriKeyResolver implements KeyResolver {

@Override
public Mono<String> resolve(ServerWebExchange exchange) {
    return Mono.just(exchange.getRequest().getURI().getPath());
}

}

@Bean
public UriKeyResolver uriKeyResolver() {
return new UriKeyResolver();
}

也可以以用户的维度去限流:

@Bean
KeyResolver userKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst(“user”));
}

用jmeter进行压测,配置10thread去循环请求lcoalhost:8081,循环间隔1s。从压测的结果上看到有部分请求通过,由部分请求失败。通过redis客户端去查看redis中存在的key。如下:

可见,RequestRateLimiter是使用Redis来进行限流的,并在redis中存储了2个key。关注这两个key含义可以看lua源代码。

在之前的文章介绍了Spring Cloud Gateway的Predict(断言)、Filter(过滤器),大家对Spring Cloud Gateway有初步的认识,其中在对服务路由转发的这一块,在之前的文章是采用硬编码的方式进行路由转发。这篇文章以案例的形式来讲解Spring Cloud Gateway如何配合服务注册中心进行路由转发。

工程介绍

本案例中使用spring boot的版本为2.0.3.RELEASE,spring cloud版本为Finchley.RELEASE。在中涉及到了三个工程, 分别为注册中心eureka-server、服务提供者service-hi、 服务网关service-gateway,如下:

工程名 端口 作用
eureka-server 8761 注册中心eureka server
service-hi 8762 服务提供者 eurka client
service-gateway 8081 路由网关 eureka client
这三个工程中,其中service-hi、service-gateway向注册中心eureka-server注册。用户的请求首先经过service-gateway,根据路径由gateway的predict 去断言进到哪一个 router, router经过各种过滤器处理后,最后路由到具体的业务服务,比如 service-hi。如图:

eureka-server、service-hi这两个工程直接复制于我的另外一篇文章https://blog.csdn.net/forezp/article/details/81040925 ,在这就不在重复,可以查看源码,源码地址见文末链接。 其中,service-hi服务对外暴露了一个RESTFUL接口“/hi”接口。现在重点讲解service-gateway。

gateway工程详细介绍

在gateway工程中引入项目所需的依赖,包括eureka-client的起步依赖和gateway的起步依赖,代码如下:


org.springframework.cloud
spring-cloud-starter-netflix-eureka-client


org.springframework.cloud
spring-cloud-starter-gateway

在工程的配置文件application.yml中 ,指定程序的启动端口为8081,注册地址、gateway的配置等信息,配置信息如下:

server:
port: 8081

spring:
application:
name: sc-gateway-service
cloud:
gateway:
discovery:
locator:
enabled: true
lowerCaseServiceId: true

eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
其中,spring.cloud.gateway.discovery.locator.enabled为true,表明gateway开启服务注册和发现的功能,并且spring cloud gateway自动根据服务发现为每一个服务创建了一个router,这个router将以服务名开头的请求路径转发到对应的服务。spring.cloud.gateway.discovery.locator.lowerCaseServiceId是将请求路径上的服务名配置为小写(因为服务注册的时候,向注册中心注册时将服务名转成大写的了),比如以/service-hi/*的请求路径被路由转发到服务名为service-hi的服务上。

在浏览器上请求输入localhost:8081/service-hi/hi?name=1323,网页获取以下的响应:

hi 1323 ,i am from port:8762

在上面的例子中,向gateway-service发送的请求时,url必须带上服务名service-hi这个前缀,才能转发到service-hi上,转发之前会将service-hi去掉。
那么我能不能自定义请求路径呢,毕竟根据服务名有时过于太长,或者历史的原因不能根据服务名去路由,需要由自定义路径并转发到具体的服务上。答案是肯定的是可以的,只需要修改工程的配置文件application.yml,具体配置如下:

spring:
application:
name: sc-gateway-server
cloud:
gateway:
discovery:
locator:
enabled: false
lowerCaseServiceId: true
routes:

- id: service-hi
  uri: lb://SERVICE-HI
  predicates:
    - Path=/demo/**
  filters:
    - StripPrefix=1

在上面的配置中,配置了一个Path 的predict,将以/demo/**开头的请求都会转发到uri为lb://SERVICE-HI的地址上,lb://SERVICE-HI即service-hi服务的负载均衡地址,并用StripPrefix的filter 在转发之前将/demo去掉。同时将spring.cloud.gateway.discovery.locator.enabled改为false,如果不改的话,之前的localhost:8081/service-hi/hi?name=1323这样的请求地址也能正常访问,因为这时为每个服务创建了2个router。

在浏览器上请求localhost:8081/demo/hi?name=1323,浏览器返回以下的响应:

hi 1323 ,i am from port:8762

1
2
返回的结果跟我们预想的一样。

redis_cluster

on the same server

based on redis 5.0.0
https://my.oschina.net/ruoli/blog/2252393

  1. create dir /root/software/redis

  2. download the source code and compile

    1
    2
    3
    4
    ​wget http://download.redis.io/releases/redis-5.0.0.tar.gz
    tar xzf redis-5.0.0.tar.gz
    cd redis-5.0.0
    make
  3. create 6 redis.conf for the cluster

    1
    2
    3
    4
    5
    6
    /root/software/redis/redis-cluster-conf/7001/redis.conf
    /root/software/redis/redis-cluster-conf/7002/redis.conf
    /root/software/redis/redis-cluster-conf/7003/redis.conf
    /root/software/redis/redis-cluster-conf/7004/redis.conf
    /root/software/redis/redis-cluster-conf/7005/redis.conf
    /root/software/redis/redis-cluster-conf/7006/redis.conf

the conf of the 1st node as below:

1
2
3
4
5
6
7
8
port 7001  #端口
cluster-enabled yes #启用集群模式
cluster-config-file nodes.conf
cluster-node-timeout 5000 #超时时间
appendonly yes
daemonize yes #后台运行
protected-mode no #非保护模式
pidfile /var/run/redis_7001.pid

NOTE: the port and pidfile SHOULD BE 7001/7002/…, redis_7001.pid/redis_7002.pid/…

  1. startup 6 nodes

    1
    2
    3
    4
    5
    6
    /root/software/redis/redis-5.0.0/src/redis-server  /root/software/redis/redis-cluster-conf/7001/redis.conf
    /root/software/redis/redis-5.0.0/src/redis-server /root/software/redis/redis-cluster-conf/7002/redis.conf
    /root/software/redis/redis-5.0.0/src/redis-server /root/software/redis/redis-cluster-conf/7003/redis.conf
    /root/software/redis/redis-5.0.0/src/redis-server /root/software/redis/redis-cluster-conf/7004/redis.conf
    /root/software/redis/redis-5.0.0/src/redis-server /root/software/redis/redis-cluster-conf/7005/redis.conf
    /root/software/redis/redis-5.0.0/src/redis-server /root/software/redis/redis-cluster-conf/7006/redis.conf
  2. startup the cluster

    1
    2
    # DO REMEMBER update the ip to your ip
    /root/software/redis/redis-5.0.0/src/redis-cli --cluster create 192.168.2.40:7001 192.168.2.40:7002 192.168.2.40:7003 192.168.2.40:7004 192.168.2.40:7005 192.168.2.40:7006 --cluster-replicas 1

on 6 servers

https://blog.51cto.com/13860853/2415197

查看节点
./redis-5.0.0/src/redis-cli -h 127.0.0.1 -p 7001 -c cluster nodes
./redis-5.0.0/src/redis-cli -h 192.1.114.84 -p 7001 -c cluster nodes

前海母基金情况汇集

股东信息 股东类型 认缴出资金额
丰益华泰实业有限公司 公司 150000万元
君康人寿保险股份有限公司 公司 150000万元
广东万和新电气股份有限公司 公司 150000万元
济南峰靖商贸有限公司 公司 150000万元
深圳市中科鼎鑫管理咨询合伙企业(有限合伙) 公司 150000万元
珠海横琴富华金灿投资企业(有限合伙) 公司 150000万元
珠海横琴富华金盛投资企业(有限合伙) 公司 150000万元
上海行普企业管理合伙企业(有限合伙) 公司 150000万元
深圳市汇通金控基金投资有限公司 公司 100000万元
深圳市引导基金投资有限公司 公司 100000万元
深圳市龙华新区引导基金投资管理有限公司 公司 100000万元
厦门金圆投资集团有限公司 公司 60000万元
新兴发展集团有限公司 公司 50000万元
北京首都科技发展集团有限公司 公司 50000万元
国信弘盛创业投资有限公司 公司 50000万元
太平人寿保险有限公司 公司 50000万元
李永魁 自然人 50000
永诚财产保险股份有限公司 公司 50000万元
深圳太太药业有限公司 公司 50000万元
深圳市福田引导基金投资有限公司 公司 50000万元

工商资料显示,前海母基金的股东有35位之多。其中有限合伙人出资额在1亿元至20亿元之间,对应出资比例在0.47%-9.3%。包括但不限于:深圳市引导基金投资有限公司 (10亿, 4.65%)、君康人寿保险股份有限公司 (15亿, 6.98%)、中国人保资产管理股份有限公司 (10亿, 4.65%)、永诚财产保险股份有限公司 (5亿, 2.33%)、北京首都科技发展集团有限公司(5亿, 2.33%)、乐视投资管理 (北京) 有限公司 (3亿, 1.39%)。

在欧美,私募股权基金资产总额的近50%由母基金管理并提供,是私募股权投资行业最大资金来源。但在中国,它却才刚刚起步。

前海母基金总裁陈文正(一):投资做得好,是因为赶上了这个时代
作者:陈文正
2018-08-04 16:01:37
摘要 : 【编者说】陈文正先生是我在清华的师兄,在投资圈是有名的低调。但低调后面,是多年来在投资界所打下的赫赫威名。从最早实践引导基金模式,到带领深创投一步一步走向辉煌,到现在跳出体制成立前海母基金,折射出来的是陈文正师兄多年潜心研究投资,对投资深刻的理解与深厚的功底。紫荆厚德商学院国际投资实战营深港班有幸能够请到陈文正师兄为我们授课,他以过去十多年的投资实践为基础,融合个人的投资理念与体会,娓娓道来,颇具大家风范。有道者谦,是对低调务实的文正师兄最好的写照。
内容提要
-

中国资本市场发展历程- 中国股权投资发展历程

一我的投资之路
上个世纪八十年代,我在清华学的是精密仪器。但是毕业后没有画过图,没有编过程序,因为专业学的不好,所以就做了投资。以前做投资的名声不好,很多人觉得一个人因为什么都不会,只好做投资。
【编者说:文正师兄,一群投资界大佬拿着斧头正在来深圳的路上】。

那个年代,不像现在的企业自己有很强的研发能力,比如华为、中兴等科技企业。那个年代主要是拿来主义,引进外资与技术,还有科技成果产业化。实际上科研成果产业化就是后来创投的起点,但是那个时候怎么产业化,以及产业化的规律大家都不是很清楚,所以我们做了很多的摸索与实践。从学校出来后,我没有去编程,没有去画图,而是去做了产业化,以及引进外资。

到后来经营企业,我去过两家公司。一个是长园集团,现在已经上市了。还一个是恒生,是中国最大的电子研发、生产、制造商。后来我觉得搞企业不过瘾,太闷。在生产、研发、销售方面,尤其是生产、研发,在公司里面看到的都是熟悉的面孔。我们一般说漂亮的女孩子集中的产业就有发展前途,结果我发现企业里面漂亮女孩子比较少,所以我就开始去做担保。深圳市有国家第一个专门扶持高新技术企业的一个担保公司,高新技术担保投资有限公司。我在那里每天都看到不同的企业,他们为了获得融资担保,都是派漂亮的女孩来沟通。大家别小看高新投,它曾经担保过深圳市大概80%以上的上市公司,为深圳市的高新技术产业发展做出了巨大贡献。
后来担保公司也开始做一些小的投资,但是投资的总体情况不是很理想。那时候香港刚刚回归,国家派了很多人以商人的身份到香港去开展工作,还给了他们很多的钱去搞企业。后来他们变成了港商,回到深圳投资做企业,但是他们有些不一定会经营。后来我们又碰到一家这种情况的企业,我们想要支持他。于是我又回去做企业。后来我们把这家公司的资产放到了恒生集团,形成了一个用这种资产重组进行担保救济的案例,并且最后确实挣钱了。最后这个公司想让我把它弄上市,但那个时候我已经决定要去做投资了。
【编者说】朱波老师先是成功创业,然后去大机构做投资;陈文正师兄先是做企业,然后做担保。他们的共同点,我认为是通过各自的经历,积累了深厚的企业管理方面的经验及对产业的直接了解。后面的很多优秀投资人导师,都有类似的经历。无论你采用什么样的方式,对企业运营,对产业发展的理解,我认为是成为一个优秀投资人的一个基本要素。
2001年我去了深创投,开始设立政府引导基金,我算是这个模式的实践者。我们2007年1月份在苏州成立第一个政府引导基金,后来在江苏省地级市基本上都有了。现在这个基金规模加起来二十多个亿,现在也有十几家上市公司。后来这种模式被不断地复制到全国各地,形成了一个网络。深创投过去这些年能够有这样的发展,我觉得最主要的是时代。因为在2006年没有股权分置改革之前,创投是没有盈利模式的。深创投开始那么艰苦,是因为你的投资让你变成了股东,还不是炒股票炒成股东,你不能变成股票,不能变现,没有退出机制。所以你不断对外投资,这些投资也不能回收,不能形成回报,也就无法持续经营。
2006年,股权分置改革以后,我们抓住了时机。因为看得准,布局早,所以这些年用市场化的方式运作,才能够走到今天。我们现在投了大概600多家企业,总投资额有两百多亿,投资企业包括一百多家上市公司。管理的基金规模如果加上深圳市的政府引导基金,有1800多个亿,这确实很不容易。但是我觉得,最主要的还是要感谢这个时代。正因为我们遇上了这个时代,我们今天才能来探讨怎么做投资。
【编者说】一个优秀的投资人,一定是能够准确把握时代的脉搏的人。与时代同步,甚至要走在时代的前列。这实际上是朱波老师深海、红海、蓝海说法的另一种诠释,这是从宏观角度来说。从微观角度来说,就是对行业趋势的分析与准确把握。

下面我从五个方面讲一讲投资:

第一个是大众投资,回顾一下中国资本市场的发展过程。虽然我们有很多的不满意,有很多东西可能你不好预计,但重要的是我们还在继续前进。
第二个是股权投资的发展过程,尤其股权投资在中国的发展。
第三个是基金的管理运作模式,主要以深创投为例来看一般的机构怎么做,来了解一下股权投资普遍的机构化趋势。
第四个是天使投资,我想谈谈自己的看法体会。因为我们现在做母基金,也接受了很多机构化的思想,与机构也有很多交流。
第五个是母基金,我会着重谈谈前海母基金的情况。
二中国资本市场发展历程
中国资本市场发展的历程,第一个是发展的初期,也就是1978年到1998年这二十年,这个阶段有一些标志性的事件发生。八十年代开始有股份制改革;到1990年,上交所开业,那时候只有两个股票上市交易;1991年深交所开业;1991年的11月,有了B股;1992年中国的证监会成立了;1997年开始有基金了,比如证券投资基金。当年为了买股票,大家用麻袋在全国各地收集身份证,收到以后就星夜兼程赶到深圳,彻夜排队买抽签表,买到抽签表就意味着你可能买到一支股票,等到股票一交易就能挣钱。因为太多人买了,就开始出现走后门,比如保安去插队诸如此类的情况,还演变成了一个群众性的事件。所以后来就开始要进一步地规范股票市场,1999年开始实行证券法。2004年有了国九条,有几个对做股权投资影响比较大的条规。第一个是有了中小板,当时虽然它还是分成发行股,发行股你不能流通的,但是另外一块你是可以流通的,就是上市了。2005年4月股权分置改革开始启动,到2006年全国股票都能流通。从2007年到现在是快速发展阶段,虽然中间有很多过程,例如IPO暂停。以上我们可以看到其实投资很痛苦,过程中不可预计的情况会很多。
这里面有一些标准性事件,一个是融资融券。创业板最早的时候开始在2000年,当时市场涌现一批的创投公司,当年每个地方政府都会成立一个券商。但是创业板一直不开,拖死了一批企业。2010年股指期货,2013年股转系统,有了新三板。新三板真正开始活跃起来是2014年。2014年5月份又有了新国九条,2014年8月份,做市系统开始了,新三板有一段时间很活跃,到最近又不活跃了,现在又开始分层。2014年11月,沪港通开通。
【编者说】天使投资虽然属于非常早期的投资行为,然而近年来越来越多的优秀项目,尤其是互联网相关项目,从初创到上市退出的周期在缩短。以前一个早期项目可能需要十年的时间成长为一个独角兽项目,进而上市,现在三到五年就成功上市的案例逐年增加。这个变化对天使投资人也提出来新的要求,我们必须更早开始规划公司的退出策略,以为我们的投资以及所投的项目带来最大的利益。这些年开始出现PE早期化,VC往后看,很大程度上是因应这方面的新变化。

现在来回顾一下当前中国资本市场的特点。

首先,作为投资人我们当然很开心。有注册制后,至少流动性可以改善。

能不能够投到好企业,能不能挣钱那是你的本事。你投到好企业,证明你眼光好,估值高,那你就赚钱了。投的不行,可能能上市,但也可能上市了也没有人理你。就跟新三板一样,新三板一大堆是没人理的,但是有的估值很高,尤其它定增的时候比IPO还好。
第二,现在注册制又被推迟了。

深圳市负责注册制的总监现在到了我们前海母基金,有一些人被借调到证监会。
第三,借壳难了

,这是最新的规定。所以说政策变化很快,中国人太聪明,我们看到很多奇葩的借壳的方法是在规避,挑战证监会。所以说运气很重要。这里说的运气是研究政策,以及研究人。
第四,IPO延期了,审核更严格了

。去年百分之百的过户率。现在不行。
第五,今年新三板创新层出来了

,单这个星期公布了几百家创新层的企业。创新层出来了,后边会不会有政策,会不会针对创新层来出台一些活跃他的政策,我想可能会有。也就是说新三板的交易的活跃一定要在某些层面某些板块,要不然的话新三板它又会出现问题。交易不活跃,没有退出机制,这样新三板没有达到一定作用,所以我估计未来可能还是会有一些改革,比如说新三板改成竞价交易,但是门槛是不是放得那么低,可能不一定,但至少能够有一些办法有一些政策出来。我想股转系统一定还是希望有一些好的企业能够继续留在新三板。就跟美国纳斯达克一样,慢慢变成一个巨大的交易所,不过我想新三板暂时还不会。而且据说现在有一个研究,从新三板直接转到其它的交易所,可能有一些新的规定去限制,这块我估计会有新规定出台。但是我们永远不知道,它什么时候又变了。所以一方面是要密切关注,另外一方面还是要碰一点运气。
第六,面粉比面包贵

。房地产现在是拍卖一块地,楼面地价比房价还贵。同样现在我们做投资,IPO,基本上是23倍市盈率。现在满足上市条件的,没有上市的,什么时候能上还不知道的这些企业,现在投资的估值二十多倍是普遍的。二十多倍如果它成长性不好,到时候上市还要亏。当然大家还是期望说,流通以后上市以后可以连来几个涨停板,可能还挣钱。例如华大基因,按照它的利润和估值,IPO的时候可能一堆投资人是亏的。
当然我们也投了,我们是基于以下几个判断,第一个判断就是它有两个组成部分,一个是华大科技,一个是华大健康。华大科技是基于测序,最早把全基因序列测试一遍大概要几万美金,现在只要一千人民币。科技的进步,设备的改进,不断地成本降低。华大健康也还是有一些亮点的,比如说对唐氏综合症的研究。所以说我们相信,华大基因上市以后还是能涨停板,它毕竟在国内还是第一大,有它的一个龙头效应。
一个是房地产市场面粉比面包贵,大家对未来房价的预期是上涨的;另外一个也是面粉比面包贵,也就是股市、股权投资。

这两个东西都贵,哪个对国家好处多一点?我想用日本和美国进行对比。日本在上世纪八十年代,东京房地产的价值可以把美国一大半的国土买下来。上个世纪九十年代美国股市泡沫,股价也很高,最后两个泡沫都破灭了,日本这个泡沫破灭带来什么问题?几十年来,日本很多的品牌没有了。但是美国的泡沫破灭它剩下的是技术,它的技术投入增加了,所以它永远走在技术的前面,只不过那些公司在变,每个年代哪些公司市值最大,一直在变。技术的创新推动公司价值的提高。所以我觉得,股市对国家好。大家都去创业去投资,产生新的技术、新的模式,能够更好地方便老百姓的生活。

【编者说】国家在这两年提出了“新经济”的概念。何谓新经济?我的理解就是以创新驱动的经济成长。创新金字塔的顶端就是创业,创业的持续发展,需要股权投资的大力扶持。创新能够产生大量的新技术新模式,即便有泡沫了,泡沫破灭了,留下来的除了一地鸡毛,还有技术的发展。而技术的发展,必将促进经济的发展。从这个角度来说,资本寒冬,其实是天使投资大显身手的时候!这个时候,是真英雄,才敢出来创业,才敢出来投资!

前海母基金陈文正:我眼中的优秀投资机构
2018-08-14 | 阅: 转: | 分享

投资人要善于发现价值,提升价值,实现价值,最好是既帮助创始人成长为一个伟大的企业家,他的公司成为一个伟大的公司,也为你的基金投资人带来好的回报,当然做到了这些,也就为自己的职业生涯打下了很好的基础。

前海母基金执行合伙人 陈文正

以下内容根据陈文正老师在沙丘学院讲课笔记整理而成,有删减。

01

国内股权投资行业发展

创业投资是指投资于未上市的企业,通过股权价值的增加,来实现我们的收益。股权投资把投资延伸到了企业上市之后,泛指在企业各阶段的权益投资,包括对处于种子期、初创期、发展期、扩展期、成熟期和Pre-IPO、以及上市后各个时期企业进行的投资。常见的基金种类主要包括VC、PE、并购基金、夹层资本等等。

从主流的来讲,投资阶段主要是VC、PE,但是现在并购基金开始发展起来了。原来很多并购基金,通过和上市公司合作,来为上市公司未来的发展服务。但是现在国内开始出现一种专业化的管理人,就是通过投资来控股一家公司,未来通过改善这家公司,实现价值提升,再来寻求投资退出。这种管理人大多来源于跨国公司,有着相当丰富的产业经验,他们组建一个团队,对所熟悉的领域进行投资并控股。

对与上市公司合作的并购基金,财务投资人会关注基金的独立性,会不会因为上市公司过度关注协同性影响基金的财务回报;对独立的并购基金,退出是一个重要考虑因素。

一个基金控制的公司能不能上市?这是一个比较大的问题。因为目前我们的上市审核是强调一家公司的实际控制人是谁,股权是不是稳定,但是基金始终是要退出的。所以,并购基金更多的是控制一家公司以后,通过对业绩的提升改造,卖给一个上市公司或者产业集团。

中国的GP已经进入大洗牌阶段
如今,GP已经进入一个优胜劣汰的阶段。从募资看,2016年,大概有将近1.6万亿;2017年,大概有2.5万亿;2018年上半年,只有几千亿。大家普遍反映募资难了。未来几年将会有一批的GP募不到后续基金,也会有一些僵尸基金,基金在存续期没人好好管了。

投资的整体估值,我们认为会下来。因为面粉比面包贵了。比如有些到美国、香港上市的企业,上市后的市值还不及上市前的估值,A股也有不少发行价低于私募价的;

同时,资源一定会向头部集中。大量的创业企业,可能会面临到后面的募资困难,很难跑出来。而真正能跑出来的,大家都追过去了,大多数钱都在等着;

另外,要耐心淘宝。最好的投资时期,都是在市场行情不好的时候、大家对行业悲观的时候。2008年美国金融危机时,市场资金紧张,那时候得到投资的企业如果发展起来了,那些投资人可获得丰厚的回报。

因为整个市场环境在发生变化,管理的任务也就不一样了。第一个上市周期延长了,现在国内A股门槛进一步提高,以前差不多一周有那么一两家,现在可能一个月只有几家。经济下行,管理压力也会增加,而且你的企业经营业绩不达标,后续融资也就更难了。

对于退出,我觉得A股还是主战场。A股门槛提高了,不到8000万不能上,但是在中国这种市场环境下,中小企业的发展一定会越来越得到国家的重视,所以我觉得A股的IPO政策会发生变化。

现在香港港股有新的规定,AB股同股不同权的可以上,没有盈利的、亏损的生物医药公司可以上。

我觉得AB股同股不同权,有它的合理性。因为一个企业从小到大的过程中,要不断的吸纳外来的资本,那么创始人在利益方面应该稀释,因为资本要获利,投资人要获得相应的回报。但是应该保持创始人对公司有足够的话语权。

另外,未弥补亏损的企业能不能上市?这是我们A股现在遇到的很大的问题。

现在很多公司一到要准备上市了,一定采取保守策略,不敢去打市场,不敢去研发,而是要维持利润的规模。你在前期的很多投入,比如市场的投入,研发的投入是很大的,你后面即使盈利了,要弥补这个亏损,也很难。

所以我认为如果这些方面得到一些修正的话,国内应该是个更好的资本市场,有利于上市企业和投资机构的发展。

02

优秀机构如何脱颖而出?

什么是优秀机构?
谁是优秀机构,大家都有不同的判断,答案也是不一样的。而且,不同的角色对优秀机构的定义也不同。

从管理人的角度来看,被多数同行视为竞争对手的或对标的,是优秀的机构。比如同样是做创投的,同样专注在互联网领域的,他们会绑定几家跟他们构成竞争的公司进行分析,而且对自己的投资经理有要求,比如要求项目覆盖率要达到80%。过一段时间一看,这些项目你们看了没有?投了没有?如果没投,为什么没投?是投不进去、没看到还是放弃?

从投资人的角度来看,首先要看基金回报,IRR(内部收益率)是多少,回报倍数是多少。第二是看影响力。影响力不光是知名度,可能在行业当中,它的投资方向和投资策略会成为其他基金学习的榜样;第三,投资人认同。有的投资机构影响力很大,但是投资人不一定认同;第四是员工荣誉感强。

优秀机构的特点——团队、策略、执行、口碑
�7�6团队。团队当中一定要有灵魂人物。比如红杉资本的沈南鹏、经纬中国的张颖、高瓴资本的张磊。另外,像深创投这样的国有创投机构,团队是在变化的,但是每个阶段可能会有一个灵魂人物,发展的方法路径可能也不一样。

同时要有核心团队,比如红杉、IDG很多人都出去创业了,但是他们还是有其他的核心成员在,它的一些文化和基因,始终还是保存在那个地方。

另外还要有成熟机制,比如能不能吸纳到优秀的人,有没有一个合理的分配机制等等。

�7�6投资策略。首先是因势而变,把握行业发展趋势。比如一些美元基金可能最早都是随着互联网科技的发展,一些企业到境外上市发展起来的。到了今天,他们都增加了很多其他的内容,除了和互联网相关的,还有消费、健康等,投资阶段也在扩展。另外在细分领域当中,以前可能to C,现在是to B,更加考虑企业服务。而且他们每年都会检讨投资策略,在大的方向之下,寻找很细分的东西,因势而变。

其次是专注擅长。比如美元基金和人民币基金有不同的基因,可能就是做不同的事儿。另外在团队当中,不同资源的人会专注不同的事。比如在健康领域,有的专注于新药研发,有的专注于器械,有的专注服务,都不一样。

�7�6执行。现在很多投资经理就跟打了鸡血一样,为什么?你首先得有足够多的项目覆盖,先看得见,才会有所选择。在“抢”项目的时候,你既要做好风控,同时又要有足够快的决策效率。另外,投后服务也很重要。

�7�6口碑。基金在行业中的口碑很重要。有的基金很低调,不参与任何排名,也不去追求任何报道,但是它每期基金都做得挺好,它的规模不断增加,投资人也都很认同,很快就能募起来;有的基金比较注重PR(公共关系),可能是投资人的要求,要有荣誉感,比如投了什么好项目一定要让领导和外界知道,所以每个基金都不一样。

新机构如何脱颖而出?
现在有很多新的GP产生,那么这个机构怎么才能出来,优势在什么地方?我们比较关心以下几个方面。

�7�6第一,有没有团队。机构刚开始不一定很大,很多投资机构,可能从四五人开始做起,慢慢发展到十几个人,到几十人;

�7�6第二,有没有钱。有些机构的募资很单一,它就是为某个公司、某个家族或者某个投资人服务,不用去操心募资的事儿,先把业务做起来;

�7�6第三,项目来源。项目从哪来,项目质量如何。因为股权投资行业的盈利模式,不是自己经营企业,依靠项目团队,靠股权变现,项目退出来挣钱,我们依赖的是项目本身,越广泛越优质的项目来源,才有优中选优的基础,才有好的回报的基础;

�7�6第四,能给项目提供什么资源。现在A轮都已经抢得一塌糊涂了,那么到后期投资阶段你怎么去抢项目,就要看你能够为项目提供什么资源。

对于新的基金而言,第一期基金可能比较好募。一般来讲,你敢于出来做基金,你都是有准备的。第二期基金相对来讲也比较容易,虽然第一期还没出结果,但是已经投得差不多了。但是第三期、第四期怎么样,拥有影响力的案例特别重要。

一个优秀的基金要能够持续不断地贡献好的案例。为什么大家老记得红杉,因为很多发展起来的企业,红杉都在里面,它有有影响力的案例。当然这跟它的投资方式和投资风格有关系,它会判断好基础,然后投很多赛道。

03

母基金的价值和商业模式

母基金最主要的价值就在于解决了股权投资中GP和LP的痛点。

母基金的作用:

解决股权投资中GP-LP关系的痛点

�7�6LP的痛点

接触不到优质基金。有很多LP,不知道哪个是优秀基金,或者知道了也不一定投得进去;

风险集中。基金的离散度是很高的,有的回报很好,有的可能就不行。你如果投单个的项目或基金,风险就太过集中了;

回报不稳定。可能某个行业只是在某个阶段的回报比较高,业绩波动较大;

拿不到好的交易条款。LP和GP之间是有博弈的,会有一些条款。如果你不是一个强有力的谈判对手,你可能争取不到更多的权益。

跟踪监督不力。对一般投资人而言,GP是十分主动的角色,一般投资人把钱给基金后,很难对基金的后续运作起到跟踪监督的作用,即使基金出现一些不利于投资人的行为也不容易纠正;

对GP的选择缺乏专业判断力。有些GP会管理很多的基金,尤其在中国,平行基金大量存在。他们可能用各种名目说什么行业不一样,阶段不一样,但实际上它就是同时管理了很多基金。

�7�6GP的痛点

LP的专业度不够,不能给予GP充分的理解。尤其在全民PE的时候,很多矿老板和房产老板都投资GP了,想挣快钱,但是实际上股权投资行业会受到各种因素的影响,尤其在中国,IPO变化很大,因为对股权投资了解不够,产生很多问题;

LP和GP沟通困难,不能有效整合资源。如果GP能够把很多的LP有效地组织起来,可能会给GP带来帮助。比如我们开个合伙人大会,我们的LP来了,看到很多感兴趣的基金,他会再去投资。如果资源整合较好的话,也会为GP本身的业务发展,以及所投资的企业带来一些资源和帮助;

缺乏长期稳定的资金来源。现在有很多基金,如果是个人或者民营企业投资,都要求资金要一次到位。尤其是大的机构,更担心前面有钱后面没钱,实际上这对大家并不一定有利,对投资人来讲,我的钱没得到有效的利用;对GP来讲,钱闲置在账户上没投出去,影响IRR。在当前的形势下,很多投资人遇到了困难,一些民营投资人原来可能有很多钱是银行放出来的,但是在资管新规和去杠杆的影响下,现在银行不给放钱了。

缺乏机构LP,投资者小而散,短钱长投。对GP来讲,投资者小而散的话,工作很难做。另外,有一些投资人的投资跟上一期的资产回报有关。他就想试图赚了钱再往后续,短钱长投;

募资周期长,LP后续出资不确定性大。其实GP希望有很稳定的资金来源,能专注于做项目。

母基金的经营管理
基金投资和直接投资相结合,形成了多快好省的商业模式。

母基金选择性直投的核心就是子基金推荐项目。在这个基础之上,母基金真正做到了优中选优,而且项目源比较丰富,投资决策也比较快。母基金通过投子基金和直投项目相结合,为投资人创造更好的收益。

母基金的好收益一般来源于三个方面。

第一,选好子基金。我们可能看了500多个子基金,但是只投了40多个。首先我要保证我的子基金是挑选出来的,在市场上肯定比大多数子基金的回报要高;

第二,我是在选择性直投,每个子基金都不可能百分之百的项目成功,或者回报很高。我们如果能把成功率提高一点,比如把子基金30%的成功率提高到50%,那我这个母基金的回报可能就比一般的基金平均水平要高;

第三,短期资金回报安排。因为我规模大,我可以有流动性的配置,比如我把年初投资人出资的50多亿在一年逐渐投出的资金闲置过程中,做一些短期回报的安排,我就能够产生比一般的基金多两到三个点的回报,尤其在深圳这种经济发展比较好的地方,还是有很多机会做这样的安排。

那么,如何选择子基金?一个是专业性,你得有自己专注的领域;一个是功能性,比如同样的领域,你跟别人是不一样的,有独特的资源;还有一个是互动性,我们的母基金和子基金的联系特别多,我们就是投资经理之间沟通,风控之间沟通,如果他们认同这个基金,说这个基金好,那我们就说这个子基金好。

我们在直投过程当中,最大的益处来源于两个方面。第一,这个项目是子基金推荐的,它通过百里挑一挑出来项目推荐给我们,或者它原来投过了后续融资时推荐给我们,这是个很好的基础;第二,我们有很多子基金,在对一个项目尽调过程中,可以很快获得其他同行对这个项目的看法。

04

优秀投资人要具备这些能力

所谓优秀投资人,一般是指单个投资经理能够持续地投出回报高、影响大的好项目。那么,如何成为优秀的投资人?我根据自己的投资体会,总结了以下几点。

�7�6第一,勤奋。

有的投资经理经手几个亿资金,到现在也没有什么好业绩。但是也有人可能短短几年就开始独立带团队募投管退了。做投资是体力活苦力活,腿要勤,嘴要勤,脑要勤,我觉得勤奋要放在第一位。

�7�6第二,学习。

无论你多么专业,经验多么丰富,做投资总是要面对新问题,面向新企业。技术在发展,商业模式也在发展,你如果没有看到新的东西,没有学习新的东西,那这个东西可能已经不是未来的方向,它的成长空间可能就有限,所以学习能力特别重要。

�7�6第三,圈子。

做投资既要有行业知识积累,又要有行业人脉的积累,这些都需要混圈子。为什么有些投资经理能够单独去管一个基金?他可能是政府圈子好,投资的项目是政府推荐的或者是通过政府的背景去拿的。也可能是在某个领域——比如在医疗器械,把这个圈子混得很熟,哪个企业都看过。项目能看得到,同时也能投得进去,出现问题也能及时获得帮助,所以圈子很重要。

�7�6第四,识人。

一方面要对创始人能不能把事做成的方方面面有了解,如经验、资源、知识、性格等等,比如说有的人可能是适合产品型创业,有的人可能适合模式类创业;

另一方面要对创始人的价值观、道德有了解,要不然投资人的利益不一定能得到保证。现实中出现过,投资人对创始人做了很大的支持,创始人也成功了,但是投资人最后可能没挣钱。企业发展了,人家可能七拐八拐,把你的权益不知道甩到哪去了。

另外,有些创始人根本不把投资人放在眼里,总觉得投资人是在靠他,遇到问题的时候,不考虑投资人的利益。

�7�6第五,判断趋势,化繁为简。

要对趋势有判断,投资是投未来,趋势对了,事半功倍。勤奋和深度思考哪个更重要?我觉得要站在不同的角度去说。有时候没有方向的勤奋,可能确实效果不好,就跟我们选不同的投资领域一样,它的天花板是不一样的。

比如人工智能,早期和现在研究人工智能的可能已经不是一拨人了。有些东西你要投了可能就是先烈,也可能正好赶上时机。

�7�6第六,沟通。

这种沟通既有外部的,又有内部的。你怎么获取信息,怎么处理问题,不同的方式得出的效果可能截然不同。

�7�6第七,公正。

这关系到对内对外能不能走远。对内来讲,你是不是一个职业操守比较好的人;对外来讲,你是不是一个公平,或者按照一个合理的方式做事的人。如果一个机构在市场上不以公平、公正的方式对待别人,可能在未来的发展中遇到的阻力会比较大。做人也是一样。

投资人要善于发现价值,提升价值,实现价值,最好是既帮助创始人成长为一个伟大的企业家,他的公司成为一个伟大的公司,也为你的基金投资人带来好的回报,当然做到了这些,也就为自己的职业生涯打下了很好的基础。

杨东来信

2019.05.05 杨东林利军常劲等大咖齐聚,畅谈科创板5G新产业

杨东:我觉得投资要做的重要的事之一,就是要观察和感受科技发展、技术变化的趋势,以及这种趋势对产业、对社会的影响。目前新能源行业可能已度过了发展初期,开始在渗透度上快速提升,趋势已经不可逆转。这一方面会带来很多投资机会,另一方面也会对某些投资构成威胁,作为投资人,我们现在比普罗大众更早地感受到这些趋势。新产业的发展是一种持续的长期趋势,但在股市上却常常表现为短期预期极高的脉冲式上涨——形成泡沫——泡沫破灭后对长期投资趋势变化趋势的忽视。毕竟市场上的投资者往往都不是很有耐心。这也符合一个规律就是人们往往高估一些短期事件三的影响而低估了一些长期趋势的影响。

杨东:巴菲特开始投资科技股,一方面可能是巴菲特的能力圈又扩大了,有些科技企业他看得足够清晰透彻了。另外巴老原来不投科技股的主要原因是技术发展太快,科技股很难有稳定的护城河,这方面也可能有些不一样了。比如苹果,通过APP Store已经形成了强大的生态圈和客户黏性,技术变化的颠覆性威胁要小多了,还有苹果有非常好的现金流,个位数的估值水平,以及足够大的规模,这些都比较对巴菲特的胃口。

杨东:我觉得投资要做的重要的事之一,就是要观察和感受科技发展、技术变化的趋势,以及这种趋势对产业、对社会的影响。目前新能源行业可能已度过了发展初期,开始在渗透度上快速提升,趋势已经不可逆转。这一方面会带来很多投资机会,另一方面也会对某些投资构成威胁,作为投资人,我们现在比普罗大众更早地感受到这些趋势。新产业的发展是一种持续的长期趋势,但在股市上却常常表现为短期预期极高的脉冲式上涨——形成泡沫——泡沫破灭后对长期投资趋势变化趋势的忽视。毕竟市场上的投资者往往都不是很有耐心。这也符合一个规律就是人们往往高估一些短期事件三的影响而低估了一些长期趋势的影响。

2018年第三季度回顾与展望 

回顾三季度,股市继续震荡下行,前期表现强势的一些板块却纷纷出现补跌,上证指数在2638点以上得到支撑后于9月下旬出现反弹,但主要以银行等权重股上涨为主,中小板和创业板则表现更弱,持续创出年内新低。
目前股市受到多方面不利因素的影响,中美贸易摩擦一直未能有良好解决,甚而不断加剧。
资金面依然比较紧张,股权质押压力不减,汽车、房地产两大支柱产业都出现了增长停滞,整体经济增长下行压力沉重,企业的利润增长也令人担忧。
但是,我们也看到积极的因素在加强。A股纳入MSCI、富时罗素指数等与国际化接轨,加上港股通机制不断吸引国际资金入场。
政策在“去杠杆”主基调不变的情况下,在节奏上也出现了微调,资管新规配套的银行理财细则较之前出现了一些折衷调整,短期压力有所缓和。
就整体而言,尽管还有大量的个股会继续被挤泡沫,但也确实有相当部分优质股票处于绝对低估值的水平之中,已经具有很好的吸引力。
如果各方面综合起来看的话,我们肯定不悲观,而且倾向于看好后市表现。目前上证2600点左右的位置应该已处于一个底部区域之中。
A股的结构性问题也不得不提下,A股历史上炒新炒小炒壳炒主题造成的股价结构的畸形仍会被不断纠正,大量资质不佳的个股还会不断被挤出泡沫,未来的中国资本市场会向成熟市场的方向靠拢。
随着与国际市场和资金的不断互联互通,大A“特色”性的东西会不断消失,企业的业绩和成长将成为驱动股价长期上涨的基本动力,投机年代留下的种种股价畸形将在时间长河中逐渐被打回原形。
虽然这个过程也肯定会出现反复,但大方向是无疑的,最终股票的定价将由股票所代表企业的盈利能力和前景回报作为基本的决定因素。
目前的去产能、去杠杆、严格环保执法等,几乎都有利于行业龙头企业、优势企业推动行业整合,未来优质企业的成长将主导股指的方向。如果以宽基指数来衡量的话,目前的指数处于低估,我们对未来的态度比较积极。
有必要特别汇报下支持我们积极态度的一个重要原因,一直以来我们都保持对前沿技术变化的跟踪观察和判断,我们的观点是随着技术的不断进步和成本的不断下降,世界将会迎来一场以光伏、电动车和储能为代表的能源革命。
以历史作为对比,人类历史上第一次工业革命以蒸汽机为代表,以煤炭为基础能源,以代替人力、畜力为特点;第二次工业革命以内燃机、电气化为代表,石油逐步成为主要能源。
这一次的新能源革命在人类主要能源的来源、能源使用方式、储存、运输等各方面都将产生革命性的变化,化石能源将退出几百年来的主导地位。
新能源革命不仅会大范围改变人类的生活,甚至国家实力对比、全球地缘政治格局都会因这次新能源革命而大大改变,以对人类社会的影响而言,这一次新能源革命对人类的影响不会亚于两次工业革命。
新能源革命将为世界经济、中国经济的新一轮上升周期带来巨大驱动力。
我们认为,此轮新能源革命的趋势已相当明朗,甚至我们已经身处其中,只因尚在萌芽初期,目前感受不太真切,甚至有很多人没有感受到。
我们相信大趋势带来大机会,投资的成功在于把握社会经济发展的大趋势。所以,我们会紧紧围绕这一主线来布局。
储能行业未来几年有望年均百分百以上增长,但是目前体量还太小,二级市场还缺乏投资标的。
电动汽车行业,锂电行业格局仍处于快速变化中,优势个股的估值还比较高,我们在密切跟踪。
相对而言,光伏行业格局更加清晰些,估值吸引力也较大,我们的产品已经进行了更多的布局。
我们有足够的耐心来等待新能源革命带来的大格局、大变化、大机会,所以随着市场的不断下挫,我们的态度将是越来越积极,在精选的标的中扎牢下去,剩下的就是等待了。 

2007.10.16

《致基金持有人的一封信》 
尊敬的持有人:
在不经意间,中国股市已经轻松越过了6000点大关,如今如果理性地进行分析的话,我们不得不承认A股的泡沫化程度已经相当高了。
近期,公司研究部相关人员专门分析和比较了同处亚洲市场的日本、台湾、韩国和泰国四个市场在历史经济高速发展时期所经历的股市泡沫,研究表明目前国内股市的整体估值水平已经超过了日本、韩国和泰国泡沫顶峰时期的估值水平,仅比台湾市场泡沫高峰期稍显温和。
今天市场上出现的种种疯狂的现象,都让我们为A股明后两年的表现表示担心。
基于上述分析,我们认为在目前市场状况下基金投资者应该避免盲目投资,尽量用闲钱进行投资,这样即使市场下跌,也能保持良好的心态。而且基金投资者要适当降低未来基金投资收益的预期,过去两年股市的辉煌造就了基金神话般的高回报,但持续的高回报是不现实的。
我们对明后年的基金投资收益较为谨慎,我们希望基金投资者认清目前普遍存在的几个错误认识。
误区一:买基金是只赚不赔的。由于我们处于一个大牛市中,尤其是过去两年,年收益翻番的基金比比皆是,这有可能造成投资者错误的认为买基金只赚不赔。但没有只涨不跌的股市,一旦股市出现大的调整,基金同样也会亏钱。
误区二:份额净值低的基金比较安全,事实上,净值1元的基金同样也有可能跌破面值,其亏钱的概率和程度与高净值基金基本是一样的。
当然,我们无法准确预测泡沫哪一天可能破灭,实际上,泡沫破灭前市场仍有可能出现大幅上涨,但根据海外的经验,泡沫破灭后往往都面临急速的下跌,所以我们想提醒您在进行基金投资之前,充分考虑可能的下跌风险,做个明白、理性的投资人。
毕竟天下没有只涨不跌的股市,在市场快速下跌过程中,基金的净值难免受到波及,如果您仅仅是因为相信基金肯定不会损失而投资的话,我们建议您全面认真的考虑;如果您是出于风险因素,赎回了基金,我们也能理解。
总之,我们希望您是在认真基金的性质,充分权衡了未来可能的风险与收益的情况之后,做出投资选择。
当然,我们并不惧怕未来可能的下跌,我们相信,凭着我们的专业能力,我们的表现依然能够领先大盘。在大牛市中,鸡犬升天往往掩盖了许多问题,但我们认为,越是在一般和不好的市况中,基金的专业理财能力越是能得以体现,大浪淘沙留下的才是真正的“金子”。
最后,感谢您一直以来对本公司的信任和支持,我们希望即使经历大风大浪,依然能够与您携手共进。

2012.01.04

《2013年股市会好转》
中国正处在一个经济转型的过程中,资本市场的分析也要从转型大背景出发来分析。
经济转型的一个重要方向是要建立消费型社会,这方面目前还有很多努力要去做。需要制度性改革配套,让老百姓获得更好的产品与服务;需要降低贫富差距,在总蛋糕给定的情况下,提高社会整体的边际消费倾向。
我们必须要面对的一个现实是,未来,我国经济增速下降不可避免。
从“三驾马车”的情况来看,投资方面,投资过剩严重,政府财力不足以及过度投资影响金融安全;出口方面,全球经济低迷,贸易保护盛行;消费方面,过去几年的消费增速并不低,未来能维持平稳增长,但也很难提速,中国经济增长的第二阶段如果能以5%-7%的速度水平再保持稳定增长十几年应该可算不错的结果。
长远来看,我们还会面临人口问题对经济增长的制约。
所以,企业盈利增长不容乐观。GDP增速下降,意味着总蛋糕增加速度会放缓。
而未来劳动者收入占比将上升;政府由于开支压力,税负占比恐怕难以下降,最终挤压的一定是资本收益的占比,如果再考虑到新兴行业的发展,某些传统行业的盈利下降将更为明显。上市公司整体利润出现年度负增长也许就是几年内会出现的事。
再谈谈政府财政的问题,无疑财政收入的增长会放缓,这些年的高速增长无法持续。但财政支出却会大幅增加。
民生投入已作为财政开支的重点,在民生方面仍有很多欠账,随着中国这几年已经建立起了几张保障网:比如城镇居民养老保险、职工基本医疗保险、城镇居民基本医疗保险和新型农村合作医疗保险等,未来保障支出会进入高速增长。
社保医疗支出是各国面临的难题,中国也不会例外。随着人口老化问题,医疗、养老支出都将快速增长。相比发达国家,我们积累下来的养老和医疗保障金储备都远远薄弱。
所以我们在调整的痛苦中可能还需要经历一段时间,当然,我相信我们国家最终会实现经济的逐步转型,并在经历调整之后迎来新一轮经济增长。
新一轮的增长靠什么呢?目前来看,新一轮经济增长的动力很可能来自新能源革命,太阳能、电动汽车等未来或成中国经济增长新动力。
中国的太阳能产业位于世界领先水平,电动汽车正与世界同时起步,太阳能的发电成本近几年已出现了大幅度的下降;世界上大部分地区实现平价上网的时间,速度也许比普遍预期要快。
我们完全可以相信,2013年,股市会好起来。

2015.04.22

《旗下基金2015年第一季度报告》
我们对A股市场当前的热度比较担忧,对下半年的股市表现较为悲观。
尽管泡沫让赚钱显得又快又轻松,我们的净值也受益于泡沫实现快速增长。我们也认同活跃的资本市场对促进直接融资和经济转型的积极意义,但我们同样认为近来高歌猛进的市场表现低估了改革的难度,忽视了转型的艰辛和可能经受的苦痛。
目前市场上绝大多数公司的股价已呈现泡沫,以创业板为代表的中小盘股票更是泡沫严重。过高的股价将让未来的收益前景蒙上阴影,即使是在最顺利的改革进程与经济前景下,买入过高价格股票的投资者也难有满意回报。
目前市场在轻松越过4000点后,越发大步狂奔,泡沫按照这样的速度不断膨胀,让我们不得不开始考虑可能很快会来临的再一次泡沫的破灭,由于巨额杠杆资金的进入,这一次的股价崩溃对投资者的伤害甚至可能超越2008年。
尽管有种种“这次不一样”的理由,却如马克吐温所说,历史不会重复自己,但会押着同样的韵脚,人性的基本特点从未改变。
虽然我们不清楚泡沫何时以何种方式破灭,但结局或许已经注定,不确定的只是过程,整体的账单已容易算得清楚,不清楚的只是各个个体的得失分配。
接下来的市场对本基金管理人将充满挑战,股市或将迎来狂风巨浪,基金的净值或也会如巨浪中的船舶大幅波动,我们为此已有心理准备,也有信心把好舵,在一次次的荣衰周期中不断前行,以专业能力为投资者赚取中长期的良好收益。

kulese_经典观点

石油

我所指俄国的70美元开采成本,是除了俄国政府税收之外的所有成本加成。主要是俄国企业腐败成本很高造成的。如果加上俄国国家的一般性国家预算,俄油的成本价格,将近100美元,如果加上军费,天知道要多少钱

我之前对石油价格有过一个判断,认为最低价格应该在29.2美元。但是,油价跌破28美元,说明我的判断已经错了,误差超出允许范围,所以,大家不能再拿这个判断指导投资。

至于石油后市如何,我不会在本帖发表任何跟直接投资有关的言论,希望大家谅解。

股市

大概说一下,仅供大家参考,不作为指导投资的意见。我认为A股现在的走势有三种可能。

第一种,概率50%。在2800一线震荡,时间超过3周。然后暴跌几天,到2450左右止跌,反弹。反弹高度在3300左右。这种走势的内在含义是,主力在2800一线建仓,下杀消灭恐慌盘,打爆融资盘,有利于筹码收集。

第二种,概率40%。在2800一线震荡,时间超过3周。然后开始上涨,上涨目标不确定,因为不能明确主力吸筹是否顺利,以及仓位情况。

第三种,概率不足10%。现在马上把大盘拉起来,上涨目标3400。主力吸筹不足,拉起大盘不可能太高。属于市场短期做多热情很高,主力顺势做一波短线,先赚点过节费的行情。我认为可能性比较小。

第四种,概率小于1%。大盘一路震荡下跌,跌到2000点。

  国内股市参与资金明显不少,现在跌回2000点可能性非常小。而且经过2014-2015一年半,国内很多公司业绩是有增长的,理论上2400-2500之间,是符合价值投资标准的。这个位置会有很多价值投资者建仓,这样对主力往上拉抬是有巨大的帮助。

  我们认为,2400-2500之间是中期A股的底部区域。在美国没有发生系统性金融危机之前,不会跌破。

美股

15375是美股的技术牛熊分界线,最近跌到比较靠近的位置,开始反弹是正常走势。至于是大反转,还是短线反弹,然后继续跌,问上帝吧。如果美股大反转,也许A股做多的热情会高涨,主力没准会趁势短线拉抬一波,赚点过节费。并且油价也会发生反转。

如果美国不给力,短期反弹后继续走低,下破15375,并且长期站到牛熊分界之下,大家都明白怎么回事了吧,呵呵

介绍经济泡沫的有一本叫《非同寻常的大众幻想与群众性癫狂》,通俗易懂。经济史看看《世界经济简史》,由埃默里大学的龙多·卡梅伦和伊利诺伊大学的拉里·尼尔合著的,千万别看国内那帮2B经济学家写的,不说人话、晦涩难懂,还误人子弟。金融史可以看看《金融简史》伯恩斯坦教授写的,他的《伯恩斯坦金融三部曲》都可以看看

install_proxy_server_squid3_on_ubuntu

========================================================================================================================

========================================================================================================================

========================================================================================================================

========================================================================================================================

========================================================================================================================

========================================================================================================================

docker 容器 设置网络代理

以/bin/bash 形式进入容器:

【命令行设置http 及https代理】,如下:

1
export http_proxy=http://10.1.205.103:3128;export https_proxy=http://10.1.205.103:3128;

要取消该设置:

1
2
unset http_proxy
unset https_proxy

========================================================================================================================

========================================================================================================================

========================================================================================================================

========================================================================================================================

========================================================================================================================

========================================================================================================================

Docker设置HTTP代理 (好像不需要这个)

参考资料:为docker配置HTTP代理服务器

一、注释掉namesserver的配置

1
2
3
4
5
[root@nvwa ~]# cat /etc/resolv.conf
# Generated by NetworkManager
search apa.gad.schneider-electric.com
nameserver xx.xx.xx.xx
nameserver xx.xx.xx.xx

改为:

1
2
3
4
5
[root@nvwa ~]# cat /etc/resolv.conf
# Generated by NetworkManager
#search apa.gad.schneider-electric.com
#nameserver xx.xx.xx.xx
#nameserver xx.xx.xx.xx

二、 代理配置

1
2
mkdir -p /etc/systemd/system/docker.service.d
vi /etc/systemd/system/docker.service.d/http-proxy.conf

具体配置内容

1
2
3
4
5
6
7
[Service]
Environment="HTTP_PROXY=http://xx.xx.xx.xx:80/
```python
## 三、重启docker
```python
systemctl daemon-reload
systemctl restart docker

四、查看配置结果

1
systemctl show --property=Environment docker

如果出现如下输出则配置成功

1
Environment=HTTP_PROXY=http://x.xx.xx.xx:80/

========================================================================================================================

========================================================================================================================

========================================================================================================================

========================================================================================================================

========================================================================================================================

========================================================================================================================

centos 下设置系统proxy

TBD

========================================================================================================================

========================================================================================================================

========================================================================================================================

========================================================================================================================

========================================================================================================================

========================================================================================================================

Linux(Debian9)下设置系统proxy

以Debian9下设置系统proxy为例

cd到/etc下 命令行 sudo vim environment

把下面的代码添加到文件中:

1
2
3
4
5
6
7
8
9
10
11
export ftp_proxy=http://192.168.1.2:1080
export http_proxy=http://192.168.1.2:1080
export https_proxy=http://192.168.1.2:1080
export socks_proxy=http://192.168.1.2:1080
export no_proxy="localhost,127.0.0.1"

export FTP_PROXY=http://192.168.1.2:1080
export HTTP_PROXY=http://192.168.1.2:1080
export HTTPS_PROXY=http://192.168.1.2:1080
export SOCKS_PROXY=http://192.168.1.2:1080
export NO_PROXY="localhost,127.0.0.1"

========================================================================================================================

========================================================================================================================

========================================================================================================================

========================================================================================================================

========================================================================================================================

========================================================================================================================

set http proxy on centos ~/.bash_profile

1
2
3
4
5
6
7
8
9
10
11
12
13
# wan
#export http_proxy="http://192.168.1.112:3128"
# lan
#export http_proxy="http://192.2.113.103:3128"
#export https_proxy="https://192.2.113.103:3128"
export http_proxy="http://proxy_server_ip:3128"
export http_proxys="https://proxy_server_ip:3128"

#https_proxy=proxy.361way.com:8080
#export https_proxy

#ftp_proxy=proxy.361way.com:8080
#export ftp_proxy

use new yum

1
2
3
4
5
6
7
8
1. add proxy in /etc/yum.conf
# The proxy server - proxy server:port number
proxy=http://proxy_server_ip:3128

2. copy the custom repo files to /ect/yum.repos.d/
like:
centos-base-163.repo
centos-base-ali.repo

https://www.cnblogs.com/dadonggg/p/10019026.html

功能用途

我们在生活中见过各种代理,比如我们距离火车站较远,我们可以选择通过距离最近的火车票代售点来购买火车票。又比如商品代理商,我们拿不到厂家的直接或者,可以通过厂家授权的代理经销商来获得产品。代理服务器负责转发你的请求到目标服务器,然后将目标服务器的响应反馈给你。你可以理解为它就是个联姻的媒婆。代理服务器可以有很多用途,比如:

作为一个网络防火墙,将内网与外网隔开。是的外网只能访问代理服务器允许的边界,这是我们常见的正向代理,比如ningx的转发。另外,在一个局域网中如果有一台主机可以上外网,那么我们就可以把这台机器作为代理服务器,为其他机器提供外网的访问功能。
作为反爬利器,如果爬虫爬取的目标网站具有较强的反爬机制,最常见的通过IP来限制抓取频率,如果你的爬虫抓取太快,你的IP就会被封禁一段时间甚至永久封禁。此时我们就可以通过高匿代理让抓取的网站识别不出我们的真实IP。

本文提供两种代理情形:

1、两台都有外网IP,一台服务器请求资源通过另外一个服务器,本文重点讲第一种。

2、两台服务器,其中一台服务器只有内网IP,另外一台服务器有公网和内网IP。

两种配置情形大同小异,与第一种情形不同的是只需确认下面配置即可

1
2
3
4
5
6
7
8
9
{
# 确认服务器端ip_forward转发开启
echo 1 > /proc/sys/net/ipv4/ip_forward
ip_forward需要设定为1
sysctl -a |grep -w ip_forward
net.ipv4.ip_forward = 1
#客户端配置
export https_proxy=http://服务端内网ip:3128
}

代理安装

服务器端安装squid3

我是在Ubuntu14.04 64位环境下使用squid3搭建的代理服务器。squid3是一个主流的可配置的、健壮、低消耗的代理服务器。

1
sudo apt-get install squid3

配置

squid3的配置文件在/etc/squid3/squid.conf,我们使用vim编辑器来配置。

1
sudo vim /etc/squid3/squid.conf

我们在配置文件的末尾加入以下几行:

1
2
3
4
5
6
7
#允许的客户端ip
acl allcomputers src 0.0.0.0/0.0.0.0
#配置用户名密码,后面会生成passwords文件
auth_param basic program /usr/lib/squid3/basic_ncsa_auth /etc/squid3/passwords
auth_param basic realm proxy
acl authenticated proxy_auth REQUIRED
http_access allow authenticated allcomputers

复制代码
找到http_access deny all并注释掉

1
#http_access deny all

最好修改一下默认的3128端口,因为这个端口是默认的,很容易被网络上的代理爬虫探测到。

1
http_port 8828

用户名密码认证

网络上有很多专门爬免认证的代理的爬虫,如果我们自己搭建的代理服务器不加认证的话,会被这些爬虫探测到然后沦为了免费代理。

使用htpasswd来创建passwords文件,htpasswd命令在软件包apache2-utils中。

1
sudo apt-get install apache2-utils

生成password文件

1
sudo htpasswd -c -d /etc/squid3/passwords 自定义用户名

然后输入两次至少8位的密码,会在/etc/squid3/目录下生成passwords文件,要保证该文件是可读的。

1
sudo chmod o+r /etc/squid3/passwords

启动服务,也可以使用restart,stop进行重启和关闭。

1
2
3
sudo service squid3 start
或者
etc/init.d/squid start

验证代理是否起作用

squid3的访问日志文件在/var/log/squid3/access.log

1
2
3
tail -f /var/log/squid3/access.log
1543199344.191 20 118.31.0.74 TCP_DENIED/407 444 HEAD http://www.baidu.com/ squid HIER_NONE/- text/html
1543199365.390 17 118.31.0.74 TCP_DENIED/407 444 HEAD http://www.baidu.com/ squid HIER_NONE/- text/html

客户端配置

另找一台linux机器打开shell,将我们的代理配置上:

1
2
export http_proxy="http://用户名:密码@代理IP:代理端口"
curl -l "http://www.baidu.com"

如果代理配置正确,回输出html,同时代理服务器上的access.log会记录这次请求。

上面的配置只会在命令行界面临时生效,如果退出命令行界面,配置会失效,接下来,我们将上面配置加入到环境变量中去

加入全局环境变量

1
2
3
4
5
#备份文件(很重要)
cp /etc/profile /etc/profile.bak
vim /etc/profile
#http 代理
export http_proxy="http://用户名:密码@代理服务器IP:代理端口"

配置高匿

代理分为透明代理、匿名代理、混淆代理、高匿代理,这4种代理,主要是在代理服务器端的配置不同,导致其向目标地址发送请求时,REMOTE_ADDR, HTTP_VIA,HTTP_X_FORWARDED_FOR三个变量不同。

1.透明代理(Transparent Proxy)
REMOTE_ADDR = Proxy IP
HTTP_VIA = Proxy IP
HTTP_X_FORWARDED_FOR = Your IP
透明代理虽然可以直接“隐藏”你的IP地址,但是还是可以从HTTP_X_FORWARDED_FOR来查到你是谁。

2.匿名代理(Anonymous Proxy)

REMOTE_ADDR = proxy IP
HTTP_VIA = proxy IP
HTTP_X_FORWARDED_FOR = proxy IP
匿名代理比透明代理进步了一点:别人只能知道你用了代理,无法知道你是谁。

3.混淆代理(Distorting Proxies)

REMOTE_ADDR = Proxy IP
HTTP_VIA = Proxy IP
HTTP_X_FORWARDED_FOR = Random IP address

如上,与匿名代理相同,如果使用了混淆代理,别人还是能知道你在用代理,但是会得到一个假的IP地址,伪装的更逼真

4.高匿代理(Elite proxy或High Anonymity Proxy)

REMOTE_ADDR = Proxy IP
HTTP_VIA = not determined
HTTP_X_FORWARDED_FOR = not determined
可以看出来,高匿代理让别人根本无法发现你是在用代理,所以是最好的选择。

下面是squid3高匿的设置,我们修改配置文件squid.conf,在最后加上

request_header_access X-Forwarded-For deny all
request_header_access From deny all
request_header_access Via deny all
测试高匿是否生效,我们用上面同样的方法访问,会显示出你使用的IP的地址,我们就可以判断显示的IP和我们使用的代理IP是否相同,如果相同,则匿名生效。

1
curl -l "http://www.abc.com"